Home | History | Annotate | Line # | Download | only in dev
grf_rh.c revision 1.1
      1 /*
      2  *	$Id: grf_rh.c,v 1.1 1994/06/05 07:48:42 chopps Exp $
      3  */
      4 
      5 #include "grf.h"
      6 #if NGRF > 0
      7 
      8 /*
      9  * Graphics routines for the Retina BLT Z3 board,
     10  * using the NCR 77C32BLT VGA controller.
     11 */
     12 
     13 #include <sys/param.h>
     14 #include <sys/errno.h>
     15 #include <sys/ioctl.h>
     16 #include <sys/device.h>
     17 #include <sys/malloc.h>
     18 #include <machine/cpu.h>
     19 #include <amiga/amiga/device.h>
     20 #include <amiga/dev/grfioctl.h>
     21 #include <amiga/dev/grfvar.h>
     22 #include <amiga/dev/grf_rhreg.h>
     23 #include <amiga/dev/zthreebusvar.h>
     24 
     25 int rh_mondefok __P((struct MonDef *));
     26 
     27 u_short CompFQ __P((u_int fq));
     28 int rh_load_mon __P((struct grf_softc *gp, struct MonDef *md));
     29 int rh_getvmode __P((struct grf_softc *gp, struct grfvideo_mode *vm));
     30 int rh_setvmode __P((struct grf_softc *gp, unsigned int mode, int txtonly));
     31 
     32 
     33 extern unsigned char kernel_font_8x8_width, kernel_font_8x8_height;
     34 extern unsigned char kernel_font_8x8_lo, kernel_font_8x8_hi;
     35 extern unsigned char kernel_font_8x8[];
     36 
     37 
     38 /*
     39  * NOTE: this driver for the MacroSystem Retina board was only possible,
     40  *       because MacroSystem provided information about the pecularities
     41  *       of the board. THANKS! Competition in Europe among gfx board
     42  *       manufacturers is rather tough, so Lutz Vieweg, who wrote the
     43  *       initial driver, has made an agreement with MS not to document
     44  *       the driver source (see also his Copyright disclaimer below).
     45  *       -> ALL comments after
     46  *       -> "/* -------------- START OF CODE -------------- * /"
     47  *       -> have been added by myself (mw) from studying the publically
     48  *       -> available "NCR 77C32BLT" Data Manual
     49  *
     50  *       Lutz' original driver source (without any of my comments) is
     51  *       available on request.
     52  */
     53 
     54 /* This code offers low-level routines to access the Retina BLT Z3
     55  * graphics-board manufactured by MS MacroSystem GmbH from within NetBSD
     56  * for the Amiga.  * No warranties for any kind of function at all - this
     57  * code may crash your hardware and scratch your harddisk.  Use at your
     58  * own risk.  Freely distributable.
     59  *
     60  * Written by Lutz Vieweg 02/94
     61  *
     62  * Thanks to MacroSystem for providing me with the neccessary information
     63  * to create theese routines. The sparse documentation of this code
     64  * results from the agreements between MS and me.
     65  */
     66 
     67 
     68 
     69 #define MDF_DBL 1
     70 #define MDF_LACE 2
     71 #define MDF_CLKDIV2 4
     72 
     73 
     74 /* -------------- START OF CODE -------------- */
     75 
     76 /* Convert big-endian long into little-endian long. */
     77 
     78 #define M2I(val)                                                     \
     79 	asm volatile (" rorw #8,%0   ;                               \
     80 	                swap %0      ;                               \
     81 	                rorw #8,%0   ; " : "=d" (val) : "0" (val));
     82 
     83 #define M2INS(val)                                                   \
     84 	asm volatile (" rorw #8,%0   ;                               \
     85 	                swap %0      ;                               \
     86 	                rorw #8,%0   ;                               \
     87  			swap %0	     ; " : "=d" (val) : "0" (val));
     88 
     89 #define ACM_OFFSET	(0x00b00000)
     90 #define LM_OFFSET	(0x00c00000)
     91 
     92 static unsigned char optab[] = {
     93 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
     94 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0
     95 };
     96 static char optabs[] = {
     97 	   0,   -1,   -1,   -1,   -1,    0,   -1,   -1,
     98 	  -1,   -1,    0,   -1,   -1,   -1,   -1,    0
     99 };
    100 
    101 void
    102 RZ3DisableHWC(gp)
    103 	struct grf_softc *gp;
    104 {
    105 	volatile void *ba = gp->g_regkva;
    106 
    107 	WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, 0x00);
    108 }
    109 
    110 void
    111 RZ3SetupHWC(gp, col1, col2, hsx, hsy, data)
    112 	struct grf_softc *gp;
    113 	unsigned char col1;
    114 	unsigned col2;
    115 	unsigned char hsx;
    116 	unsigned char hsy;
    117 	const unsigned long *data;
    118 {
    119 	volatile unsigned char *ba = gp->g_regkva;
    120 	unsigned long *c = (unsigned long *)(ba + LM_OFFSET + HWC_MEM_OFF);
    121 	const unsigned long *s = data;
    122 	struct MonDef *MonitorDef = (struct MonDef *) gp->g_data;
    123 	short x = (HWC_MEM_SIZE / (4*4)) - 1;
    124 	/* copy only, if there is a data pointer. */
    125 	if (data) do {
    126 		*c++ = *s++;
    127 		*c++ = *s++;
    128 		*c++ = *s++;
    129 		*c++ = *s++;
    130 	} while (x-- > 0);
    131 
    132 	WSeq(ba, SEQ_ID_CURSOR_COLOR1, col1);
    133 	WSeq(ba, SEQ_ID_CURSOR_COLOR0, col2);
    134 	if (MonitorDef->DEP < 16)
    135 		WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x85);
    136 	else
    137 		WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0xa5);
    138 	WSeq(ba, SEQ_ID_CURSOR_X_LOC_HI, 0x00);
    139 	WSeq(ba, SEQ_ID_CURSOR_X_LOC_LO, 0x00);
    140 	WSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI, 0x00);
    141 	WSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO, 0x00);
    142 	WSeq(ba, SEQ_ID_CURSOR_X_INDEX, hsx);
    143 	WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, hsy);
    144 	WSeq(ba, SEQ_ID_CURSOR_STORE_HI, 0x00);
    145 	WSeq(ba, SEQ_ID_CURSOR_STORE_LO,  ((HWC_MEM_OFF / 4) & 0x0000f));
    146 	WSeq(ba, SEQ_ID_CURSOR_ST_OFF_HI, (((HWC_MEM_OFF / 4) & 0xff000) >> 12));
    147 	WSeq(ba, SEQ_ID_CURSOR_ST_OFF_LO, (((HWC_MEM_OFF / 4) & 0x00ff0) >>  4));
    148 	WSeq(ba, SEQ_ID_CURSOR_PIXELMASK, 0xff);
    149 }
    150 
    151 void
    152 RZ3AlphaErase (gp, xd, yd, w, h)
    153 	struct grf_softc *gp;
    154 	unsigned short xd;
    155 	unsigned short yd;
    156 	unsigned short  w;
    157 	unsigned short  h;
    158 {
    159 	const struct MonDef * md = (struct MonDef *) gp->g_data;
    160 	RZ3AlphaCopy(gp, xd, yd+md->TY, xd, yd, w, h);
    161 }
    162 
    163 void
    164 RZ3AlphaCopy (gp, xs, ys, xd, yd, w, h)
    165 	struct grf_softc *gp;
    166 	unsigned short xs;
    167 	unsigned short ys;
    168 	unsigned short xd;
    169 	unsigned short yd;
    170 	unsigned short  w;
    171 	unsigned short  h;
    172 {
    173 	volatile unsigned char *ba = gp->g_regkva;
    174 	const struct MonDef *md = (struct MonDef *) gp->g_data;
    175 	volatile unsigned long *acm = (unsigned long *) (ba + ACM_OFFSET);
    176 	unsigned short mod;
    177 
    178 	xs *= 4;
    179 	ys *= 4;
    180 	xd *= 4;
    181 	yd *= 4;
    182 	w  *= 4;
    183 
    184 	{
    185 		/* anyone got Windoze GDI opcodes handy?... */
    186 		unsigned long tmp = 0x0000ca00;
    187 		*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
    188 	}
    189 
    190 	mod = 0xc0c2;
    191 
    192 	{
    193 		unsigned long pat = 8 * PAT_MEM_OFF;
    194 		unsigned long dst = 8 * (xd + yd * md->TX);
    195 
    196 		unsigned long src = 8 * (xs + ys * md->TX);
    197 
    198 		if (xd > xs) {
    199 			mod &= ~0x8000;
    200 			src += 8 * (w - 1);
    201 			dst += 8 * (w - 1);
    202 			pat += 8 * 2;
    203 		}
    204 		if (yd > ys) {
    205 			mod &= ~0x4000;
    206 			src += 8 * (h - 1) * md->TX * 4;
    207 			dst += 8 * (h - 1) * md->TX * 4;
    208 			pat += 8 * 4;
    209 		}
    210 
    211 		M2I(src);
    212 		*(acm + ACM_SOURCE/4) = src;
    213 
    214 		M2I(pat);
    215 		*(acm + ACM_PATTERN/4) = pat;
    216 
    217 		M2I(dst);
    218 		*(acm + ACM_DESTINATION/4) = dst;
    219 	}
    220 	{
    221 
    222 		unsigned long tmp = mod << 16;
    223 		*(acm + ACM_CONTROL/4) = tmp;
    224 	}
    225 	{
    226 
    227 		unsigned long tmp  = w | (h << 16);
    228 		M2I(tmp);
    229 		*(acm + ACM_BITMAP_DIMENSION/4) = tmp;
    230 	}
    231 
    232 	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
    233 	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
    234 
    235 	while ((*(((volatile unsigned char *)acm) +
    236 	    (ACM_START_STATUS + 2)) & 1) == 0);
    237 }
    238 
    239 void
    240 RZ3BitBlit (gp, gbb)
    241 	struct grf_softc *gp;
    242 	struct grf_bitblt * gbb;
    243 {
    244 	volatile unsigned char *ba = gp->g_regkva;
    245 	volatile unsigned char *lm = ba + LM_OFFSET;
    246 	volatile unsigned long *acm = (unsigned long *) (ba + ACM_OFFSET);
    247 	const struct MonDef *md = (struct MonDef *) gp->g_data;
    248 	unsigned short mod;
    249 
    250 	{
    251 		unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF);
    252 		unsigned long tmp  = gbb->mask | ((unsigned long)gbb->mask << 16);
    253 		*pt++ = tmp;
    254 		*pt   = tmp;
    255 	}
    256 
    257 	{
    258 
    259 		unsigned long tmp = optab[ gbb->op ] << 8;
    260 		*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
    261 	}
    262 
    263 	mod = 0xc0c2;
    264 
    265 	{
    266 		unsigned long pat = 8 * PAT_MEM_OFF;
    267 		unsigned long dst = 8 * (gbb->dst_x + gbb->dst_y * md->TX);
    268 
    269 		if (optabs[gbb->op]) {
    270 			unsigned long src = 8 * (gbb->src_x + gbb->src_y * md->TX);
    271 
    272 			if (gbb->dst_x > gbb->src_x) {
    273 				mod &= ~0x8000;
    274 				src += 8 * (gbb->w - 1);
    275 				dst += 8 * (gbb->w - 1);
    276 				pat += 8 * 2;
    277 			}
    278 			if (gbb->dst_y > gbb->src_y) {
    279 				mod &= ~0x4000;
    280 				src += 8 * (gbb->h - 1) * md->TX;
    281 				dst += 8 * (gbb->h - 1) * md->TX;
    282 				pat += 8 * 4;
    283 			}
    284 
    285 			M2I(src);
    286 			*(acm + ACM_SOURCE/4) = src;
    287 		}
    288 
    289 		M2I(pat);
    290 		*(acm + ACM_PATTERN/4) = pat;
    291 
    292 		M2I(dst);
    293 		*(acm + ACM_DESTINATION/4) = dst;
    294 	}
    295 	{
    296 
    297 		unsigned long tmp = mod << 16;
    298 		*(acm + ACM_CONTROL/4) = tmp;
    299 	}
    300 	{
    301 		unsigned long tmp  = gbb->w | (gbb->h << 16);
    302 		M2I(tmp);
    303 		*(acm + ACM_BITMAP_DIMENSION/4) = tmp;
    304 	}
    305 
    306 	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
    307 	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
    308 
    309 	while ((*(((volatile unsigned char *)acm) +
    310 	    (ACM_START_STATUS + 2)) & 1) == 0);
    311 }
    312 
    313 void
    314 RZ3BitBlit16 (gp, gbb)
    315 	struct grf_softc *gp;
    316 	struct grf_bitblt * gbb;
    317 {
    318 	volatile unsigned char *ba = gp->g_regkva;
    319 	volatile unsigned char *lm = ba + LM_OFFSET;
    320 	volatile unsigned long * acm = (unsigned long *) (ba + ACM_OFFSET);
    321 	const struct MonDef * md = (struct MonDef *) gp->g_data;
    322 	unsigned short mod;
    323 
    324 	{
    325 		unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF);
    326 		unsigned long tmp  = gbb->mask | ((unsigned long)gbb->mask << 16);
    327 		*pt++ = tmp;
    328 		*pt++ = tmp;
    329 		*pt++ = tmp;
    330 		*pt   = tmp;
    331 	}
    332 
    333 	{
    334 
    335 		unsigned long tmp = optab[ gbb->op ] << 8;
    336 		*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
    337 	}
    338 
    339 	mod = 0xc0c2;
    340 
    341 	{
    342 		unsigned long pat = 8 * PAT_MEM_OFF;
    343 		unsigned long dst = 8 * 2 * (gbb->dst_x + gbb->dst_y * md->TX);
    344 
    345 		if (optabs[gbb->op]) {
    346 			unsigned long src = 8 * 2 * (gbb->src_x + gbb->src_y * md->TX);
    347 
    348 			if (gbb->dst_x > gbb->src_x) {
    349 				mod &= ~0x8000;
    350 				src += 8 * 2 * (gbb->w);
    351 				dst += 8 * 2 * (gbb->w);
    352 				pat += 8 * 2 * 2;
    353 			}
    354 			if (gbb->dst_y > gbb->src_y) {
    355 				mod &= ~0x4000;
    356 				src += 8 * 2 * (gbb->h - 1) * md->TX;
    357 				dst += 8 * 2 * (gbb->h - 1) * md->TX;
    358 				pat += 8 * 4 * 2;
    359 			}
    360 
    361 			M2I(src);
    362 			*(acm + ACM_SOURCE/4) = src;
    363 		}
    364 
    365 		M2I(pat);
    366 		*(acm + ACM_PATTERN/4) = pat;
    367 
    368 		M2I(dst);
    369 		*(acm + ACM_DESTINATION/4) = dst;
    370 	}
    371 	{
    372 
    373 		unsigned long tmp = mod << 16;
    374 		*(acm + ACM_CONTROL/4) = tmp;
    375 	}
    376 	{
    377 
    378 		unsigned long tmp  = gbb->w | (gbb->h << 16);
    379 		M2I(tmp);
    380 		*(acm + ACM_BITMAP_DIMENSION/4) = tmp;
    381 	}
    382 
    383 	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
    384 	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
    385 
    386 	while ((*(((volatile unsigned char *)acm) +
    387 	    (ACM_START_STATUS+ 2)) & 1) == 0);
    388 }
    389 
    390 void
    391 RZ3SetCursorPos (gp, pos)
    392 	struct grf_softc *gp;
    393 	unsigned short pos;
    394 {
    395 	volatile unsigned char *ba = gp->g_regkva;
    396 
    397 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, (unsigned char)pos);
    398 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, (unsigned char)(pos >> 8));
    399 
    400 }
    401 
    402 void
    403 RZ3LoadPalette (gp, pal, firstcol, colors)
    404 	struct grf_softc *gp;
    405 	unsigned char * pal;
    406 	unsigned char firstcol;
    407 	unsigned char colors;
    408 {
    409 	volatile unsigned char *ba = gp->g_regkva;
    410 
    411 	if (colors == 0)
    412 		return;
    413 
    414 	vgaw(ba, VDAC_ADDRESS_W, firstcol);
    415 
    416 	{
    417 
    418 		short x = colors-1;
    419 		const unsigned char * col = pal;
    420 		do {
    421 
    422 			vgaw(ba, VDAC_DATA, (*col++ >> 2));
    423 			vgaw(ba, VDAC_DATA, (*col++ >> 2));
    424 			vgaw(ba, VDAC_DATA, (*col++ >> 2));
    425 
    426 		} while (x-- > 0);
    427 
    428 	}
    429 }
    430 
    431 void
    432 RZ3SetPalette (gp, colornum, red, green, blue)
    433 	struct grf_softc *gp;
    434 	unsigned char colornum;
    435 	unsigned char red, green, blue;
    436 {
    437 	volatile unsigned char *ba = gp->g_regkva;
    438 
    439 	vgaw(ba, VDAC_ADDRESS_W, colornum);
    440 
    441 	vgaw(ba, VDAC_DATA, (red >> 2));
    442 	vgaw(ba, VDAC_DATA, (green >> 2));
    443 	vgaw(ba, VDAC_DATA, (blue >> 2));
    444 
    445 }
    446 
    447 /* XXXXXXXXX !! */
    448 static unsigned short xpan;
    449 static unsigned short ypan;
    450 
    451 void
    452 RZ3SetPanning (gp, xoff, yoff)
    453 	struct grf_softc *gp;
    454 	unsigned short xoff, yoff;
    455 {
    456 	volatile unsigned char *ba = gp->g_regkva;
    457 	const struct MonDef * md = (struct MonDef *) gp->g_data;
    458 	unsigned long off;
    459 
    460 	xpan = xoff;
    461 	ypan = yoff;
    462 
    463 
    464 	if (md->DEP > 8)
    465 		xoff *= 2;
    466 
    467 	vgar(ba, ACT_ADDRESS_RESET);
    468 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, (unsigned char)((xoff << 1) & 0x07));
    469 	/* have the color lookup function normally again */
    470 	vgaw(ba,  ACT_ADDRESS_W, 0x20);
    471 
    472 	if (md->DEP == 8)
    473 		off = ((yoff * md->TX)/ 4) + (xoff >> 2);
    474 	else
    475 		off = ((yoff * md->TX * 2)/ 4) + (xoff >> 2);
    476 
    477 	WCrt(ba, CRT_ID_START_ADDR_LOW, ((unsigned char)off));
    478 
    479 	off >>= 8;
    480 
    481 	WCrt(ba, CRT_ID_START_ADDR_HIGH, ((unsigned char)off));
    482 
    483 	off >>= 8;
    484 
    485 	WCrt(ba, CRT_ID_EXT_START_ADDR,
    486 	    ((RCrt(ba, CRT_ID_EXT_START_ADDR) & 0xf0) | (off & 0x0f)));
    487 
    488 
    489 }
    490 
    491 void
    492 RZ3SetHWCloc (gp, x, y)
    493 	struct grf_softc *gp;
    494 	unsigned short x, y;
    495 {
    496 	volatile unsigned char *ba = gp->g_regkva;
    497 	const struct MonDef *md = (struct MonDef *) gp->g_data;
    498 	volatile unsigned char *acm = ba + ACM_OFFSET;
    499 
    500 	if (x < xpan)
    501 		RZ3SetPanning(gp, x, ypan);
    502 
    503 	if (x >= (xpan+md->MW))
    504 		RZ3SetPanning(gp, (1 + x - md->MW) , ypan);
    505 
    506 	if (y < ypan)
    507 		RZ3SetPanning(gp, xpan, y);
    508 
    509 	if (y >= (ypan+md->MH))
    510 		RZ3SetPanning(gp, xpan, (1 + y - md->MH));
    511 
    512 	x -= xpan;
    513 	y -= ypan;
    514 
    515 	*(acm + (ACM_CURSOR_POSITION+0)) = x & 0xff;
    516 	*(acm + (ACM_CURSOR_POSITION+1)) = x >> 8;
    517 	*(acm + (ACM_CURSOR_POSITION+2)) = y & 0xff;
    518 	*(acm + (ACM_CURSOR_POSITION+3)) = y >> 8;
    519 }
    520 
    521 u_short
    522 CompFQ(fq)
    523 	u_int fq;
    524 {
    525  	/* yuck... this sure could need some explanation.. */
    526 
    527 	unsigned long f = fq;
    528 	long n2 = 3;
    529 	long abw = 0x7fffffff;
    530 	long n1 = 3;
    531 	unsigned long m;
    532 	unsigned short erg = 0;
    533 
    534 	f *= 8;
    535 
    536 	do {
    537 
    538 		if (f <= 250000000)
    539 			break;
    540 		f /= 2;
    541 
    542 	} while (n2-- > 0);
    543 
    544 	if (n2 < 0)
    545 		return(0);
    546 
    547 
    548 	do {
    549 	  	long tmp;
    550 
    551 		f = fq;
    552 		f >>= 3;
    553 		f <<= n2;
    554 		f >>= 7;
    555 
    556 		m = (f * n1) / (14318180/1024);
    557 
    558 		if (m > 129)
    559 			break;
    560 
    561 		tmp =  (((m * 14318180) >> n2) / n1) - fq;
    562 		if (tmp < 0)
    563 			tmp = -tmp;
    564 
    565 		if (tmp < abw) {
    566 			abw = tmp;
    567 			erg = (((n2 << 5) | (n1-2)) << 8) | (m-2);
    568 		}
    569 
    570 	} while ( (++n1) <= 21);
    571 
    572 	return(erg);
    573 }
    574 
    575 int
    576 rh_mondefok(mdp)
    577 	struct MonDef *mdp;
    578 {
    579 	switch(mdp->DEP) {
    580 	case 8:
    581 	case 16:
    582 		return(1);
    583 	case 4:
    584 		if (mdp->FX == 4 || (mdp->FX >= 7 && mdp->FX <= 16))
    585 			return(0);
    586 		/*FALLTHROUGH*/
    587 	default:
    588 		return(0);
    589 	}
    590 }
    591 
    592 
    593 int
    594 rh_load_mon(gp, md)
    595 	struct grf_softc *gp;
    596 	struct MonDef *md;
    597 {
    598 	struct grfinfo *gi = &gp->g_display;
    599 	volatile unsigned char *ba;
    600 	volatile unsigned char *fb;
    601 	short FW, clksel, HDE, VDE;
    602 	unsigned short *c, z;
    603 	const unsigned char *f;
    604 
    605 	ba = gp->g_regkva;;
    606 	fb = gp->g_fbkva;
    607 
    608 	/* provide all needed information in grf device-independant
    609 	 * locations */
    610 	gp->g_data 		= (caddr_t) md;
    611 	gi->gd_regaddr	 	= (caddr_t) kvtop (ba);
    612 	gi->gd_regsize		= LM_OFFSET;
    613 	gi->gd_fbaddr		= (caddr_t) kvtop (fb);
    614 	gi->gd_fbsize		= MEMSIZE *1024*1024;
    615 #ifdef BANKEDDEVPAGER
    616 	/* we're not using banks NO MORE! */
    617 	gi->gd_bank_size	= 0;
    618 #endif
    619 	gi->gd_colors		= 1 << md->DEP;
    620 	gi->gd_planes		= md->DEP;
    621 
    622 	if (md->DEP == 4) {
    623 		gi->gd_fbwidth	= md->MW;
    624 		gi->gd_fbheight	= md->MH;
    625 		gi->gd_fbx	= 0;
    626 		gi->gd_fby	= 0;
    627 		gi->gd_dwidth	= md->TX * md->FX;
    628 		gi->gd_dheight	= md->TY * md->FY;
    629 		gi->gd_dx	= 0;
    630 		gi->gd_dy	= 0;
    631 	} else {
    632 		gi->gd_fbwidth	= md->TX;
    633 		gi->gd_fbheight	= md->TY;
    634 		gi->gd_fbx	= 0;
    635 		gi->gd_fby	= 0;
    636 		gi->gd_dwidth	= md->MW;
    637 		gi->gd_dheight	= md->MH;
    638 		gi->gd_dx	= 0;
    639 		gi->gd_dy	= 0;
    640 	}
    641 
    642 	FW =0;
    643 	if (md->DEP == 4) {		/* XXX some text-mode! */
    644 		switch (md->FX) {
    645 		case 4:
    646 			FW = 0;
    647 			break;
    648 		case 7:
    649 			FW = 1;
    650 			break;
    651 		case 8:
    652 			FW = 2;
    653 			break;
    654 		case 9:
    655 			FW = 3;
    656 			break;
    657 		case 10:
    658 			FW = 4;
    659 			break;
    660 		case 11:
    661 			FW = 5;
    662 			break;
    663 		case 12:
    664 			FW = 6;
    665 			break;
    666 		case 13:
    667 			FW = 7;
    668 			break;
    669 		case 14:
    670 			FW = 8;
    671 			break;
    672 		case 15:
    673 			FW = 9;
    674 			break;
    675 		case 16:
    676 			FW = 11;
    677 			break;
    678 		default:
    679 			return(0);
    680 			break;
    681 		}
    682 	}
    683 
    684 	if (md->DEP == 4)
    685 		HDE = (md->MW+md->FX-1)/md->FX;
    686 	else if (md->DEP == 8)
    687 		HDE = (md->MW+3)/4;
    688 	else if (md->DEP == 16)
    689 		HDE = (md->MW*2+3)/4;
    690 
    691 	VDE = md->MH-1;
    692 
    693 	clksel = 0;
    694 
    695 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
    696 	vgaw(ba, GREG_FEATURE_CONTROL_W, 0x00);
    697 
    698 	WSeq(ba, SEQ_ID_RESET, 0x00);
    699 	WSeq(ba, SEQ_ID_RESET, 0x03);
    700 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
    701 	WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
    702 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
    703 	WSeq(ba, SEQ_ID_MEMORY_MODE, 0x06);
    704 	WSeq(ba, SEQ_ID_RESET, 0x01);
    705 	WSeq(ba, SEQ_ID_RESET, 0x03);
    706 
    707 	WSeq(ba, SEQ_ID_EXTENDED_ENABLE, 0x05);
    708 	WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x00);
    709 	WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
    710 	WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
    711 	WSeq(ba, SEQ_ID_LINEAR_0, 0x4a);
    712 	WSeq(ba, SEQ_ID_LINEAR_1, 0x00);
    713 
    714 	WSeq(ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00);
    715 	WSeq(ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00);
    716 	WSeq(ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
    717 	WSeq(ba, SEQ_ID_EXT_CLOCK_MODE, 0x10 | (FW & 0x0f));
    718 	WSeq(ba, SEQ_ID_EXT_VIDEO_ADDR, 0x03);
    719 	if (md->DEP == 4) {
    720 	  	/* 8bit pixel, no gfx byte path */
    721 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
    722 	} else if (md->DEP == 8) {
    723 	  	/* 8bit pixel, gfx byte path */
    724 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01);
    725 	} else if (md->DEP == 16) {
    726 	  	/* 16bit pixel, gfx byte path */
    727 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x11);
    728 	}
    729 	WSeq(ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x04);
    730 	WSeq(ba, SEQ_ID_COLOR_EXP_WFG, 0x01);
    731 	WSeq(ba, SEQ_ID_COLOR_EXP_WBG, 0x00);
    732 	WSeq(ba, SEQ_ID_EXT_RW_CONTROL, 0x00);
    733 	WSeq(ba, SEQ_ID_MISC_FEATURE_SEL, (0x51 | (clksel & 8)));
    734 	WSeq(ba, SEQ_ID_COLOR_KEY_CNTL, 0x40);
    735 	WSeq(ba, SEQ_ID_COLOR_KEY_MATCH0, 0x00);
    736 	WSeq(ba, SEQ_ID_COLOR_KEY_MATCH1, 0x00);
    737 	WSeq(ba, SEQ_ID_COLOR_KEY_MATCH2, 0x00);
    738 	WSeq(ba, SEQ_ID_CRC_CONTROL, 0x00);
    739 	WSeq(ba, SEQ_ID_PERF_SELECT, 0x10);
    740 	WSeq(ba, SEQ_ID_ACM_APERTURE_1, 0x00);
    741 	WSeq(ba, SEQ_ID_ACM_APERTURE_2, 0x30);
    742 	WSeq(ba, SEQ_ID_ACM_APERTURE_3, 0x00);
    743 	WSeq(ba, SEQ_ID_MEMORY_MAP_CNTL, 0x07);
    744 
    745 	WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x20);
    746 	WCrt(ba, CRT_ID_HOR_TOTAL, md->HT    & 0xff);
    747 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1)   & 0xff);
    748 	WCrt(ba, CRT_ID_START_HOR_BLANK, md->HBS   & 0xff);
    749 	WCrt(ba, CRT_ID_END_HOR_BLANK, (md->HBE   & 0x1f) | 0x80);
    750 
    751 	WCrt(ba, CRT_ID_START_HOR_RETR, md->HSS   & 0xff);
    752 	WCrt(ba, CRT_ID_END_HOR_RETR,
    753 	    (md->HSE & 0x1f)   |
    754 	    ((md->HBE & 0x20)/ 0x20 * 0x80));
    755 	WCrt(ba, CRT_ID_VER_TOTAL,  (md->VT  & 0xff));
    756 	WCrt(ba, CRT_ID_OVERFLOW,
    757 	    ((md->VSS & 0x200) / 0x200 * 0x80) |
    758 	    ((VDE     & 0x200) / 0x200 * 0x40) |
    759 	    ((md->VT  & 0x200) / 0x200 * 0x20) |
    760 	    0x10                               |
    761 	    ((md->VBS & 0x100) / 0x100 * 8)    |
    762 	    ((md->VSS & 0x100) / 0x100 * 4)    |
    763 	    ((VDE     & 0x100) / 0x100 * 2)    |
    764 	    ((md->VT  & 0x100) / 0x100));
    765 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
    766 
    767 	if (md->DEP == 4) {
    768 		WCrt(ba, CRT_ID_MAX_SCAN_LINE,
    769 		    ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
    770 		    0x40 |
    771 		    ((md->VBS & 0x200)/0x200*0x20) |
    772 		    ((md->FY-1) & 0x1f));
    773 	} else {
    774 		WCrt(ba, CRT_ID_MAX_SCAN_LINE,
    775 		    ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
    776 		    0x40 |
    777 		    ((md->VBS & 0x200)/0x200*0x20) |
    778 		    (0 & 0x1f));
    779 	}
    780 
    781 	/* I prefer "_" cursor to "block" cursor.. */
    782 #if 1
    783 	WCrt(ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
    784 	WCrt(ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
    785 #else
    786 	WCrt(ba, CRT_ID_CURSOR_START, 0x00);
    787 	WCrt(ba, CRT_ID_CURSOR_END, md->FY & 0x1f);
    788 #endif
    789 
    790 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
    791 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
    792 
    793 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
    794 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
    795 
    796 	WCrt(ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
    797 	WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x80 | 0x20);
    798 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE  & 0xff);
    799 
    800 	if (md->DEP == 4)
    801 		WCrt(ba, CRT_ID_OFFSET, (HDE / 2) & 0xff);
    802 	else if (md->DEP == 8)
    803 		WCrt(ba, CRT_ID_OFFSET, (md->TX / 8) & 0xff);
    804 	else
    805 		WCrt(ba, CRT_ID_OFFSET, (md->TX / 4) & 0xff);
    806 
    807 	WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
    808 	WCrt(ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff);
    809 	WCrt(ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
    810 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
    811 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
    812 
    813 	WCrt(ba, CRT_ID_EXT_HOR_TIMING1,
    814 		    0 | 0x20                                    |
    815 		    ((md->FLG & MDF_LACE)  / MDF_LACE   * 0x10) |
    816 		    ((md->HT  & 0x100) / 0x100)                 |
    817 		    (((HDE-1) & 0x100) / 0x100 * 2)             |
    818 		    ((md->HBS & 0x100) / 0x100 * 4)             |
    819 		    ((md->HSS & 0x100) / 0x100 * 8));
    820 
    821 	if (md->DEP == 4)
    822 		WCrt(ba, CRT_ID_EXT_START_ADDR,
    823 		    (((HDE / 2) & 0x100)/0x100 * 16));
    824 	else if (md->DEP == 8)
    825 		WCrt(ba, CRT_ID_EXT_START_ADDR,
    826 		    (((md->TX / 8) & 0x100)/0x100 * 16));
    827 	else
    828 		WCrt(ba, CRT_ID_EXT_START_ADDR,
    829 		    (((md->TX / 4) & 0x100)/0x100 * 16));
    830 
    831 	WCrt(ba, CRT_ID_EXT_HOR_TIMING2,
    832 		    ((md->HT  & 0x200)/ 0x200)       |
    833 	            (((HDE-1) & 0x200)/ 0x200 * 2  ) |
    834 	            ((md->HBS & 0x200)/ 0x200 * 4  ) |
    835 	            ((md->HSS & 0x200)/ 0x200 * 8  ) |
    836 	            ((md->HBE & 0xc0) / 0x40  * 16 ) |
    837 	            ((md->HSE & 0x60) / 0x20  * 64));
    838 
    839 	WCrt(ba, CRT_ID_EXT_VER_TIMING,
    840 		    ((md->VSE & 0x10) / 0x10  * 0x80  ) |
    841 		    ((md->VBE & 0x300)/ 0x100 * 0x20  ) |
    842 		    0x10                                |
    843 		    ((md->VSS & 0x400)/ 0x400 * 8     ) |
    844 		    ((md->VBS & 0x400)/ 0x400 * 4     ) |
    845 		    ((VDE     & 0x400)/ 0x400 * 2     ) |
    846 		    ((md->VT & 0x400)/ 0x400));
    847 	WCrt(ba, CRT_ID_MONITOR_POWER, 0x00);
    848 
    849 	{
    850 		unsigned short tmp = CompFQ(md->FQ);
    851 		WPLL(ba, 2   , tmp);
    852 		tmp = CompFQ(MEMCLK);
    853 		WPLL(ba,10   , tmp);
    854 		WPLL(ba,14   , 0x22);
    855 	}
    856 
    857 	WGfx(ba, GCT_ID_SET_RESET, 0x00);
    858 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
    859 	WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
    860 	WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
    861 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
    862 	WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
    863 	if (md->DEP == 4)
    864 		WGfx(ba, GCT_ID_MISC, 0x04);
    865 	else
    866 		WGfx(ba, GCT_ID_MISC, 0x05);
    867 	WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
    868 	WGfx(ba, GCT_ID_BITMASK, 0xff);
    869 
    870 	vgar(ba, ACT_ADDRESS_RESET);
    871 	WAttr(ba, ACT_ID_PALETTE0 , 0x00);
    872 	WAttr(ba, ACT_ID_PALETTE1 , 0x01);
    873 	WAttr(ba, ACT_ID_PALETTE2 , 0x02);
    874 	WAttr(ba, ACT_ID_PALETTE3 , 0x03);
    875 	WAttr(ba, ACT_ID_PALETTE4 , 0x04);
    876 	WAttr(ba, ACT_ID_PALETTE5 , 0x05);
    877 	WAttr(ba, ACT_ID_PALETTE6 , 0x06);
    878 	WAttr(ba, ACT_ID_PALETTE7 , 0x07);
    879 	WAttr(ba, ACT_ID_PALETTE8 , 0x08);
    880 	WAttr(ba, ACT_ID_PALETTE9 , 0x09);
    881 	WAttr(ba, ACT_ID_PALETTE10, 0x0a);
    882 	WAttr(ba, ACT_ID_PALETTE11, 0x0b);
    883 	WAttr(ba, ACT_ID_PALETTE12, 0x0c);
    884 	WAttr(ba, ACT_ID_PALETTE13, 0x0d);
    885 	WAttr(ba, ACT_ID_PALETTE14, 0x0e);
    886 	WAttr(ba, ACT_ID_PALETTE15, 0x0f);
    887 
    888 	vgar(ba, ACT_ADDRESS_RESET);
    889 	if (md->DEP == 4)
    890 		WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
    891 	else
    892 		WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x09);
    893 
    894 	WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
    895 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
    896 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
    897 	WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
    898 
    899 	vgar(ba, ACT_ADDRESS_RESET);
    900 	vgaw(ba, ACT_ADDRESS_W, 0x20);
    901 
    902 	vgaw(ba, VDAC_MASK, 0xff);
    903 	if (md->DEP < 16)
    904 	  	/* well... probably the PLL chip */
    905 		vgaw(ba, 0x83c6, ((0 & 7) << 5));
    906 	else if (md->DEP == 16)
    907 	  	/* well... */
    908 		vgaw(ba, 0x83c6, ((3 & 7) << 5));
    909 	vgaw(ba, VDAC_ADDRESS_W, 0x00);
    910 
    911 	if (md->DEP < 16) {
    912 		short x = 256-17;
    913 		unsigned char cl = 16;
    914 		RZ3LoadPalette(gp, md->PAL, 0, 16);
    915 		do {
    916 			vgaw(ba, VDAC_DATA, (cl >> 2));
    917 			vgaw(ba, VDAC_DATA, (cl >> 2));
    918 			vgaw(ba, VDAC_DATA, (cl >> 2));
    919 			cl++;
    920 		} while (x-- > 0);
    921 	}
    922 
    923 	if (md->DEP == 4) {
    924 		{
    925 			struct grf_bitblt bb = {
    926 				GRFBBOPset,
    927 				0, 0,
    928 				0, 0,
    929 				md->TX*4, 2*md->TY,
    930 				EMPTY_ALPHA
    931 			};
    932 			RZ3BitBlit(gp, &bb);
    933 		}
    934 
    935 		c = (unsigned short *)(ba + LM_OFFSET);
    936 		c += 2 * md->FLo*32;
    937 		c += 1;
    938 		f = md->FData;
    939 		for (z = md->FLo; z <= md->FHi; z++) {
    940 			short y = md->FY-1;
    941 			if (md->FX > 8){
    942 				do {
    943 					*c = *((const unsigned short *)f);
    944 					c += 2;
    945 					f += 2;
    946 				} while (y-- > 0);
    947 			} else {
    948 				do {
    949 					*c = (*f++) << 8;
    950 					c += 2;
    951 				} while (y-- > 0);
    952 			}
    953 
    954 			c += 2 * (32-md->FY);
    955 		}
    956 		{
    957 			unsigned long * pt = (unsigned long *) (ba + LM_OFFSET + PAT_MEM_OFF);
    958 			unsigned long tmp  = 0xffff0000;
    959 			*pt++ = tmp;
    960 			*pt = tmp;
    961 		}
    962 
    963 		WSeq(ba, SEQ_ID_MAP_MASK, 3);
    964 
    965 		c = (unsigned short *)(ba + LM_OFFSET);
    966 		c += (md->TX-6)*2;
    967 		{
    968 		  	/* it's show-time :-) */
    969 			static unsigned short init_msg[6] = {
    970 				0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f
    971 			};
    972 			unsigned short * m = init_msg;
    973 			short x = 5;
    974 			do {
    975 				*c = *m++;
    976 				c += 2;
    977 			} while (x-- > 0);
    978 		}
    979 
    980 		return(1);
    981 	} else if (md->DEP == 8) {
    982 		struct grf_bitblt bb = {
    983 			GRFBBOPset,
    984 			0, 0,
    985 			0, 0,
    986 			md->TX, md->TY,
    987 			0x0000
    988 		};
    989 		WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
    990 
    991 		RZ3BitBlit(gp, &bb);
    992 
    993 		xpan = 0;
    994 		ypan = 0;
    995 
    996 		return(1);
    997 	} else if (md->DEP == 16) {
    998 		struct grf_bitblt bb = {
    999 			GRFBBOPset,
   1000 			0, 0,
   1001 			0, 0,
   1002 			md->TX, md->TY,
   1003 			0x0000
   1004 		};
   1005 		WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
   1006 
   1007 		RZ3BitBlit16(gp, &bb);
   1008 
   1009 		xpan = 0;
   1010 		ypan = 0;
   1011 
   1012 		return(1);
   1013 	} else
   1014 		return(0);
   1015 }
   1016 
   1017 /* standard-palette definition */
   1018 
   1019 unsigned char RZ3StdPalette[16*3] = {
   1020 /*        R   G   B  */
   1021 	  0,  0,  0,
   1022 	192,192,192,
   1023 	128,  0,  0,
   1024 	  0,128,  0,
   1025 	  0,  0,128,
   1026 	128,128,  0,
   1027 	  0,128,128,
   1028 	128,  0,128,
   1029 	 64, 64, 64, /* the higher 8 colors have more intensity for  */
   1030 	255,255,255, /* compatibility with standard attributes       */
   1031 	255,  0,  0,
   1032 	  0,255,  0,
   1033 	  0,  0,255,
   1034 	255,255,  0,
   1035 	  0,255,255,
   1036 	255,  0,255
   1037 };
   1038 
   1039 /*
   1040  * The following structures are examples for monitor-definitions. To make one
   1041  * of your own, first use "DefineMonitor" and create the 8-bit or 16-bit
   1042  * monitor-mode of your dreams. Then save it, and make a structure from the
   1043  * values provided in the file DefineMonitor stored - the labels in the comment
   1044  * above the structure definition show where to put what value.
   1045  *
   1046  * If you want to use your definition for the text-mode, you'll need to adapt
   1047  * your 8-bit monitor-definition to the font you want to use. Be FX the width of
   1048  * the font, then the following modifications have to be applied to your values:
   1049  *
   1050  * HBS = (HBS * 4) / FX
   1051  * HSS = (HSS * 4) / FX
   1052  * HSE = (HSE * 4) / FX
   1053  * HBE = (HBE * 4) / FX
   1054  * HT  = (HT  * 4) / FX
   1055  *
   1056  * Make sure your maximum width (MW) and height (MH) are even multiples of
   1057  * the fonts' width and height.
   1058  *
   1059  * You may use definitons created by the old DefineMonitor, but you'll get
   1060  * better results with the new DefineMonitor supplied along with the Retin Z3.
   1061 */
   1062 
   1063 /*
   1064  *  FQ     FLG    MW   MH   HBS HSS HSE HBE  HT  VBS  VSS  VSE  VBE   VT
   1065  * Depth,          PAL, TX,  TY,    XY,FontX, FontY,    FontData,  FLo,  Fhi
   1066  */
   1067 static struct MonDef monitor_defs[] = {
   1068   /* Text-mode definitions */
   1069 
   1070   /* horizontal 31.5 kHz */
   1071   { 50000000,  28,  640, 512,   81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
   1072       4, RZ3StdPalette, 80,  64,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1073 #if 0
   1074   /* horizontal 31.62 KHz (1950) */
   1075   { 32000000,  0,  800, 600,  201,202,218,249,248, 601, 602, 612, 628, 628,
   1076       8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1077 #endif
   1078 
   1079   /* horizontal 38kHz */
   1080   { 75000000,  28,  768, 600,   97, 99,107,120,117, 601, 615, 625, 638, 638,
   1081       4, RZ3StdPalette, 96,  75,  7200,    8,     8, kernel_font_8x8,   32,  255},
   1082 
   1083   /* horizontal 64kHz */
   1084   { 50000000, 24,  768, 600,   97,104,112,122,119, 601, 606, 616, 628, 628,
   1085       4, RZ3StdPalette, 96,  75,  7200,    8,     8, kernel_font_8x8,   32,  255},
   1086 
   1087   /* 8-bit gfx-mode definitions */
   1088 
   1089   /*
   1090    * IMPORTANT: the "logical" screen size can be up to 2048x2048 pixels,
   1091    * independent from the "physical" screen size. If your code does NOT
   1092    * support panning, please adjust the "logical" screen sizes below to
   1093    * match the physical ones
   1094    */
   1095 
   1096   /* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */
   1097   { 26000000,  0,  640, 480,  161,175,188,200,199, 481, 483, 491, 502, 502,
   1098       8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1099   /* This is the logical ^    ^    screen size */
   1100 
   1101   /* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */
   1102  { 31000000,  0,  640, 480,  161,169,182,198,197, 481, 482, 490, 502, 502,
   1103      8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1104 
   1105   /* 800 x 600, 8 Bit, 31620 Hz, 50 Hz (1950) */
   1106   { 32000000,  0,  800, 600,  201,202,218,249,248, 601, 602, 612, 628, 628,
   1107       8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1108   /* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */
   1109   { 39000000,  0,  800, 600,  201,211,227,249,248, 601, 603, 613, 628, 628,
   1110       8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1111 
   1112   /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
   1113   { 82000000,  0, 1024, 768,  257,257,277,317,316, 769, 771, 784, 804, 804,
   1114       8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1115 
   1116   /* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */
   1117   { 97000000,  0, 1120, 896,  281,283,306,369,368, 897, 898, 913, 938, 938,
   1118       8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1119 
   1120   /* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */
   1121   {110000000,  0, 1152, 910,  289,310,333,357,356, 911, 923, 938, 953, 953,
   1122       8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1123 
   1124   /* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */
   1125   {110000000,  0, 1184, 848,  297,319,342,370,369, 849, 852, 866, 888, 888,
   1126       8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1127 
   1128   /* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */
   1129   {104000000, 0, 1280,1024,  321,323,348,399,398,1025,1026,1043,1073,1073,
   1130      8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1131 
   1132 /* WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
   1133             HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
   1134             MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!     */
   1135   /* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */
   1136   {121000000, 0, 1280,1024,  321,322,347,397,396,1025,1026,1043,1073,1073,
   1137      8, RZ3StdPalette,1280,1024,  5120,    8,     8, kernel_font_8x8,   32,  255},
   1138 
   1139 
   1140   /* 16-bit gfx-mode definitions */
   1141 
   1142   /* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */
   1143   { 51000000, 0,  640, 480,  321,344,369,397,396, 481, 482, 490, 502, 502,
   1144       16,           0,1280, 1024,  7200,    8,     8, kernel_font_8x8,   32,  255},
   1145 
   1146   /* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */
   1147   { 77000000, 0,  800, 600,  401,418,449,496,495, 601, 602, 612, 628, 628,
   1148       16,           0,1280, 1024,  7200,    8,     8, kernel_font_8x8,   32,  255},
   1149 
   1150   /* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */
   1151   {110000000,  0, 1024, 768,  513,514,554,639,638, 769, 770, 783, 804, 804,
   1152       16,           0,1280, 1024,  7200,    8,     8, kernel_font_8x8,   32,  255},
   1153 
   1154   /* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */
   1155   {109000000,  0,  864, 648,  433,434,468,537,536, 649, 650, 661, 678, 678,
   1156       16,           0,1280, 1024,  7200,    8,     8, kernel_font_8x8,   32,  255},
   1157 
   1158 /*
   1159  * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
   1160  *          HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
   1161  *          MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
   1162  */
   1163   /* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */
   1164   {124000000,  0, 1024, 768,  513,537,577,636,635, 769, 770, 783, 804, 804,
   1165       16,           0,1280, 1024,  7200,    8,     8, kernel_font_8x8,   32,  255},
   1166 };
   1167 
   1168 static const char *monitor_descr[] = {
   1169   "80x64 (640x512) 31.5kHz",
   1170   "96x75 (768x600) 38kHz",
   1171   "96x75 (768x600) 64kHz",
   1172 
   1173   "GFX-8 (640x480) 31.5kHz",
   1174   "GFX-8 (640x480) 38kHz",
   1175   "GFX-8 (800x600) 31.6kHz",
   1176   "GFX-8 (800x600) 38.5kHz",
   1177   "GFX-8 (1024x768) 64kHz",
   1178   "GFX-8 (1120x896) 64kHz",
   1179   "GFX-8 (1152x910) 76kHz",
   1180   "GFX-8 (1182x848) 73kHz",
   1181   "GFX-8 (1280x1024) 64.5kHz",
   1182   "GFX-8 (1280x1024) 75.5kHz ***EXCEEDS CHIP LIMIT!!!***",
   1183 
   1184   "GFX-16 (640x480) 31.8kHz",
   1185   "GFX-16 (800x600) 38.5kHz",
   1186   "GFX-16 (1024x768) 42.8kHz",
   1187   "GFX-16 (864x648) 50kHz",
   1188   "GFX-16 (1024x768) 48.5kHz ***EXCEEDS CHIP LIMIT!!!***",
   1189 };
   1190 
   1191 int rh_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
   1192 
   1193 /* patchable */
   1194 int rh_default_mon = 0;
   1195 int rh_default_gfx = 4;
   1196 
   1197 static struct MonDef *current_mon;
   1198 
   1199 int  rh_mode     __P((struct grf_softc *, int, void *, int, int));
   1200 void grfrhattach __P((struct device *, struct device *, void *));
   1201 int  grfrhprint  __P((void *, char *));
   1202 int  grfrhmatch  __P((struct device *, struct cfdata *, void *));
   1203 
   1204 struct cfdriver grfrhcd = {
   1205 	NULL, "grfrh", grfrhmatch, grfrhattach,
   1206 	DV_DULL, sizeof(struct grf_softc), NULL, 0
   1207 };
   1208 
   1209 static struct cfdata *cfdata;
   1210 
   1211 int
   1212 grfrhmatch(pdp, cfp, auxp)
   1213 	struct device *pdp;
   1214 	struct cfdata *cfp;
   1215 	void *auxp;
   1216 {
   1217 #ifdef RETINACONSOLE
   1218 	static int rhconunit = -1;
   1219 #endif
   1220 	struct zthreebus_args *zap;
   1221 
   1222 	zap = auxp;
   1223 
   1224 	if (amiga_realconfig == 0)
   1225 #ifdef RETINACONSOLE
   1226 		if (rhconunit != -1)
   1227 #endif
   1228 			return(0);
   1229 	if (zap->manid != 18260 || zap->prodid != 16)
   1230 		return(0);
   1231 #ifdef RETINACONSOLE
   1232 	if (amiga_realconfig == 0 || rhconunit != cfp->cf_unit) {
   1233 #endif
   1234 		if ((unsigned)rh_default_mon >= rh_mon_max ||
   1235 		    monitor_defs[rh_default_mon].DEP == 8)
   1236 			rh_default_mon = 0;
   1237 		current_mon = monitor_defs + rh_default_mon;
   1238 		if (rh_mondefok(current_mon) == 0)
   1239 			return(0);
   1240 #ifdef RETINACONSOLE
   1241 		if (amiga_realconfig == 0) {
   1242 			rhconunit = cfp->cf_unit;
   1243 			cfdata = cfp;
   1244 		}
   1245 	}
   1246 #endif
   1247 	return(1);
   1248 }
   1249 
   1250 void
   1251 grfrhattach(pdp, dp, auxp)
   1252 	struct device *pdp, *dp;
   1253 	void *auxp;
   1254 {
   1255 	static struct grf_softc congrf;
   1256 	static int coninited;
   1257 	struct zthreebus_args *zap;
   1258 	struct grf_softc *gp;
   1259 
   1260 	zap = auxp;
   1261 
   1262 	if (dp == NULL)
   1263 		gp = &congrf;
   1264 	else
   1265 		gp = (struct grf_softc *)dp;
   1266 	if (dp != NULL && congrf.g_regkva != 0) {
   1267 		/*
   1268 		 * inited earlier, just copy (not device struct)
   1269 		 */
   1270 		bcopy(&congrf.g_display, &gp->g_display,
   1271 		    (char *)&gp[1] - (char *)&gp->g_display);
   1272 	} else {
   1273 		gp->g_regkva = (volatile caddr_t)zap->va;
   1274 		gp->g_fbkva = (volatile caddr_t)zap->va + LM_OFFSET;
   1275 		gp->g_unit = GRF_RETINAIII_UNIT;
   1276 		gp->g_mode = rh_mode;
   1277 		gp->g_conpri = grfrh_cnprobe();
   1278 		gp->g_flags = GF_ALIVE;
   1279 		grfrh_iteinit(gp);
   1280 		(void)rh_load_mon(gp, current_mon);
   1281 	}
   1282 	if (dp != NULL)
   1283 		printf("\n");
   1284 	/*
   1285 	 * attach grf
   1286 	 */
   1287 	amiga_config_found(cfdata, &gp->g_device, gp, grfrhprint);
   1288 }
   1289 
   1290 int
   1291 grfrhprint(auxp, pnp)
   1292 	void *auxp;
   1293 	char *pnp;
   1294 {
   1295 	if (pnp)
   1296 		printf("ite at %s", pnp);
   1297 	return(UNCONF);
   1298 }
   1299 
   1300 int
   1301 rh_getvmode(gp, vm)
   1302 	struct grf_softc *gp;
   1303 	struct grfvideo_mode *vm;
   1304 {
   1305 	struct MonDef *md;
   1306 
   1307 	if (vm->mode_num && vm->mode_num > rh_mon_max)
   1308 		return(EINVAL);
   1309 
   1310 	if (! vm->mode_num)
   1311 		vm->mode_num = (current_mon - monitor_defs) + 1;
   1312 
   1313 	md = monitor_defs + (vm->mode_num - 1);
   1314 	strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
   1315 	   sizeof (vm->mode_descr));
   1316 	vm->pixel_clock  = md->FQ;
   1317 	vm->disp_width   = md->MW;
   1318 	vm->disp_height  = md->MH;
   1319 	vm->depth        = md->DEP;
   1320 	vm->hblank_start = md->HBS;
   1321 	vm->hblank_stop  = md->HBE;
   1322 	vm->hsync_start  = md->HSS;
   1323 	vm->hsync_stop   = md->HSE;
   1324 	vm->htotal       = md->HT;
   1325 	vm->vblank_start = md->VBS;
   1326 	vm->vblank_stop  = md->VBE;
   1327 	vm->vsync_start  = md->VSS;
   1328 	vm->vsync_stop   = md->VSE;
   1329 	vm->vtotal       = md->VT;
   1330 
   1331 	return(0);
   1332 }
   1333 
   1334 
   1335 int
   1336 rh_setvmode(gp, mode, txtonly)
   1337 	struct grf_softc *gp;
   1338 	unsigned mode;
   1339 	int txtonly;
   1340 {
   1341 	struct MonDef *md;
   1342 	int error;
   1343 
   1344 	if (!mode || mode > rh_mon_max)
   1345 		return(EINVAL);
   1346 
   1347 	if (txtonly && monitor_defs[mode-1].DEP != 4)
   1348 		return(EINVAL);
   1349 
   1350 	current_mon = monitor_defs + (mode - 1);
   1351 
   1352 	error = rh_load_mon (gp, current_mon) ? 0 : EINVAL;
   1353 
   1354 	return(error);
   1355 }
   1356 
   1357 
   1358 /*
   1359  * Change the mode of the display.
   1360  * Return a UNIX error number or 0 for success.
   1361  */
   1362 rh_mode(gp, cmd, arg, a2, a3)
   1363 	register struct grf_softc *gp;
   1364 	int cmd;
   1365 	void *arg;
   1366 	int a2, a3;
   1367 {
   1368   /* implement these later... */
   1369 
   1370 	switch (cmd) {
   1371 	case GM_GRFON:
   1372 		rh_setvmode (gp, rh_default_gfx + 1, 0);
   1373 		return(0);
   1374 
   1375 	case GM_GRFOFF:
   1376 		rh_setvmode (gp, rh_default_mon + 1, 0);
   1377 		return(0);
   1378 
   1379 	case GM_GRFCONFIG:
   1380 		return(0);
   1381 
   1382 	case GM_GRFGETVMODE:
   1383 		return(rh_getvmode (gp, (struct grfvideo_mode *) arg));
   1384 
   1385 	case GM_GRFSETVMODE:
   1386 		return(rh_setvmode (gp, *(unsigned *) arg, 1));
   1387 
   1388 	case GM_GRFGETNUMVM:
   1389 		*(int *)arg = rh_mon_max;
   1390 		return(0);
   1391 
   1392 #ifdef BANKEDDEVPAGER
   1393 	case GM_GRFGETBANK:
   1394 	case GM_GRFGETCURBANK:
   1395 	case GM_GRFSETBANK:
   1396 		return(EINVAL);
   1397 #endif
   1398 	case GM_GRFIOCTL:
   1399 		return(rh_ioctl (gp, (int) arg, (caddr_t) a2));
   1400 
   1401 	default:
   1402 		break;
   1403 	}
   1404 
   1405 	return(EINVAL);
   1406 }
   1407 
   1408 int
   1409 rh_ioctl (gp, cmd, data)
   1410 	register struct grf_softc *gp;
   1411 	int cmd;
   1412 	void *data;
   1413 {
   1414 	switch (cmd) {
   1415 	case GRFIOCGSPRITEPOS:
   1416 		return(rh_getspritepos (gp, (struct grf_position *) data));
   1417 
   1418 	case GRFIOCSSPRITEPOS:
   1419 		return(rh_setspritepos (gp, (struct grf_position *) data));
   1420 
   1421 	case GRFIOCSSPRITEINF:
   1422 		return(rh_setspriteinfo (gp, (struct grf_spriteinfo *) data));
   1423 
   1424 	case GRFIOCGSPRITEINF:
   1425 		return(rh_getspriteinfo (gp, (struct grf_spriteinfo *) data));
   1426 
   1427 	case GRFIOCGSPRITEMAX:
   1428 		return(rh_getspritemax (gp, (struct grf_position *) data));
   1429 
   1430 	case GRFIOCGETCMAP:
   1431 		return(rh_getcmap (gp, (struct grf_colormap *) data));
   1432 
   1433 	case GRFIOCPUTCMAP:
   1434 		return(rh_putcmap (gp, (struct grf_colormap *) data));
   1435 
   1436 	case GRFIOCBITBLT:
   1437 		return(rh_bitblt (gp, (struct grf_bitblt *) data));
   1438 	}
   1439 
   1440 	return(EINVAL);
   1441 }
   1442 
   1443 
   1444 int
   1445 rh_getcmap (gfp, cmap)
   1446 	struct grf_softc *gfp;
   1447 	struct grf_colormap *cmap;
   1448 {
   1449 	volatile unsigned char *ba;
   1450 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1451 	short x;
   1452 	int error;
   1453 
   1454 	if (cmap->count == 0 || cmap->index >= 256)
   1455 		return 0;
   1456 
   1457 	if (cmap->index + cmap->count > 256)
   1458 		cmap->count = 256 - cmap->index;
   1459 
   1460 	ba = gfp->g_regkva;
   1461 	/* first read colors out of the chip, then copyout to userspace */
   1462 	vgaw (ba, VDAC_ADDRESS_W, cmap->index);
   1463 	x = cmap->count - 1;
   1464 	rp = red + cmap->index;
   1465 	gp = green + cmap->index;
   1466 	bp = blue + cmap->index;
   1467 	do {
   1468 		*rp++ = vgar (ba, VDAC_DATA) << 2;
   1469 		*gp++ = vgar (ba, VDAC_DATA) << 2;
   1470 		*bp++ = vgar (ba, VDAC_DATA) << 2;
   1471 	} while (x-- > 0);
   1472 
   1473 	if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
   1474 	    && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
   1475 	    && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
   1476 		return(0);
   1477 
   1478 	return(error);
   1479 }
   1480 
   1481 int
   1482 rh_putcmap (gfp, cmap)
   1483 	struct grf_softc *gfp;
   1484 	struct grf_colormap *cmap;
   1485 {
   1486 	volatile unsigned char *ba;
   1487 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1488 	short x;
   1489 	int error;
   1490 
   1491 	if (cmap->count == 0 || cmap->index >= 256)
   1492 		return(0);
   1493 
   1494 	if (cmap->index + cmap->count > 256)
   1495 		cmap->count = 256 - cmap->index;
   1496 
   1497 	/* first copy the colors into kernelspace */
   1498 	if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
   1499 	    && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
   1500 	    && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
   1501 		/* argl.. LoadPalette wants a different format, so do it like with
   1502 		* Retina2.. */
   1503 		ba = gfp->g_regkva;
   1504 		vgaw (ba, VDAC_ADDRESS_W, cmap->index);
   1505 		x = cmap->count - 1;
   1506 		rp = red + cmap->index;
   1507 		gp = green + cmap->index;
   1508 		bp = blue + cmap->index;
   1509 		do {
   1510 			vgaw (ba, VDAC_DATA, *rp++ >> 2);
   1511 			vgaw (ba, VDAC_DATA, *gp++ >> 2);
   1512 			vgaw (ba, VDAC_DATA, *bp++ >> 2);
   1513 		} while (x-- > 0);
   1514 		return(0);
   1515 	}
   1516 	else
   1517 		return(error);
   1518 }
   1519 
   1520 int
   1521 rh_getspritepos (gp, pos)
   1522 	struct grf_softc *gp;
   1523 	struct grf_position *pos;
   1524 {
   1525 	volatile unsigned char *acm = gp->g_regkva + ACM_OFFSET;
   1526 
   1527 	pos->x = acm[ACM_CURSOR_POSITION + 0] +
   1528 	    (acm[ACM_CURSOR_POSITION + 1] << 8);
   1529 	pos->y = acm[ACM_CURSOR_POSITION + 2] +
   1530 	    (acm[ACM_CURSOR_POSITION + 3] << 8);
   1531 
   1532 	pos->x += xpan;
   1533 	pos->y += ypan;
   1534 
   1535 	return(0);
   1536 }
   1537 
   1538 int
   1539 rh_setspritepos (gp, pos)
   1540 	struct grf_softc *gp;
   1541 	struct grf_position *pos;
   1542 {
   1543 	RZ3SetHWCloc (gp, pos->x, pos->y);
   1544 	return(0);
   1545 }
   1546 
   1547 int
   1548 rh_getspriteinfo (gp, info)
   1549 	struct grf_softc *gp;
   1550 	struct grf_spriteinfo *info;
   1551 {
   1552 	volatile unsigned char *ba, *fb;
   1553 
   1554 	ba = gp->g_regkva;
   1555 	fb = gp->g_fbkva;
   1556 	if (info->set & GRFSPRSET_ENABLE)
   1557 		info->enable = RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
   1558 	if (info->set & GRFSPRSET_POS)
   1559 		rh_getspritepos (gp, &info->pos);
   1560 	if (info->set & GRFSPRSET_HOT) {
   1561 		info->hot.x = RSeq (ba, SEQ_ID_CURSOR_X_INDEX) & 0x3f;
   1562 		info->hot.y = RSeq (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
   1563 	}
   1564 	if (info->set & GRFSPRSET_CMAP) {
   1565 		struct grf_colormap cmap;
   1566 		int index;
   1567 		cmap.index = 0;
   1568 		cmap.count = 256;
   1569 		rh_getcmap (gp, &cmap);
   1570 		index = RSeq (ba, SEQ_ID_CURSOR_COLOR0);
   1571 		info->cmap.red[0] = cmap.red[index];
   1572 		info->cmap.green[0] = cmap.green[index];
   1573 		info->cmap.blue[0] = cmap.blue[index];
   1574 		index = RSeq (ba, SEQ_ID_CURSOR_COLOR1);
   1575 		info->cmap.red[1] = cmap.red[index];
   1576 		info->cmap.green[1] = cmap.green[index];
   1577 		info->cmap.blue[1] = cmap.blue[index];
   1578 	}
   1579 	if (info->set & GRFSPRSET_SHAPE) {
   1580 		u_char image[128], mask[128];
   1581 		volatile u_long *hwp;
   1582 		u_char *imp, *mp;
   1583 		short row;
   1584 
   1585 		/* sprite bitmap is WEIRD in this chip.. see grf_rhvar.h
   1586 		 * for an explanation. To convert to "our" format, the
   1587 		 * following holds:
   1588 		 *   col2   = !image & mask
   1589 		 *   col1   = image & mask
   1590 		 *   transp = !mask
   1591 		 * and thus:
   1592 		 *   image  = col1
   1593 		 *   mask   = col1 | col2
   1594 		 * hope I got these bool-eqs right below..
   1595 		 */
   1596 
   1597 		info->size.x = 64;
   1598 		info->size.y = 64;
   1599 		for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
   1600 		    mp = mask, imp = image;
   1601 		    row < 64;
   1602 		    row++) {
   1603 			u_long bp10, bp20, bp11, bp21;
   1604 			bp10 = *hwp++;
   1605 			bp20 = *hwp++;
   1606 			bp11 = *hwp++;
   1607 			bp21 = *hwp++;
   1608 			M2I (bp10);
   1609 			M2I (bp20);
   1610 			M2I (bp11);
   1611 			M2I (bp21);
   1612 			*imp++ = (~bp10) & bp11;
   1613 			*imp++ = (~bp20) & bp21;
   1614 			*mp++  = (~bp10) | (bp10 & ~bp11);
   1615 			*mp++  = (~bp20) & (bp20 & ~bp21);
   1616 		}
   1617 		copyout (image, info->image, sizeof (image));
   1618 		copyout (mask, info->mask, sizeof (mask));
   1619 	}
   1620 	return(0);
   1621 }
   1622 
   1623 int
   1624 rh_setspriteinfo (gp, info)
   1625 	struct grf_softc *gp;
   1626 	struct grf_spriteinfo *info;
   1627 {
   1628 	volatile unsigned char *ba, *fb;
   1629 	u_char control;
   1630 
   1631 	ba = gp->g_regkva;
   1632 	fb = gp->g_fbkva;
   1633 
   1634 	if (info->set & GRFSPRSET_SHAPE) {
   1635 		/*
   1636 		 * For an explanation of these weird actions here, see above
   1637 		 * when reading the shape.  We set the shape directly into
   1638 		 * the video memory, there's no reason to keep 1k on the
   1639 		 * kernel stack just as template
   1640 		 */
   1641 		u_char *image, *mask;
   1642 		volatile u_long *hwp;
   1643 		u_char *imp, *mp;
   1644 		short row;
   1645 
   1646 		if (info->size.y > 64)
   1647 			info->size.y = 64;
   1648 		if (info->size.x > 64)
   1649 			info->size.x = 64;
   1650 
   1651 		if (info->size.x < 32)
   1652 			info->size.x = 32;
   1653 
   1654 		image = malloc(HWC_MEM_SIZE, M_TEMP, M_WAITOK);
   1655 		mask  = image + HWC_MEM_SIZE/2;
   1656 
   1657 		copyin(info->image, image, info->size.y * info->size.x / 8);
   1658 		copyin(info->mask, mask, info->size.y * info->size.x / 8);
   1659 
   1660 		hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF);
   1661 
   1662 		/*
   1663 		 * setting it is slightly more difficult, because we can't
   1664 		 * force the application to not pass a *smaller* than
   1665 		 * supported bitmap
   1666 		 */
   1667 
   1668 		for (row = 0, mp = mask, imp = image;
   1669 		    row < info->size.y;
   1670 		    row++) {
   1671 			u_long im1, im2, m1, m2;
   1672 
   1673 			im1 = *(unsigned long *)imp;
   1674 			imp += 4;
   1675 			m1  = *(unsigned long *)mp;
   1676 			mp  += 4;
   1677 			if (info->size.x > 32) {
   1678 	      			im2 = *(unsigned long *)imp;
   1679 				imp += 4;
   1680 				m2  = *(unsigned long *)mp;
   1681 				mp  += 4;
   1682 			}
   1683 			else
   1684 				im2 = m2 = 0;
   1685 
   1686 			M2I(im1);
   1687 			M2I(im2);
   1688 			M2I(m1);
   1689 			M2I(m2);
   1690 
   1691 			*hwp++ = ~m1;
   1692 			*hwp++ = ~m2;
   1693 			*hwp++ = m1 & im1;
   1694 			*hwp++ = m2 & im2;
   1695 		}
   1696 		for (; row < 64; row++) {
   1697 			*hwp++ = 0xffffffff;
   1698 			*hwp++ = 0xffffffff;
   1699 			*hwp++ = 0x00000000;
   1700 			*hwp++ = 0x00000000;
   1701 		}
   1702 
   1703 		free(image, M_TEMP);
   1704 		RZ3SetupHWC(gp, 1, 0, 0, 0, 0);
   1705 	}
   1706 	if (info->set & GRFSPRSET_CMAP) {
   1707 		/* hey cheat a bit here.. XXX */
   1708 		WSeq(ba, SEQ_ID_CURSOR_COLOR0, 0);
   1709 		WSeq(ba, SEQ_ID_CURSOR_COLOR1, 1);
   1710 	}
   1711 	if (info->set & GRFSPRSET_ENABLE) {
   1712 		if (info->enable)
   1713 			control = 0x85;
   1714 		else
   1715 			control = 0;
   1716 		WSeq(ba, SEQ_ID_CURSOR_CONTROL, control);
   1717 	}
   1718 	if (info->set & GRFSPRSET_POS)
   1719 		rh_setspritepos(gp, &info->pos);
   1720 	if (info->set & GRFSPRSET_HOT) {
   1721 		WSeq(ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x3f);
   1722 		WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
   1723 	}
   1724 
   1725 	return(0);
   1726 }
   1727 
   1728 int
   1729 rh_getspritemax (gp, pos)
   1730 	struct grf_softc *gp;
   1731 	struct grf_position *pos;
   1732 {
   1733 	pos->x = 64;
   1734 	pos->y = 64;
   1735 
   1736 	return(0);
   1737 }
   1738 
   1739 
   1740 int
   1741 rh_bitblt (gp, bb)
   1742 	struct grf_softc *gp;
   1743 	struct grf_bitblt *bb;
   1744 {
   1745 	struct MonDef *md = (struct MonDef *)gp->g_data;
   1746 	if (md->DEP < 16)
   1747 		RZ3BitBlit(gp, bb);
   1748 	else
   1749 		RZ3BitBlit16(gp, bb);
   1750 }
   1751 #endif	/* NGRF */
   1752