xref: /netbsd-src/sys/arch/amiga/dev/grf_rh.c (revision ce0bb6e8d2e560ecacbe865a848624f94498063b)
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