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