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