1 /* 2 * $Id: grf_rt.c,v 1.11 1994/05/08 05:53:07 chopps Exp $ 3 */ 4 5 #include "grf.h" 6 #if NGRF > 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 = ztwomap(ba); 714 gi->gd_regsize = 64*1024; 715 716 gi->gd_fbaddr = 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 /* 757 * we make sure to only init things once. this is somewhat 758 * tricky regarding the console. 759 */ 760 int 761 grfrtmatch(pdp, cfp, auxp) 762 struct device *pdp; 763 struct cfdata *cfp; 764 void *auxp; 765 { 766 static int rtconunit = -1; 767 struct ztwobus_args *zap; 768 769 zap = auxp; 770 771 /* 772 * allow only one retina console 773 */ 774 if (amiga_realconfig == 0 && rtconunit != -1) 775 return(0); 776 /* 777 * check that this is a retina board. 778 */ 779 if (zap->manid != 18260 || zap->prodid != 6) 780 return(0); 781 782 if (amiga_realconfig == 0 || rtconunit != cfp->cf_unit) { 783 if ((unsigned)retina_default_mon >= retina_mon_max || 784 monitor_defs[retina_default_mon].DEP == 8) 785 retina_default_mon = 0; 786 787 current_mon = monitor_defs + retina_default_mon; 788 if (retina_alive(current_mon) == 0) 789 return(0); 790 if (amiga_realconfig == 0) { 791 rtconunit = cfp->cf_unit; 792 cfdata = cfp; 793 } 794 } 795 return(1); 796 } 797 798 /* 799 * attach to the grfbus (ztwobus) 800 */ 801 void 802 grfrtattach(pdp, dp, auxp) 803 struct device *pdp, *dp; 804 void *auxp; 805 { 806 static struct grf_softc congrf; 807 static int coninited; 808 struct ztwobus_args *zap; 809 struct grf_softc *gp; 810 811 zap = auxp; 812 813 if (dp == NULL) 814 gp = &congrf; 815 else 816 gp = (struct grf_softc *)dp; 817 818 if (dp != NULL && congrf.g_regkva != 0) { 819 /* 820 * we inited earlier just copy the info 821 * take care not to copy the device struct though. 822 */ 823 bcopy(&congrf.g_display, &gp->g_display, 824 (char *)&gp[1] - (char *)&gp->g_display); 825 } else { 826 gp->g_regkva = (volatile caddr_t)zap->va; 827 gp->g_fbkva = (volatile caddr_t)zap->va + 64 * 1024; 828 gp->g_unit = GRF_RETINAII_UNIT; 829 gp->g_mode = rt_mode; 830 gp->g_conpri = grfrt_cnprobe(); 831 grfrt_iteinit(gp); 832 (void)rt_load_mon(gp, current_mon); 833 } 834 if (dp != NULL) 835 printf("\n"); 836 /* 837 * attach grf 838 */ 839 amiga_config_found(cfdata, &gp->g_device, gp, grfrtprint); 840 } 841 842 int 843 grfrtprint(auxp, pnp) 844 void *auxp; 845 char *pnp; 846 { 847 if (pnp) 848 printf("grf%d at %s", ((struct grf_softc *)auxp)->g_unit, 849 pnp); 850 return(UNCONF); 851 } 852 853 static int 854 rt_getvmode (gp, vm) 855 struct grf_softc *gp; 856 struct grfvideo_mode *vm; 857 { 858 struct MonDef *md; 859 860 if (vm->mode_num && vm->mode_num > retina_mon_max) 861 return EINVAL; 862 863 if (! vm->mode_num) 864 vm->mode_num = (current_mon - monitor_defs) + 1; 865 866 md = monitor_defs + (vm->mode_num - 1); 867 strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1), 868 sizeof (vm->mode_descr)); 869 vm->pixel_clock = md->FQ; 870 vm->disp_width = md->MW; 871 vm->disp_height = md->MH; 872 vm->depth = md->DEP; 873 vm->hblank_start = md->HBS; 874 vm->hblank_stop = md->HBE; 875 vm->hsync_start = md->HSS; 876 vm->hsync_stop = md->HSE; 877 vm->htotal = md->HT; 878 vm->vblank_start = md->VBS; 879 vm->vblank_stop = md->VBE; 880 vm->vsync_start = md->VSS; 881 vm->vsync_stop = md->VSE; 882 vm->vtotal = md->VT; 883 884 return 0; 885 } 886 887 888 static int 889 rt_setvmode (gp, mode, txtonly) 890 struct grf_softc *gp; 891 unsigned mode; 892 int txtonly; 893 { 894 struct MonDef *md; 895 int error; 896 897 if (!mode || mode > retina_mon_max) 898 return EINVAL; 899 900 if (txtonly && monitor_defs[mode-1].DEP == 8) 901 return EINVAL; 902 903 current_mon = monitor_defs + (mode - 1); 904 905 error = rt_load_mon (gp, current_mon) ? 0 : EINVAL; 906 907 return error; 908 } 909 910 911 /* 912 * Change the mode of the display. 913 * Return a UNIX error number or 0 for success. 914 */ 915 int 916 rt_mode(gp, cmd, arg, a2, a3) 917 struct grf_softc *gp; 918 int cmd; 919 void *arg; 920 int a2, a3; 921 { 922 /* implement these later... */ 923 924 switch (cmd) 925 { 926 case GM_GRFON: 927 rt_setvmode (gp, retina_default_gfx + 1, 0); 928 return 0; 929 930 case GM_GRFOFF: 931 rt_setvmode (gp, retina_default_mon + 1, 0); 932 return 0; 933 934 case GM_GRFCONFIG: 935 return 0; 936 937 case GM_GRFGETVMODE: 938 return rt_getvmode (gp, (struct grfvideo_mode *) arg); 939 940 case GM_GRFSETVMODE: 941 return rt_setvmode (gp, *(unsigned *) arg, 1); 942 943 case GM_GRFGETNUMVM: 944 *(int *)arg = retina_mon_max; 945 return 0; 946 947 #ifdef BANKEDDEVPAGER 948 case GM_GRFGETBANK: 949 *(int *)arg = rt_getbank (gp, a2, a3); 950 return 0; 951 952 case GM_GRFGETCURBANK: 953 *(int *)arg = rt_getcurbank (gp); 954 return 0; 955 956 case GM_GRFSETBANK: 957 return rt_setbank (gp, arg); 958 #endif 959 case GM_GRFIOCTL: 960 return rt_ioctl (gp, arg, a2); 961 962 default: 963 break; 964 } 965 966 return EINVAL; 967 } 968 969 int 970 rt_ioctl (gp, cmd, data) 971 register struct grf_softc *gp; 972 int cmd; 973 void *data; 974 { 975 switch (cmd) 976 { 977 case GRFIOCGSPRITEPOS: 978 return rt_getspritepos (gp, (struct grf_position *) data); 979 980 case GRFIOCSSPRITEPOS: 981 return rt_setspritepos (gp, (struct grf_position *) data); 982 983 case GRFIOCSSPRITEINF: 984 return rt_setspriteinfo (gp, (struct grf_spriteinfo *) data); 985 986 case GRFIOCGSPRITEINF: 987 return rt_getspriteinfo (gp, (struct grf_spriteinfo *) data); 988 989 case GRFIOCGSPRITEMAX: 990 return rt_getspritemax (gp, (struct grf_position *) data); 991 992 case GRFIOCGETCMAP: 993 return rt_getcmap (gp, (struct grf_colormap *) data); 994 995 case GRFIOCPUTCMAP: 996 return rt_putcmap (gp, (struct grf_colormap *) data); 997 998 case GRFIOCBITBLT: 999 return rt_bitblt (gp, (struct grf_bitblt *) data); 1000 } 1001 1002 return EINVAL; 1003 } 1004 1005 #ifdef BANKEDDEVPAGER 1006 1007 /* Retina banks can overlap. Don't use this information (yet?), and 1008 only switch 64k sized banks. */ 1009 1010 int 1011 rt_getbank (gp, offs, prot) 1012 struct grf_softc *gp; 1013 off_t offs; 1014 int prot; 1015 { 1016 /* XXX */ 1017 if (offs < 0 || offs >= 4*1024*1024) 1018 return -1; 1019 else 1020 return offs >> 16; 1021 } 1022 1023 int 1024 rt_getcurbank (gp) 1025 struct grf_softc *gp; 1026 { 1027 struct grfinfo *gi = &gp->g_display; 1028 volatile unsigned char *ba; 1029 int bank; 1030 1031 ba = gp->g_regkva; 1032 bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8); 1033 1034 /* bank register is multiple of 64 byte, make this multiple of 64k */ 1035 bank >>= 10; 1036 return bank; 1037 } 1038 1039 int 1040 rt_setbank (gp, bank) 1041 struct grf_softc *gp; 1042 int bank; 1043 { 1044 volatile unsigned char *ba; 1045 1046 ba = gp->g_regkva; 1047 /* bank register is multiple of 64 byte, make this multiple of 64k */ 1048 bank <<= 10; 1049 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank); 1050 bank >>= 8; 1051 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank); 1052 1053 return 0; 1054 } 1055 1056 #endif 1057 1058 int 1059 rt_getcmap (gfp, cmap) 1060 struct grf_softc *gfp; 1061 struct grf_colormap *cmap; 1062 { 1063 volatile unsigned char *ba; 1064 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1065 short x; 1066 int error; 1067 1068 if (cmap->count == 0 || cmap->index >= 256) 1069 return 0; 1070 1071 if (cmap->index + cmap->count > 256) 1072 cmap->count = 256 - cmap->index; 1073 1074 ba = gfp->g_regkva; 1075 /* first read colors out of the chip, then copyout to userspace */ 1076 vgaw (ba, VDAC_REG_SELECT, cmap->index); 1077 x = cmap->count - 1; 1078 rp = red + cmap->index; 1079 gp = green + cmap->index; 1080 bp = blue + cmap->index; 1081 do 1082 { 1083 *rp++ = vgar (ba, VDAC_REG_DATA); 1084 *gp++ = vgar (ba, VDAC_REG_DATA); 1085 *bp++ = vgar (ba, VDAC_REG_DATA); 1086 } 1087 while (x--); 1088 1089 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count)) 1090 && !(error = copyout (green + cmap->index, cmap->green, cmap->count)) 1091 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count))) 1092 return 0; 1093 1094 return error; 1095 } 1096 1097 int 1098 rt_putcmap (gfp, cmap) 1099 struct grf_softc *gfp; 1100 struct grf_colormap *cmap; 1101 { 1102 volatile unsigned char *ba; 1103 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1104 short x; 1105 int error; 1106 1107 if (cmap->count == 0 || cmap->index >= 256) 1108 return 0; 1109 1110 if (cmap->index + cmap->count > 256) 1111 cmap->count = 256 - cmap->index; 1112 1113 /* first copy the colors into kernelspace */ 1114 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count)) 1115 && !(error = copyin (cmap->green, green + cmap->index, cmap->count)) 1116 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) 1117 { 1118 ba = gfp->g_regkva; 1119 vgaw (ba, VDAC_REG_SELECT, cmap->index); 1120 x = cmap->count - 1; 1121 rp = red + cmap->index; 1122 gp = green + cmap->index; 1123 bp = blue + cmap->index; 1124 do 1125 { 1126 vgaw (ba, VDAC_REG_DATA, *rp++); 1127 vgaw (ba, VDAC_REG_DATA, *gp++); 1128 vgaw (ba, VDAC_REG_DATA, *bp++); 1129 } 1130 while (x--); 1131 return 0; 1132 } 1133 else 1134 return error; 1135 } 1136 1137 int 1138 rt_getspritepos (gp, pos) 1139 struct grf_softc *gp; 1140 struct grf_position *pos; 1141 { 1142 volatile unsigned char *ba; 1143 1144 ba = gp->g_regkva; 1145 pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8); 1146 pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8); 1147 return 0; 1148 } 1149 1150 int 1151 rt_setspritepos (gp, pos) 1152 struct grf_softc *gp; 1153 struct grf_position *pos; 1154 { 1155 volatile unsigned char *ba; 1156 1157 ba = gp->g_regkva; 1158 vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff); 1159 vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07); 1160 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff); 1161 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07); 1162 return 0; 1163 } 1164 1165 /* assume an at least 2M retina (XXX), sprite is last in memory. 1166 According to the bogus docs, the cursor can be at most 128 lines 1167 in height, and the x-hostspot can be placed at most at pos 31, 1168 this gives width of a long */ 1169 #define SPRITE_ADDR (2*1024*1024 - 128*4) 1170 1171 int 1172 rt_getspriteinfo (gp, info) 1173 struct grf_softc *gp; 1174 struct grf_spriteinfo *info; 1175 { 1176 volatile unsigned char *ba, *fb; 1177 1178 ba = gp->g_regkva; 1179 fb = gp->g_fbkva; 1180 if (info->set & GRFSPRSET_ENABLE) 1181 info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01; 1182 if (info->set & GRFSPRSET_POS) 1183 rt_getspritepos (gp, &info->pos); 1184 if (info->set & GRFSPRSET_HOT) 1185 { 1186 info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f; 1187 info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f; 1188 } 1189 if (info->set & GRFSPRSET_CMAP) 1190 { 1191 struct grf_colormap cmap; 1192 int index; 1193 cmap.index = 0; 1194 cmap.count = 256; 1195 rt_getcmap (gp, &cmap); 1196 index = vgar (ba, SEQ_ID_CURSOR_COLOR0); 1197 info->cmap.red[0] = cmap.red[index]; 1198 info->cmap.green[0] = cmap.green[index]; 1199 info->cmap.blue[0] = cmap.blue[index]; 1200 index = vgar (ba, SEQ_ID_CURSOR_COLOR1); 1201 info->cmap.red[1] = cmap.red[index]; 1202 info->cmap.green[1] = cmap.green[index]; 1203 info->cmap.blue[1] = cmap.blue[index]; 1204 } 1205 if (info->set & GRFSPRSET_SHAPE) 1206 { 1207 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO); 1208 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI); 1209 int last_bank = SPRITE_ADDR >> 6; 1210 int last_bank_lo = last_bank & 0xff; 1211 int last_bank_hi = last_bank >> 8; 1212 u_char mask; 1213 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo); 1214 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi); 1215 copyout (fb, info->image, 128*4); 1216 mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK); 1217 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo); 1218 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi); 1219 copyout (&mask, info->mask, 1); 1220 info->size.x = 32; /* ??? */ 1221 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4; 1222 } 1223 1224 } 1225 1226 int 1227 rt_setspriteinfo (gp, info) 1228 struct grf_softc *gp; 1229 struct grf_spriteinfo *info; 1230 { 1231 volatile unsigned char *ba, *fb; 1232 u_char control; 1233 1234 ba = gp->g_regkva; 1235 fb = gp->g_fbkva; 1236 control = vgar (ba, SEQ_ID_CURSOR_CONTROL); 1237 if (info->set & GRFSPRSET_ENABLE) 1238 { 1239 if (info->enable) 1240 control |= 1; 1241 else 1242 control &= ~1; 1243 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control); 1244 } 1245 if (info->set & GRFSPRSET_POS) 1246 rt_setspritepos (gp, &info->pos); 1247 if (info->set & GRFSPRSET_HOT) 1248 { 1249 vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f); 1250 vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f); 1251 } 1252 if (info->set & GRFSPRSET_CMAP) 1253 { 1254 /* hey cheat a bit here.. XXX */ 1255 vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0); 1256 vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1); 1257 } 1258 if (info->set & GRFSPRSET_SHAPE) 1259 { 1260 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO); 1261 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI); 1262 int last_bank = SPRITE_ADDR >> 6; 1263 int last_bank_lo = last_bank & 0xff; 1264 int last_bank_hi = last_bank >> 8; 1265 u_char mask; 1266 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo); 1267 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi); 1268 copyin (info->image, fb, 128*4); 1269 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo); 1270 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi); 1271 copyin (info->mask, &mask, 1); 1272 WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask); 1273 /* info->size.x = 32; *//* ??? */ 1274 1275 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4; 1276 control = (control & ~6) | ((info->size.y >> 4) & 6); 1277 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control); 1278 1279 /* sick intel bull-addressing.. */ 1280 WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f); 1281 WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0); 1282 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff); 1283 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff); 1284 } 1285 1286 return 0; 1287 } 1288 1289 int 1290 rt_getspritemax (gp, pos) 1291 struct grf_softc *gp; 1292 struct grf_position *pos; 1293 { 1294 pos->x = 32; 1295 pos->y = 128; 1296 1297 return 0; 1298 } 1299 1300 1301 /* 1302 * !!! THIS AREA UNDER CONSTRUCTION !!! 1303 */ 1304 1305 int 1306 rt_bitblt (gp, bb) 1307 struct grf_softc *gp; 1308 struct grf_bitblt *bb; 1309 { 1310 return EINVAL; 1311 1312 1313 #if 0 1314 volatile unsigned char *ba, *fb; 1315 u_char control; 1316 u_char saved_bank_lo; 1317 u_char saved_bank_hi; 1318 u_char src_bank_lo, src_bank_hi; 1319 u_char dst_bank_lo, dst_bank_hi; 1320 u_long src_offset, dst_offset; 1321 u_short src_bank, dst_bank; 1322 u_char *srcp, *dstp; 1323 short x, y; 1324 u_long tot; 1325 1326 ba = gp->g_regkva; 1327 fb = gp->g_fbkva; 1328 1329 saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO); 1330 saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI); 1331 1332 /* for now, only GRFBBcopy is supported, and only for depth 8. No 1333 clipping is performed, either... */ 1334 1335 if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8) 1336 return EINVAL; 1337 1338 src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth; 1339 dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth; 1340 tot = op->w * op->h; 1341 1342 /* set write mode 1, "[...] data in the read latches is written 1343 to memory during CPU memory write cycles. [...]" */ 1344 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1); 1345 /* write to primary, read from secondary */ 1346 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 ); 1347 1348 if (src_offset < dst_offset) 1349 { 1350 /* start at end */ 1351 src_offset += tot; 1352 dst_offset += tot; 1353 } 1354 1355 src_bank_lo = (src_offset >> 6) & 0xff; 1356 src_bank_hi = (src_offset >> 14) & 0xff; 1357 dst_bank_lo = (dst_offset >> 6) & 0xff; 1358 dst_bank_hi = (dst_offset >> 14) & 0xff; 1359 1360 while (tot) 1361 { 1362 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo); 1363 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi); 1364 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo); 1365 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi); 1366 1367 if (src_offset < dst_offset) 1368 { 1369 1370 1371 } 1372 else 1373 { 1374 1375 } 1376 } 1377 1378 1379 #endif 1380 } 1381 1382 1383 #endif /* NGRF */ 1384