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