Home | History | Annotate | Line # | Download | only in dev
grf_rh.c revision 1.41
      1 /*	$NetBSD: grf_rh.c,v 1.41 2003/01/20 05:29:59 simonb 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.41 2003/01/20 05:29:59 simonb 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 	gi->gd_colors		= 1 << md->DEP;
    736 	gi->gd_planes		= md->DEP;
    737 
    738 	if (md->DEP == 4) {
    739 		gi->gd_fbwidth	= md->MW;
    740 		gi->gd_fbheight	= md->MH;
    741 		gi->gd_fbx	= 0;
    742 		gi->gd_fby	= 0;
    743 		gi->gd_dwidth	= md->TX * md->FX;
    744 		gi->gd_dheight	= md->TY * md->FY;
    745 		gi->gd_dx	= 0;
    746 		gi->gd_dy	= 0;
    747 	} else {
    748 		gi->gd_fbwidth	= md->TX;
    749 		gi->gd_fbheight	= md->TY;
    750 		gi->gd_fbx	= 0;
    751 		gi->gd_fby	= 0;
    752 		gi->gd_dwidth	= md->MW;
    753 		gi->gd_dheight	= md->MH;
    754 		gi->gd_dx	= 0;
    755 		gi->gd_dy	= 0;
    756 	}
    757 
    758 	FW =0;
    759 	if (md->DEP == 4) {		/* XXX some text-mode! */
    760 		switch (md->FX) {
    761 		    case 4:
    762 			FW = 0;
    763 			break;
    764 		    case 7:
    765 			FW = 1;
    766 			break;
    767 		    case 8:
    768 			FW = 2;
    769 			break;
    770 		    case 9:
    771 			FW = 3;
    772 			break;
    773 		    case 10:
    774 			FW = 4;
    775 			break;
    776 		    case 11:
    777 			FW = 5;
    778 			break;
    779 		    case 12:
    780 			FW = 6;
    781 			break;
    782 		    case 13:
    783 			FW = 7;
    784 			break;
    785 		    case 14:
    786 			FW = 8;
    787 			break;
    788 		    case 15:
    789 			FW = 9;
    790 			break;
    791 		    case 16:
    792 			FW = 11;
    793 			break;
    794 		    default:
    795 			return(0);
    796 			break;
    797 		}
    798 	}
    799 
    800 	if      (md->DEP == 4)  HDE = (md->MW+md->FX-1)/md->FX;
    801 	else if (md->DEP == 8)  HDE = (md->MW+3)/4;
    802 	else if (md->DEP == 16) HDE = (md->MW*2+3)/4;
    803 	else if (md->DEP == 24) HDE = (md->MW*3+3)/4;
    804 
    805 	VDE = md->MH-1;
    806 
    807 	clksel = 0;
    808 
    809 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
    810 	vgaw(ba, GREG_FEATURE_CONTROL_W, 0x00);
    811 
    812 	WSeq(ba, SEQ_ID_RESET, 0x00);
    813 	WSeq(ba, SEQ_ID_RESET, 0x03);
    814 	WSeq(ba, SEQ_ID_CLOCKING_MODE,
    815 		0x01 | ((md->FLG & MDF_CLKDIV2) / MDF_CLKDIV2 * 8));
    816 	WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
    817 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
    818 	WSeq(ba, SEQ_ID_MEMORY_MODE, 0x06);
    819 	WSeq(ba, SEQ_ID_RESET, 0x01);
    820 	WSeq(ba, SEQ_ID_RESET, 0x03);
    821 
    822 	WSeq(ba, SEQ_ID_EXTENDED_ENABLE, 0x05);
    823 	WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x00);
    824 	WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
    825 	WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
    826 	WSeq(ba, SEQ_ID_LINEAR_0, 0x4a);
    827 	WSeq(ba, SEQ_ID_LINEAR_1, 0x00);
    828 
    829 	WSeq(ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00);
    830 	WSeq(ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00);
    831 	WSeq(ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
    832 	WSeq(ba, SEQ_ID_EXT_CLOCK_MODE, 0x10 | (FW & 0x0f));
    833 	WSeq(ba, SEQ_ID_EXT_VIDEO_ADDR, 0x03);
    834 	if (md->DEP == 4) {
    835 	  	/* 8bit pixel, no gfx byte path */
    836 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
    837 	}
    838 	else if (md->DEP == 8) {
    839 	  	/* 8bit pixel, gfx byte path */
    840 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01);
    841 	}
    842 	else if (md->DEP == 16) {
    843 	  	/* 16bit pixel, gfx byte path */
    844 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x11);
    845 	}
    846 	else if (md->DEP == 24) {
    847 		/* 24bit pixel, gfx byte path */
    848 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x21);
    849 	}
    850 	WSeq(ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x04);
    851 	WSeq(ba, SEQ_ID_COLOR_EXP_WFG, 0x01);
    852 	WSeq(ba, SEQ_ID_COLOR_EXP_WBG, 0x00);
    853 	WSeq(ba, SEQ_ID_EXT_RW_CONTROL, 0x00);
    854 	WSeq(ba, SEQ_ID_MISC_FEATURE_SEL, (0x51 | (clksel & 8)));
    855 	WSeq(ba, SEQ_ID_COLOR_KEY_CNTL, 0x40);
    856 	WSeq(ba, SEQ_ID_COLOR_KEY_MATCH0, 0x00);
    857 	WSeq(ba, SEQ_ID_COLOR_KEY_MATCH1, 0x00);
    858 	WSeq(ba, SEQ_ID_COLOR_KEY_MATCH2, 0x00);
    859 	WSeq(ba, SEQ_ID_CRC_CONTROL, 0x00);
    860 	WSeq(ba, SEQ_ID_PERF_SELECT, 0x10);
    861 	WSeq(ba, SEQ_ID_ACM_APERTURE_1, 0x00);
    862 	WSeq(ba, SEQ_ID_ACM_APERTURE_2, 0x30);
    863 	WSeq(ba, SEQ_ID_ACM_APERTURE_3, 0x00);
    864 	WSeq(ba, SEQ_ID_MEMORY_MAP_CNTL, 0x03);	/* was 7, but stupid cursor */
    865 
    866 	WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x20);
    867 	WCrt(ba, CRT_ID_HOR_TOTAL, md->HT    & 0xff);
    868 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1)   & 0xff);
    869 	WCrt(ba, CRT_ID_START_HOR_BLANK, md->HBS   & 0xff);
    870 	WCrt(ba, CRT_ID_END_HOR_BLANK, (md->HBE   & 0x1f) | 0x80);
    871 
    872 	WCrt(ba, CRT_ID_START_HOR_RETR, md->HSS   & 0xff);
    873 	WCrt(ba, CRT_ID_END_HOR_RETR,
    874 	    (md->HSE & 0x1f)   |
    875 	    ((md->HBE & 0x20)/ 0x20 * 0x80));
    876 	WCrt(ba, CRT_ID_VER_TOTAL,  (md->VT  & 0xff));
    877 	WCrt(ba, CRT_ID_OVERFLOW,
    878 	    ((md->VSS & 0x200) / 0x200 * 0x80) |
    879 	    ((VDE     & 0x200) / 0x200 * 0x40) |
    880 	    ((md->VT  & 0x200) / 0x200 * 0x20) |
    881 	    0x10                               |
    882 	    ((md->VBS & 0x100) / 0x100 * 8)    |
    883 	    ((md->VSS & 0x100) / 0x100 * 4)    |
    884 	    ((VDE     & 0x100) / 0x100 * 2)    |
    885 	    ((md->VT  & 0x100) / 0x100));
    886 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
    887 
    888 	if (md->DEP == 4) {
    889 		WCrt(ba, CRT_ID_MAX_SCAN_LINE,
    890 		    ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
    891 		    0x40 |
    892 		    ((md->VBS & 0x200)/0x200*0x20) |
    893 		    ((md->FY-1) & 0x1f));
    894 	} else {
    895 		WCrt(ba, CRT_ID_MAX_SCAN_LINE,
    896 		    ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
    897 		    0x40 |
    898 		    ((md->VBS & 0x200)/0x200*0x20) |
    899 		    (0 & 0x1f));
    900 	}
    901 
    902 	/* I prefer "_" cursor to "block" cursor.. */
    903 #if 1
    904 	WCrt(ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
    905 	WCrt(ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
    906 #else
    907 	WCrt(ba, CRT_ID_CURSOR_START, 0x00);
    908 	WCrt(ba, CRT_ID_CURSOR_END, md->FY & 0x1f);
    909 #endif
    910 
    911 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
    912 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
    913 
    914 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
    915 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
    916 
    917 	WCrt(ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
    918 	WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x80 | 0x20);
    919 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE  & 0xff);
    920 
    921 	if (md->DEP == 4) {
    922 		WCrt(ba, CRT_ID_OFFSET, (HDE / 2) & 0xff );
    923 	}
    924 	/* all gfx-modes are in byte-mode, means values are multiplied by 8 */
    925 	else if (md->DEP == 8) {
    926 		WCrt(ba, CRT_ID_OFFSET, (md->TX / 8) & 0xff );
    927 	} else if (md->DEP == 16) {
    928 		WCrt(ba, CRT_ID_OFFSET, (md->TX / 4) & 0xff );
    929 	} else {
    930 		WCrt(ba, CRT_ID_OFFSET, (md->TX * 3 / 8) & 0xff );
    931 	}
    932 
    933 	WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
    934 	WCrt(ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff);
    935 	WCrt(ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
    936 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
    937 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
    938 
    939 	WCrt(ba, CRT_ID_EXT_HOR_TIMING1,
    940 		    0 | 0x20                                    |
    941 		    ((md->FLG & MDF_LACE)  / MDF_LACE   * 0x10) |
    942 		    ((md->HT  & 0x100) / 0x100)                 |
    943 		    (((HDE-1) & 0x100) / 0x100 * 2)             |
    944 		    ((md->HBS & 0x100) / 0x100 * 4)             |
    945 		    ((md->HSS & 0x100) / 0x100 * 8));
    946 
    947 	if (md->DEP == 4)
    948 		WCrt(ba, CRT_ID_EXT_START_ADDR,
    949 			(((HDE / 2) & 0x100)/0x100 * 16));
    950 	else if (md->DEP == 8)
    951 		WCrt(ba, CRT_ID_EXT_START_ADDR,
    952 			(((md->TX / 8) & 0x100)/0x100 * 16));
    953 	else if (md->DEP == 16)
    954 		WCrt(ba, CRT_ID_EXT_START_ADDR,
    955 			(((md->TX / 4) & 0x100)/0x100 * 16));
    956 	else
    957 		WCrt(ba, CRT_ID_EXT_START_ADDR,
    958 			(((md->TX * 3 / 8) & 0x100)/0x100 * 16));
    959 
    960 	WCrt(ba, CRT_ID_EXT_HOR_TIMING2,
    961 		    ((md->HT  & 0x200)/ 0x200)       |
    962 		    (((HDE-1) & 0x200)/ 0x200 * 2  ) |
    963 		    ((md->HBS & 0x200)/ 0x200 * 4  ) |
    964 		    ((md->HSS & 0x200)/ 0x200 * 8  ) |
    965 		    ((md->HBE & 0xc0) / 0x40  * 16 ) |
    966 		    ((md->HSE & 0x60) / 0x20  * 64));
    967 
    968 	WCrt(ba, CRT_ID_EXT_VER_TIMING,
    969 		    ((md->VSE & 0x10) / 0x10  * 0x80  ) |
    970 		    ((md->VBE & 0x300)/ 0x100 * 0x20  ) |
    971 		    0x10                                |
    972 		    ((md->VSS & 0x400)/ 0x400 * 8     ) |
    973 		    ((md->VBS & 0x400)/ 0x400 * 4     ) |
    974 		    ((VDE     & 0x400)/ 0x400 * 2     ) |
    975 		    ((md->VT & 0x400)/ 0x400));
    976 	WCrt(ba, CRT_ID_MONITOR_POWER, 0x00);
    977 
    978 	{
    979 		unsigned short tmp = rh_CompFQ(md->FQ);
    980 		WPLL(ba, 2   , tmp);
    981 		tmp = rh_CompFQ(rh_memclk);
    982 		WPLL(ba,10   , tmp);
    983 		WPLL(ba,14   , 0x22);
    984 	}
    985 
    986 	WGfx(ba, GCT_ID_SET_RESET, 0x00);
    987 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
    988 	WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
    989 	WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
    990 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
    991 	WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
    992 	if (md->DEP == 4)
    993 		WGfx(ba, GCT_ID_MISC, 0x04);
    994 	else
    995 		WGfx(ba, GCT_ID_MISC, 0x05);
    996 	WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
    997 	WGfx(ba, GCT_ID_BITMASK, 0xff);
    998 
    999 	vgar(ba, ACT_ADDRESS_RESET);
   1000 	WAttr(ba, ACT_ID_PALETTE0 , 0x00);
   1001 	WAttr(ba, ACT_ID_PALETTE1 , 0x01);
   1002 	WAttr(ba, ACT_ID_PALETTE2 , 0x02);
   1003 	WAttr(ba, ACT_ID_PALETTE3 , 0x03);
   1004 	WAttr(ba, ACT_ID_PALETTE4 , 0x04);
   1005 	WAttr(ba, ACT_ID_PALETTE5 , 0x05);
   1006 	WAttr(ba, ACT_ID_PALETTE6 , 0x06);
   1007 	WAttr(ba, ACT_ID_PALETTE7 , 0x07);
   1008 	WAttr(ba, ACT_ID_PALETTE8 , 0x08);
   1009 	WAttr(ba, ACT_ID_PALETTE9 , 0x09);
   1010 	WAttr(ba, ACT_ID_PALETTE10, 0x0a);
   1011 	WAttr(ba, ACT_ID_PALETTE11, 0x0b);
   1012 	WAttr(ba, ACT_ID_PALETTE12, 0x0c);
   1013 	WAttr(ba, ACT_ID_PALETTE13, 0x0d);
   1014 	WAttr(ba, ACT_ID_PALETTE14, 0x0e);
   1015 	WAttr(ba, ACT_ID_PALETTE15, 0x0f);
   1016 
   1017 	vgar(ba, ACT_ADDRESS_RESET);
   1018 	if (md->DEP == 4)
   1019 		WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
   1020 	else
   1021 		WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x09);
   1022 
   1023 	WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
   1024 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
   1025 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
   1026 	WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
   1027 
   1028 	vgar(ba, ACT_ADDRESS_RESET);
   1029 	vgaw(ba, ACT_ADDRESS_W, 0x20);
   1030 
   1031 	vgaw(ba, VDAC_MASK, 0xff);
   1032 	/* probably some PLL timing stuff here. The value
   1033 	   for 24bit was found by trial&error :-) */
   1034 	if (md->DEP < 16) {
   1035 		vgaw(ba, 0x83c6, ((0 & 7) << 5) );
   1036 	}
   1037 	else if (md->DEP == 16) {
   1038 	  	/* well... */
   1039 		vgaw(ba, 0x83c6, ((3 & 7) << 5) );
   1040 	}
   1041 	else if (md->DEP == 24) {
   1042 		vgaw(ba, 0x83c6, 0xe0);
   1043 	}
   1044 	vgaw(ba, VDAC_ADDRESS_W, 0x00);
   1045 
   1046 	if (md->DEP < 16) {
   1047 		short x = 256-17;
   1048 		unsigned char cl = 16;
   1049 		RZ3LoadPalette(gp, md->PAL, 0, 16);
   1050 		do {
   1051 			vgaw(ba, VDAC_DATA, (cl >> 2));
   1052 			vgaw(ba, VDAC_DATA, (cl >> 2));
   1053 			vgaw(ba, VDAC_DATA, (cl >> 2));
   1054 			cl++;
   1055 		} while (x-- > 0);
   1056 	}
   1057 
   1058 	if (md->DEP == 4) {
   1059 		{
   1060 			struct grf_bitblt bb = {
   1061 				GRFBBOPset,
   1062 				0, 0,
   1063 				0, 0,
   1064 				md->TX*4, 2*md->TY,
   1065 				EMPTY_ALPHA
   1066 			};
   1067 			RZ3BitBlit(gp, &bb);
   1068 		}
   1069 
   1070 		c = (unsigned short *)(ba + LM_OFFSET);
   1071 		c += 2 * md->FLo*32;
   1072 		c += 1;
   1073 		f = md->FData;
   1074 		for (z = md->FLo; z <= md->FHi; z++) {
   1075 			short y = md->FY-1;
   1076 			if (md->FX > 8){
   1077 				do {
   1078 					*c = *((const unsigned short *)f);
   1079 					c += 2;
   1080 					f += 2;
   1081 				} while (y-- > 0);
   1082 			} else {
   1083 				do {
   1084 					*c = (*f++) << 8;
   1085 					c += 2;
   1086 				} while (y-- > 0);
   1087 			}
   1088 
   1089 			c += 2 * (32-md->FY);
   1090 		}
   1091 		{
   1092 			unsigned long *pt = (unsigned long *)
   1093 						(ba + LM_OFFSET + PAT_MEM_OFF);
   1094 			unsigned long tmp  = 0xffff0000;
   1095 			*pt++ = tmp;
   1096 			*pt = tmp;
   1097 		}
   1098 
   1099 		WSeq(ba, SEQ_ID_MAP_MASK, 3);
   1100 
   1101 		c = (unsigned short *)(ba + LM_OFFSET);
   1102 		c += (md->TX-6)*2;
   1103 		{
   1104 		  	/* it's show-time :-) */
   1105 			static unsigned short init_msg[6] = {
   1106 				0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f
   1107 			};
   1108 			unsigned short * m = init_msg;
   1109 			short x = 5;
   1110 			do {
   1111 				*c = *m++;
   1112 				c += 2;
   1113 			} while (x-- > 0);
   1114 		}
   1115 
   1116 		return(1);
   1117 	} else if (md->DEP == 8) {
   1118 		struct grf_bitblt bb = {
   1119 			GRFBBOPset,
   1120 			0, 0,
   1121 			0, 0,
   1122 			md->TX, md->TY,
   1123 			0x0000
   1124 		};
   1125 		WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
   1126 
   1127 		RZ3BitBlit(gp, &bb);
   1128 
   1129 		gi->gd_fbx = 0;
   1130 		gi->gd_fby = 0;
   1131 
   1132 		return(1);
   1133 	} else if (md->DEP == 16) {
   1134 		struct grf_bitblt bb = {
   1135 			GRFBBOPset,
   1136 			0, 0,
   1137 			0, 0,
   1138 			md->TX, md->TY,
   1139 			0x0000
   1140 		};
   1141 		WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
   1142 
   1143 		RZ3BitBlit16(gp, &bb);
   1144 
   1145 		gi->gd_fbx = 0;
   1146 		gi->gd_fby = 0;
   1147 
   1148 		return(1);
   1149 	} else if (md->DEP == 24) {
   1150 		struct grf_bitblt bb = {
   1151 			GRFBBOPset,
   1152 			0, 0,
   1153 			0, 0,
   1154 			md->TX, md->TY,
   1155 			0x0000
   1156 		};
   1157 		WSeq(ba, SEQ_ID_MAP_MASK, 0x0f );
   1158 
   1159 		RZ3BitBlit24(gp, &bb );
   1160 
   1161 		gi->gd_fbx = 0;
   1162 		gi->gd_fby = 0;
   1163 
   1164 		return 1;
   1165 	} else
   1166 		return(0);
   1167 }
   1168 
   1169 /* standard-palette definition */
   1170 
   1171 unsigned char RZ3StdPalette[16*3] = {
   1172 /*        R   G   B  */
   1173 	  0,  0,  0,
   1174 	192,192,192,
   1175 	128,  0,  0,
   1176 	  0,128,  0,
   1177 	  0,  0,128,
   1178 	128,128,  0,
   1179 	  0,128,128,
   1180 	128,  0,128,
   1181 	 64, 64, 64, /* the higher 8 colors have more intensity for  */
   1182 	255,255,255, /* compatibility with standard attributes       */
   1183 	255,  0,  0,
   1184 	  0,255,  0,
   1185 	  0,  0,255,
   1186 	255,255,  0,
   1187 	  0,255,255,
   1188 	255,  0,255
   1189 };
   1190 
   1191 /*
   1192  * The following structures are examples for monitor-definitions. To make one
   1193  * of your own, first use "DefineMonitor" and create the 8-bit or 16-bit
   1194  * monitor-mode of your dreams. Then save it, and make a structure from the
   1195  * values provided in the file DefineMonitor stored - the labels in the comment
   1196  * above the structure definition show where to put what value.
   1197  *
   1198  * If you want to use your definition for the text-mode, you'll need to adapt
   1199  * your 8-bit monitor-definition to the font you want to use. Be FX the width of
   1200  * the font, then the following modifications have to be applied to your values:
   1201  *
   1202  * HBS = (HBS * 4) / FX
   1203  * HSS = (HSS * 4) / FX
   1204  * HSE = (HSE * 4) / FX
   1205  * HBE = (HBE * 4) / FX
   1206  * HT  = (HT  * 4) / FX
   1207  *
   1208  * Make sure your maximum width (MW) and height (MH) are even multiples of
   1209  * the fonts' width and height.
   1210  *
   1211  * You may use definitons created by the old DefineMonitor, but you'll get
   1212  * better results with the new DefineMonitor supplied along with the Retin Z3.
   1213 */
   1214 
   1215 /*
   1216  *  FQ     FLG    MW   MH   HBS HSS HSE HBE  HT  VBS  VSS  VSE  VBE   VT
   1217  * Depth,          PAL, TX,  TY,    XY,FontX, FontY,    FontData,  FLo,  Fhi
   1218  */
   1219 #ifdef KFONT_8X11
   1220 #define KERNEL_FONT kernel_font_8x11
   1221 #define FY 11
   1222 #define FX  8
   1223 #else
   1224 #define KERNEL_FONT kernel_font_8x8
   1225 #define FY  8
   1226 #define FX  8
   1227 #endif
   1228 
   1229 
   1230 static struct MonDef monitor_defs[] = {
   1231   /* Text-mode definitions */
   1232 
   1233   /* horizontal 31.5 kHz */
   1234   { 50000000,  28,  640, 440,   81, 86, 93, 98, 95, 481, 490, 498, 522, 522,
   1235       4, RZ3StdPalette, 80,  55,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1236 
   1237   /* horizontal 38kHz */
   1238   { 75000000,  28,  768, 600,   97, 99,107,120,117, 601, 615, 625, 638, 638,
   1239       4, RZ3StdPalette, 96,  75,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1240 
   1241   /* horizontal 64kHz */
   1242   { 50000000, 24,  768, 600,   97,104,112,122,119, 601, 606, 616, 628, 628,
   1243       4, RZ3StdPalette, 96,  75,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1244 
   1245   /* 8-bit gfx-mode definitions */
   1246 
   1247   /* IMPORTANT: the "logical" screen size can be up to 2048x2048 pixels,
   1248      independent from the "physical" screen size. If your code does NOT
   1249      support panning, please adjust the "logical" screen sizes below to
   1250      match the physical ones
   1251    */
   1252 
   1253 #ifdef RH_HARDWARECURSOR
   1254 
   1255   /* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */
   1256   { 26000000,  0,  640, 480,  161,175,188,200,199, 481, 483, 491, 502, 502,
   1257       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1258   /* This is the logical ^    ^    screen size */
   1259 
   1260   /* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */
   1261  { 31000000,  0,  640, 480,  161,169,182,198,197, 481, 482, 490, 502, 502,
   1262      8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1263 
   1264   /* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */
   1265   { 39000000,  0,  800, 600,  201,211,227,249,248, 601, 603, 613, 628, 628,
   1266       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1267 
   1268   /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
   1269   { 62000000,  0, 1024, 768,  257,257,277,317,316, 769, 771, 784, 804, 804,
   1270       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1271 
   1272   /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
   1273   { 77000000,  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   { 82000000,  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   /* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */
   1281   { 97000000,  0, 1120, 896,  281,283,306,369,368, 897, 898, 913, 938, 938,
   1282       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1283 
   1284   /* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */
   1285   {110000000,  0, 1152, 910,  289,310,333,357,356, 911, 923, 938, 953, 953,
   1286       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1287 
   1288   /* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */
   1289   {110000000,  0, 1184, 848,  297,319,342,370,369, 849, 852, 866, 888, 888,
   1290       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1291 
   1292   /* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */
   1293   {104000000, 0, 1280,1024,  321,323,348,399,398,1025,1026,1043,1073,1073,
   1294      8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1295 
   1296 /*
   1297  * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
   1298  *          HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
   1299  *          MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
   1300  */
   1301   /* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */
   1302   {121000000, 0, 1280,1024,  321,322,347,397,396,1025,1026,1043,1073,1073,
   1303      8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1304 
   1305 
   1306   /* 16-bit gfx-mode definitions */
   1307 
   1308   /* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */
   1309   { 51000000, 0,  640, 480,  321,344,369,397,396, 481, 482, 490, 502, 502,
   1310       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1311 
   1312   /* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */
   1313   { 77000000, 0,  800, 600,  401,418,449,496,495, 601, 602, 612, 628, 628,
   1314       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1315 
   1316   /* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */
   1317   {110000000,  0, 1024, 768,  513,514,554,639,638, 769, 770, 783, 804, 804,
   1318       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1319 
   1320   /* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */
   1321   {109000000,  0,  864, 648,  433,434,468,537,536, 649, 650, 661, 678, 678,
   1322       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1323 
   1324 /*
   1325  * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
   1326  *          HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
   1327  *          MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
   1328  */
   1329   /* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */
   1330   {124000000,  0, 1024, 768,  513,537,577,636,635, 769, 770, 783, 804, 804,
   1331       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1332 
   1333 
   1334   /* 24-bit gfx-mode definitions */
   1335 
   1336   /* 320 x 200, 24 Bit, 35060 Hz, 83 Hz d */
   1337   { 46000000,  1,  320, 200,  241,268,287,324,323, 401, 405, 412, 418, 418,
   1338       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1339 
   1340   /* 640 x 400, 24 Bit, 31404 Hz, 75 Hz */
   1341   { 76000000,  0,  640, 400,  481,514,552,601,600, 401, 402, 409, 418, 418,
   1342       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1343 
   1344   /* 724 x 482, 24 Bit, 36969 Hz, 73 Hz */
   1345   {101000000,  0,  724, 482,  544,576,619,682,678, 483, 487, 495, 495, 504,
   1346       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1347 
   1348   /* 800 x 600, 24 Bit, 37826 Hz, 60 Hz */
   1349   {110000000,  0,  800, 600,  601,602,647,723,722, 601, 602, 612, 628, 628,
   1350       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1351 
   1352   /* 800 x 600, 24 Bit, 43824 Hz, 69 Hz */
   1353   {132000000,  0,  800, 600,  601,641,688,749,748, 601, 611, 621, 628, 628,
   1354       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1355 
   1356   /*1024 x 768, 24 Bit, 32051 Hz, 79 Hz i */
   1357   {110000000,  2, 1024, 768,  769,770,824,854,853, 385, 386, 392, 401, 401,
   1358       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1359 
   1360 #else /* RH_HARDWARECURSOR */
   1361 
   1362   /* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */
   1363   { 26000000,  0,  640, 480,  161,175,188,200,199, 481, 483, 491, 502, 502,
   1364       8, RZ3StdPalette,  640,  480,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1365   /* This is the logical  ^     ^    screen size */
   1366 
   1367   /* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */
   1368  { 31000000,  0,  640, 480,  161,169,182,198,197, 481, 482, 490, 502, 502,
   1369      8, RZ3StdPalette,  640,  480,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1370 
   1371   /* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */
   1372   { 39000000,  0,  800, 600,  201,211,227,249,248, 601, 603, 613, 628, 628,
   1373       8, RZ3StdPalette,  800,  600,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1374 
   1375   /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
   1376   { 62000000,  0, 1024, 768,  257,257,277,317,316, 769, 771, 784, 804, 804,
   1377       8, RZ3StdPalette, 1024,  768,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1378 
   1379   /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
   1380   { 77000000,  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   { 82000000,  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   /* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */
   1388   { 97000000,  0, 1120, 896,  281,283,306,369,368, 897, 898, 913, 938, 938,
   1389       8, RZ3StdPalette, 1120,  896,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1390 
   1391   /* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */
   1392   {110000000,  0, 1152, 910,  289,310,333,357,356, 911, 923, 938, 953, 953,
   1393       8, RZ3StdPalette, 1152,  910,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1394 
   1395   /* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */
   1396   {110000000,  0, 1184, 848,  297,319,342,370,369, 849, 852, 866, 888, 888,
   1397       8, RZ3StdPalette, 1184,  848,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1398 
   1399   /* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */
   1400   {104000000, 0, 1280,1024,  321,323,348,399,398,1025,1026,1043,1073,1073,
   1401      8, RZ3StdPalette, 1280, 1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1402 
   1403 /*
   1404  * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
   1405  *            HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
   1406  *            MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
   1407  */
   1408   /* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */
   1409   {121000000, 0, 1280,1024,  321,322,347,397,396,1025,1026,1043,1073,1073,
   1410      8, RZ3StdPalette, 1280, 1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
   1411 
   1412 
   1413   /* 16-bit gfx-mode definitions */
   1414 
   1415   /* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */
   1416   { 51000000, 0,  640, 480,  321,344,369,397,396, 481, 482, 490, 502, 502,
   1417       16,           0,  640,  480,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1418 
   1419   /* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */
   1420   { 77000000, 0,  800, 600,  401,418,449,496,495, 601, 602, 612, 628, 628,
   1421       16,           0,  800,  600,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1422 
   1423   /* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */
   1424   {110000000,  0, 1024, 768,  513,514,554,639,638, 769, 770, 783, 804, 804,
   1425       16,           0, 1024,  768,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1426 
   1427   /* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */
   1428   {109000000,  0,  864, 648,  433,434,468,537,536, 649, 650, 661, 678, 678,
   1429       16,           0,  864,  648,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1430 
   1431 /*
   1432  * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
   1433  *          HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
   1434  *          MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
   1435  */
   1436   /* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */
   1437   {124000000,  0, 1024, 768,  513,537,577,636,635, 769, 770, 783, 804, 804,
   1438       16,           0, 1024,  768,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1439 
   1440 
   1441   /* 24-bit gfx-mode definitions */
   1442 
   1443   /* 320 x 200, 24 Bit, 35060 Hz, 83 Hz d */
   1444   { 46000000,  1,  320, 200,  241,268,287,324,323, 401, 405, 412, 418, 418,
   1445       24,           0,  320,  200,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1446 
   1447   /* 640 x 400, 24 Bit, 31404 Hz, 75 Hz */
   1448   { 76000000,  0,  640, 400,  481,514,552,601,600, 401, 402, 409, 418, 418,
   1449       24,           0,  640,  400,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1450 
   1451   /* 724 x 482, 24 Bit, 36969 Hz, 73 Hz */
   1452   {101000000,  0,  724, 482,  544,576,619,682,678, 483, 487, 495, 495, 504,
   1453       24,           0,  724,  482,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1454 
   1455   /* 800 x 600, 24 Bit, 37826 Hz, 60 Hz */
   1456   {110000000,  0,  800, 600,  601,602,647,723,722, 601, 602, 612, 628, 628,
   1457       24,           0,  800,  600,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1458 
   1459   /* 800 x 600, 24 Bit, 43824 Hz, 69 Hz */
   1460   {132000000,  0,  800, 600,  601,641,688,749,748, 601, 611, 621, 628, 628,
   1461       24,           0,  800,  600,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1462 
   1463   /*1024 x 768, 24 Bit, 32051 Hz, 79 Hz i */
   1464   {110000000,  2, 1024, 768,  769,770,824,854,853, 385, 386, 392, 401, 401,
   1465       24,           0, 1024,  768,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
   1466 
   1467 #endif /* RH_HARDWARECURSOR */
   1468 };
   1469 #undef KERNEL_FONT
   1470 #undef FX
   1471 #undef FY
   1472 
   1473 static const char *monitor_descr[] = {
   1474 #ifdef KFONT_8X11
   1475   "80x46 (640x506) 31.5kHz",
   1476   "96x54 (768x594) 38kHz",
   1477   "96x54 (768x594) 64kHz",
   1478 #else
   1479   "80x64 (640x512) 31.5kHz",
   1480   "96x75 (768x600) 38kHz",
   1481   "96x75 (768x600) 64kHz",
   1482 #endif
   1483 
   1484   "GFX-8 (640x480) 31.5kHz",
   1485   "GFX-8 (640x480) 38kHz",
   1486   "GFX-8 (800x600) 38.5kHz",
   1487   "GFX-8 (1024x768) 44kHz",
   1488   "GFX-8 (1024x768) 50kHz",
   1489   "GFX-8 (1024x768) 64kHz",
   1490   "GFX-8 (1120x896) 64kHz",
   1491   "GFX-8 (1152x910) 76kHz",
   1492   "GFX-8 (1182x848) 73kHz",
   1493   "GFX-8 (1280x1024) 64.5kHz",
   1494   "GFX-8 (1280x1024) 75.5kHz ***EXCEEDS CHIP LIMIT!!!***",
   1495 
   1496   "GFX-16 (640x480) 31.8kHz",
   1497   "GFX-16 (800x600) 38.5kHz",
   1498   "GFX-16 (1024x768) 42.8kHz",
   1499   "GFX-16 (864x648) 50kHz",
   1500   "GFX-16 (1024x768) 48.5kHz ***EXCEEDS CHIP LIMIT!!!***",
   1501 
   1502   "GFX-24 (320x200 d) 35kHz",
   1503   "GFX-24 (640x400) 31.4kHz",
   1504   "GFX-24 (724x482) 37kHz",
   1505   "GFX-24 (800x600) 38kHz",
   1506   "GFX-24 (800x600) 44kHz ***EXCEEDS CHIP LIMIT!!!***",
   1507   "GFX-24 (1024x768) 32kHz-i",
   1508 };
   1509 
   1510 int rh_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
   1511 
   1512 /* patchable */
   1513 int rh_default_mon = 0;
   1514 int rh_default_gfx = 4;
   1515 
   1516 static struct MonDef *current_mon;	/* EVIL */
   1517 
   1518 int  rh_mode(struct grf_softc *, u_long, void *, u_long, int);
   1519 void grfrhattach(struct device *, struct device *, void *);
   1520 int  grfrhprint(void *, const char *);
   1521 int  grfrhmatch(struct device *, struct cfdata *, void *);
   1522 
   1523 CFATTACH_DECL(grfrh, sizeof(struct grf_softc),
   1524     grfrhmatch, grfrhattach, NULL, NULL);
   1525 
   1526 static struct cfdata *cfdata;
   1527 
   1528 int
   1529 grfrhmatch(struct device *pdp, struct cfdata *cfp, void *auxp)
   1530 {
   1531 #ifdef RETINACONSOLE
   1532 	static int rhconunit = -1;
   1533 #endif
   1534 	struct zbus_args *zap;
   1535 
   1536 	zap = auxp;
   1537 
   1538 	if (amiga_realconfig == 0)
   1539 #ifdef RETINACONSOLE
   1540 		if (rhconunit != -1)
   1541 #endif
   1542 			return(0);
   1543 	if (zap->manid != 18260 ||
   1544 			((zap->prodid != 16) && (zap->prodid != 19)))
   1545 		return(0);
   1546 #ifdef RETINACONSOLE
   1547 	if (amiga_realconfig == 0 || rhconunit != cfp->cf_unit) {
   1548 #endif
   1549 		if ((unsigned)rh_default_mon >= rh_mon_max ||
   1550 		    monitor_defs[rh_default_mon].DEP == 8)
   1551 			rh_default_mon = 0;
   1552 		current_mon = monitor_defs + rh_default_mon;
   1553 		if (rh_mondefok(current_mon) == 0)
   1554 			return(0);
   1555 #ifdef RETINACONSOLE
   1556 		if (amiga_realconfig == 0) {
   1557 			rhconunit = cfp->cf_unit;
   1558 			cfdata = cfp;
   1559 		}
   1560 	}
   1561 #endif
   1562 	return(1);
   1563 }
   1564 
   1565 void
   1566 grfrhattach(struct device *pdp, struct device *dp, void *auxp)
   1567 {
   1568 	static struct grf_softc congrf;
   1569 	struct zbus_args *zap;
   1570 	struct grf_softc *gp;
   1571 
   1572 	zap = auxp;
   1573 
   1574 	if (dp == NULL)
   1575 		gp = &congrf;
   1576 	else
   1577 		gp = (struct grf_softc *)dp;
   1578 	if (dp != NULL && congrf.g_regkva != 0) {
   1579 		/*
   1580 		 * inited earlier, just copy (not device struct)
   1581 		 */
   1582 		bcopy(&congrf.g_display, &gp->g_display,
   1583 		    (char *)&gp[1] - (char *)&gp->g_display);
   1584 	} else {
   1585 		gp->g_regkva = (volatile caddr_t)zap->va;
   1586 		gp->g_fbkva = (volatile caddr_t)zap->va + LM_OFFSET;
   1587 		gp->g_unit = GRF_RETINAIII_UNIT;
   1588 		gp->g_mode = rh_mode;
   1589 		gp->g_conpri = grfrh_cnprobe();
   1590 		gp->g_flags = GF_ALIVE;
   1591 		grfrh_iteinit(gp);
   1592 		(void)rh_load_mon(gp, current_mon);
   1593 	}
   1594 	if (dp != NULL)
   1595 		printf("\n");
   1596 	/*
   1597 	 * attach grf
   1598 	 */
   1599 	amiga_config_found(cfdata, &gp->g_device, gp, grfrhprint);
   1600 }
   1601 
   1602 int
   1603 grfrhprint(void *auxp, const char *pnp)
   1604 {
   1605 	if (pnp)
   1606 		aprint_normal("ite at %s", pnp);
   1607 	return(UNCONF);
   1608 }
   1609 
   1610 int
   1611 rh_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
   1612 {
   1613 	struct MonDef *md;
   1614 	int vmul;
   1615 
   1616 	if (vm->mode_num && vm->mode_num > rh_mon_max)
   1617 		return(EINVAL);
   1618 
   1619 	if (! vm->mode_num)
   1620 		vm->mode_num = (current_mon - monitor_defs) + 1;
   1621 
   1622 	md = monitor_defs + (vm->mode_num - 1);
   1623 	strncpy (vm->mode_descr, monitor_descr[vm->mode_num - 1],
   1624 	   sizeof (vm->mode_descr));
   1625 	vm->pixel_clock  = md->FQ;
   1626 	vm->disp_width   = (md->DEP == 4) ? md->MW : md->TX;
   1627 	vm->disp_height  = (md->DEP == 4) ? md->MH : md->TY;
   1628 	vm->depth        = md->DEP;
   1629 
   1630 	/*
   1631 	 * From observation of the monitor definition table above, I guess
   1632 	 * that the horizontal timings are in units of longwords. Hence, I
   1633 	 * get the pixels by multiplication with 32 and division by the depth.
   1634 	 * The text modes, apparently marked by depth == 4, are even more
   1635 	 * weird. According to a comment above, they are computed from a
   1636 	 * depth==8 mode thats for us: * 32 / 8) by applying another factor
   1637 	 * of 4 / font width.
   1638 	 * Reverse applying the latter formula most of the constants cancel
   1639 	 * themselves and we are left with a nice (* font width).
   1640 	 * That is, internal timings are in units of longwords for graphics
   1641 	 * modes, or in units of characters widths for text modes.
   1642 	 * We better don't WRITE modes until this has been real live checked.
   1643 	 *                    - Ignatios Souvatzis
   1644 	 */
   1645 
   1646 	if (md->DEP != 4) {
   1647 		vm->hblank_start = md->HBS * 32 / md->DEP;
   1648 		vm->hsync_start  = md->HSS * 32 / md->DEP;
   1649 		vm->hsync_stop   = md->HSE * 32 / md->DEP;
   1650 		vm->htotal       = md->HT * 32 / md->DEP;
   1651 	} else {
   1652 		vm->hblank_start = md->HBS * md->FX;
   1653 		vm->hsync_start  = md->HSS * md->FX;
   1654 		vm->hsync_stop   = md->HSE * md->FX;
   1655 		vm->htotal       = md->HT * md->FX;
   1656 	}
   1657 
   1658 	/* XXX move vm->disp_flags and vmul to rh_load_mon
   1659 	 * if rh_setvmode can add new modes with grfconfig */
   1660 	vm->disp_flags = 0;
   1661 	vmul = 2;
   1662 	if (md->FLG & MDF_DBL) {
   1663 		vm->disp_flags |= GRF_FLAGS_DBLSCAN;
   1664 		vmul = 4;
   1665 	}
   1666 	if (md->FLG & MDF_LACE) {
   1667 		vm->disp_flags |= GRF_FLAGS_LACE;
   1668 		vmul = 1;
   1669 	}
   1670 	vm->vblank_start = md->VBS * vmul / 2;
   1671 	vm->vsync_start  = md->VSS * vmul / 2;
   1672 	vm->vsync_stop   = md->VSE * vmul / 2;
   1673 	vm->vtotal       = md->VT * vmul / 2;
   1674 
   1675 	return(0);
   1676 }
   1677 
   1678 
   1679 int
   1680 rh_setvmode(struct grf_softc *gp, unsigned mode, enum mode_type type)
   1681 {
   1682 	int error;
   1683 
   1684 	if (!mode || mode > rh_mon_max)
   1685 		return(EINVAL);
   1686 
   1687 	if ((type == MT_TXTONLY && monitor_defs[mode-1].DEP != 4)
   1688 	    || (type == MT_GFXONLY && monitor_defs[mode-1].DEP == 4))
   1689 		return(EINVAL);
   1690 
   1691 	current_mon = monitor_defs + (mode - 1);
   1692 
   1693 	error = rh_load_mon (gp, current_mon) ? 0 : EINVAL;
   1694 
   1695 	return(error);
   1696 }
   1697 
   1698 
   1699 /*
   1700  * Change the mode of the display.
   1701  * Return a UNIX error number or 0 for success.
   1702  */
   1703 int
   1704 rh_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2,
   1705 	int a3)
   1706 {
   1707 	switch (cmd) {
   1708 	    case GM_GRFON:
   1709 		rh_setvmode (gp, rh_default_gfx + 1, MT_GFXONLY);
   1710 		return(0);
   1711 
   1712 	    case GM_GRFOFF:
   1713 		rh_setvmode (gp, rh_default_mon + 1, MT_TXTONLY);
   1714 		return(0);
   1715 
   1716 	    case GM_GRFCONFIG:
   1717 		return(0);
   1718 
   1719 	    case GM_GRFGETVMODE:
   1720 		return(rh_getvmode (gp, (struct grfvideo_mode *) arg));
   1721 
   1722 	    case GM_GRFSETVMODE:
   1723 		return(rh_setvmode(gp, *(unsigned *) arg,
   1724 			(gp->g_flags & GF_GRFON) ? MT_GFXONLY : MT_TXTONLY));
   1725 
   1726 	    case GM_GRFGETNUMVM:
   1727 		*(int *)arg = rh_mon_max;
   1728 		return(0);
   1729 
   1730 	    case GM_GRFIOCTL:
   1731 		return(rh_ioctl (gp, a2, arg));
   1732 
   1733 	    default:
   1734 		break;
   1735 	}
   1736 
   1737 	return(EPASSTHROUGH);
   1738 }
   1739 
   1740 int
   1741 rh_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
   1742 {
   1743 	switch (cmd) {
   1744 #ifdef RH_HARDWARECURSOR
   1745 	    case GRFIOCGSPRITEPOS:
   1746 		return(rh_getspritepos (gp, (struct grf_position *) data));
   1747 
   1748 	    case GRFIOCSSPRITEPOS:
   1749 		return(rh_setspritepos (gp, (struct grf_position *) data));
   1750 
   1751 	    case GRFIOCSSPRITEINF:
   1752 		return(rh_setspriteinfo (gp, (struct grf_spriteinfo *) data));
   1753 
   1754 	    case GRFIOCGSPRITEINF:
   1755 		return(rh_getspriteinfo (gp, (struct grf_spriteinfo *) data));
   1756 
   1757 	    case GRFIOCGSPRITEMAX:
   1758 		return(rh_getspritemax (gp, (struct grf_position *) data));
   1759 #else /* RH_HARDWARECURSOR */
   1760 	    case GRFIOCGSPRITEPOS:
   1761 	    case GRFIOCSSPRITEPOS:
   1762 	    case GRFIOCSSPRITEINF:
   1763 	    case GRFIOCGSPRITEMAX:
   1764 		break;
   1765 #endif /* RH_HARDWARECURSOR */
   1766 
   1767 	    case GRFIOCGETCMAP:
   1768 		return(rh_getcmap (gp, (struct grf_colormap *) data));
   1769 
   1770 	    case GRFIOCPUTCMAP:
   1771 		return(rh_putcmap (gp, (struct grf_colormap *) data));
   1772 
   1773 	    case GRFIOCBITBLT:
   1774 		return(rh_bitblt (gp, (struct grf_bitblt *) data));
   1775 
   1776 	    case GRFIOCBLANK:
   1777 		return (rh_blank(gp, (int *)data));
   1778 	}
   1779 
   1780 	return(EPASSTHROUGH);
   1781 }
   1782 
   1783 
   1784 int
   1785 rh_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
   1786 {
   1787 	volatile unsigned char *ba;
   1788 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1789 	short x;
   1790 	int error;
   1791 
   1792 	if (cmap->count == 0 || cmap->index >= 256)
   1793 		return 0;
   1794 
   1795 	if (cmap->count > 256 - cmap->index)
   1796 		cmap->count = 256 - cmap->index;
   1797 
   1798 	ba = gfp->g_regkva;
   1799 	/* first read colors out of the chip, then copyout to userspace */
   1800 	vgaw (ba, VDAC_ADDRESS_W, cmap->index);
   1801 	x = cmap->count - 1;
   1802 	rp = red + cmap->index;
   1803 	gp = green + cmap->index;
   1804 	bp = blue + cmap->index;
   1805 	do {
   1806 		*rp++ = vgar (ba, VDAC_DATA) << 2;
   1807 		*gp++ = vgar (ba, VDAC_DATA) << 2;
   1808 		*bp++ = vgar (ba, VDAC_DATA) << 2;
   1809 	} while (x-- > 0);
   1810 
   1811 	if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
   1812 	    && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
   1813 	    && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
   1814 		return(0);
   1815 
   1816 	return(error);
   1817 }
   1818 
   1819 int
   1820 rh_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
   1821 {
   1822 	volatile unsigned char *ba;
   1823 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1824 	short x;
   1825 	int error;
   1826 
   1827 	if (cmap->count == 0 || cmap->index >= 256)
   1828 		return(0);
   1829 
   1830 	if (cmap->count > 256 - cmap->index)
   1831 		cmap->count = 256 - cmap->index;
   1832 
   1833 	/* first copy the colors into kernelspace */
   1834 	if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
   1835 	    && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
   1836 	    && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
   1837 		/* argl.. LoadPalette wants a different format, so do it like with
   1838 		* Retina2.. */
   1839 		ba = gfp->g_regkva;
   1840 		vgaw (ba, VDAC_ADDRESS_W, cmap->index);
   1841 		x = cmap->count - 1;
   1842 		rp = red + cmap->index;
   1843 		gp = green + cmap->index;
   1844 		bp = blue + cmap->index;
   1845 		do {
   1846 			vgaw (ba, VDAC_DATA, *rp++ >> 2);
   1847 			vgaw (ba, VDAC_DATA, *gp++ >> 2);
   1848 			vgaw (ba, VDAC_DATA, *bp++ >> 2);
   1849 		} while (x-- > 0);
   1850 		return(0);
   1851 	}
   1852 	else
   1853 		return(error);
   1854 }
   1855 
   1856 int
   1857 rh_getspritepos(struct grf_softc *gp, struct grf_position *pos)
   1858 {
   1859 	struct grfinfo *gi = &gp->g_display;
   1860 #if 1
   1861 	volatile unsigned char *ba = gp->g_regkva;
   1862 
   1863 	pos->x = (RSeq(ba, SEQ_ID_CURSOR_X_LOC_HI) << 8) |
   1864 	    RSeq(ba, SEQ_ID_CURSOR_X_LOC_LO);
   1865 	pos->y = (RSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8) |
   1866 	    RSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO);
   1867 #else
   1868 	volatile unsigned char *acm = gp->g_regkva + ACM_OFFSET;
   1869 
   1870 	pos->x = acm[ACM_CURSOR_POSITION + 0] +
   1871 	    (acm[ACM_CURSOR_POSITION + 1] << 8);
   1872 	pos->y = acm[ACM_CURSOR_POSITION + 2] +
   1873 	    (acm[ACM_CURSOR_POSITION + 3] << 8);
   1874 #endif
   1875 	pos->x += gi->gd_fbx;
   1876 	pos->y += gi->gd_fby;
   1877 
   1878 	return(0);
   1879 }
   1880 
   1881 int
   1882 rh_setspritepos (gp, pos)
   1883 	struct grf_softc *gp;
   1884 	struct grf_position *pos;
   1885 {
   1886 	RZ3SetHWCloc (gp, pos->x, pos->y);
   1887 	return(0);
   1888 }
   1889 
   1890 int
   1891 rh_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
   1892 {
   1893 	volatile unsigned char *ba, *fb;
   1894 
   1895 	ba = gp->g_regkva;
   1896 	fb = gp->g_fbkva;
   1897 	if (info->set & GRFSPRSET_ENABLE)
   1898 		info->enable = RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
   1899 	if (info->set & GRFSPRSET_POS)
   1900 		rh_getspritepos (gp, &info->pos);
   1901 	if (info->set & GRFSPRSET_HOT) {
   1902 		info->hot.x = RSeq (ba, SEQ_ID_CURSOR_X_INDEX) & 0x3f;
   1903 		info->hot.y = RSeq (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
   1904 	}
   1905 	if (info->set & GRFSPRSET_CMAP) {
   1906 		struct grf_colormap cmap;
   1907 		int index;
   1908 		cmap.index = 0;
   1909 		cmap.count = 256;
   1910 		rh_getcmap (gp, &cmap);
   1911 		index = RSeq (ba, SEQ_ID_CURSOR_COLOR0);
   1912 		info->cmap.red[0] = cmap.red[index];
   1913 		info->cmap.green[0] = cmap.green[index];
   1914 		info->cmap.blue[0] = cmap.blue[index];
   1915 		index = RSeq (ba, SEQ_ID_CURSOR_COLOR1);
   1916 		info->cmap.red[1] = cmap.red[index];
   1917 		info->cmap.green[1] = cmap.green[index];
   1918 		info->cmap.blue[1] = cmap.blue[index];
   1919 	}
   1920 	if (info->set & GRFSPRSET_SHAPE) {
   1921 		u_char image[128], mask[128];
   1922 		volatile u_long *hwp;
   1923 		u_char *imp, *mp;
   1924 		short row;
   1925 
   1926 		/* sprite bitmap is WEIRD in this chip.. see grf_rhvar.h
   1927 		 * for an explanation. To convert to "our" format, the
   1928 		 * following holds:
   1929 		 *   col2   = !image & mask
   1930 		 *   col1   = image & mask
   1931 		 *   transp = !mask
   1932 		 * and thus:
   1933 		 *   image  = col1
   1934 		 *   mask   = col1 | col2
   1935 		 * hope I got these bool-eqs right below..
   1936 		 */
   1937 
   1938 #ifdef RH_64BIT_SPRITE
   1939 		info->size.x = 64;
   1940 		info->size.y = 64;
   1941 		for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
   1942 		    mp = mask, imp = image;
   1943 		    row < 64;
   1944 		    row++) {
   1945 			u_long bp10, bp20, bp11, bp21;
   1946 			bp10 = *hwp++;
   1947 			bp20 = *hwp++;
   1948 			bp11 = *hwp++;
   1949 			bp21 = *hwp++;
   1950 			M2I (bp10);
   1951 			M2I (bp20);
   1952 			M2I (bp11);
   1953 			M2I (bp21);
   1954 			*imp++ = (~bp10) & bp11;
   1955 			*imp++ = (~bp20) & bp21;
   1956 			*mp++  = (~bp10) | (bp10 & ~bp11);
   1957 			*mp++  = (~bp20) & (bp20 & ~bp21);
   1958 		}
   1959 #else
   1960 		info->size.x = 32;
   1961 		info->size.y = 32;
   1962 		for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
   1963 		    mp = mask, imp = image;
   1964 		    row < 32;
   1965 		    row++) {
   1966 			u_long bp10, bp11;
   1967 			bp10 = *hwp++;
   1968 			bp11 = *hwp++;
   1969 			M2I (bp10);
   1970 			M2I (bp11);
   1971 			*imp++ = (~bp10) & bp11;
   1972 			*mp++  = (~bp10) | (bp10 & ~bp11);
   1973 		}
   1974 #endif
   1975 		copyout (image, info->image, sizeof (image));
   1976 		copyout (mask, info->mask, sizeof (mask));
   1977 	}
   1978 	return(0);
   1979 }
   1980 
   1981 int
   1982 rh_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
   1983 {
   1984 	volatile unsigned char *ba, *fb;
   1985 #if 0
   1986 	u_char control;
   1987 #endif
   1988 
   1989 	ba = gp->g_regkva;
   1990 	fb = gp->g_fbkva;
   1991 
   1992 	if (info->set & GRFSPRSET_SHAPE) {
   1993 		/*
   1994 		 * For an explanation of these weird actions here, see above
   1995 		 * when reading the shape.  We set the shape directly into
   1996 		 * the video memory, there's no reason to keep 1k on the
   1997 		 * kernel stack just as template
   1998 		 */
   1999 		u_char *image, *mask;
   2000 		volatile u_long *hwp;
   2001 		u_char *imp, *mp;
   2002 		short row;
   2003 
   2004 #ifdef RH_64BIT_SPRITE
   2005 		if (info->size.y > 64)
   2006 			info->size.y = 64;
   2007 		if (info->size.x > 64)
   2008 			info->size.x = 64;
   2009 #else
   2010 		if (info->size.y > 32)
   2011 			info->size.y = 32;
   2012 		if (info->size.x > 32)
   2013 			info->size.x = 32;
   2014 #endif
   2015 
   2016 		if (info->size.x < 32)
   2017 			info->size.x = 32;
   2018 
   2019 		image = malloc(HWC_MEM_SIZE, M_TEMP, M_WAITOK);
   2020 		mask  = image + HWC_MEM_SIZE/2;
   2021 
   2022 		copyin(info->image, image, info->size.y * info->size.x / 8);
   2023 		copyin(info->mask, mask, info->size.y * info->size.x / 8);
   2024 
   2025 		hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF);
   2026 
   2027 		/*
   2028 		 * setting it is slightly more difficult, because we can't
   2029 		 * force the application to not pass a *smaller* than
   2030 		 * supported bitmap
   2031 		 */
   2032 
   2033 		for (row = 0, mp = mask, imp = image;
   2034 		    row < info->size.y;
   2035 		    row++) {
   2036 			u_long im1, im2, m1, m2;
   2037 
   2038 			im1 = *(unsigned long *)imp;
   2039 			imp += 4;
   2040 			m1  = *(unsigned long *)mp;
   2041 			mp  += 4;
   2042 #ifdef RH_64BIT_SPRITE
   2043 			if (info->size.x > 32) {
   2044 	      			im2 = *(unsigned long *)imp;
   2045 				imp += 4;
   2046 				m2  = *(unsigned long *)mp;
   2047 				mp  += 4;
   2048 			}
   2049 			else
   2050 #endif
   2051 				im2 = m2 = 0;
   2052 
   2053 			M2I(im1);
   2054 			M2I(im2);
   2055 			M2I(m1);
   2056 			M2I(m2);
   2057 
   2058 			*hwp++ = ~m1;
   2059 #ifdef RH_64BIT_SPRITE
   2060 			*hwp++ = ~m2;
   2061 #endif
   2062 			*hwp++ = m1 & im1;
   2063 #ifdef RH_64BIT_SPRITE
   2064 			*hwp++ = m2 & im2;
   2065 #endif
   2066 		}
   2067 #ifdef RH_64BIT_SPRITE
   2068 		for (; row < 64; row++) {
   2069 			*hwp++ = 0xffffffff;
   2070 			*hwp++ = 0xffffffff;
   2071 			*hwp++ = 0x00000000;
   2072 			*hwp++ = 0x00000000;
   2073 		}
   2074 #else
   2075 		for (; row < 32; row++) {
   2076 			*hwp++ = 0xffffffff;
   2077 			*hwp++ = 0x00000000;
   2078 		}
   2079 #endif
   2080 
   2081 		free(image, M_TEMP);
   2082 		RZ3SetupHWC(gp, 1, 0, 0, 0, 0);
   2083 	}
   2084 	if (info->set & GRFSPRSET_CMAP) {
   2085 		/* hey cheat a bit here.. XXX */
   2086 		WSeq(ba, SEQ_ID_CURSOR_COLOR0, 0);
   2087 		WSeq(ba, SEQ_ID_CURSOR_COLOR1, 1);
   2088 	}
   2089 	if (info->set & GRFSPRSET_ENABLE) {
   2090 #if 0
   2091 		if (info->enable)
   2092 			control = 0x85;
   2093 		else
   2094 			control = 0;
   2095 		WSeq(ba, SEQ_ID_CURSOR_CONTROL, control);
   2096 #endif
   2097 	}
   2098 	if (info->set & GRFSPRSET_POS)
   2099 		rh_setspritepos(gp, &info->pos);
   2100 	if (info->set & GRFSPRSET_HOT) {
   2101 		WSeq(ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x3f);
   2102 		WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
   2103 	}
   2104 
   2105 	return(0);
   2106 }
   2107 
   2108 int
   2109 rh_getspritemax(struct grf_softc *gp, struct grf_position *pos)
   2110 {
   2111 #ifdef RH_64BIT_SPRITE
   2112 	pos->x = 64;
   2113 	pos->y = 64;
   2114 #else
   2115 	pos->x = 32;
   2116 	pos->y = 32;
   2117 #endif
   2118 
   2119 	return(0);
   2120 }
   2121 
   2122 
   2123 int
   2124 rh_bitblt(struct grf_softc *gp, struct grf_bitblt *bb)
   2125 {
   2126 	struct MonDef *md = (struct MonDef *)gp->g_data;
   2127 	if (md->DEP <= 8)
   2128 		RZ3BitBlit(gp, bb);
   2129 	else if (md->DEP <= 16)
   2130 		RZ3BitBlit16(gp, bb);
   2131 	else
   2132 		RZ3BitBlit24(gp, bb);
   2133 
   2134 	return(0);
   2135 }
   2136 
   2137 
   2138 int
   2139 rh_blank(struct grf_softc *gp, int *on)
   2140 {
   2141 	struct MonDef *md = (struct MonDef *)gp->g_data;
   2142 	int r;
   2143 
   2144 	r = 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8);
   2145 
   2146 	WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? r : 0x21);
   2147 
   2148 	return(0);
   2149 }
   2150 
   2151 #endif	/* NGRF */
   2152