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