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 struct MonDef MON_1024_768_80 = { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 118 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}; 119 120 struct MonDef MON_1024_1024_59= { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087, 121 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255}; 122 123 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR 124 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT 125 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */ 126 127 struct MonDef MON_1280_1024_60= {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073, 128 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}; 129 130 /* horizontal 75kHz */ 131 132 struct MonDef MON_1280_1024_69= {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073, 133 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}; 134 135 #else 136 137 struct MonDef monitor_defs[] = { 138 /* horizontal 31.5 kHz */ 139 140 { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535, 141 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font, 32, 255}, 142 143 /* horizontal 38kHz */ 144 145 { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638, 146 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}, 147 148 /* horizontal 64kHz */ 149 150 { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628, 151 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}, 152 153 { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 154 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, 155 156 { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087, 157 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255}, 158 159 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR 160 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT 161 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */ 162 163 {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073, 164 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}, 165 166 /* horizontal 75kHz */ 167 168 {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073, 169 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}, 170 171 }; 172 173 static const char *monitor_descr[] = { 174 "80x64 (640x512) 31.5kHz", 175 "96x75 (768x600) 38kHz", 176 "96x75 (768x600) 64kHz", 177 "128x96 (1024x768) 64kHz", 178 "128x128 (1024x1024) 64kHz", 179 "160x128 (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***", 180 "160x128 (1280x1024) 75kHz ***EXCEEDS CHIP LIMIT!!!***", 181 }; 182 183 int retina_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]); 184 185 /* patchable */ 186 int retina_default_mon = 2; 187 188 #endif 189 190 191 static struct MonDef *current_mon; 192 193 /* -------------- START OF CODE -------------- */ 194 195 196 static const long FQTab[16] = 197 { 25175000, 28322000, 36000000, 65000000, 198 44900000, 50000000, 80000000, 75000000, 199 56644000, 63000000, 72000000, 130000000, 200 90000000, 100000000, 110000000, 120000000 }; 201 202 203 /*--------------------------------------------------*/ 204 /*--------------------------------------------------*/ 205 206 #if 0 207 static struct MonDef *default_monitor = &DEFAULT_MONDEF; 208 #endif 209 210 211 static int rt_load_mon (struct grf_softc *gp, struct MonDef *md) 212 { 213 struct grfinfo *gi = &gp->g_display; 214 volatile unsigned char *ba; 215 volatile unsigned char *fb; 216 short FW, clksel, HDE, VDE; 217 218 for (clksel = 15; clksel; clksel--) { 219 if (FQTab[clksel] == md->FQ) break; 220 } 221 if (clksel < 0) return 0; 222 223 ba = gp->g_regkva;; 224 fb = gp->g_fbkva; 225 226 switch (md->FX) { 227 case 4: 228 FW = 0; 229 break; 230 case 7: 231 FW = 1; 232 break; 233 case 8: 234 FW = 2; 235 break; 236 case 9: 237 FW = 3; 238 break; 239 case 10: 240 FW = 4; 241 break; 242 case 11: 243 FW = 5; 244 break; 245 case 12: 246 FW = 6; 247 break; 248 case 13: 249 FW = 7; 250 break; 251 case 14: 252 FW = 8; 253 break; 254 case 15: 255 FW = 9; 256 break; 257 case 16: 258 FW = 11; 259 break; 260 default: 261 return 0; 262 break; 263 }; 264 265 HDE = (md->MW+md->FX-1)/md->FX; 266 VDE = md->MH-1; 267 268 /* hmm... */ 269 fb[0x8000] = 0; 270 271 /* program the clock oscillator */ 272 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04)); 273 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00); 274 275 /* XXXX according to the NCR specs, this register should be set to 1 276 XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE 277 XXXX setting. */ 278 WSeq (ba, SEQ_ID_RESET, 0x03); 279 280 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8)); 281 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f); 282 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 283 /* odd/even write select + extended memory */ 284 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06); 285 /* XXXX I think this order of setting RESET is wrong... */ 286 WSeq (ba, SEQ_ID_RESET, 0x01); 287 WSeq (ba, SEQ_ID_RESET, 0x03); 288 289 /* enable extension registers * 290 WSeq (ba, SEQ_ID_EXTENDED_ENABLE, 0x05); 291 /* monochrome cursor */ 292 WSeq (ba, SEQ_ID_CURSOR_CONTROL, 0x00); 293 /* bank0 */ 294 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00); 295 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0x00); 296 WSeq (ba, 0x1a , 0x00); /* these are reserved, really set them to 0 ??? */ 297 WSeq (ba, 0x1b , 0x00); /* these are reserved, really set them to 0 ??? */ 298 /* bank0 */ 299 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00); 300 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00); 301 /* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */ 302 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40); 303 /* set font width + rest of clocks */ 304 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) ); 305 /* no ext-chain4 + no host-addr-bit-16 */ 306 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, 0x00); 307 /* no packed/nibble + no 256bit gfx format */ 308 WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00); 309 /* AT-interface */ 310 WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x06); 311 /* see fg/bg color expansion */ 312 WSeq (ba, SEQ_ID_COLOR_EXP_WFG, 0x01); 313 WSeq (ba, SEQ_ID_COLOR_EXP_WBG, 0x00); 314 WSeq (ba, SEQ_ID_EXT_RW_CONTROL, 0x00); 315 /* another clock bit, plus hw stuff */ 316 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) ); 317 /* don't tristate PCLK and PIX */ 318 WSeq (ba, SEQ_ID_COLOR_KEY_CNTL, 0x40 ); 319 /* reset CRC circuit */ 320 WSeq (ba, SEQ_ID_CRC_CONTROL, 0x00 ); 321 /* set RAS/CAS swap */ 322 WSeq (ba, SEQ_ID_PERF_SELECT, 0x20); 323 324 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf ) | 0x20); 325 WCrt (ba, CRT_ID_HOR_TOTAL, md->HT & 0xff); 326 WCrt (ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff); 327 WCrt (ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff); 328 WCrt (ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80); 329 330 WCrt (ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff); 331 WCrt (ba, CRT_ID_END_HOR_RETR, (md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80)); 332 WCrt (ba, CRT_ID_VER_TOTAL, (md->VT & 0xff)); 333 WCrt (ba, CRT_ID_OVERFLOW, (( (md->VSS & 0x200) / 0x200 * 0x80) 334 | ((VDE & 0x200) / 0x200 * 0x40) 335 | ((md->VT & 0x200) / 0x200 * 0x20) 336 | 0x10 337 | ((md->VBS & 0x100) / 0x100 * 8 ) 338 | ((md->VSS & 0x100) / 0x100 * 4 ) 339 | ((VDE & 0x100) / 0x100 * 2 ) 340 | ((md->VT & 0x100) / 0x100 ))); 341 WCrt (ba, CRT_ID_PRESET_ROW_SCAN, 0x00); 342 343 WCrt (ba, CRT_ID_MAX_SCAN_LINE, (( (md->FLG & MDF_DBL)/ MDF_DBL * 0x80) 344 | 0x40 345 | ((md->VBS & 0x200)/0x200 * 0x20) 346 | ((md->FY-1) & 0x1f))); 347 348 WCrt (ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2); 349 WCrt (ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1); 350 351 WCrt (ba, CRT_ID_START_ADDR_HIGH, 0x00); 352 WCrt (ba, CRT_ID_START_ADDR_LOW, 0x00); 353 354 WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 355 WCrt (ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 356 357 WCrt (ba, CRT_ID_START_VER_RETR, md->VSS & 0xff); 358 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0x0f) | 0x80 | 0x20); 359 WCrt (ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff); 360 WCrt (ba, CRT_ID_OFFSET, (HDE / 2) & 0xff); 361 WCrt (ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f); 362 WCrt (ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff); 363 WCrt (ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff); 364 /* byte mode + wrap + select row scan counter + cms */ 365 WCrt (ba, CRT_ID_MODE_CONTROL, 0xe3); 366 WCrt (ba, CRT_ID_LINE_COMPARE, 0xff); 367 368 /* enable extended end bits + those bits */ 369 WCrt (ba, CRT_ID_EXT_HOR_TIMING1, ( 0x20 370 | ((md->FLG & MDF_LACE) / MDF_LACE * 0x10) 371 | ((md->HT & 0x100) / 0x100 * 0x01) 372 | (((HDE-1) & 0x100) / 0x100 * 0x02) 373 | ((md->HBS & 0x100) / 0x100 * 0x04) 374 | ((md->HSS & 0x100) / 0x100 * 0x08))); 375 376 WCrt (ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16)); 377 378 WCrt (ba, CRT_ID_EXT_HOR_TIMING2, ( ((md->HT & 0x200)/ 0x200 * 0x01) 379 | (((HDE-1) & 0x200)/ 0x200 * 0x02) 380 | ((md->HBS & 0x200)/ 0x200 * 0x04) 381 | ((md->HSS & 0x200)/ 0x200 * 0x08) 382 | ((md->HBE & 0xc0) / 0x40 * 0x10) 383 | ((md->HSE & 0x60) / 0x20 * 0x40))); 384 385 WCrt (ba, CRT_ID_EXT_VER_TIMING, ( ((md->VSE & 0x10) / 0x10 * 0x80) 386 | ((md->VBE & 0x300)/ 0x100 * 0x20) 387 | 0x10 388 | ((md->VSS & 0x400)/ 0x400 * 0x08) 389 | ((md->VBS & 0x400)/ 0x400 * 0x04) 390 | ((VDE & 0x400)/ 0x400 * 0x02) 391 | ((md->VT & 0x400)/ 0x400 * 0x01))); 392 393 WGfx (ba, GCT_ID_SET_RESET, 0x00); 394 WGfx (ba, GCT_ID_ENABLE_SET_RESET, 0x00); 395 WGfx (ba, GCT_ID_COLOR_COMPARE, 0x00); 396 WGfx (ba, GCT_ID_DATA_ROTATE, 0x00); 397 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0x00); 398 WGfx (ba, GCT_ID_GRAPHICS_MODE, 0x00); 399 WGfx (ba, GCT_ID_MISC, 0x04); 400 WGfx (ba, GCT_ID_COLOR_XCARE, 0xff); 401 WGfx (ba, GCT_ID_BITMASK, 0xff); 402 403 /* reset the Attribute Controller flipflop */ 404 vgar (ba, GREG_STATUS1_R); 405 WAttr (ba, ACT_ID_PALETTE0, 0x00); 406 WAttr (ba, ACT_ID_PALETTE1, 0x01); 407 WAttr (ba, ACT_ID_PALETTE2, 0x02); 408 WAttr (ba, ACT_ID_PALETTE3, 0x03); 409 WAttr (ba, ACT_ID_PALETTE4, 0x04); 410 WAttr (ba, ACT_ID_PALETTE5, 0x05); 411 WAttr (ba, ACT_ID_PALETTE6, 0x06); 412 WAttr (ba, ACT_ID_PALETTE7, 0x07); 413 WAttr (ba, ACT_ID_PALETTE8, 0x08); 414 WAttr (ba, ACT_ID_PALETTE9, 0x09); 415 WAttr (ba, ACT_ID_PALETTE10, 0x0a); 416 WAttr (ba, ACT_ID_PALETTE11, 0x0b); 417 WAttr (ba, ACT_ID_PALETTE12, 0x0c); 418 WAttr (ba, ACT_ID_PALETTE13, 0x0d); 419 WAttr (ba, ACT_ID_PALETTE14, 0x0e); 420 WAttr (ba, ACT_ID_PALETTE15, 0x0f); 421 422 vgar (ba, GREG_STATUS1_R); 423 WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x08); 424 425 WAttr (ba, ACT_ID_OVERSCAN_COLOR, 0x00); 426 WAttr (ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); 427 WAttr (ba, ACT_ID_HOR_PEL_PANNING, 0x00); 428 WAttr (ba, ACT_ID_COLOR_SELECT, 0x00); 429 430 vgar (ba, GREG_STATUS1_R); 431 /* I have *NO* idea what strobing reg-0x20 might do... */ 432 vgaw (ba, ACT_ADDRESS_W, 0x20); 433 434 WCrt (ba, CRT_ID_MAX_SCAN_LINE, ( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) 435 | 0x40 436 | ((md->VBS & 0x200)/0x200 * 0x20) 437 | ((md->FY-1) & 0x1f))); 438 439 440 /* not it's time for guessing... */ 441 442 vgaw (ba, VDAC_REG_D, 0x02); 443 444 /* if this does what I think it does, it selects DAC 445 register 0, and writes the palette in subsequent 446 registers, thus it works similar to the WD33C93 447 select/data mechanism */ 448 vgaw (ba, VDAC_REG_SELECT, 0x00); 449 450 { 451 452 short x = 15; 453 const unsigned char * col = md->PAL; 454 do { 455 456 vgaw (ba, VDAC_REG_DATA, *col++); 457 vgaw (ba, VDAC_REG_DATA, *col++); 458 vgaw (ba, VDAC_REG_DATA, *col++); 459 460 461 } while (x--); 462 463 } 464 465 466 /* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */ 467 { 468 469 /* first set the whole font memory to a test-pattern, so we 470 can see if something that shouldn't be drawn IS drawn.. */ 471 { 472 unsigned char * c = fb; 473 long x; 474 Map(2); 475 476 for (x = 0; x < 65536; x++) { 477 *c++ = (x & 1)? 0xaa : 0x55; 478 } 479 } 480 481 { 482 unsigned char * c = fb; 483 long x; 484 Map(3); 485 486 for (x = 0; x < 65536; x++) { 487 *c++ = (x & 1)? 0xaa : 0x55; 488 } 489 } 490 491 { 492 /* ok, now position at first defined character, and 493 copy over the images */ 494 unsigned char * c = fb + md->FLo * 32; 495 const unsigned char * f = md->FData; 496 unsigned short z; 497 498 Map(2); 499 for (z = md->FLo; z <= md->FHi; z++) { 500 501 short y = md->FY-1; 502 if (md->FX > 8){ 503 do { 504 *c++ = *f; 505 f += 2; 506 } while (y--); 507 } 508 else { 509 do { 510 *c++ = *f++; 511 } while (y--); 512 } 513 514 c += 32-md->FY; 515 516 } 517 518 if (md->FX > 8) { 519 unsigned short z; 520 521 Map(3); 522 c = fb + md->FLo*32; 523 f = md->FData+1; 524 for (z = md->FLo; z <= md->FHi; z++) { 525 526 short y = md->FY-1; 527 do { 528 *c++ = *f; 529 f += 2; 530 } while (y--); 531 532 c += 32-md->FY; 533 534 } 535 } 536 } 537 538 } 539 540 /* select map 0 */ 541 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0); 542 /* allow writes into maps 0 and 1 */ 543 WSeq (ba, SEQ_ID_MAP_MASK, 3); 544 /* select extended chain4 addressing: 545 !A0/!A1 map 0 character to be displayed 546 !A1/ A1 map 1 attribute of that character 547 A0/!A1 map 2 not used (masked out, ignored) 548 A0/ A1 map 3 not used (masked out, ignored) */ 549 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02); 550 551 { 552 /* position in display memory */ 553 unsigned short * c = (unsigned short *) fb; 554 555 /* fill with blank, white on black */ 556 const unsigned short fill_val = 0x2010; 557 short x = md->XY; 558 do { 559 *c = fill_val; 560 c += 2; 561 } while (x--); 562 563 /* I won't comment this :-)) */ 564 c = (unsigned short *) fb; 565 c += (md->TX-6)*2; 566 { 567 unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f}; 568 unsigned short * f = init_msg; 569 x = 5; 570 do { 571 *c = *f++; 572 c += 2; 573 } while (x--); 574 } 575 576 577 } 578 579 580 gi->gd_regaddr = (caddr_t) md; /* XXX */ 581 gi->gd_regsize = 0; 582 583 gi->gd_fbaddr = (long)fb - (long)ZORRO2ADDR + (long)ZORRO2BASE; 584 gi->gd_fbsize = 64*1024; /* larger, but that's whats mappable */ 585 586 gi->gd_colors = 1 << md->DEP; 587 gi->gd_planes = md->DEP; 588 589 gi->gd_fbwidth = md->MW; 590 gi->gd_fbheight = md->MH; 591 gi->gd_fbx = 0; 592 gi->gd_fby = 0; 593 gi->gd_dwidth = md->TX * md->FX; 594 gi->gd_dheight = md->TY * md->FY; 595 gi->gd_dx = 0; 596 gi->gd_dy = 0; 597 598 /* initialized, works, return 1 */ 599 return 1; 600 } 601 602 int rt_init (struct grf_softc *gp, struct amiga_device *ad, struct amiga_hw *ahw) 603 { 604 /* if already initialized, fail */ 605 if (gp->g_regkva) 606 return 0; 607 608 gp->g_regkva = ahw->hw_kva; 609 gp->g_fbkva = ahw->hw_kva + 64*1024; 610 611 /* don't let them patch it out of bounds */ 612 if ((unsigned)retina_default_mon >= retina_mon_max) 613 retina_default_mon = 0; 614 615 current_mon = monitor_defs + retina_default_mon; 616 617 return rt_load_mon (gp, current_mon); 618 } 619 620 static int 621 rt_getvmode (gp, vm) 622 struct grf_softc *gp; 623 struct grfvideo_mode *vm; 624 { 625 struct MonDef *md; 626 627 if (vm->mode_num && vm->mode_num > retina_mon_max) 628 return EINVAL; 629 630 if (! vm->mode_num) 631 vm->mode_num = (current_mon - monitor_defs) + 1; 632 633 md = monitor_defs + (vm->mode_num - 1); 634 strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1), 635 sizeof (vm->mode_descr)); 636 vm->pixel_clock = md->FQ; 637 vm->disp_width = md->MW; 638 vm->disp_height = md->MH; 639 vm->depth = md->DEP; 640 vm->hblank_start = md->HBS; 641 vm->hblank_stop = md->HBE; 642 vm->hsync_start = md->HSS; 643 vm->hsync_stop = md->HSE; 644 vm->htotal = md->HT; 645 vm->vblank_start = md->VBS; 646 vm->vblank_stop = md->VBE; 647 vm->vsync_start = md->VSS; 648 vm->vsync_stop = md->VSE; 649 vm->vtotal = md->VT; 650 651 return 0; 652 } 653 654 655 static int 656 rt_setvmode (gp, mode) 657 struct grf_softc *gp; 658 unsigned mode; 659 { 660 struct MonDef *md; 661 662 if (!mode || mode > retina_mon_max) 663 return EINVAL; 664 665 current_mon = monitor_defs + (mode - 1); 666 return rt_load_mon (gp, current_mon) ? 0 : EINVAL; 667 } 668 669 670 /* 671 * Change the mode of the display. 672 * Right now all we can do is grfon/grfoff. 673 * Return a UNIX error number or 0 for success. 674 */ 675 rt_mode(gp, cmd, arg) 676 register struct grf_softc *gp; 677 int cmd; 678 void *arg; 679 { 680 /* implement these later... */ 681 682 switch (cmd) 683 { 684 case GM_GRFON: 685 return 0; 686 687 case GM_GRFOFF: 688 return 0; 689 690 case GM_GRFCONFIG: 691 return 0; 692 693 case GM_GRFGETVMODE: 694 return rt_getvmode (gp, (struct grfvideo_mode *) arg); 695 696 case GM_GRFSETVMODE: 697 return rt_setvmode (gp, *(unsigned *) arg); 698 699 case GM_GRFGETNUMVM: 700 *(int *)arg = retina_mon_max; 701 return 0; 702 703 default: 704 break; 705 } 706 707 return EINVAL; 708 } 709 710 #endif /* NGRF */ 711