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