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