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