1 #include "grf.h" 2 #if NGRF > 0 3 4 /* Graphics routines for the Retina board, 5 using the NCR 77C22E+ VGA controller. */ 6 7 #include "sys/param.h" 8 #include "sys/errno.h" 9 #include "grfioctl.h" 10 #include "grfvar.h" 11 #include "grf_rtreg.h" 12 #include "../include/cpu.h" 13 #include "device.h" 14 15 extern caddr_t ZORRO2ADDR; 16 17 /* NOTE: this driver for the MacroSystem Retina board was only possible, 18 because MacroSystem provided information about the pecularities 19 of the board. THANKS! Competition in Europe among gfx board 20 manufacturers is rather tough, so Lutz Vieweg, who wrote the 21 initial driver, has made an agreement with MS not to document 22 the driver source (see also his Copyright disclaimer below). 23 -> ALL comments after 24 -> "/* -------------- START OF CODE -------------- * /" 25 -> have been added by myself (mw) from studying the publically 26 -> available "NCR 77C22E+" Data Manual 27 28 Lutz' original driver source (without any of my comments) is 29 available on request. */ 30 31 32 /* This code offers low-level routines to access the Retina graphics-board 33 manufactured by MS MacroSystem GmbH from within NetBSD for the Amiga. 34 No warranties for any kind of function at all - this code may crash 35 your hardware and scratch your harddisk. 36 Use at your own risk. 37 Freely distributable. 38 39 Written by Lutz Vieweg 07/93 40 41 Thanks to MacroSystem for providing me with the neccessary information 42 to create theese routines. The sparse documentation of this code 43 results from the agreements between MS and me. 44 */ 45 46 extern unsigned char kernel_font_width, kernel_font_height; 47 extern unsigned char kernel_font_lo, kernel_font_hi; 48 extern unsigned char kernel_font[]; 49 50 51 #define MDF_DBL 1 52 #define MDF_LACE 2 53 #define MDF_CLKDIV2 4 54 55 56 /* standard-palette definition */ 57 58 unsigned char NCRStdPalette[16*3] = { 59 /* R G B */ 60 0, 0, 0, 61 192,192,192, 62 128, 0, 0, 63 0,128, 0, 64 0, 0,128, 65 128,128, 0, 66 0,128,128, 67 128, 0,128, 68 64, 64, 64, /* the higher 8 colors have more intensity for */ 69 255,255,255, /* compatibility with standard attributes */ 70 255, 0, 0, 71 0,255, 0, 72 0, 0,255, 73 255,255, 0, 74 0,255,255, 75 255, 0,255 76 }; 77 78 79 /* The following structures are examples for monitor-definitions. To make one 80 of your own, first use "DefineMonitor" and create the 8-bit monitor-mode of 81 your dreams. Then save it, and make a structure from the values provided in 82 the file DefineMonitor stored - the labels in the comment above the 83 structure definition show where to put what value. 84 85 Then you'll need to adapt your monitor-definition to the font you want to 86 use. Be FX the width of the font, then the following modifications have to 87 be applied to your values: 88 89 HBS = (HBS * 4) / FX 90 HSS = (HSS * 4) / FX 91 HSE = (HSE * 4) / FX 92 HBE = (HBE * 4) / FX 93 HT = (HT * 4) / FX 94 95 Make sure your maximum width (MW) and height (MH) are even multiples of 96 the fonts' width and height. 97 */ 98 99 #if 0 100 /* horizontal 31.5 kHz */ 101 102 /* FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT */ 103 struct MonDef MON_640_512_60 = { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535, 104 /* Depth, PAL, TX, TY, XY,FontX, FontY, FontData, FLo, Fhi */ 105 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font, 32, 255}; 106 107 /* horizontal 38kHz */ 108 109 struct MonDef MON_768_600_60 = { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638, 110 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}; 111 112 /* horizontal 64kHz */ 113 114 struct MonDef MON_768_600_80 = { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628, 115 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}; 116 117 #if 0 118 struct MonDef MON_1024_768_80 = { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 119 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}; 120 #else 121 struct MonDef MON_1024_768_80 = { 90000000, 0, 1024, 768, 257,258,278,321,320, 769, 770, 783, 804, 804, 122 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}; 123 #endif 124 125 struct MonDef MON_1024_1024_59= { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087, 126 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255}; 127 128 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR 129 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT 130 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */ 131 132 struct MonDef MON_1280_1024_60= {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073, 133 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}; 134 135 /* horizontal 75kHz */ 136 137 struct MonDef MON_1280_1024_69= {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073, 138 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}; 139 140 #else 141 142 struct MonDef monitor_defs[] = { 143 /* horizontal 31.5 kHz */ 144 145 { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535, 146 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font, 32, 255}, 147 148 /* horizontal 38kHz */ 149 150 { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638, 151 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}, 152 153 /* horizontal 64kHz */ 154 155 { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628, 156 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}, 157 158 159 160 { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 161 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, 162 163 { 100000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 164 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, 165 166 { 110000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 167 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, 168 169 { 120000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 170 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, 171 172 { 13000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 173 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, 174 175 { 72000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 176 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, 177 178 { 75000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 179 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, 180 181 182 183 184 { 90000000, 24, 1024, 768, 129,130,139,161,160, 769, 770, 783, 804, 804, 185 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, 186 187 { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087, 188 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255}, 189 190 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR 191 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT 192 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */ 193 194 {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073, 195 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}, 196 197 /* horizontal 75kHz */ 198 199 {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073, 200 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}, 201 202 }; 203 204 static const char *monitor_descr[] = { 205 "80x64 (640x512) 31.5kHz", 206 "96x75 (768x600) 38kHz", 207 "96x75 (768x600) 64kHz", 208 "128x96 (1024x768) 64kHz", 209 "128x128 (1024x1024) 64kHz", 210 "160x128 (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***", 211 "160x128 (1280x1024) 75kHz ***EXCEEDS CHIP LIMIT!!!***", 212 }; 213 214 int retina_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]); 215 216 /* patchable */ 217 int retina_default_mon = 2; 218 219 #endif 220 221 222 static struct MonDef *current_mon; 223 224 /* -------------- START OF CODE -------------- */ 225 226 227 static const long FQTab[16] = 228 { 25175000, 28322000, 36000000, 65000000, 229 44900000, 50000000, 80000000, 75000000, 230 56644000, 63000000, 72000000, 130000000, 231 90000000, 100000000, 110000000, 120000000 }; 232 233 234 /*--------------------------------------------------*/ 235 /*--------------------------------------------------*/ 236 237 #if 0 238 static struct MonDef *default_monitor = &DEFAULT_MONDEF; 239 #endif 240 241 242 static int rt_load_mon (struct grf_softc *gp, struct MonDef *md) 243 { 244 struct grfinfo *gi = &gp->g_display; 245 volatile unsigned char *ba; 246 volatile unsigned char *fb; 247 short FW, clksel, HDE, VDE; 248 249 for (clksel = 15; clksel; clksel--) { 250 if (FQTab[clksel] == md->FQ) break; 251 } 252 if (clksel < 0) return 0; 253 254 ba = gp->g_regkva;; 255 fb = gp->g_fbkva; 256 257 switch (md->FX) { 258 case 4: 259 FW = 0; 260 break; 261 case 7: 262 FW = 1; 263 break; 264 case 8: 265 FW = 2; 266 break; 267 case 9: 268 FW = 3; 269 break; 270 case 10: 271 FW = 4; 272 break; 273 case 11: 274 FW = 5; 275 break; 276 case 12: 277 FW = 6; 278 break; 279 case 13: 280 FW = 7; 281 break; 282 case 14: 283 FW = 8; 284 break; 285 case 15: 286 FW = 9; 287 break; 288 case 16: 289 FW = 11; 290 break; 291 default: 292 return 0; 293 break; 294 }; 295 296 HDE = (md->MW+md->FX-1)/md->FX; 297 VDE = md->MH-1; 298 299 /* hmm... */ 300 fb[0x8000] = 0; 301 302 /* enable extension registers */ 303 WSeq (ba, SEQ_ID_EXTENDED_ENABLE, 0x05); 304 305 #if 0 306 /* program the clock oscillator */ 307 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04)); 308 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00); 309 310 /* XXXX according to the NCR specs, this register should be set to 1 311 XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE 312 XXXX setting. */ 313 WSeq (ba, SEQ_ID_RESET, 0x03); 314 315 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8)); 316 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f); 317 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 318 /* odd/even write select + extended memory */ 319 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06); 320 /* XXXX I think this order of setting RESET is wrong... */ 321 WSeq (ba, SEQ_ID_RESET, 0x01); 322 WSeq (ba, SEQ_ID_RESET, 0x03); 323 #else 324 WSeq (ba, SEQ_ID_RESET, 0x01); 325 326 /* set font width + rest of clocks */ 327 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) ); 328 /* another clock bit, plus hw stuff */ 329 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) ); 330 331 /* program the clock oscillator */ 332 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04)); 333 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00); 334 335 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8)); 336 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f); 337 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 338 /* odd/even write select + extended memory */ 339 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06); 340 WSeq (ba, SEQ_ID_RESET, 0x03); 341 #endif 342 343 /* monochrome cursor */ 344 WSeq (ba, SEQ_ID_CURSOR_CONTROL, 0x00); 345 /* bank0 */ 346 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00); 347 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0x00); 348 WSeq (ba, 0x1a , 0x00); /* these are reserved, really set them to 0 ??? */ 349 WSeq (ba, 0x1b , 0x00); /* these are reserved, really set them to 0 ??? */ 350 /* bank0 */ 351 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00); 352 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00); 353 /* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */ 354 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40); 355 #if 0 356 /* set font width + rest of clocks */ 357 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) ); 358 #endif 359 /* no ext-chain4 + no host-addr-bit-16 */ 360 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, 0x00); 361 /* no packed/nibble + no 256bit gfx format */ 362 WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00); 363 /* AT-interface */ 364 WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x06); 365 /* see fg/bg color expansion */ 366 WSeq (ba, SEQ_ID_COLOR_EXP_WFG, 0x01); 367 WSeq (ba, SEQ_ID_COLOR_EXP_WBG, 0x00); 368 WSeq (ba, SEQ_ID_EXT_RW_CONTROL, 0x00); 369 #if 0 370 /* another clock bit, plus hw stuff */ 371 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) ); 372 #endif 373 /* don't tristate PCLK and PIX */ 374 WSeq (ba, SEQ_ID_COLOR_KEY_CNTL, 0x40 ); 375 /* reset CRC circuit */ 376 WSeq (ba, SEQ_ID_CRC_CONTROL, 0x00 ); 377 /* set RAS/CAS swap */ 378 WSeq (ba, SEQ_ID_PERF_SELECT, 0x20); 379 380 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf ) | 0x20); 381 WCrt (ba, CRT_ID_HOR_TOTAL, md->HT & 0xff); 382 WCrt (ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff); 383 WCrt (ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff); 384 WCrt (ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80); 385 386 WCrt (ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff); 387 WCrt (ba, CRT_ID_END_HOR_RETR, (md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80)); 388 WCrt (ba, CRT_ID_VER_TOTAL, (md->VT & 0xff)); 389 WCrt (ba, CRT_ID_OVERFLOW, (( (md->VSS & 0x200) / 0x200 * 0x80) 390 | ((VDE & 0x200) / 0x200 * 0x40) 391 | ((md->VT & 0x200) / 0x200 * 0x20) 392 | 0x10 393 | ((md->VBS & 0x100) / 0x100 * 8 ) 394 | ((md->VSS & 0x100) / 0x100 * 4 ) 395 | ((VDE & 0x100) / 0x100 * 2 ) 396 | ((md->VT & 0x100) / 0x100 ))); 397 WCrt (ba, CRT_ID_PRESET_ROW_SCAN, 0x00); 398 399 WCrt (ba, CRT_ID_MAX_SCAN_LINE, (( (md->FLG & MDF_DBL)/ MDF_DBL * 0x80) 400 | 0x40 401 | ((md->VBS & 0x200)/0x200 * 0x20) 402 | ((md->FY-1) & 0x1f))); 403 404 WCrt (ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2); 405 WCrt (ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1); 406 407 WCrt (ba, CRT_ID_START_ADDR_HIGH, 0x00); 408 WCrt (ba, CRT_ID_START_ADDR_LOW, 0x00); 409 410 WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 411 WCrt (ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 412 413 WCrt (ba, CRT_ID_START_VER_RETR, md->VSS & 0xff); 414 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0x0f) | 0x80 | 0x20); 415 WCrt (ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff); 416 WCrt (ba, CRT_ID_OFFSET, (HDE / 2) & 0xff); 417 WCrt (ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f); 418 WCrt (ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff); 419 WCrt (ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff); 420 /* byte mode + wrap + select row scan counter + cms */ 421 WCrt (ba, CRT_ID_MODE_CONTROL, 0xe3); 422 WCrt (ba, CRT_ID_LINE_COMPARE, 0xff); 423 424 /* enable extended end bits + those bits */ 425 WCrt (ba, CRT_ID_EXT_HOR_TIMING1, ( 0x20 426 | ((md->FLG & MDF_LACE) / MDF_LACE * 0x10) 427 | ((md->HT & 0x100) / 0x100 * 0x01) 428 | (((HDE-1) & 0x100) / 0x100 * 0x02) 429 | ((md->HBS & 0x100) / 0x100 * 0x04) 430 | ((md->HSS & 0x100) / 0x100 * 0x08))); 431 432 WCrt (ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16)); 433 434 WCrt (ba, CRT_ID_EXT_HOR_TIMING2, ( ((md->HT & 0x200)/ 0x200 * 0x01) 435 | (((HDE-1) & 0x200)/ 0x200 * 0x02) 436 | ((md->HBS & 0x200)/ 0x200 * 0x04) 437 | ((md->HSS & 0x200)/ 0x200 * 0x08) 438 | ((md->HBE & 0xc0) / 0x40 * 0x10) 439 | ((md->HSE & 0x60) / 0x20 * 0x40))); 440 441 WCrt (ba, CRT_ID_EXT_VER_TIMING, ( ((md->VSE & 0x10) / 0x10 * 0x80) 442 | ((md->VBE & 0x300)/ 0x100 * 0x20) 443 | 0x10 444 | ((md->VSS & 0x400)/ 0x400 * 0x08) 445 | ((md->VBS & 0x400)/ 0x400 * 0x04) 446 | ((VDE & 0x400)/ 0x400 * 0x02) 447 | ((md->VT & 0x400)/ 0x400 * 0x01))); 448 449 WGfx (ba, GCT_ID_SET_RESET, 0x00); 450 WGfx (ba, GCT_ID_ENABLE_SET_RESET, 0x00); 451 WGfx (ba, GCT_ID_COLOR_COMPARE, 0x00); 452 WGfx (ba, GCT_ID_DATA_ROTATE, 0x00); 453 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0x00); 454 WGfx (ba, GCT_ID_GRAPHICS_MODE, 0x00); 455 WGfx (ba, GCT_ID_MISC, 0x04); 456 WGfx (ba, GCT_ID_COLOR_XCARE, 0xff); 457 WGfx (ba, GCT_ID_BITMASK, 0xff); 458 459 /* reset the Attribute Controller flipflop */ 460 vgar (ba, GREG_STATUS1_R); 461 WAttr (ba, ACT_ID_PALETTE0, 0x00); 462 WAttr (ba, ACT_ID_PALETTE1, 0x01); 463 WAttr (ba, ACT_ID_PALETTE2, 0x02); 464 WAttr (ba, ACT_ID_PALETTE3, 0x03); 465 WAttr (ba, ACT_ID_PALETTE4, 0x04); 466 WAttr (ba, ACT_ID_PALETTE5, 0x05); 467 WAttr (ba, ACT_ID_PALETTE6, 0x06); 468 WAttr (ba, ACT_ID_PALETTE7, 0x07); 469 WAttr (ba, ACT_ID_PALETTE8, 0x08); 470 WAttr (ba, ACT_ID_PALETTE9, 0x09); 471 WAttr (ba, ACT_ID_PALETTE10, 0x0a); 472 WAttr (ba, ACT_ID_PALETTE11, 0x0b); 473 WAttr (ba, ACT_ID_PALETTE12, 0x0c); 474 WAttr (ba, ACT_ID_PALETTE13, 0x0d); 475 WAttr (ba, ACT_ID_PALETTE14, 0x0e); 476 WAttr (ba, ACT_ID_PALETTE15, 0x0f); 477 478 vgar (ba, GREG_STATUS1_R); 479 WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x08); 480 481 WAttr (ba, ACT_ID_OVERSCAN_COLOR, 0x00); 482 WAttr (ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); 483 WAttr (ba, ACT_ID_HOR_PEL_PANNING, 0x00); 484 WAttr (ba, ACT_ID_COLOR_SELECT, 0x00); 485 486 vgar (ba, GREG_STATUS1_R); 487 /* I have *NO* idea what strobing reg-0x20 might do... */ 488 vgaw (ba, ACT_ADDRESS_W, 0x20); 489 490 WCrt (ba, CRT_ID_MAX_SCAN_LINE, ( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) 491 | 0x40 492 | ((md->VBS & 0x200)/0x200 * 0x20) 493 | ((md->FY-1) & 0x1f))); 494 495 496 /* not it's time for guessing... */ 497 498 vgaw (ba, VDAC_REG_D, 0x02); 499 500 /* if this does what I think it does, it selects DAC 501 register 0, and writes the palette in subsequent 502 registers, thus it works similar to the WD33C93 503 select/data mechanism */ 504 vgaw (ba, VDAC_REG_SELECT, 0x00); 505 506 { 507 508 short x = 15; 509 const unsigned char * col = md->PAL; 510 do { 511 512 vgaw (ba, VDAC_REG_DATA, *col++); 513 vgaw (ba, VDAC_REG_DATA, *col++); 514 vgaw (ba, VDAC_REG_DATA, *col++); 515 516 517 } while (x--); 518 519 } 520 521 522 /* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */ 523 { 524 525 /* first set the whole font memory to a test-pattern, so we 526 can see if something that shouldn't be drawn IS drawn.. */ 527 { 528 unsigned char * c = fb; 529 long x; 530 Map(2); 531 532 for (x = 0; x < 65536; x++) { 533 *c++ = (x & 1)? 0xaa : 0x55; 534 } 535 } 536 537 { 538 unsigned char * c = fb; 539 long x; 540 Map(3); 541 542 for (x = 0; x < 65536; x++) { 543 *c++ = (x & 1)? 0xaa : 0x55; 544 } 545 } 546 547 { 548 /* ok, now position at first defined character, and 549 copy over the images */ 550 unsigned char * c = fb + md->FLo * 32; 551 const unsigned char * f = md->FData; 552 unsigned short z; 553 554 Map(2); 555 for (z = md->FLo; z <= md->FHi; z++) { 556 557 short y = md->FY-1; 558 if (md->FX > 8){ 559 do { 560 *c++ = *f; 561 f += 2; 562 } while (y--); 563 } 564 else { 565 do { 566 *c++ = *f++; 567 } while (y--); 568 } 569 570 c += 32-md->FY; 571 572 } 573 574 if (md->FX > 8) { 575 unsigned short z; 576 577 Map(3); 578 c = fb + md->FLo*32; 579 f = md->FData+1; 580 for (z = md->FLo; z <= md->FHi; z++) { 581 582 short y = md->FY-1; 583 do { 584 *c++ = *f; 585 f += 2; 586 } while (y--); 587 588 c += 32-md->FY; 589 590 } 591 } 592 } 593 594 } 595 596 /* select map 0 */ 597 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0); 598 /* allow writes into maps 0 and 1 */ 599 WSeq (ba, SEQ_ID_MAP_MASK, 3); 600 /* select extended chain4 addressing: 601 !A0/!A1 map 0 character to be displayed 602 !A1/ A1 map 1 attribute of that character 603 A0/!A1 map 2 not used (masked out, ignored) 604 A0/ A1 map 3 not used (masked out, ignored) */ 605 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02); 606 607 { 608 /* position in display memory */ 609 unsigned short * c = (unsigned short *) fb; 610 611 /* fill with blank, white on black */ 612 const unsigned short fill_val = 0x2010; 613 short x = md->XY; 614 do { 615 *c = fill_val; 616 c += 2; 617 } while (x--); 618 619 /* I won't comment this :-)) */ 620 c = (unsigned short *) fb; 621 c += (md->TX-6)*2; 622 { 623 unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f}; 624 unsigned short * f = init_msg; 625 x = 5; 626 do { 627 *c = *f++; 628 c += 2; 629 } while (x--); 630 } 631 632 633 } 634 635 636 gp->g_data = (caddr_t) md; 637 gi->gd_regaddr = (long)ba - (long)ZORRO2ADDR + (long)ZORRO2BASE;; 638 gi->gd_regsize = 64*1024; 639 640 gi->gd_fbaddr = (long)fb - (long)ZORRO2ADDR + (long)ZORRO2BASE; 641 gi->gd_fbsize = 64*1024; /* larger, but that's whats mappable */ 642 643 gi->gd_colors = 1 << md->DEP; 644 gi->gd_planes = md->DEP; 645 646 gi->gd_fbwidth = md->MW; 647 gi->gd_fbheight = md->MH; 648 gi->gd_fbx = 0; 649 gi->gd_fby = 0; 650 gi->gd_dwidth = md->TX * md->FX; 651 gi->gd_dheight = md->TY * md->FY; 652 gi->gd_dx = 0; 653 gi->gd_dy = 0; 654 655 /* initialized, works, return 1 */ 656 return 1; 657 } 658 659 int rt_init (struct grf_softc *gp, struct amiga_device *ad, struct amiga_hw *ahw) 660 { 661 /* if already initialized, fail */ 662 if (gp->g_regkva) 663 return 0; 664 665 gp->g_regkva = ahw->hw_kva; 666 gp->g_fbkva = ahw->hw_kva + 64*1024; 667 668 /* don't let them patch it out of bounds */ 669 if ((unsigned)retina_default_mon >= retina_mon_max) 670 retina_default_mon = 0; 671 672 current_mon = monitor_defs + retina_default_mon; 673 674 return rt_load_mon (gp, current_mon); 675 } 676 677 static int 678 rt_getvmode (gp, vm) 679 struct grf_softc *gp; 680 struct grfvideo_mode *vm; 681 { 682 struct MonDef *md; 683 684 if (vm->mode_num && vm->mode_num > retina_mon_max) 685 return EINVAL; 686 687 if (! vm->mode_num) 688 vm->mode_num = (current_mon - monitor_defs) + 1; 689 690 md = monitor_defs + (vm->mode_num - 1); 691 strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1), 692 sizeof (vm->mode_descr)); 693 vm->pixel_clock = md->FQ; 694 vm->disp_width = md->MW; 695 vm->disp_height = md->MH; 696 vm->depth = md->DEP; 697 vm->hblank_start = md->HBS; 698 vm->hblank_stop = md->HBE; 699 vm->hsync_start = md->HSS; 700 vm->hsync_stop = md->HSE; 701 vm->htotal = md->HT; 702 vm->vblank_start = md->VBS; 703 vm->vblank_stop = md->VBE; 704 vm->vsync_start = md->VSS; 705 vm->vsync_stop = md->VSE; 706 vm->vtotal = md->VT; 707 708 return 0; 709 } 710 711 712 static int 713 rt_setvmode (gp, mode) 714 struct grf_softc *gp; 715 unsigned mode; 716 { 717 struct MonDef *md; 718 719 if (!mode || mode > retina_mon_max) 720 return EINVAL; 721 722 current_mon = monitor_defs + (mode - 1); 723 return rt_load_mon (gp, current_mon) ? 0 : EINVAL; 724 } 725 726 727 /* 728 * Change the mode of the display. 729 * Right now all we can do is grfon/grfoff. 730 * Return a UNIX error number or 0 for success. 731 */ 732 rt_mode(gp, cmd, arg) 733 register struct grf_softc *gp; 734 int cmd; 735 void *arg; 736 { 737 /* implement these later... */ 738 739 switch (cmd) 740 { 741 case GM_GRFON: 742 return 0; 743 744 case GM_GRFOFF: 745 return 0; 746 747 case GM_GRFCONFIG: 748 return 0; 749 750 case GM_GRFGETVMODE: 751 return rt_getvmode (gp, (struct grfvideo_mode *) arg); 752 753 case GM_GRFSETVMODE: 754 return rt_setvmode (gp, *(unsigned *) arg); 755 756 case GM_GRFGETNUMVM: 757 *(int *)arg = retina_mon_max; 758 return 0; 759 760 default: 761 break; 762 } 763 764 return EINVAL; 765 } 766 767 #endif /* NGRF */ 768