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