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