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