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