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