Home | History | Annotate | Line # | Download | only in dev
grf_rt.c revision 1.26
      1 /*	$NetBSD: grf_rt.c,v 1.26 1996/05/01 09:59:28 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 *, char *));
    768 int grfrtmatch __P((struct device *, void *, 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 
    782 struct cfattach grfrt_ca = {
    783 	sizeof(struct grf_softc), grfrtmatch, grfrtattach
    784 };
    785 
    786 struct cfdriver grfrt_cd = {
    787 	NULL, "grfrt", DV_DULL, NULL, 0
    788 };
    789 
    790 /*
    791  * only used in console init
    792  */
    793 static struct cfdata *cfdata;
    794 
    795 /*
    796  * we make sure to only init things once.  this is somewhat
    797  * tricky regarding the console.
    798  */
    799 int
    800 grfrtmatch(pdp, match, auxp)
    801 	struct device *pdp;
    802 	void *match, *auxp;
    803 {
    804 #ifdef RETINACONSOLE
    805 	struct cfdata *cfp = match;
    806 	static int rtconunit = -1;
    807 #endif
    808 	struct zbus_args *zap;
    809 
    810 	zap = auxp;
    811 
    812 	/*
    813 	 * allow only one retina console
    814 	 */
    815 	if (amiga_realconfig == 0)
    816 #ifdef RETINACONSOLE
    817 		if (rtconunit != -1)
    818 #endif
    819 			return(0);
    820 	/*
    821 	 * check that this is a retina board.
    822 	 */
    823 	if (zap->manid != 18260 || zap->prodid != 6)
    824 		return(0);
    825 
    826 #ifdef RETINACONSOLE
    827 	if (amiga_realconfig == 0 || rtconunit != cfp->cf_unit) {
    828 #endif
    829 		if ((unsigned)retina_default_mon >= retina_mon_max ||
    830 		    monitor_defs[retina_default_mon].DEP == 8)
    831 			retina_default_mon = 0;
    832 
    833 		current_mon = monitor_defs + retina_default_mon;
    834 		if (retina_alive(current_mon) == 0)
    835 			return(0);
    836 #ifdef RETINACONSOLE
    837 		if (amiga_realconfig == 0) {
    838 			rtconunit = cfp->cf_unit;
    839 			cfdata = cfp;
    840 		}
    841 	}
    842 #endif
    843 	return(1);
    844 }
    845 
    846 /*
    847  * attach to the grfbus (zbus)
    848  */
    849 void
    850 grfrtattach(pdp, dp, auxp)
    851 	struct device *pdp, *dp;
    852 	void *auxp;
    853 {
    854 	static struct grf_softc congrf;
    855 	struct zbus_args *zap;
    856 	struct grf_softc *gp;
    857 
    858 	zap = auxp;
    859 
    860 	if (dp == NULL)
    861 		gp = &congrf;
    862 	else
    863 		gp = (struct grf_softc *)dp;
    864 
    865 	if (dp != NULL && congrf.g_regkva != 0) {
    866 		/*
    867 		 * we inited earlier just copy the info
    868 		 * take care not to copy the device struct though.
    869 		 */
    870 		bcopy(&congrf.g_display, &gp->g_display,
    871 		    (char *)&gp[1] - (char *)&gp->g_display);
    872 	} else {
    873 		gp->g_regkva = (volatile caddr_t)zap->va;
    874 		gp->g_fbkva = (volatile caddr_t)zap->va + 64 * 1024;
    875 		gp->g_unit = GRF_RETINAII_UNIT;
    876 		gp->g_flags = GF_ALIVE;
    877 		gp->g_mode = rt_mode;
    878 		gp->g_conpri = grfrt_cnprobe();
    879 		grfrt_iteinit(gp);
    880 		(void)rt_load_mon(gp, current_mon);
    881 	}
    882 	if (dp != NULL)
    883 		printf("\n");
    884 	/*
    885 	 * attach grf
    886 	 */
    887 	amiga_config_found(cfdata, &gp->g_device, gp, grfrtprint);
    888 }
    889 
    890 int
    891 grfrtprint(auxp, pnp)
    892 	void *auxp;
    893 	char *pnp;
    894 {
    895 	if (pnp)
    896 		printf("grf%d at %s", ((struct grf_softc *)auxp)->g_unit,
    897 			pnp);
    898 	return(UNCONF);
    899 }
    900 
    901 static int
    902 rt_getvmode (gp, vm)
    903      struct grf_softc *gp;
    904      struct grfvideo_mode *vm;
    905 {
    906   struct MonDef *md;
    907 
    908   if (vm->mode_num && vm->mode_num > retina_mon_max)
    909     return EINVAL;
    910 
    911   if (! vm->mode_num)
    912     vm->mode_num = (current_mon - monitor_defs) + 1;
    913 
    914   md = monitor_defs + (vm->mode_num - 1);
    915   strncpy (vm->mode_descr, monitor_descr[vm->mode_num - 1],
    916 	   sizeof (vm->mode_descr));
    917   vm->pixel_clock  = md->FQ;
    918   vm->disp_width   = md->MW;
    919   vm->disp_height  = md->MH;
    920   vm->depth        = md->DEP;
    921 
    922   /*
    923    * From observation of the monitor definition table above, I guess that
    924    * the horizontal timings are in units of longwords. Hence, I get the
    925    * pixels by multiplication with 32 and division by the depth.
    926    * The text modes, apparently marked by depth == 4, are even more wierd.
    927    * According to a comment above, they are computed from a depth==8 mode
    928    * (thats for us: * 32 / 8) by applying another factor of 4 / font width.
    929    * Reverse applying the latter formula most of the constants cancel
    930    * themselves and we are left with a nice (* font width).
    931    * That is, internal timings are in units of longwords for graphics
    932    * modes, or in units of characters widths for text modes.
    933    * We better don't WRITE modes until this has been real live checked.
    934    * 			- Ignatios Souvatzis
    935    */
    936 
    937   if (md->DEP == 4) {
    938 	vm->hblank_start = md->HBS * 32 / md->DEP;
    939 	vm->hblank_stop  = md->HBE * 32 / md->DEP;
    940 	vm->hsync_start  = md->HSS * 32 / md->DEP;
    941 	vm->hsync_stop   = md->HSE * 32 / md->DEP;
    942 	vm->htotal       = md->HT * 32 / md->DEP;
    943   } else {
    944 	vm->hblank_start = md->HBS * md->FX;
    945 	vm->hblank_stop  = md->HBE * 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   vm->vblank_start = md->VBS;
    951   vm->vblank_stop  = md->VBE;
    952   vm->vsync_start  = md->VSS;
    953   vm->vsync_stop   = md->VSE;
    954   vm->vtotal       = md->VT;
    955 
    956   return 0;
    957 }
    958 
    959 
    960 static int
    961 rt_setvmode (gp, mode, txtonly)
    962      struct grf_softc *gp;
    963      unsigned mode;
    964      int txtonly;
    965 {
    966   int error;
    967 
    968   if (!mode || mode > retina_mon_max)
    969     return EINVAL;
    970 
    971   if (txtonly && monitor_defs[mode-1].DEP == 8)
    972     return EINVAL;
    973 
    974   current_mon = monitor_defs + (mode - 1);
    975 
    976   error = rt_load_mon (gp, current_mon) ? 0 : EINVAL;
    977 
    978   return error;
    979 }
    980 
    981 
    982 /*
    983  * Change the mode of the display.
    984  * Return a UNIX error number or 0 for success.
    985  */
    986 int
    987 rt_mode(gp, cmd, arg, a2, a3)
    988 	struct grf_softc *gp;
    989 	u_long cmd;
    990 	void *arg;
    991 	u_long a2;
    992 	int a3;
    993 {
    994   /* implement these later... */
    995 
    996   switch (cmd)
    997     {
    998     case GM_GRFON:
    999       rt_setvmode (gp, retina_default_gfx + 1, 0);
   1000       return 0;
   1001 
   1002     case GM_GRFOFF:
   1003       rt_setvmode (gp, retina_default_mon + 1, 0);
   1004       return 0;
   1005 
   1006     case GM_GRFCONFIG:
   1007       return 0;
   1008 
   1009     case GM_GRFGETVMODE:
   1010       return rt_getvmode (gp, (struct grfvideo_mode *) arg);
   1011 
   1012     case GM_GRFSETVMODE:
   1013       return rt_setvmode (gp, *(unsigned *) arg, 1);
   1014 
   1015     case GM_GRFGETNUMVM:
   1016       *(int *)arg = retina_mon_max;
   1017       return 0;
   1018 
   1019 #ifdef BANKEDDEVPAGER
   1020     case GM_GRFGETBANK:
   1021       *(int *)arg = rt_getbank (gp, a2, a3);
   1022       return 0;
   1023 
   1024     case GM_GRFGETCURBANK:
   1025       *(int *)arg = rt_getcurbank (gp);
   1026       return 0;
   1027 
   1028     case GM_GRFSETBANK:
   1029       return rt_setbank (gp, arg);
   1030 #endif
   1031     case GM_GRFIOCTL:
   1032       return rt_ioctl (gp, a2, arg);
   1033 
   1034     default:
   1035       break;
   1036     }
   1037 
   1038   return EINVAL;
   1039 }
   1040 
   1041 int
   1042 rt_ioctl (gp, cmd, data)
   1043 	register struct grf_softc *gp;
   1044 	u_long cmd;
   1045 	void *data;
   1046 {
   1047   switch (cmd)
   1048     {
   1049     case GRFIOCGSPRITEPOS:
   1050       return rt_getspritepos (gp, (struct grf_position *) data);
   1051 
   1052     case GRFIOCSSPRITEPOS:
   1053       return rt_setspritepos (gp, (struct grf_position *) data);
   1054 
   1055     case GRFIOCSSPRITEINF:
   1056       return rt_setspriteinfo (gp, (struct grf_spriteinfo *) data);
   1057 
   1058     case GRFIOCGSPRITEINF:
   1059       return rt_getspriteinfo (gp, (struct grf_spriteinfo *) data);
   1060 
   1061     case GRFIOCGSPRITEMAX:
   1062       return rt_getspritemax (gp, (struct grf_position *) data);
   1063 
   1064     case GRFIOCGETCMAP:
   1065       return rt_getcmap (gp, (struct grf_colormap *) data);
   1066 
   1067     case GRFIOCPUTCMAP:
   1068       return rt_putcmap (gp, (struct grf_colormap *) data);
   1069 
   1070     case GRFIOCBITBLT:
   1071       return rt_bitblt (gp, (struct grf_bitblt *) data);
   1072     }
   1073 
   1074   return EINVAL;
   1075 }
   1076 
   1077 #ifdef BANKEDDEVPAGER
   1078 
   1079 /* Retina banks can overlap. Don't use this information (yet?), and
   1080    only switch 64k sized banks. */
   1081 
   1082 int
   1083 rt_getbank (gp, offs, prot)
   1084      struct grf_softc *gp;
   1085      u_long offs;
   1086      int prot;
   1087 {
   1088   /* XXX */
   1089   if (offs <  0 || offs >= 4*1024*1024)
   1090     return -1;
   1091   else
   1092     return offs >> 16;
   1093 }
   1094 
   1095 int
   1096 rt_getcurbank (gp)
   1097      struct grf_softc *gp;
   1098 {
   1099   struct grfinfo *gi = &gp->g_display;
   1100   volatile unsigned char *ba;
   1101   int bank;
   1102 
   1103   ba = gp->g_regkva;
   1104   bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8);
   1105 
   1106   /* bank register is multiple of 64 byte, make this multiple of 64k */
   1107   bank >>= 10;
   1108   return bank;
   1109 }
   1110 
   1111 int
   1112 rt_setbank (gp, bank)
   1113      struct grf_softc *gp;
   1114      int bank;
   1115 {
   1116   volatile unsigned char *ba;
   1117 
   1118   ba = gp->g_regkva;
   1119   /* bank register is multiple of 64 byte, make this multiple of 64k */
   1120   bank <<= 10;
   1121   WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
   1122   bank >>= 8;
   1123   WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
   1124 
   1125   return 0;
   1126 }
   1127 
   1128 #endif
   1129 
   1130 int
   1131 rt_getcmap (gfp, cmap)
   1132      struct grf_softc *gfp;
   1133      struct grf_colormap *cmap;
   1134 {
   1135   volatile unsigned char *ba;
   1136   u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1137   short x;
   1138   int error;
   1139 
   1140   if (cmap->count == 0 || cmap->index >= 256)
   1141     return 0;
   1142 
   1143   if (cmap->index + cmap->count > 256)
   1144     cmap->count = 256 - cmap->index;
   1145 
   1146   ba = gfp->g_regkva;
   1147   /* first read colors out of the chip, then copyout to userspace */
   1148   vgaw (ba, VDAC_REG_SELECT, cmap->index);
   1149   x = cmap->count - 1;
   1150   rp = red + cmap->index;
   1151   gp = green + cmap->index;
   1152   bp = blue + cmap->index;
   1153   do
   1154     {
   1155       *rp++ = vgar (ba, VDAC_REG_DATA);
   1156       *gp++ = vgar (ba, VDAC_REG_DATA);
   1157       *bp++ = vgar (ba, VDAC_REG_DATA);
   1158     }
   1159   while (x--);
   1160 
   1161   if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
   1162       && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
   1163       && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
   1164     return 0;
   1165 
   1166   return error;
   1167 }
   1168 
   1169 int
   1170 rt_putcmap (gfp, cmap)
   1171      struct grf_softc *gfp;
   1172      struct grf_colormap *cmap;
   1173 {
   1174   volatile unsigned char *ba;
   1175   u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1176   short x;
   1177   int error;
   1178 
   1179   if (cmap->count == 0 || cmap->index >= 256)
   1180     return 0;
   1181 
   1182   if (cmap->index + cmap->count > 256)
   1183     cmap->count = 256 - cmap->index;
   1184 
   1185   /* first copy the colors into kernelspace */
   1186   if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
   1187       && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
   1188       && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count)))
   1189     {
   1190       ba = gfp->g_regkva;
   1191       vgaw (ba, VDAC_REG_SELECT, cmap->index);
   1192       x = cmap->count - 1;
   1193       rp = red + cmap->index;
   1194       gp = green + cmap->index;
   1195       bp = blue + cmap->index;
   1196       do
   1197 	{
   1198 	  vgaw (ba, VDAC_REG_DATA, *rp++);
   1199 	  vgaw (ba, VDAC_REG_DATA, *gp++);
   1200 	  vgaw (ba, VDAC_REG_DATA, *bp++);
   1201 	}
   1202       while (x--);
   1203       return 0;
   1204     }
   1205   else
   1206     return error;
   1207 }
   1208 
   1209 int
   1210 rt_getspritepos (gp, pos)
   1211      struct grf_softc *gp;
   1212      struct grf_position *pos;
   1213 {
   1214   volatile unsigned char *ba;
   1215 
   1216   ba = gp->g_regkva;
   1217   pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8);
   1218   pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8);
   1219   return 0;
   1220 }
   1221 
   1222 int
   1223 rt_setspritepos (gp, pos)
   1224      struct grf_softc *gp;
   1225      struct grf_position *pos;
   1226 {
   1227   volatile unsigned char *ba;
   1228 
   1229   ba = gp->g_regkva;
   1230   vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff);
   1231   vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07);
   1232   vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff);
   1233   vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07);
   1234   return 0;
   1235 }
   1236 
   1237 /* assume an at least 2M retina (XXX), sprite is last in memory.
   1238    According to the bogus docs, the cursor can be at most 128 lines
   1239    in height, and the x-hostspot can be placed at most at pos 31,
   1240    this gives width of a long */
   1241 #define SPRITE_ADDR (2*1024*1024 - 128*4)
   1242 
   1243 int
   1244 rt_getspriteinfo (gp, info)
   1245      struct grf_softc *gp;
   1246      struct grf_spriteinfo *info;
   1247 {
   1248   volatile caddr_t ba, fb;
   1249 
   1250   ba = gp->g_regkva;
   1251   fb = gp->g_fbkva;
   1252   if (info->set & GRFSPRSET_ENABLE)
   1253     info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
   1254   if (info->set & GRFSPRSET_POS)
   1255     rt_getspritepos (gp, &info->pos);
   1256   if (info->set & GRFSPRSET_HOT)
   1257     {
   1258       info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f;
   1259       info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
   1260     }
   1261   if (info->set & GRFSPRSET_CMAP)
   1262     {
   1263       struct grf_colormap cmap;
   1264       int index;
   1265       cmap.index = 0;
   1266       cmap.count = 256;
   1267       rt_getcmap (gp, &cmap);
   1268       index = vgar (ba, SEQ_ID_CURSOR_COLOR0);
   1269       info->cmap.red[0] = cmap.red[index];
   1270       info->cmap.green[0] = cmap.green[index];
   1271       info->cmap.blue[0] = cmap.blue[index];
   1272       index = vgar (ba, SEQ_ID_CURSOR_COLOR1);
   1273       info->cmap.red[1] = cmap.red[index];
   1274       info->cmap.green[1] = cmap.green[index];
   1275       info->cmap.blue[1] = cmap.blue[index];
   1276     }
   1277   if (info->set & GRFSPRSET_SHAPE)
   1278     {
   1279       int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1280       int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1281       int last_bank = SPRITE_ADDR >> 6;
   1282       int last_bank_lo = last_bank & 0xff;
   1283       int last_bank_hi = last_bank >> 8;
   1284       u_char mask;
   1285       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1286       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1287       copyout (fb, info->image, 128*4);
   1288       mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK);
   1289       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1290       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1291       copyout (&mask, info->mask, 1);
   1292       info->size.x = 32; /* ??? */
   1293       info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1294     }
   1295 
   1296   return 0;
   1297 }
   1298 
   1299 int
   1300 rt_setspriteinfo (gp, info)
   1301      struct grf_softc *gp;
   1302      struct grf_spriteinfo *info;
   1303 {
   1304   volatile caddr_t ba, fb;
   1305   u_char control;
   1306 
   1307   ba = gp->g_regkva;
   1308   fb = gp->g_fbkva;
   1309   control = vgar (ba, SEQ_ID_CURSOR_CONTROL);
   1310   if (info->set & GRFSPRSET_ENABLE)
   1311     {
   1312       if (info->enable)
   1313 	control |= 1;
   1314       else
   1315 	control &= ~1;
   1316       vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1317     }
   1318   if (info->set & GRFSPRSET_POS)
   1319     rt_setspritepos (gp, &info->pos);
   1320   if (info->set & GRFSPRSET_HOT)
   1321     {
   1322       vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f);
   1323       vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
   1324     }
   1325   if (info->set & GRFSPRSET_CMAP)
   1326     {
   1327       /* hey cheat a bit here.. XXX */
   1328       vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0);
   1329       vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1);
   1330     }
   1331   if (info->set & GRFSPRSET_SHAPE)
   1332     {
   1333       int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1334       int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1335       int last_bank = SPRITE_ADDR >> 6;
   1336       int last_bank_lo = last_bank & 0xff;
   1337       int last_bank_hi = last_bank >> 8;
   1338       u_char mask;
   1339       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1340       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1341       copyin (info->image, fb, 128*4);
   1342       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1343       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1344       copyin (info->mask, &mask, 1);
   1345       WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask);
   1346       /* info->size.x = 32; *//* ??? */
   1347 
   1348       info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1349       control = (control & ~6) | ((info->size.y >> 4) & 6);
   1350       vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1351 
   1352       /* sick intel bull-addressing.. */
   1353       WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f);
   1354       WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0);
   1355       WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff);
   1356       WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff);
   1357     }
   1358 
   1359   return 0;
   1360 }
   1361 
   1362 int
   1363 rt_getspritemax (gp, pos)
   1364      struct grf_softc *gp;
   1365      struct grf_position *pos;
   1366 {
   1367   pos->x = 32;
   1368   pos->y = 128;
   1369 
   1370   return 0;
   1371 }
   1372 
   1373 
   1374 /*
   1375  * !!! THIS AREA UNDER CONSTRUCTION !!!
   1376  */
   1377 
   1378 int
   1379 rt_bitblt (gp, bb)
   1380      struct grf_softc *gp;
   1381      struct grf_bitblt *bb;
   1382 {
   1383   return EINVAL;
   1384 
   1385 
   1386 #if 0
   1387   volatile caddr_t ba, fb;
   1388   u_char control;
   1389   u_char saved_bank_lo;
   1390   u_char saved_bank_hi;
   1391   u_char src_bank_lo, src_bank_hi;
   1392   u_char dst_bank_lo, dst_bank_hi;
   1393   u_long src_offset, dst_offset;
   1394   u_short src_bank, dst_bank;
   1395   u_char *srcp, *dstp;
   1396   short x, y;
   1397   u_long tot;
   1398 
   1399   ba = gp->g_regkva;
   1400   fb = gp->g_fbkva;
   1401 
   1402   saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1403   saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1404 
   1405   /* for now, only GRFBBcopy is supported, and only for depth 8. No
   1406      clipping is performed, either... */
   1407 
   1408   if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8)
   1409     return EINVAL;
   1410 
   1411   src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth;
   1412   dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth;
   1413   tot = op->w * op->h;
   1414 
   1415   /* set write mode 1, "[...] data in the read latches is written
   1416      to memory during CPU memory write cycles. [...]" */
   1417   WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
   1418   /* write to primary, read from secondary */
   1419   WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
   1420 
   1421   if (src_offset < dst_offset)
   1422     {
   1423       /* start at end */
   1424       src_offset += tot;
   1425       dst_offset += tot;
   1426     }
   1427 
   1428   src_bank_lo = (src_offset >> 6) & 0xff;
   1429   src_bank_hi = (src_offset >> 14) & 0xff;
   1430   dst_bank_lo = (dst_offset >> 6) & 0xff;
   1431   dst_bank_hi = (dst_offset >> 14) & 0xff;
   1432 
   1433   while (tot)
   1434     {
   1435       WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo);
   1436       WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi);
   1437       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo);
   1438       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi);
   1439 
   1440       if (src_offset < dst_offset)
   1441 	{
   1442 
   1443 
   1444 	}
   1445       else
   1446 	{
   1447 
   1448 	}
   1449     }
   1450 
   1451 
   1452 #endif
   1453 }
   1454 
   1455 
   1456 #endif	/* NGRF */
   1457