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