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