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