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