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