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