1 /* $NetBSD: grf_rt.c,v 1.18 1994/10/26 02:03:16 cgd Exp $ */ 2 3 #include "grfrt.h" 4 #if NGRFRT > 0 5 6 /* Graphics routines for the Retina board, 7 using the NCR 77C22E+ VGA controller. */ 8 9 #include <sys/param.h> 10 #include <sys/errno.h> 11 #include <sys/ioctl.h> 12 #include <sys/device.h> 13 #include <machine/cpu.h> 14 #include <amiga/amiga/device.h> 15 #include <amiga/dev/ztwobusvar.h> 16 #include <amiga/dev/grfioctl.h> 17 #include <amiga/dev/grfvar.h> 18 #include <amiga/dev/grf_rtreg.h> 19 20 /* 21 * marked true early so that retina_cnprobe() can tell if we are alive. 22 */ 23 int retina_inited; 24 25 26 /* NOTE: this driver for the MacroSystem Retina board was only possible, 27 because MacroSystem provided information about the pecularities 28 of the board. THANKS! Competition in Europe among gfx board 29 manufacturers is rather tough, so Lutz Vieweg, who wrote the 30 initial driver, has made an agreement with MS not to document 31 the driver source (see also his Copyright disclaimer below). 32 -> ALL comments after 33 -> "/* -------------- START OF CODE -------------- * /" 34 -> have been added by myself (mw) from studying the publically 35 -> available "NCR 77C22E+" Data Manual 36 37 Lutz' original driver source (without any of my comments) is 38 available on request. */ 39 40 41 /* This code offers low-level routines to access the Retina graphics-board 42 manufactured by MS MacroSystem GmbH from within NetBSD for the Amiga. 43 No warranties for any kind of function at all - this code may crash 44 your hardware and scratch your harddisk. 45 Use at your own risk. 46 Freely distributable. 47 48 Written by Lutz Vieweg 07/93 49 50 Thanks to MacroSystem for providing me with the neccessary information 51 to create theese routines. The sparse documentation of this code 52 results from the agreements between MS and me. 53 */ 54 55 extern unsigned char kernel_font_8x8_width, kernel_font_8x8_height; 56 extern unsigned char kernel_font_8x8_lo, kernel_font_8x8_hi; 57 extern unsigned char kernel_font_8x8[]; 58 59 60 #define MDF_DBL 1 61 #define MDF_LACE 2 62 #define MDF_CLKDIV2 4 63 64 65 /* standard-palette definition */ 66 67 unsigned char NCRStdPalette[16*3] = { 68 /* R G B */ 69 0, 0, 0, 70 192,192,192, 71 128, 0, 0, 72 0,128, 0, 73 0, 0,128, 74 128,128, 0, 75 0,128,128, 76 128, 0,128, 77 64, 64, 64, /* the higher 8 colors have more intensity for */ 78 255,255,255, /* compatibility with standard attributes */ 79 255, 0, 0, 80 0,255, 0, 81 0, 0,255, 82 255,255, 0, 83 0,255,255, 84 255, 0,255 85 }; 86 87 88 /* The following structures are examples for monitor-definitions. To make one 89 of your own, first use "DefineMonitor" and create the 8-bit monitor-mode of 90 your dreams. Then save it, and make a structure from the values provided in 91 the file DefineMonitor stored - the labels in the comment above the 92 structure definition show where to put what value. 93 94 Then you'll need to adapt your monitor-definition to the font you want to 95 use. Be FX the width of the font, then the following modifications have to 96 be applied to your values: 97 98 HBS = (HBS * 4) / FX 99 HSS = (HSS * 4) / FX 100 HSE = (HSE * 4) / FX 101 HBE = (HBE * 4) / FX 102 HT = (HT * 4) / FX 103 104 Make sure your maximum width (MW) and height (MH) are even multiples of 105 the fonts' width and height. 106 */ 107 108 #if 0 109 /* horizontal 31.5 kHz */ 110 111 /* FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT */ 112 struct MonDef MON_640_512_60 = { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535, 113 /* Depth, PAL, TX, TY, XY,FontX, FontY, FontData, FLo, Fhi */ 114 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font_8x8, 32, 255}; 115 116 struct MonDef MON_640_480_62_G = { 50000000, 4, 640, 480, 161,171,184,196,195, 481, 484, 492, 502, 502, 117 8, NCRStdPalette,640,480, 5120, 8, 8, kernel_font_8x8, 32, 255}; 118 /* Enter higher values here ^ ^ for panning! */ 119 120 /* horizontal 38kHz */ 121 122 struct MonDef MON_768_600_60 = { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638, 123 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font_8x8, 32, 255}; 124 125 /* horizontal 64kHz */ 126 127 struct MonDef MON_768_600_80 = { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628, 128 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font_8x8, 32, 255}; 129 130 struct MonDef MON_1024_768_80 = { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 131 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font_8x8, 32, 255}; 132 133 /* FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT */ 134 struct MonDef MON_1024_768_80_G = { 90000000, 0, 1024, 768, 257,258,280,344,343, 769, 770, 783, 804, 804, 135 8, NCRStdPalette, 1024, 768, 12288, 8, 8, kernel_font_8x8, 32, 255}; 136 137 struct MonDef MON_1024_1024_59= { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087, 138 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font_8x8, 32, 255}; 139 140 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR 141 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT 142 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */ 143 144 struct MonDef MON_1280_1024_60= {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073, 145 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font_8x8, 32, 255}; 146 147 struct MonDef MON_1280_1024_60_G= {110000000, 0, 1280,1024, 321,322,349,422,421,1025,1026,1043,1073,1073, 148 8, NCRStdPalette,1280,1024, 20480, 8, 8, kernel_font_8x8, 32, 255}; 149 150 /* horizontal 75kHz */ 151 152 struct MonDef MON_1280_1024_69= {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073, 153 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font_8x8, 32, 255}; 154 155 #else 156 157 struct MonDef monitor_defs[] = { 158 /* horizontal 31.5 kHz */ 159 160 { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535, 161 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font_8x8, 32, 255}, 162 163 /* horizontal 38kHz */ 164 165 { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638, 166 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font_8x8, 32, 255}, 167 168 /* horizontal 64kHz */ 169 170 { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628, 171 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font_8x8, 32, 255}, 172 173 { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 174 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font_8x8, 32, 255}, 175 176 /* GFX modes */ 177 178 /* horizontal 31.5 kHz */ 179 180 { 50000000, 4, 640, 480, 161,171,184,196,195, 481, 484, 492, 502, 502, 181 8, NCRStdPalette,640, 480, 5120, 8, 8, kernel_font_8x8, 32, 255}, 182 183 /* horizontal 64kHz */ 184 185 { 90000000, 0, 1024, 768, 257,258,280,344,343, 769, 770, 783, 804, 804, 186 8, NCRStdPalette, 1024, 768, 12288, 8, 8, kernel_font_8x8, 32, 255}, 187 188 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR 189 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT 190 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */ 191 192 {110000000, 0, 1280,1024, 321,322,349,422,421,1025,1026,1043,1073,1073, 193 8, NCRStdPalette,1280,1024, 20480, 8, 8, kernel_font_8x8, 32, 255}, 194 }; 195 196 static const char *monitor_descr[] = { 197 "80x64 (640x512) 31.5kHz", 198 "96x75 (768x600) 38kHz", 199 "96x75 (768x600) 64kHz", 200 "128x96 (1024x768) 64kHz", 201 202 "GFX (640x480) 31.5kHz", 203 "GFX (1024x768) 64kHz", 204 "GFX (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***", 205 }; 206 207 int retina_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]); 208 209 /* patchable */ 210 int retina_default_mon = 0; 211 int retina_default_gfx = 4; 212 213 #endif 214 215 216 static struct MonDef *current_mon; 217 218 /* -------------- START OF CODE -------------- */ 219 220 221 static const long FQTab[16] = 222 { 25175000, 28322000, 36000000, 65000000, 223 44900000, 50000000, 80000000, 75000000, 224 56644000, 63000000, 72000000, 130000000, 225 90000000, 100000000, 110000000, 120000000 }; 226 227 228 /*--------------------------------------------------*/ 229 /*--------------------------------------------------*/ 230 231 #if 0 232 static struct MonDef *default_monitor = &DEFAULT_MONDEF; 233 #endif 234 235 /* 236 * used to query the retina to see if its alive (?) 237 */ 238 int 239 retina_alive(mdp) 240 struct MonDef *mdp; 241 { 242 short clksel; 243 244 for (clksel = 15; clksel; clksel--) { 245 if (FQTab[clksel] == mdp->FQ) 246 break; 247 } 248 if (clksel < 0) 249 return(0); 250 if (mdp->DEP != 4) 251 return(1); 252 if (mdp->FX == 4 || (mdp->FX >= 7 && mdp->FX <= 16)) 253 return(1); 254 return(0); 255 } 256 257 static int 258 rt_load_mon(gp, md) 259 struct grf_softc *gp; 260 struct MonDef *md; 261 { 262 struct grfinfo *gi = &gp->g_display; 263 volatile unsigned char *ba; 264 volatile unsigned char *fb; 265 short FW, clksel, HDE, VDE; 266 267 for (clksel = 15; clksel; clksel--) { 268 if (FQTab[clksel] == md->FQ) break; 269 } 270 if (clksel < 0) 271 return(0); 272 273 ba = gp->g_regkva;; 274 fb = gp->g_fbkva; 275 276 FW = 0; 277 if (md->DEP == 4) { 278 switch (md->FX) { 279 case 4: 280 FW = 0; 281 break; 282 case 7: 283 FW = 1; 284 break; 285 case 8: 286 FW = 2; 287 break; 288 case 9: 289 FW = 3; 290 break; 291 case 10: 292 FW = 4; 293 break; 294 case 11: 295 FW = 5; 296 break; 297 case 12: 298 FW = 6; 299 break; 300 case 13: 301 FW = 7; 302 break; 303 case 14: 304 FW = 8; 305 break; 306 case 15: 307 FW = 9; 308 break; 309 case 16: 310 FW = 11; 311 break; 312 default: 313 return(0); 314 break; 315 }; 316 } 317 318 if (md->DEP == 4) HDE = (md->MW+md->FX-1)/md->FX; 319 else HDE = (md->MW+3)/4; 320 VDE = md->MH-1; 321 322 /* hmm... */ 323 fb[0x8000] = 0; 324 325 /* enable extension registers */ 326 WSeq (ba, SEQ_ID_EXTENDED_ENABLE, 0x05); 327 328 #if 0 329 /* program the clock oscillator */ 330 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04)); 331 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00); 332 333 /* XXXX according to the NCR specs, this register should be set to 1 334 XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE 335 XXXX setting. */ 336 WSeq (ba, SEQ_ID_RESET, 0x03); 337 338 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8)); 339 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f); 340 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 341 /* odd/even write select + extended memory */ 342 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06); 343 /* XXXX I think this order of setting RESET is wrong... */ 344 WSeq (ba, SEQ_ID_RESET, 0x01); 345 WSeq (ba, SEQ_ID_RESET, 0x03); 346 #else 347 WSeq (ba, SEQ_ID_RESET, 0x01); 348 349 /* set font width + rest of clocks */ 350 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) ); 351 /* another clock bit, plus hw stuff */ 352 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) ); 353 354 /* program the clock oscillator */ 355 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04)); 356 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00); 357 358 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8)); 359 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f); 360 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 361 /* odd/even write select + extended memory */ 362 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06); 363 WSeq (ba, SEQ_ID_RESET, 0x03); 364 #endif 365 366 /* monochrome cursor */ 367 WSeq (ba, SEQ_ID_CURSOR_CONTROL, 0x00); 368 /* bank0 */ 369 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00); 370 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0x00); 371 WSeq (ba, SEQ_ID_DISP_OFF_HI , 0x00); 372 WSeq (ba, SEQ_ID_DISP_OFF_LO , 0x00); 373 /* bank0 */ 374 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00); 375 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00); 376 /* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */ 377 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40); 378 #if 0 379 /* set font width + rest of clocks */ 380 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) ); 381 #endif 382 if (md->DEP == 4) { 383 /* no ext-chain4 + no host-addr-bit-16 */ 384 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, 0x00); 385 /* no packed/nibble + no 256bit gfx format */ 386 WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00); 387 } 388 else { 389 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, 0x02); 390 /* 256bit gfx format */ 391 WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01); 392 } 393 /* AT-interface */ 394 WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x06); 395 /* see fg/bg color expansion */ 396 WSeq (ba, SEQ_ID_COLOR_EXP_WFG, 0x01); 397 WSeq (ba, SEQ_ID_COLOR_EXP_WBG, 0x00); 398 WSeq (ba, SEQ_ID_EXT_RW_CONTROL, 0x00); 399 #if 0 400 /* another clock bit, plus hw stuff */ 401 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) ); 402 #endif 403 /* don't tristate PCLK and PIX */ 404 WSeq (ba, SEQ_ID_COLOR_KEY_CNTL, 0x40 ); 405 /* reset CRC circuit */ 406 WSeq (ba, SEQ_ID_CRC_CONTROL, 0x00 ); 407 /* set RAS/CAS swap */ 408 WSeq (ba, SEQ_ID_PERF_SELECT, 0x20); 409 410 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf ) | 0x20); 411 WCrt (ba, CRT_ID_HOR_TOTAL, md->HT & 0xff); 412 WCrt (ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff); 413 WCrt (ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff); 414 WCrt (ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80); 415 416 WCrt (ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff); 417 WCrt (ba, CRT_ID_END_HOR_RETR, (md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80)); 418 WCrt (ba, CRT_ID_VER_TOTAL, (md->VT & 0xff)); 419 WCrt (ba, CRT_ID_OVERFLOW, (( (md->VSS & 0x200) / 0x200 * 0x80) 420 | ((VDE & 0x200) / 0x200 * 0x40) 421 | ((md->VT & 0x200) / 0x200 * 0x20) 422 | 0x10 423 | ((md->VBS & 0x100) / 0x100 * 8 ) 424 | ((md->VSS & 0x100) / 0x100 * 4 ) 425 | ((VDE & 0x100) / 0x100 * 2 ) 426 | ((md->VT & 0x100) / 0x100 ))); 427 WCrt (ba, CRT_ID_PRESET_ROW_SCAN, 0x00); 428 429 if (md->DEP == 4) { 430 WCrt (ba, CRT_ID_MAX_SCAN_LINE, (( (md->FLG & MDF_DBL)/ MDF_DBL * 0x80) 431 | 0x40 432 | ((md->VBS & 0x200)/0x200 * 0x20) 433 | ((md->FY-1) & 0x1f))); 434 } 435 else { 436 WCrt (ba, CRT_ID_MAX_SCAN_LINE, (( (md->FLG & MDF_DBL)/ MDF_DBL * 0x80) 437 | 0x40 438 | ((md->VBS & 0x200)/0x200 * 0x20) 439 | (0 & 0x1f))); 440 } 441 442 WCrt (ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2); 443 WCrt (ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1); 444 445 WCrt (ba, CRT_ID_START_ADDR_HIGH, 0x00); 446 WCrt (ba, CRT_ID_START_ADDR_LOW, 0x00); 447 448 WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 449 WCrt (ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 450 451 WCrt (ba, CRT_ID_START_VER_RETR, md->VSS & 0xff); 452 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0x0f) | 0x80 | 0x20); 453 WCrt (ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff); 454 if (md->DEP == 4) 455 WCrt (ba, CRT_ID_OFFSET, (HDE / 2) & 0xff); 456 else 457 WCrt (ba, CRT_ID_OFFSET, (md->TX / 8) & 0xff); 458 459 WCrt (ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f); 460 WCrt (ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff); 461 WCrt (ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff); 462 /* byte mode + wrap + select row scan counter + cms */ 463 WCrt (ba, CRT_ID_MODE_CONTROL, 0xe3); 464 WCrt (ba, CRT_ID_LINE_COMPARE, 0xff); 465 466 /* enable extended end bits + those bits */ 467 WCrt (ba, CRT_ID_EXT_HOR_TIMING1, ( 0x20 468 | ((md->FLG & MDF_LACE) / MDF_LACE * 0x10) 469 | ((md->HT & 0x100) / 0x100 * 0x01) 470 | (((HDE-1) & 0x100) / 0x100 * 0x02) 471 | ((md->HBS & 0x100) / 0x100 * 0x04) 472 | ((md->HSS & 0x100) / 0x100 * 0x08))); 473 474 if (md->DEP == 4) 475 WCrt (ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16)); 476 else 477 WCrt (ba, CRT_ID_EXT_START_ADDR, (((md->TX / 8) & 0x100)/0x100 * 16)); 478 479 WCrt (ba, CRT_ID_EXT_HOR_TIMING2, ( ((md->HT & 0x200)/ 0x200 * 0x01) 480 | (((HDE-1) & 0x200)/ 0x200 * 0x02) 481 | ((md->HBS & 0x200)/ 0x200 * 0x04) 482 | ((md->HSS & 0x200)/ 0x200 * 0x08) 483 | ((md->HBE & 0xc0) / 0x40 * 0x10) 484 | ((md->HSE & 0x60) / 0x20 * 0x40))); 485 486 WCrt (ba, CRT_ID_EXT_VER_TIMING, ( ((md->VSE & 0x10) / 0x10 * 0x80) 487 | ((md->VBE & 0x300)/ 0x100 * 0x20) 488 | 0x10 489 | ((md->VSS & 0x400)/ 0x400 * 0x08) 490 | ((md->VBS & 0x400)/ 0x400 * 0x04) 491 | ((VDE & 0x400)/ 0x400 * 0x02) 492 | ((md->VT & 0x400)/ 0x400 * 0x01))); 493 494 WGfx (ba, GCT_ID_SET_RESET, 0x00); 495 WGfx (ba, GCT_ID_ENABLE_SET_RESET, 0x00); 496 WGfx (ba, GCT_ID_COLOR_COMPARE, 0x00); 497 WGfx (ba, GCT_ID_DATA_ROTATE, 0x00); 498 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0x00); 499 WGfx (ba, GCT_ID_GRAPHICS_MODE, 0x00); 500 if (md->DEP == 4) 501 WGfx (ba, GCT_ID_MISC, 0x04); 502 else 503 WGfx (ba, GCT_ID_MISC, 0x05); 504 WGfx (ba, GCT_ID_COLOR_XCARE, 0xff); 505 WGfx (ba, GCT_ID_BITMASK, 0xff); 506 507 /* reset the Attribute Controller flipflop */ 508 vgar (ba, GREG_STATUS1_R); 509 WAttr (ba, ACT_ID_PALETTE0, 0x00); 510 WAttr (ba, ACT_ID_PALETTE1, 0x01); 511 WAttr (ba, ACT_ID_PALETTE2, 0x02); 512 WAttr (ba, ACT_ID_PALETTE3, 0x03); 513 WAttr (ba, ACT_ID_PALETTE4, 0x04); 514 WAttr (ba, ACT_ID_PALETTE5, 0x05); 515 WAttr (ba, ACT_ID_PALETTE6, 0x06); 516 WAttr (ba, ACT_ID_PALETTE7, 0x07); 517 WAttr (ba, ACT_ID_PALETTE8, 0x08); 518 WAttr (ba, ACT_ID_PALETTE9, 0x09); 519 WAttr (ba, ACT_ID_PALETTE10, 0x0a); 520 WAttr (ba, ACT_ID_PALETTE11, 0x0b); 521 WAttr (ba, ACT_ID_PALETTE12, 0x0c); 522 WAttr (ba, ACT_ID_PALETTE13, 0x0d); 523 WAttr (ba, ACT_ID_PALETTE14, 0x0e); 524 WAttr (ba, ACT_ID_PALETTE15, 0x0f); 525 526 vgar (ba, GREG_STATUS1_R); 527 if (md->DEP == 4) 528 WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x08); 529 else 530 WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x09); 531 532 WAttr (ba, ACT_ID_OVERSCAN_COLOR, 0x00); 533 WAttr (ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); 534 WAttr (ba, ACT_ID_HOR_PEL_PANNING, 0x00); 535 WAttr (ba, ACT_ID_COLOR_SELECT, 0x00); 536 537 vgar (ba, GREG_STATUS1_R); 538 /* I have *NO* idea what strobing reg-0x20 might do... */ 539 vgaw (ba, ACT_ADDRESS_W, 0x20); 540 541 if (md->DEP == 4) 542 WCrt (ba, CRT_ID_MAX_SCAN_LINE, ( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) 543 | 0x40 544 | ((md->VBS & 0x200)/0x200 * 0x20) 545 | ((md->FY-1) & 0x1f))); 546 else 547 WCrt (ba, CRT_ID_MAX_SCAN_LINE, ( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) 548 | 0x40 549 | ((md->VBS & 0x200)/0x200 * 0x20) 550 | (0 & 0x1f))); 551 552 553 /* not it's time for guessing... */ 554 555 vgaw (ba, VDAC_REG_D, 0x02); 556 557 /* if this does what I think it does, it selects DAC 558 register 0, and writes the palette in subsequent 559 registers, thus it works similar to the WD33C93 560 select/data mechanism */ 561 vgaw (ba, VDAC_REG_SELECT, 0x00); 562 563 { 564 565 short x = 15; 566 const unsigned char * col = md->PAL; 567 do { 568 569 vgaw (ba, VDAC_REG_DATA, *col++); 570 vgaw (ba, VDAC_REG_DATA, *col++); 571 vgaw (ba, VDAC_REG_DATA, *col++); 572 573 574 } while (x--); 575 576 if (md->DEP != 4) { 577 short x = 256-17; 578 unsigned char col = 16; 579 do { 580 581 vgaw(ba, VDAC_REG_DATA, col); 582 vgaw(ba, VDAC_REG_DATA, col); 583 vgaw(ba, VDAC_REG_DATA, col); 584 col++; 585 586 } while (x--); 587 } 588 } 589 590 591 /* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */ 592 if (md->DEP == 4) { 593 594 /* first set the whole font memory to a test-pattern, so we 595 can see if something that shouldn't be drawn IS drawn.. */ 596 { 597 volatile unsigned char * c = fb; 598 long x; 599 Map(2); 600 601 for (x = 0; x < 65536; x++) { 602 *c++ = (x & 1)? 0xaa : 0x55; 603 } 604 } 605 606 { 607 volatile unsigned char * c = fb; 608 long x; 609 Map(3); 610 611 for (x = 0; x < 65536; x++) { 612 *c++ = (x & 1)? 0xaa : 0x55; 613 } 614 } 615 616 { 617 /* ok, now position at first defined character, and 618 copy over the images */ 619 volatile unsigned char * c = fb + md->FLo * 32; 620 const unsigned char * f = md->FData; 621 unsigned short z; 622 623 Map(2); 624 for (z = md->FLo; z <= md->FHi; z++) { 625 626 short y = md->FY-1; 627 if (md->FX > 8){ 628 do { 629 *c++ = *f; 630 f += 2; 631 } while (y--); 632 } 633 else { 634 do { 635 *c++ = *f++; 636 } while (y--); 637 } 638 639 c += 32-md->FY; 640 641 } 642 643 if (md->FX > 8) { 644 unsigned short z; 645 646 Map(3); 647 c = fb + md->FLo*32; 648 f = md->FData+1; 649 for (z = md->FLo; z <= md->FHi; z++) { 650 651 short y = md->FY-1; 652 do { 653 *c++ = *f; 654 f += 2; 655 } while (y--); 656 657 c += 32-md->FY; 658 659 } 660 } 661 } 662 663 } 664 665 /* select map 0 */ 666 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0); 667 if (md->DEP == 4) 668 /* allow writes into maps 0 and 1 */ 669 WSeq (ba, SEQ_ID_MAP_MASK, 3); 670 else 671 /* allow writes into all maps */ 672 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f); 673 674 /* select extended chain4 addressing: 675 !A0/!A1 map 0 character to be displayed 676 !A1/ A1 map 1 attribute of that character 677 A0/!A1 map 2 not used (masked out, ignored) 678 A0/ A1 map 3 not used (masked out, ignored) */ 679 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02); 680 681 if (md->DEP == 4) { 682 /* position in display memory */ 683 unsigned short * c = (unsigned short *) fb; 684 685 /* fill with blank, white on black */ 686 const unsigned short fill_val = 0x2010; 687 short x = md->XY; 688 do { 689 *c = fill_val; 690 c += 2; } while (x--); 691 692 /* I won't comment this :-)) */ 693 c = (unsigned short *) fb; 694 c += (md->TX-6)*2; 695 { 696 unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f}; 697 unsigned short * f = init_msg; 698 x = 5; 699 do { 700 *c = *f++; 701 c += 2; 702 } while (x--); 703 } 704 } 705 else if (md->DEP == 8) { 706 /* could clear the gfx screen here, but that's what the X server does anyway */ 707 ; 708 } 709 710 gp->g_data = (caddr_t)md; 711 gi->gd_regaddr = (caddr_t)ztwopa(ba); 712 gi->gd_regsize = 64*1024; 713 714 gi->gd_fbaddr = (caddr_t)ztwopa(fb); 715 #ifdef BANKEDDEVPAGER 716 gi->gd_fbsize = 4*1024*1024; /* XXX */ 717 gi->gd_bank_size = 64*1024; 718 #else 719 gi->gd_fbsize = 64*1024; /* larger, but that's whats mappable */ 720 #endif 721 722 gi->gd_colors = 1 << md->DEP; 723 gi->gd_planes = md->DEP; 724 725 gi->gd_fbwidth = md->MW; 726 gi->gd_fbheight = md->MH; 727 gi->gd_fbx = 0; 728 gi->gd_fby = 0; 729 gi->gd_dwidth = md->TX * md->FX; 730 gi->gd_dheight = md->TY * md->FY; 731 gi->gd_dx = 0; 732 gi->gd_dy = 0; 733 734 /* initialized, works, return 1 */ 735 return(1); 736 } 737 738 int rt_mode __P((struct grf_softc *, int, void *, int , int)); 739 740 void grfrtattach __P((struct device *, struct device *, void *)); 741 int grfrtprint __P((void *, char *)); 742 int grfrtmatch __P((struct device *, struct cfdata *, void *)); 743 744 struct cfdriver grfrtcd = { 745 NULL, "grfrt", grfrtmatch, grfrtattach, 746 DV_DULL, sizeof(struct grf_softc), NULL, 0 }; 747 748 /* 749 * only used in console init 750 */ 751 static struct cfdata *cfdata; 752 753 /* 754 * we make sure to only init things once. this is somewhat 755 * tricky regarding the console. 756 */ 757 int 758 grfrtmatch(pdp, cfp, auxp) 759 struct device *pdp; 760 struct cfdata *cfp; 761 void *auxp; 762 { 763 #ifdef RETINACONSOLE 764 static int rtconunit = -1; 765 #endif 766 struct ztwobus_args *zap; 767 768 zap = auxp; 769 770 /* 771 * allow only one retina console 772 */ 773 if (amiga_realconfig == 0) 774 #ifdef RETINACONSOLE 775 if (rtconunit != -1) 776 #endif 777 return(0); 778 /* 779 * check that this is a retina board. 780 */ 781 if (zap->manid != 18260 || zap->prodid != 6) 782 return(0); 783 784 #ifdef RETINACONSOLE 785 if (amiga_realconfig == 0 || rtconunit != cfp->cf_unit) { 786 #endif 787 if ((unsigned)retina_default_mon >= retina_mon_max || 788 monitor_defs[retina_default_mon].DEP == 8) 789 retina_default_mon = 0; 790 791 current_mon = monitor_defs + retina_default_mon; 792 if (retina_alive(current_mon) == 0) 793 return(0); 794 #ifdef RETINACONSOLE 795 if (amiga_realconfig == 0) { 796 rtconunit = cfp->cf_unit; 797 cfdata = cfp; 798 } 799 } 800 #endif 801 return(1); 802 } 803 804 /* 805 * attach to the grfbus (ztwobus) 806 */ 807 void 808 grfrtattach(pdp, dp, auxp) 809 struct device *pdp, *dp; 810 void *auxp; 811 { 812 static struct grf_softc congrf; 813 static int coninited; 814 struct ztwobus_args *zap; 815 struct grf_softc *gp; 816 817 zap = auxp; 818 819 if (dp == NULL) 820 gp = &congrf; 821 else 822 gp = (struct grf_softc *)dp; 823 824 if (dp != NULL && congrf.g_regkva != 0) { 825 /* 826 * we inited earlier just copy the info 827 * take care not to copy the device struct though. 828 */ 829 bcopy(&congrf.g_display, &gp->g_display, 830 (char *)&gp[1] - (char *)&gp->g_display); 831 } else { 832 gp->g_regkva = (volatile caddr_t)zap->va; 833 gp->g_fbkva = (volatile caddr_t)zap->va + 64 * 1024; 834 gp->g_unit = GRF_RETINAII_UNIT; 835 gp->g_flags = GF_ALIVE; 836 gp->g_mode = rt_mode; 837 gp->g_conpri = grfrt_cnprobe(); 838 grfrt_iteinit(gp); 839 (void)rt_load_mon(gp, current_mon); 840 } 841 if (dp != NULL) 842 printf("\n"); 843 /* 844 * attach grf 845 */ 846 amiga_config_found(cfdata, &gp->g_device, gp, grfrtprint); 847 } 848 849 int 850 grfrtprint(auxp, pnp) 851 void *auxp; 852 char *pnp; 853 { 854 if (pnp) 855 printf("grf%d at %s", ((struct grf_softc *)auxp)->g_unit, 856 pnp); 857 return(UNCONF); 858 } 859 860 static int 861 rt_getvmode (gp, vm) 862 struct grf_softc *gp; 863 struct grfvideo_mode *vm; 864 { 865 struct MonDef *md; 866 867 if (vm->mode_num && vm->mode_num > retina_mon_max) 868 return EINVAL; 869 870 if (! vm->mode_num) 871 vm->mode_num = (current_mon - monitor_defs) + 1; 872 873 md = monitor_defs + (vm->mode_num - 1); 874 strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1), 875 sizeof (vm->mode_descr)); 876 vm->pixel_clock = md->FQ; 877 vm->disp_width = md->MW; 878 vm->disp_height = md->MH; 879 vm->depth = md->DEP; 880 vm->hblank_start = md->HBS; 881 vm->hblank_stop = md->HBE; 882 vm->hsync_start = md->HSS; 883 vm->hsync_stop = md->HSE; 884 vm->htotal = md->HT; 885 vm->vblank_start = md->VBS; 886 vm->vblank_stop = md->VBE; 887 vm->vsync_start = md->VSS; 888 vm->vsync_stop = md->VSE; 889 vm->vtotal = md->VT; 890 891 return 0; 892 } 893 894 895 static int 896 rt_setvmode (gp, mode, txtonly) 897 struct grf_softc *gp; 898 unsigned mode; 899 int txtonly; 900 { 901 struct MonDef *md; 902 int error; 903 904 if (!mode || mode > retina_mon_max) 905 return EINVAL; 906 907 if (txtonly && monitor_defs[mode-1].DEP == 8) 908 return EINVAL; 909 910 current_mon = monitor_defs + (mode - 1); 911 912 error = rt_load_mon (gp, current_mon) ? 0 : EINVAL; 913 914 return error; 915 } 916 917 918 /* 919 * Change the mode of the display. 920 * Return a UNIX error number or 0 for success. 921 */ 922 int 923 rt_mode(gp, cmd, arg, a2, a3) 924 struct grf_softc *gp; 925 int cmd; 926 void *arg; 927 int a2, a3; 928 { 929 /* implement these later... */ 930 931 switch (cmd) 932 { 933 case GM_GRFON: 934 rt_setvmode (gp, retina_default_gfx + 1, 0); 935 return 0; 936 937 case GM_GRFOFF: 938 rt_setvmode (gp, retina_default_mon + 1, 0); 939 return 0; 940 941 case GM_GRFCONFIG: 942 return 0; 943 944 case GM_GRFGETVMODE: 945 return rt_getvmode (gp, (struct grfvideo_mode *) arg); 946 947 case GM_GRFSETVMODE: 948 return rt_setvmode (gp, *(unsigned *) arg, 1); 949 950 case GM_GRFGETNUMVM: 951 *(int *)arg = retina_mon_max; 952 return 0; 953 954 #ifdef BANKEDDEVPAGER 955 case GM_GRFGETBANK: 956 *(int *)arg = rt_getbank (gp, a2, a3); 957 return 0; 958 959 case GM_GRFGETCURBANK: 960 *(int *)arg = rt_getcurbank (gp); 961 return 0; 962 963 case GM_GRFSETBANK: 964 return rt_setbank (gp, arg); 965 #endif 966 case GM_GRFIOCTL: 967 return rt_ioctl (gp, arg, a2); 968 969 default: 970 break; 971 } 972 973 return EINVAL; 974 } 975 976 int 977 rt_ioctl (gp, cmd, data) 978 register struct grf_softc *gp; 979 int cmd; 980 void *data; 981 { 982 switch (cmd) 983 { 984 case GRFIOCGSPRITEPOS: 985 return rt_getspritepos (gp, (struct grf_position *) data); 986 987 case GRFIOCSSPRITEPOS: 988 return rt_setspritepos (gp, (struct grf_position *) data); 989 990 case GRFIOCSSPRITEINF: 991 return rt_setspriteinfo (gp, (struct grf_spriteinfo *) data); 992 993 case GRFIOCGSPRITEINF: 994 return rt_getspriteinfo (gp, (struct grf_spriteinfo *) data); 995 996 case GRFIOCGSPRITEMAX: 997 return rt_getspritemax (gp, (struct grf_position *) data); 998 999 case GRFIOCGETCMAP: 1000 return rt_getcmap (gp, (struct grf_colormap *) data); 1001 1002 case GRFIOCPUTCMAP: 1003 return rt_putcmap (gp, (struct grf_colormap *) data); 1004 1005 case GRFIOCBITBLT: 1006 return rt_bitblt (gp, (struct grf_bitblt *) data); 1007 } 1008 1009 return EINVAL; 1010 } 1011 1012 #ifdef BANKEDDEVPAGER 1013 1014 /* Retina banks can overlap. Don't use this information (yet?), and 1015 only switch 64k sized banks. */ 1016 1017 int 1018 rt_getbank (gp, offs, prot) 1019 struct grf_softc *gp; 1020 off_t offs; 1021 int prot; 1022 { 1023 /* XXX */ 1024 if (offs < 0 || offs >= 4*1024*1024) 1025 return -1; 1026 else 1027 return offs >> 16; 1028 } 1029 1030 int 1031 rt_getcurbank (gp) 1032 struct grf_softc *gp; 1033 { 1034 struct grfinfo *gi = &gp->g_display; 1035 volatile unsigned char *ba; 1036 int bank; 1037 1038 ba = gp->g_regkva; 1039 bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8); 1040 1041 /* bank register is multiple of 64 byte, make this multiple of 64k */ 1042 bank >>= 10; 1043 return bank; 1044 } 1045 1046 int 1047 rt_setbank (gp, bank) 1048 struct grf_softc *gp; 1049 int bank; 1050 { 1051 volatile unsigned char *ba; 1052 1053 ba = gp->g_regkva; 1054 /* bank register is multiple of 64 byte, make this multiple of 64k */ 1055 bank <<= 10; 1056 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank); 1057 bank >>= 8; 1058 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank); 1059 1060 return 0; 1061 } 1062 1063 #endif 1064 1065 int 1066 rt_getcmap (gfp, cmap) 1067 struct grf_softc *gfp; 1068 struct grf_colormap *cmap; 1069 { 1070 volatile unsigned char *ba; 1071 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1072 short x; 1073 int error; 1074 1075 if (cmap->count == 0 || cmap->index >= 256) 1076 return 0; 1077 1078 if (cmap->index + cmap->count > 256) 1079 cmap->count = 256 - cmap->index; 1080 1081 ba = gfp->g_regkva; 1082 /* first read colors out of the chip, then copyout to userspace */ 1083 vgaw (ba, VDAC_REG_SELECT, cmap->index); 1084 x = cmap->count - 1; 1085 rp = red + cmap->index; 1086 gp = green + cmap->index; 1087 bp = blue + cmap->index; 1088 do 1089 { 1090 *rp++ = vgar (ba, VDAC_REG_DATA); 1091 *gp++ = vgar (ba, VDAC_REG_DATA); 1092 *bp++ = vgar (ba, VDAC_REG_DATA); 1093 } 1094 while (x--); 1095 1096 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count)) 1097 && !(error = copyout (green + cmap->index, cmap->green, cmap->count)) 1098 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count))) 1099 return 0; 1100 1101 return error; 1102 } 1103 1104 int 1105 rt_putcmap (gfp, cmap) 1106 struct grf_softc *gfp; 1107 struct grf_colormap *cmap; 1108 { 1109 volatile unsigned char *ba; 1110 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1111 short x; 1112 int error; 1113 1114 if (cmap->count == 0 || cmap->index >= 256) 1115 return 0; 1116 1117 if (cmap->index + cmap->count > 256) 1118 cmap->count = 256 - cmap->index; 1119 1120 /* first copy the colors into kernelspace */ 1121 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count)) 1122 && !(error = copyin (cmap->green, green + cmap->index, cmap->count)) 1123 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) 1124 { 1125 ba = gfp->g_regkva; 1126 vgaw (ba, VDAC_REG_SELECT, cmap->index); 1127 x = cmap->count - 1; 1128 rp = red + cmap->index; 1129 gp = green + cmap->index; 1130 bp = blue + cmap->index; 1131 do 1132 { 1133 vgaw (ba, VDAC_REG_DATA, *rp++); 1134 vgaw (ba, VDAC_REG_DATA, *gp++); 1135 vgaw (ba, VDAC_REG_DATA, *bp++); 1136 } 1137 while (x--); 1138 return 0; 1139 } 1140 else 1141 return error; 1142 } 1143 1144 int 1145 rt_getspritepos (gp, pos) 1146 struct grf_softc *gp; 1147 struct grf_position *pos; 1148 { 1149 volatile unsigned char *ba; 1150 1151 ba = gp->g_regkva; 1152 pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8); 1153 pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8); 1154 return 0; 1155 } 1156 1157 int 1158 rt_setspritepos (gp, pos) 1159 struct grf_softc *gp; 1160 struct grf_position *pos; 1161 { 1162 volatile unsigned char *ba; 1163 1164 ba = gp->g_regkva; 1165 vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff); 1166 vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07); 1167 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff); 1168 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07); 1169 return 0; 1170 } 1171 1172 /* assume an at least 2M retina (XXX), sprite is last in memory. 1173 According to the bogus docs, the cursor can be at most 128 lines 1174 in height, and the x-hostspot can be placed at most at pos 31, 1175 this gives width of a long */ 1176 #define SPRITE_ADDR (2*1024*1024 - 128*4) 1177 1178 int 1179 rt_getspriteinfo (gp, info) 1180 struct grf_softc *gp; 1181 struct grf_spriteinfo *info; 1182 { 1183 volatile unsigned char *ba, *fb; 1184 1185 ba = gp->g_regkva; 1186 fb = gp->g_fbkva; 1187 if (info->set & GRFSPRSET_ENABLE) 1188 info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01; 1189 if (info->set & GRFSPRSET_POS) 1190 rt_getspritepos (gp, &info->pos); 1191 if (info->set & GRFSPRSET_HOT) 1192 { 1193 info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f; 1194 info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f; 1195 } 1196 if (info->set & GRFSPRSET_CMAP) 1197 { 1198 struct grf_colormap cmap; 1199 int index; 1200 cmap.index = 0; 1201 cmap.count = 256; 1202 rt_getcmap (gp, &cmap); 1203 index = vgar (ba, SEQ_ID_CURSOR_COLOR0); 1204 info->cmap.red[0] = cmap.red[index]; 1205 info->cmap.green[0] = cmap.green[index]; 1206 info->cmap.blue[0] = cmap.blue[index]; 1207 index = vgar (ba, SEQ_ID_CURSOR_COLOR1); 1208 info->cmap.red[1] = cmap.red[index]; 1209 info->cmap.green[1] = cmap.green[index]; 1210 info->cmap.blue[1] = cmap.blue[index]; 1211 } 1212 if (info->set & GRFSPRSET_SHAPE) 1213 { 1214 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO); 1215 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI); 1216 int last_bank = SPRITE_ADDR >> 6; 1217 int last_bank_lo = last_bank & 0xff; 1218 int last_bank_hi = last_bank >> 8; 1219 u_char mask; 1220 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo); 1221 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi); 1222 copyout (fb, info->image, 128*4); 1223 mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK); 1224 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo); 1225 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi); 1226 copyout (&mask, info->mask, 1); 1227 info->size.x = 32; /* ??? */ 1228 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4; 1229 } 1230 1231 } 1232 1233 int 1234 rt_setspriteinfo (gp, info) 1235 struct grf_softc *gp; 1236 struct grf_spriteinfo *info; 1237 { 1238 volatile unsigned char *ba, *fb; 1239 u_char control; 1240 1241 ba = gp->g_regkva; 1242 fb = gp->g_fbkva; 1243 control = vgar (ba, SEQ_ID_CURSOR_CONTROL); 1244 if (info->set & GRFSPRSET_ENABLE) 1245 { 1246 if (info->enable) 1247 control |= 1; 1248 else 1249 control &= ~1; 1250 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control); 1251 } 1252 if (info->set & GRFSPRSET_POS) 1253 rt_setspritepos (gp, &info->pos); 1254 if (info->set & GRFSPRSET_HOT) 1255 { 1256 vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f); 1257 vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f); 1258 } 1259 if (info->set & GRFSPRSET_CMAP) 1260 { 1261 /* hey cheat a bit here.. XXX */ 1262 vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0); 1263 vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1); 1264 } 1265 if (info->set & GRFSPRSET_SHAPE) 1266 { 1267 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO); 1268 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI); 1269 int last_bank = SPRITE_ADDR >> 6; 1270 int last_bank_lo = last_bank & 0xff; 1271 int last_bank_hi = last_bank >> 8; 1272 u_char mask; 1273 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo); 1274 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi); 1275 copyin (info->image, fb, 128*4); 1276 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo); 1277 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi); 1278 copyin (info->mask, &mask, 1); 1279 WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask); 1280 /* info->size.x = 32; *//* ??? */ 1281 1282 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4; 1283 control = (control & ~6) | ((info->size.y >> 4) & 6); 1284 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control); 1285 1286 /* sick intel bull-addressing.. */ 1287 WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f); 1288 WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0); 1289 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff); 1290 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff); 1291 } 1292 1293 return 0; 1294 } 1295 1296 int 1297 rt_getspritemax (gp, pos) 1298 struct grf_softc *gp; 1299 struct grf_position *pos; 1300 { 1301 pos->x = 32; 1302 pos->y = 128; 1303 1304 return 0; 1305 } 1306 1307 1308 /* 1309 * !!! THIS AREA UNDER CONSTRUCTION !!! 1310 */ 1311 1312 int 1313 rt_bitblt (gp, bb) 1314 struct grf_softc *gp; 1315 struct grf_bitblt *bb; 1316 { 1317 return EINVAL; 1318 1319 1320 #if 0 1321 volatile unsigned char *ba, *fb; 1322 u_char control; 1323 u_char saved_bank_lo; 1324 u_char saved_bank_hi; 1325 u_char src_bank_lo, src_bank_hi; 1326 u_char dst_bank_lo, dst_bank_hi; 1327 u_long src_offset, dst_offset; 1328 u_short src_bank, dst_bank; 1329 u_char *srcp, *dstp; 1330 short x, y; 1331 u_long tot; 1332 1333 ba = gp->g_regkva; 1334 fb = gp->g_fbkva; 1335 1336 saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO); 1337 saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI); 1338 1339 /* for now, only GRFBBcopy is supported, and only for depth 8. No 1340 clipping is performed, either... */ 1341 1342 if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8) 1343 return EINVAL; 1344 1345 src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth; 1346 dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth; 1347 tot = op->w * op->h; 1348 1349 /* set write mode 1, "[...] data in the read latches is written 1350 to memory during CPU memory write cycles. [...]" */ 1351 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1); 1352 /* write to primary, read from secondary */ 1353 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 ); 1354 1355 if (src_offset < dst_offset) 1356 { 1357 /* start at end */ 1358 src_offset += tot; 1359 dst_offset += tot; 1360 } 1361 1362 src_bank_lo = (src_offset >> 6) & 0xff; 1363 src_bank_hi = (src_offset >> 14) & 0xff; 1364 dst_bank_lo = (dst_offset >> 6) & 0xff; 1365 dst_bank_hi = (dst_offset >> 14) & 0xff; 1366 1367 while (tot) 1368 { 1369 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo); 1370 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi); 1371 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo); 1372 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi); 1373 1374 if (src_offset < dst_offset) 1375 { 1376 1377 1378 } 1379 else 1380 { 1381 1382 } 1383 } 1384 1385 1386 #endif 1387 } 1388 1389 1390 #endif /* NGRF */ 1391