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