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