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