xref: /netbsd-src/sys/arch/amiga/dev/grf_rh.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
1 /*	$NetBSD: grf_rh.c,v 1.24 1996/10/13 03:07:05 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1994 Markus Wild
5  * Copyright (c) 1994 Lutz Vieweg
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by Lutz Vieweg.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include "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 /* XXXXXXXXX !! */
595 static unsigned short xpan;
596 static unsigned short ypan;
597 
598 void
599 RZ3SetPanning (gp, xoff, yoff)
600 	struct grf_softc *gp;
601 	unsigned short xoff, yoff;
602 {
603 	volatile unsigned char *ba = gp->g_regkva;
604 	const struct MonDef * md = (struct MonDef *) gp->g_data;
605 	unsigned long off;
606 
607 	xpan = xoff;
608 	ypan = yoff;
609 
610 
611         if (md->DEP > 8 && md->DEP <= 16) xoff *= 2;
612         else if (md->DEP > 16) xoff *= 3;
613 
614 	vgar(ba, ACT_ADDRESS_RESET);
615 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, (unsigned char)((xoff << 1) & 0x07));
616 	/* have the color lookup function normally again */
617 	vgaw(ba,  ACT_ADDRESS_W, 0x20);
618 
619 	if (md->DEP == 8)
620 		off = ((yoff * md->TX)/ 4) + (xoff >> 2);
621         else if (md->DEP == 16)
622 		off = ((yoff * md->TX * 2)/ 4) + (xoff >> 2);
623         else
624                 off = ((yoff * md->TX * 3)/ 4) + (xoff >> 2);
625 	WCrt(ba, CRT_ID_START_ADDR_LOW, ((unsigned char)off));
626 	off >>= 8;
627 	WCrt(ba, CRT_ID_START_ADDR_HIGH, ((unsigned char)off));
628 	off >>= 8;
629 	WCrt(ba, CRT_ID_EXT_START_ADDR,
630 	    ((RCrt(ba, CRT_ID_EXT_START_ADDR) & 0xf0) | (off & 0x0f)));
631 
632 
633 }
634 
635 void
636 RZ3SetHWCloc (gp, x, y)
637 	struct grf_softc *gp;
638 	unsigned short x, y;
639 {
640 	volatile unsigned char *ba = gp->g_regkva;
641 	const struct MonDef *md = (struct MonDef *) gp->g_data;
642 	volatile unsigned char *acm = ba + ACM_OFFSET;
643 
644 	if (x < xpan)
645 		RZ3SetPanning(gp, x, ypan);
646 
647 	if (x >= (xpan+md->MW))
648 		RZ3SetPanning(gp, (1 + x - md->MW) , ypan);
649 
650 	if (y < ypan)
651 		RZ3SetPanning(gp, xpan, y);
652 
653 	if (y >= (ypan+md->MH))
654 		RZ3SetPanning(gp, xpan, (1 + y - md->MH));
655 
656 	x -= xpan;
657 	y -= ypan;
658 
659 	*(acm + (ACM_CURSOR_POSITION+0)) = x & 0xff;
660 	*(acm + (ACM_CURSOR_POSITION+1)) = x >> 8;
661 	*(acm + (ACM_CURSOR_POSITION+2)) = y & 0xff;
662 	*(acm + (ACM_CURSOR_POSITION+3)) = y >> 8;
663 }
664 
665 u_short
666 rh_CompFQ(fq)
667 	u_int fq;
668 {
669  	/* yuck... this sure could need some explanation.. */
670 
671 	unsigned long f = fq;
672 	long n2 = 3;
673 	long abw = 0x7fffffff;
674 	long n1 = 3;
675 	unsigned long m;
676 	unsigned short erg = 0;
677 
678 	f *= 8;
679 
680 	do {
681 
682 		if (f <= 250000000)
683 			break;
684 		f /= 2;
685 
686 	} while (n2-- > 0);
687 
688 	if (n2 < 0)
689 		return(0);
690 
691 
692 	do {
693 	  	long tmp;
694 
695 		f = fq;
696 		f >>= 3;
697 		f <<= n2;
698 		f >>= 7;
699 
700 		m = (f * n1) / (14318180/1024);
701 
702 		if (m > 129)
703 			break;
704 
705 		tmp =  (((m * 14318180) >> n2) / n1) - fq;
706 		if (tmp < 0)
707 			tmp = -tmp;
708 
709 		if (tmp < abw) {
710 			abw = tmp;
711 			erg = (((n2 << 5) | (n1-2)) << 8) | (m-2);
712 		}
713 
714 	} while ( (++n1) <= 21);
715 
716 	return(erg);
717 }
718 
719 int
720 rh_mondefok(mdp)
721 	struct MonDef *mdp;
722 {
723 	switch(mdp->DEP) {
724 	    case 8:
725 	    case 16:
726             case 24:
727 		return(1);
728 	    case 4:
729 		if (mdp->FX == 4 || (mdp->FX >= 7 && mdp->FX <= 16))
730 			return(1);
731 		/*FALLTHROUGH*/
732 	    default:
733 		return(0);
734 	}
735 }
736 
737 
738 int
739 rh_load_mon(gp, md)
740 	struct grf_softc *gp;
741 	struct MonDef *md;
742 {
743 	struct grfinfo *gi = &gp->g_display;
744 	volatile caddr_t ba;
745 	volatile caddr_t fb;
746 	short FW, clksel, HDE = 0, VDE;
747 	unsigned short *c, z;
748 	const unsigned char *f;
749 
750 	ba = gp->g_regkva;;
751 	fb = gp->g_fbkva;
752 
753 	/* provide all needed information in grf device-independant
754 	 * locations */
755 	gp->g_data 		= (caddr_t) md;
756 	gi->gd_regaddr	 	= (caddr_t) kvtop (ba);
757 	gi->gd_regsize		= LM_OFFSET;
758 	gi->gd_fbaddr		= (caddr_t) kvtop (fb);
759 	gi->gd_fbsize		= MEMSIZE *1024*1024;
760 #ifdef BANKEDDEVPAGER
761 	/* we're not using banks NO MORE! */
762 	gi->gd_bank_size	= 0;
763 #endif
764 	gi->gd_colors		= 1 << md->DEP;
765 	gi->gd_planes		= md->DEP;
766 
767 	if (md->DEP == 4) {
768 		gi->gd_fbwidth	= md->MW;
769 		gi->gd_fbheight	= md->MH;
770 		gi->gd_fbx	= 0;
771 		gi->gd_fby	= 0;
772 		gi->gd_dwidth	= md->TX * md->FX;
773 		gi->gd_dheight	= md->TY * md->FY;
774 		gi->gd_dx	= 0;
775 		gi->gd_dy	= 0;
776 	} else {
777 		gi->gd_fbwidth	= md->TX;
778 		gi->gd_fbheight	= md->TY;
779 		gi->gd_fbx	= 0;
780 		gi->gd_fby	= 0;
781 		gi->gd_dwidth	= md->MW;
782 		gi->gd_dheight	= md->MH;
783 		gi->gd_dx	= 0;
784 		gi->gd_dy	= 0;
785 	}
786 
787 	FW =0;
788 	if (md->DEP == 4) {		/* XXX some text-mode! */
789 		switch (md->FX) {
790 		    case 4:
791 			FW = 0;
792 			break;
793 		    case 7:
794 			FW = 1;
795 			break;
796 		    case 8:
797 			FW = 2;
798 			break;
799 		    case 9:
800 			FW = 3;
801 			break;
802 		    case 10:
803 			FW = 4;
804 			break;
805 		    case 11:
806 			FW = 5;
807 			break;
808 		    case 12:
809 			FW = 6;
810 			break;
811 		    case 13:
812 			FW = 7;
813 			break;
814 		    case 14:
815 			FW = 8;
816 			break;
817 		    case 15:
818 			FW = 9;
819 			break;
820 		    case 16:
821 			FW = 11;
822 			break;
823 		    default:
824 			return(0);
825 			break;
826 		}
827 	}
828 
829         if      (md->DEP == 4)  HDE = (md->MW+md->FX-1)/md->FX;
830         else if (md->DEP == 8)  HDE = (md->MW+3)/4;
831         else if (md->DEP == 16) HDE = (md->MW*2+3)/4;
832         else if (md->DEP == 24) HDE = (md->MW*3+3)/4;
833 
834 	VDE = md->MH-1;
835 
836 	clksel = 0;
837 
838 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
839 	vgaw(ba, GREG_FEATURE_CONTROL_W, 0x00);
840 
841 	WSeq(ba, SEQ_ID_RESET, 0x00);
842 	WSeq(ba, SEQ_ID_RESET, 0x03);
843 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
844 	WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
845 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
846 	WSeq(ba, SEQ_ID_MEMORY_MODE, 0x06);
847 	WSeq(ba, SEQ_ID_RESET, 0x01);
848 	WSeq(ba, SEQ_ID_RESET, 0x03);
849 
850 	WSeq(ba, SEQ_ID_EXTENDED_ENABLE, 0x05);
851 	WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x00);
852 	WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
853 	WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
854 	WSeq(ba, SEQ_ID_LINEAR_0, 0x4a);
855 	WSeq(ba, SEQ_ID_LINEAR_1, 0x00);
856 
857 	WSeq(ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00);
858 	WSeq(ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00);
859 	WSeq(ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
860 	WSeq(ba, SEQ_ID_EXT_CLOCK_MODE, 0x10 | (FW & 0x0f));
861 	WSeq(ba, SEQ_ID_EXT_VIDEO_ADDR, 0x03);
862 	if (md->DEP == 4) {
863 	  	/* 8bit pixel, no gfx byte path */
864 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
865         }
866         else if (md->DEP == 8) {
867 	  	/* 8bit pixel, gfx byte path */
868 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01);
869         }
870         else if (md->DEP == 16) {
871 	  	/* 16bit pixel, gfx byte path */
872 		WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x11);
873 	}
874         else if (md->DEP == 24) {
875                 /* 24bit pixel, gfx byte path */
876                 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x21);
877         }
878 	WSeq(ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x04);
879 	WSeq(ba, SEQ_ID_COLOR_EXP_WFG, 0x01);
880 	WSeq(ba, SEQ_ID_COLOR_EXP_WBG, 0x00);
881 	WSeq(ba, SEQ_ID_EXT_RW_CONTROL, 0x00);
882 	WSeq(ba, SEQ_ID_MISC_FEATURE_SEL, (0x51 | (clksel & 8)));
883 	WSeq(ba, SEQ_ID_COLOR_KEY_CNTL, 0x40);
884 	WSeq(ba, SEQ_ID_COLOR_KEY_MATCH0, 0x00);
885 	WSeq(ba, SEQ_ID_COLOR_KEY_MATCH1, 0x00);
886 	WSeq(ba, SEQ_ID_COLOR_KEY_MATCH2, 0x00);
887 	WSeq(ba, SEQ_ID_CRC_CONTROL, 0x00);
888 	WSeq(ba, SEQ_ID_PERF_SELECT, 0x10);
889 	WSeq(ba, SEQ_ID_ACM_APERTURE_1, 0x00);
890 	WSeq(ba, SEQ_ID_ACM_APERTURE_2, 0x30);
891 	WSeq(ba, SEQ_ID_ACM_APERTURE_3, 0x00);
892 	WSeq(ba, SEQ_ID_MEMORY_MAP_CNTL, 0x07);
893 
894 	WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x20);
895 	WCrt(ba, CRT_ID_HOR_TOTAL, md->HT    & 0xff);
896 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1)   & 0xff);
897 	WCrt(ba, CRT_ID_START_HOR_BLANK, md->HBS   & 0xff);
898 	WCrt(ba, CRT_ID_END_HOR_BLANK, (md->HBE   & 0x1f) | 0x80);
899 
900 	WCrt(ba, CRT_ID_START_HOR_RETR, md->HSS   & 0xff);
901 	WCrt(ba, CRT_ID_END_HOR_RETR,
902 	    (md->HSE & 0x1f)   |
903 	    ((md->HBE & 0x20)/ 0x20 * 0x80));
904 	WCrt(ba, CRT_ID_VER_TOTAL,  (md->VT  & 0xff));
905 	WCrt(ba, CRT_ID_OVERFLOW,
906 	    ((md->VSS & 0x200) / 0x200 * 0x80) |
907 	    ((VDE     & 0x200) / 0x200 * 0x40) |
908 	    ((md->VT  & 0x200) / 0x200 * 0x20) |
909 	    0x10                               |
910 	    ((md->VBS & 0x100) / 0x100 * 8)    |
911 	    ((md->VSS & 0x100) / 0x100 * 4)    |
912 	    ((VDE     & 0x100) / 0x100 * 2)    |
913 	    ((md->VT  & 0x100) / 0x100));
914 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
915 
916 	if (md->DEP == 4) {
917 		WCrt(ba, CRT_ID_MAX_SCAN_LINE,
918 		    ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
919 		    0x40 |
920 		    ((md->VBS & 0x200)/0x200*0x20) |
921 		    ((md->FY-1) & 0x1f));
922 	} else {
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 		    (0 & 0x1f));
928 	}
929 
930 	/* I prefer "_" cursor to "block" cursor.. */
931 #if 1
932 	WCrt(ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
933 	WCrt(ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
934 #else
935 	WCrt(ba, CRT_ID_CURSOR_START, 0x00);
936 	WCrt(ba, CRT_ID_CURSOR_END, md->FY & 0x1f);
937 #endif
938 
939 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
940 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
941 
942 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
943 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
944 
945 	WCrt(ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
946 	WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x80 | 0x20);
947 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE  & 0xff);
948 
949         if (md->DEP == 4) {
950                 WCrt(ba, CRT_ID_OFFSET, (HDE / 2) & 0xff );
951         }
952         /* all gfx-modes are in byte-mode, means values are multiplied by 8 */
953         else if (md->DEP == 8) {
954                 WCrt(ba, CRT_ID_OFFSET, (md->TX / 8) & 0xff );
955         } else if (md->DEP == 16) {
956                 WCrt(ba, CRT_ID_OFFSET, (md->TX / 4) & 0xff );
957         } else {
958                 WCrt(ba, CRT_ID_OFFSET, (md->TX * 3 / 8) & 0xff );
959         }
960 
961 	WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
962 	WCrt(ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff);
963 	WCrt(ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
964 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
965 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
966 
967 	WCrt(ba, CRT_ID_EXT_HOR_TIMING1,
968 		    0 | 0x20                                    |
969 		    ((md->FLG & MDF_LACE)  / MDF_LACE   * 0x10) |
970 		    ((md->HT  & 0x100) / 0x100)                 |
971 		    (((HDE-1) & 0x100) / 0x100 * 2)             |
972 		    ((md->HBS & 0x100) / 0x100 * 4)             |
973 		    ((md->HSS & 0x100) / 0x100 * 8));
974 
975         if (md->DEP == 4) {
976                 WCrt(ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16));
977         }
978         else if (md->DEP == 8) {
979                 WCrt(ba, CRT_ID_EXT_START_ADDR, (((md->TX / 8) & 0x100)/0x100 * 16));
980         } else if (md->DEP == 16) {
981                 WCrt(ba, CRT_ID_EXT_START_ADDR, (((md->TX / 4) & 0x100)/0x100 * 16));
982         } else {
983                 WCrt(ba, CRT_ID_EXT_START_ADDR, (((md->TX * 3 / 8) & 0x100)/0x100 * 16));
984         }
985 
986 	WCrt(ba, CRT_ID_EXT_HOR_TIMING2,
987 		    ((md->HT  & 0x200)/ 0x200)       |
988 	            (((HDE-1) & 0x200)/ 0x200 * 2  ) |
989 	            ((md->HBS & 0x200)/ 0x200 * 4  ) |
990 	            ((md->HSS & 0x200)/ 0x200 * 8  ) |
991 	            ((md->HBE & 0xc0) / 0x40  * 16 ) |
992 	            ((md->HSE & 0x60) / 0x20  * 64));
993 
994 	WCrt(ba, CRT_ID_EXT_VER_TIMING,
995 		    ((md->VSE & 0x10) / 0x10  * 0x80  ) |
996 		    ((md->VBE & 0x300)/ 0x100 * 0x20  ) |
997 		    0x10                                |
998 		    ((md->VSS & 0x400)/ 0x400 * 8     ) |
999 		    ((md->VBS & 0x400)/ 0x400 * 4     ) |
1000 		    ((VDE     & 0x400)/ 0x400 * 2     ) |
1001 		    ((md->VT & 0x400)/ 0x400));
1002 	WCrt(ba, CRT_ID_MONITOR_POWER, 0x00);
1003 
1004 	{
1005 		unsigned short tmp = rh_CompFQ(md->FQ);
1006 		WPLL(ba, 2   , tmp);
1007                 tmp = rh_CompFQ(rh_memclk);
1008 		WPLL(ba,10   , tmp);
1009 		WPLL(ba,14   , 0x22);
1010 	}
1011 
1012 	WGfx(ba, GCT_ID_SET_RESET, 0x00);
1013 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
1014 	WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
1015 	WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
1016 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1017 	WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
1018 	if (md->DEP == 4)
1019 		WGfx(ba, GCT_ID_MISC, 0x04);
1020 	else
1021 		WGfx(ba, GCT_ID_MISC, 0x05);
1022 	WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
1023 	WGfx(ba, GCT_ID_BITMASK, 0xff);
1024 
1025 	vgar(ba, ACT_ADDRESS_RESET);
1026 	WAttr(ba, ACT_ID_PALETTE0 , 0x00);
1027 	WAttr(ba, ACT_ID_PALETTE1 , 0x01);
1028 	WAttr(ba, ACT_ID_PALETTE2 , 0x02);
1029 	WAttr(ba, ACT_ID_PALETTE3 , 0x03);
1030 	WAttr(ba, ACT_ID_PALETTE4 , 0x04);
1031 	WAttr(ba, ACT_ID_PALETTE5 , 0x05);
1032 	WAttr(ba, ACT_ID_PALETTE6 , 0x06);
1033 	WAttr(ba, ACT_ID_PALETTE7 , 0x07);
1034 	WAttr(ba, ACT_ID_PALETTE8 , 0x08);
1035 	WAttr(ba, ACT_ID_PALETTE9 , 0x09);
1036 	WAttr(ba, ACT_ID_PALETTE10, 0x0a);
1037 	WAttr(ba, ACT_ID_PALETTE11, 0x0b);
1038 	WAttr(ba, ACT_ID_PALETTE12, 0x0c);
1039 	WAttr(ba, ACT_ID_PALETTE13, 0x0d);
1040 	WAttr(ba, ACT_ID_PALETTE14, 0x0e);
1041 	WAttr(ba, ACT_ID_PALETTE15, 0x0f);
1042 
1043 	vgar(ba, ACT_ADDRESS_RESET);
1044 	if (md->DEP == 4)
1045 		WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
1046 	else
1047 		WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x09);
1048 
1049 	WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
1050 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
1051 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
1052 	WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
1053 
1054 	vgar(ba, ACT_ADDRESS_RESET);
1055 	vgaw(ba, ACT_ADDRESS_W, 0x20);
1056 
1057 	vgaw(ba, VDAC_MASK, 0xff);
1058         /* probably some PLL timing stuff here. The value
1059            for 24bit was found by trial&error :-) */
1060         if (md->DEP < 16) {
1061                 vgaw(ba, 0x83c6, ((0 & 7) << 5) );
1062         }
1063         else if (md->DEP == 16) {
1064 	  	/* well... */
1065                 vgaw(ba, 0x83c6, ((3 & 7) << 5) );
1066         }
1067         else if (md->DEP == 24) {
1068                 vgaw(ba, 0x83c6, 0xe0);
1069         }
1070 	vgaw(ba, VDAC_ADDRESS_W, 0x00);
1071 
1072 	if (md->DEP < 16) {
1073 		short x = 256-17;
1074 		unsigned char cl = 16;
1075 		RZ3LoadPalette(gp, md->PAL, 0, 16);
1076 		do {
1077 			vgaw(ba, VDAC_DATA, (cl >> 2));
1078 			vgaw(ba, VDAC_DATA, (cl >> 2));
1079 			vgaw(ba, VDAC_DATA, (cl >> 2));
1080 			cl++;
1081 		} while (x-- > 0);
1082 	}
1083 
1084 	if (md->DEP == 4) {
1085 		{
1086 			struct grf_bitblt bb = {
1087 				GRFBBOPset,
1088 				0, 0,
1089 				0, 0,
1090 				md->TX*4, 2*md->TY,
1091 				EMPTY_ALPHA
1092 			};
1093 			RZ3BitBlit(gp, &bb);
1094 		}
1095 
1096 		c = (unsigned short *)(ba + LM_OFFSET);
1097 		c += 2 * md->FLo*32;
1098 		c += 1;
1099 		f = md->FData;
1100 		for (z = md->FLo; z <= md->FHi; z++) {
1101 			short y = md->FY-1;
1102 			if (md->FX > 8){
1103 				do {
1104 					*c = *((const unsigned short *)f);
1105 					c += 2;
1106 					f += 2;
1107 				} while (y-- > 0);
1108 			} else {
1109 				do {
1110 					*c = (*f++) << 8;
1111 					c += 2;
1112 				} while (y-- > 0);
1113 			}
1114 
1115 			c += 2 * (32-md->FY);
1116 		}
1117 		{
1118 			unsigned long * pt = (unsigned long *) (ba + LM_OFFSET + PAT_MEM_OFF);
1119 			unsigned long tmp  = 0xffff0000;
1120 			*pt++ = tmp;
1121 			*pt = tmp;
1122 		}
1123 
1124 		WSeq(ba, SEQ_ID_MAP_MASK, 3);
1125 
1126 		c = (unsigned short *)(ba + LM_OFFSET);
1127 		c += (md->TX-6)*2;
1128 		{
1129 		  	/* it's show-time :-) */
1130 			static unsigned short init_msg[6] = {
1131 				0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f
1132 			};
1133 			unsigned short * m = init_msg;
1134 			short x = 5;
1135 			do {
1136 				*c = *m++;
1137 				c += 2;
1138 			} while (x-- > 0);
1139 		}
1140 
1141 		return(1);
1142 	} else if (md->DEP == 8) {
1143 		struct grf_bitblt bb = {
1144 			GRFBBOPset,
1145 			0, 0,
1146 			0, 0,
1147 			md->TX, md->TY,
1148 			0x0000
1149 		};
1150 		WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
1151 
1152 		RZ3BitBlit(gp, &bb);
1153 
1154 		xpan = 0;
1155 		ypan = 0;
1156 
1157 		return(1);
1158 	} else if (md->DEP == 16) {
1159 		struct grf_bitblt bb = {
1160 			GRFBBOPset,
1161 			0, 0,
1162 			0, 0,
1163 			md->TX, md->TY,
1164 			0x0000
1165 		};
1166 		WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
1167 
1168 		RZ3BitBlit16(gp, &bb);
1169 
1170 		xpan = 0;
1171 		ypan = 0;
1172 
1173 		return(1);
1174         } else if (md->DEP == 24) {
1175                 struct grf_bitblt bb = {
1176                         GRFBBOPset,
1177                         0, 0,
1178                         0, 0,
1179                         md->TX, md->TY,
1180                         0x0000
1181                 };
1182                 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f );
1183 
1184                 RZ3BitBlit24(gp, &bb );
1185 
1186                 xpan = 0;
1187                 ypan = 0;
1188 
1189                 return 1;
1190 	} else
1191 		return(0);
1192 }
1193 
1194 /* standard-palette definition */
1195 
1196 unsigned char RZ3StdPalette[16*3] = {
1197 /*        R   G   B  */
1198 	  0,  0,  0,
1199 	192,192,192,
1200 	128,  0,  0,
1201 	  0,128,  0,
1202 	  0,  0,128,
1203 	128,128,  0,
1204 	  0,128,128,
1205 	128,  0,128,
1206 	 64, 64, 64, /* the higher 8 colors have more intensity for  */
1207 	255,255,255, /* compatibility with standard attributes       */
1208 	255,  0,  0,
1209 	  0,255,  0,
1210 	  0,  0,255,
1211 	255,255,  0,
1212 	  0,255,255,
1213 	255,  0,255
1214 };
1215 
1216 /*
1217  * The following structures are examples for monitor-definitions. To make one
1218  * of your own, first use "DefineMonitor" and create the 8-bit or 16-bit
1219  * monitor-mode of your dreams. Then save it, and make a structure from the
1220  * values provided in the file DefineMonitor stored - the labels in the comment
1221  * above the structure definition show where to put what value.
1222  *
1223  * If you want to use your definition for the text-mode, you'll need to adapt
1224  * your 8-bit monitor-definition to the font you want to use. Be FX the width of
1225  * the font, then the following modifications have to be applied to your values:
1226  *
1227  * HBS = (HBS * 4) / FX
1228  * HSS = (HSS * 4) / FX
1229  * HSE = (HSE * 4) / FX
1230  * HBE = (HBE * 4) / FX
1231  * HT  = (HT  * 4) / FX
1232  *
1233  * Make sure your maximum width (MW) and height (MH) are even multiples of
1234  * the fonts' width and height.
1235  *
1236  * You may use definitons created by the old DefineMonitor, but you'll get
1237  * better results with the new DefineMonitor supplied along with the Retin Z3.
1238 */
1239 
1240 /*
1241  *  FQ     FLG    MW   MH   HBS HSS HSE HBE  HT  VBS  VSS  VSE  VBE   VT
1242  * Depth,          PAL, TX,  TY,    XY,FontX, FontY,    FontData,  FLo,  Fhi
1243  */
1244 #ifdef KFONT_8X11
1245 #define KERNEL_FONT kernel_font_8x11
1246 #define FY 11
1247 #define FX  8
1248 #else
1249 #define KERNEL_FONT kernel_font_8x8
1250 #define FY  8
1251 #define FX  8
1252 #endif
1253 
1254 
1255 static struct MonDef monitor_defs[] = {
1256   /* Text-mode definitions */
1257 
1258   /* horizontal 31.5 kHz */
1259   { 50000000,  28,  640, 512,   81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
1260       4, RZ3StdPalette, 80,  64,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1261 
1262   /* horizontal 38kHz */
1263   { 75000000,  28,  768, 600,   97, 99,107,120,117, 601, 615, 625, 638, 638,
1264       4, RZ3StdPalette, 96,  75,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1265 
1266   /* horizontal 64kHz */
1267   { 50000000, 24,  768, 600,   97,104,112,122,119, 601, 606, 616, 628, 628,
1268       4, RZ3StdPalette, 96,  75,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1269 
1270   /* 8-bit gfx-mode definitions */
1271 
1272   /* IMPORTANT: the "logical" screen size can be up to 2048x2048 pixels,
1273      independent from the "physical" screen size. If your code does NOT
1274      support panning, please adjust the "logical" screen sizes below to
1275      match the physical ones
1276    */
1277 
1278 #ifdef RH_HARDWARECURSOR
1279 
1280   /* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */
1281   { 26000000,  0,  640, 480,  161,175,188,200,199, 481, 483, 491, 502, 502,
1282       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1283   /* This is the logical ^    ^    screen size */
1284 
1285   /* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */
1286  { 31000000,  0,  640, 480,  161,169,182,198,197, 481, 482, 490, 502, 502,
1287      8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1288 
1289   /* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */
1290   { 39000000,  0,  800, 600,  201,211,227,249,248, 601, 603, 613, 628, 628,
1291       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1292 
1293   /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
1294   { 82000000,  0, 1024, 768,  257,257,277,317,316, 769, 771, 784, 804, 804,
1295       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1296 
1297   /* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */
1298   { 97000000,  0, 1120, 896,  281,283,306,369,368, 897, 898, 913, 938, 938,
1299       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1300 
1301   /* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */
1302   {110000000,  0, 1152, 910,  289,310,333,357,356, 911, 923, 938, 953, 953,
1303       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1304 
1305   /* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */
1306   {110000000,  0, 1184, 848,  297,319,342,370,369, 849, 852, 866, 888, 888,
1307       8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1308 
1309   /* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */
1310   {104000000, 0, 1280,1024,  321,323,348,399,398,1025,1026,1043,1073,1073,
1311      8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1312 
1313 /*
1314  * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1315  *          HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1316  *          MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
1317  */
1318   /* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */
1319   {121000000, 0, 1280,1024,  321,322,347,397,396,1025,1026,1043,1073,1073,
1320      8, RZ3StdPalette,1280,1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1321 
1322 
1323   /* 16-bit gfx-mode definitions */
1324 
1325   /* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */
1326   { 51000000, 0,  640, 480,  321,344,369,397,396, 481, 482, 490, 502, 502,
1327       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1328 
1329   /* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */
1330   { 77000000, 0,  800, 600,  401,418,449,496,495, 601, 602, 612, 628, 628,
1331       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1332 
1333   /* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */
1334   {110000000,  0, 1024, 768,  513,514,554,639,638, 769, 770, 783, 804, 804,
1335       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1336 
1337   /* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */
1338   {109000000,  0,  864, 648,  433,434,468,537,536, 649, 650, 661, 678, 678,
1339       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1340 
1341 /*
1342  * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1343  *          HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1344  *          MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
1345  */
1346   /* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */
1347   {124000000,  0, 1024, 768,  513,537,577,636,635, 769, 770, 783, 804, 804,
1348       16,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1349 
1350 
1351   /* 24-bit gfx-mode definitions */
1352 
1353   /* 320 x 200, 24 Bit, 35060 Hz, 83 Hz d */
1354   { 46000000,  1,  320, 200,  241,268,287,324,323, 401, 405, 412, 418, 418,
1355       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1356 
1357   /* 640 x 400, 24 Bit, 31404 Hz, 75 Hz */
1358   { 76000000,  0,  640, 400,  481,514,552,601,600, 401, 402, 409, 418, 418,
1359       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1360 
1361   /* 724 x 482, 24 Bit, 36969 Hz, 73 Hz */
1362   {101000000,  0,  724, 482,  544,576,619,682,678, 483, 487, 495, 495, 504,
1363       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1364 
1365   /* 800 x 600, 24 Bit, 37826 Hz, 60 Hz */
1366   {110000000,  0,  800, 600,  601,602,647,723,722, 601, 602, 612, 628, 628,
1367       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1368 
1369   /* 800 x 600, 24 Bit, 43824 Hz, 69 Hz */
1370   {132000000,  0,  800, 600,  601,641,688,749,748, 601, 611, 621, 628, 628,
1371       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1372 
1373   /*1024 x 768, 24 Bit, 32051 Hz, 79 Hz i */
1374   {110000000,  2, 1024, 768,  769,770,824,854,853, 385, 386, 392, 401, 401,
1375       24,           0,1280, 1024,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1376 
1377 #else /* RH_HARDWARECURSOR */
1378 
1379   /* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */
1380   { 26000000,  0,  640, 480,  161,175,188,200,199, 481, 483, 491, 502, 502,
1381       8, RZ3StdPalette,  640,  480,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1382   /* This is the logical  ^     ^    screen size */
1383 
1384   /* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */
1385  { 31000000,  0,  640, 480,  161,169,182,198,197, 481, 482, 490, 502, 502,
1386      8, RZ3StdPalette,  640,  480,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1387 
1388   /* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */
1389   { 39000000,  0,  800, 600,  201,211,227,249,248, 601, 603, 613, 628, 628,
1390       8, RZ3StdPalette,  800,  600,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1391 
1392   /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
1393   { 82000000,  0, 1024, 768,  257,257,277,317,316, 769, 771, 784, 804, 804,
1394       8, RZ3StdPalette, 1024,  768,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1395 
1396   /* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */
1397   { 97000000,  0, 1120, 896,  281,283,306,369,368, 897, 898, 913, 938, 938,
1398       8, RZ3StdPalette, 1120,  896,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1399 
1400   /* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */
1401   {110000000,  0, 1152, 910,  289,310,333,357,356, 911, 923, 938, 953, 953,
1402       8, RZ3StdPalette, 1152,  910,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1403 
1404   /* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */
1405   {110000000,  0, 1184, 848,  297,319,342,370,369, 849, 852, 866, 888, 888,
1406       8, RZ3StdPalette, 1184,  848,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1407 
1408   /* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */
1409   {104000000, 0, 1280,1024,  321,323,348,399,398,1025,1026,1043,1073,1073,
1410      8, RZ3StdPalette, 1280, 1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1411 
1412 /*
1413  * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1414  *            HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1415  *            MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
1416  */
1417   /* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */
1418   {121000000, 0, 1280,1024,  321,322,347,397,396,1025,1026,1043,1073,1073,
1419      8, RZ3StdPalette, 1280, 1024,  5120,   FX,    FY, KERNEL_FONT,   32,  255},
1420 
1421 
1422   /* 16-bit gfx-mode definitions */
1423 
1424   /* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */
1425   { 51000000, 0,  640, 480,  321,344,369,397,396, 481, 482, 490, 502, 502,
1426       16,           0,  640,  480,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1427 
1428   /* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */
1429   { 77000000, 0,  800, 600,  401,418,449,496,495, 601, 602, 612, 628, 628,
1430       16,           0,  800,  600,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1431 
1432   /* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */
1433   {110000000,  0, 1024, 768,  513,514,554,639,638, 769, 770, 783, 804, 804,
1434       16,           0, 1024,  768,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1435 
1436   /* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */
1437   {109000000,  0,  864, 648,  433,434,468,537,536, 649, 650, 661, 678, 678,
1438       16,           0,  864,  648,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1439 
1440 /*
1441  * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1442  *          HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1443  *          MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
1444  */
1445   /* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */
1446   {124000000,  0, 1024, 768,  513,537,577,636,635, 769, 770, 783, 804, 804,
1447       16,           0, 1024,  768,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1448 
1449 
1450   /* 24-bit gfx-mode definitions */
1451 
1452   /* 320 x 200, 24 Bit, 35060 Hz, 83 Hz d */
1453   { 46000000,  1,  320, 200,  241,268,287,324,323, 401, 405, 412, 418, 418,
1454       24,           0,  320,  200,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1455 
1456   /* 640 x 400, 24 Bit, 31404 Hz, 75 Hz */
1457   { 76000000,  0,  640, 400,  481,514,552,601,600, 401, 402, 409, 418, 418,
1458       24,           0,  640,  400,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1459 
1460   /* 724 x 482, 24 Bit, 36969 Hz, 73 Hz */
1461   {101000000,  0,  724, 482,  544,576,619,682,678, 483, 487, 495, 495, 504,
1462       24,           0,  724,  482,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1463 
1464   /* 800 x 600, 24 Bit, 37826 Hz, 60 Hz */
1465   {110000000,  0,  800, 600,  601,602,647,723,722, 601, 602, 612, 628, 628,
1466       24,           0,  800,  600,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1467 
1468   /* 800 x 600, 24 Bit, 43824 Hz, 69 Hz */
1469   {132000000,  0,  800, 600,  601,641,688,749,748, 601, 611, 621, 628, 628,
1470       24,           0,  800,  600,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1471 
1472   /*1024 x 768, 24 Bit, 32051 Hz, 79 Hz i */
1473   {110000000,  2, 1024, 768,  769,770,824,854,853, 385, 386, 392, 401, 401,
1474       24,           0, 1024,  768,  7200,   FX,    FY, KERNEL_FONT,   32,  255},
1475 
1476 #endif /* RH_HARDWARECURSOR */
1477 };
1478 #undef KERNEL_FONT
1479 #undef FX
1480 #undef FY
1481 
1482 static const char *monitor_descr[] = {
1483 #ifdef KFONT_8X11
1484   "80x46 (640x506) 31.5kHz",
1485   "96x54 (768x594) 38kHz",
1486   "96x54 (768x594) 64kHz",
1487 #else
1488   "80x64 (640x512) 31.5kHz",
1489   "96x75 (768x600) 38kHz",
1490   "96x75 (768x600) 64kHz",
1491 #endif
1492 
1493   "GFX-8 (640x480) 31.5kHz",
1494   "GFX-8 (640x480) 38kHz",
1495   "GFX-8 (800x600) 38.5kHz",
1496   "GFX-8 (1024x768) 64kHz",
1497   "GFX-8 (1120x896) 64kHz",
1498   "GFX-8 (1152x910) 76kHz",
1499   "GFX-8 (1182x848) 73kHz",
1500   "GFX-8 (1280x1024) 64.5kHz",
1501   "GFX-8 (1280x1024) 75.5kHz ***EXCEEDS CHIP LIMIT!!!***",
1502 
1503   "GFX-16 (640x480) 31.8kHz",
1504   "GFX-16 (800x600) 38.5kHz",
1505   "GFX-16 (1024x768) 42.8kHz",
1506   "GFX-16 (864x648) 50kHz",
1507   "GFX-16 (1024x768) 48.5kHz ***EXCEEDS CHIP LIMIT!!!***",
1508 
1509   "GFX-24 (320x200 d) 35kHz",
1510   "GFX-24 (640x400) 31.4kHz",
1511   "GFX-24 (724x482) 37kHz",
1512   "GFX-24 (800x600) 38kHz",
1513   "GFX-24 (800x600) 44kHz ***EXCEEDS CHIP LIMIT!!!***",
1514   "GFX-24 (1024x768) 32kHz-i",
1515 };
1516 
1517 int rh_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
1518 
1519 /* patchable */
1520 int rh_default_mon = 0;
1521 int rh_default_gfx = 4;
1522 
1523 static struct MonDef *current_mon;	/* EVIL */
1524 
1525 int  rh_mode     __P((struct grf_softc *, u_long, void *, u_long, int));
1526 void grfrhattach __P((struct device *, struct device *, void *));
1527 int  grfrhprint  __P((void *, const char *));
1528 int  grfrhmatch  __P((struct device *, void *, void *));
1529 
1530 struct cfattach grfrh_ca = {
1531 	sizeof(struct grf_softc), grfrhmatch, grfrhattach
1532 };
1533 
1534 struct cfdriver grfrh_cd = {
1535 	NULL, "grfrh", DV_DULL, NULL, 0
1536 };
1537 
1538 static struct cfdata *cfdata;
1539 
1540 int
1541 grfrhmatch(pdp, match, auxp)
1542 	struct device *pdp;
1543 	void *match, *auxp;
1544 {
1545 #ifdef RETINACONSOLE
1546 	struct cfdata *cfp = match;
1547 	static int rhconunit = -1;
1548 #endif
1549 	struct zbus_args *zap;
1550 
1551 	zap = auxp;
1552 
1553 	if (amiga_realconfig == 0)
1554 #ifdef RETINACONSOLE
1555 		if (rhconunit != -1)
1556 #endif
1557 			return(0);
1558 	if (zap->manid != 18260 ||
1559 			((zap->prodid != 16) && (zap->prodid != 19)))
1560 		return(0);
1561 #ifdef RETINACONSOLE
1562 	if (amiga_realconfig == 0 || rhconunit != cfp->cf_unit) {
1563 #endif
1564 		if ((unsigned)rh_default_mon >= rh_mon_max ||
1565 		    monitor_defs[rh_default_mon].DEP == 8)
1566 			rh_default_mon = 0;
1567 		current_mon = monitor_defs + rh_default_mon;
1568 		if (rh_mondefok(current_mon) == 0)
1569 			return(0);
1570 #ifdef RETINACONSOLE
1571 		if (amiga_realconfig == 0) {
1572 			rhconunit = cfp->cf_unit;
1573 			cfdata = cfp;
1574 		}
1575 	}
1576 #endif
1577 	return(1);
1578 }
1579 
1580 void
1581 grfrhattach(pdp, dp, auxp)
1582 	struct device *pdp, *dp;
1583 	void *auxp;
1584 {
1585 	static struct grf_softc congrf;
1586 	struct zbus_args *zap;
1587 	struct grf_softc *gp;
1588 
1589 	zap = auxp;
1590 
1591 	if (dp == NULL)
1592 		gp = &congrf;
1593 	else
1594 		gp = (struct grf_softc *)dp;
1595 	if (dp != NULL && congrf.g_regkva != 0) {
1596 		/*
1597 		 * inited earlier, just copy (not device struct)
1598 		 */
1599 		bcopy(&congrf.g_display, &gp->g_display,
1600 		    (char *)&gp[1] - (char *)&gp->g_display);
1601 	} else {
1602 		gp->g_regkva = (volatile caddr_t)zap->va;
1603 		gp->g_fbkva = (volatile caddr_t)zap->va + LM_OFFSET;
1604 		gp->g_unit = GRF_RETINAIII_UNIT;
1605 		gp->g_mode = rh_mode;
1606 		gp->g_conpri = grfrh_cnprobe();
1607 		gp->g_flags = GF_ALIVE;
1608 		grfrh_iteinit(gp);
1609 		(void)rh_load_mon(gp, current_mon);
1610 	}
1611 	if (dp != NULL)
1612 		printf("\n");
1613 	/*
1614 	 * attach grf
1615 	 */
1616 	amiga_config_found(cfdata, &gp->g_device, gp, grfrhprint);
1617 }
1618 
1619 int
1620 grfrhprint(auxp, pnp)
1621 	void *auxp;
1622 	const char *pnp;
1623 {
1624 	if (pnp)
1625 		printf("ite at %s", pnp);
1626 	return(UNCONF);
1627 }
1628 
1629 int
1630 rh_getvmode(gp, vm)
1631 	struct grf_softc *gp;
1632 	struct grfvideo_mode *vm;
1633 {
1634 	struct MonDef *md;
1635 
1636 	if (vm->mode_num && vm->mode_num > rh_mon_max)
1637 		return(EINVAL);
1638 
1639 	if (! vm->mode_num)
1640 		vm->mode_num = (current_mon - monitor_defs) + 1;
1641 
1642 	md = monitor_defs + (vm->mode_num - 1);
1643 	strncpy (vm->mode_descr, monitor_descr[vm->mode_num - 1],
1644 	   sizeof (vm->mode_descr));
1645 	vm->pixel_clock  = md->FQ;
1646         vm->disp_width   = (md->DEP == 4) ? md->MW : md->TX;
1647         vm->disp_height  = (md->DEP == 4) ? md->MH : md->TY;
1648 	vm->depth        = md->DEP;
1649 
1650 	/*
1651 	 * From observation of the monitor definition table above, I guess
1652 	 * that the horizontal timings are in units of longwords. Hence, I
1653 	 * get the pixels by multiplication with 32 and division by the depth.
1654 	 * The text modes, apparently marked by depth == 4, are even more
1655 	 * wierd. According to a comment above, they are computed from a
1656 	 * depth==8 mode thats for us: * 32 / 8) by applying another factor
1657 	 * of 4 / font width.
1658 	 * Reverse applying the latter formula most of the constants cancel
1659 	 * themselves and we are left with a nice (* font width).
1660 	 * That is, internal timings are in units of longwords for graphics
1661 	 * modes, or in units of characters widths for text modes.
1662 	 * We better don't WRITE modes until this has been real live checked.
1663 	 *                    - Ignatios Souvatzis
1664 	 */
1665 
1666 	if (md->DEP == 4) {
1667 		vm->hblank_start = md->HBS * 32 / md->DEP;
1668 		vm->hblank_stop  = md->HBE * 32 / md->DEP;
1669 		vm->hsync_start  = md->HSS * 32 / md->DEP;
1670 		vm->hsync_stop   = md->HSE * 32 / md->DEP;
1671 		vm->htotal       = md->HT * 32 / md->DEP;
1672 	} else {
1673 		vm->hblank_start = md->HBS * md->FX;
1674 		vm->hblank_stop  = md->HBE * md->FX;
1675 		vm->hsync_start  = md->HSS * md->FX;
1676 		vm->hsync_stop   = md->HSE * md->FX;
1677 		vm->htotal       = md->HT * md->FX;
1678 	}
1679 
1680 	vm->vblank_start = md->VBS;
1681 	vm->vblank_stop  = md->VBE;
1682 	vm->vsync_start  = md->VSS;
1683 	vm->vsync_stop   = md->VSE;
1684 	vm->vtotal       = md->VT;
1685 
1686 	return(0);
1687 }
1688 
1689 
1690 int
1691 rh_setvmode(gp, mode, type)
1692 	struct grf_softc *gp;
1693 	unsigned mode;
1694         enum mode_type type;
1695 {
1696 	int error;
1697 
1698 	if (!mode || mode > rh_mon_max)
1699 		return(EINVAL);
1700 
1701         if ((type == MT_TXTONLY && monitor_defs[mode-1].DEP != 4)
1702             || (type == MT_GFXONLY && monitor_defs[mode-1].DEP == 4))
1703 		return(EINVAL);
1704 
1705 	current_mon = monitor_defs + (mode - 1);
1706 
1707 	error = rh_load_mon (gp, current_mon) ? 0 : EINVAL;
1708 
1709 	return(error);
1710 }
1711 
1712 
1713 /*
1714  * Change the mode of the display.
1715  * Return a UNIX error number or 0 for success.
1716  */
1717 int
1718 rh_mode(gp, cmd, arg, a2, a3)
1719 	register struct grf_softc *gp;
1720 	u_long cmd;
1721 	void *arg;
1722 	u_long a2;
1723 	int a3;
1724 {
1725 	switch (cmd) {
1726 	    case GM_GRFON:
1727                 rh_setvmode (gp, rh_default_gfx + 1, MT_GFXONLY);
1728 		return(0);
1729 
1730 	    case GM_GRFOFF:
1731                 rh_setvmode (gp, rh_default_mon + 1, MT_TXTONLY);
1732 		return(0);
1733 
1734 	    case GM_GRFCONFIG:
1735 		return(0);
1736 
1737 	    case GM_GRFGETVMODE:
1738 		return(rh_getvmode (gp, (struct grfvideo_mode *) arg));
1739 
1740 	    case GM_GRFSETVMODE:
1741                 return(rh_setvmode (gp, *(unsigned *) arg,
1742                                     (gp->g_flags & GF_GRFON) ? MT_GFXONLY : MT_TXTONLY));
1743 
1744 	    case GM_GRFGETNUMVM:
1745 		*(int *)arg = rh_mon_max;
1746 		return(0);
1747 
1748 #ifdef BANKEDDEVPAGER
1749 	    case GM_GRFGETBANK:
1750 	    case GM_GRFGETCURBANK:
1751 	    case GM_GRFSETBANK:
1752 		return(EINVAL);
1753 #endif
1754 	    case GM_GRFIOCTL:
1755 		return(rh_ioctl (gp, a2, arg));
1756 
1757 	    default:
1758 		break;
1759 	}
1760 
1761 	return(EINVAL);
1762 }
1763 
1764 int
1765 rh_ioctl (gp, cmd, data)
1766 	register struct grf_softc *gp;
1767 	u_long cmd;
1768 	void *data;
1769 {
1770 	switch (cmd) {
1771 #ifdef RH_HARDWARECURSOR
1772 	    case GRFIOCGSPRITEPOS:
1773 		return(rh_getspritepos (gp, (struct grf_position *) data));
1774 
1775 	    case GRFIOCSSPRITEPOS:
1776 		return(rh_setspritepos (gp, (struct grf_position *) data));
1777 
1778 	    case GRFIOCSSPRITEINF:
1779 		return(rh_setspriteinfo (gp, (struct grf_spriteinfo *) data));
1780 
1781 	    case GRFIOCGSPRITEINF:
1782 		return(rh_getspriteinfo (gp, (struct grf_spriteinfo *) data));
1783 
1784 	    case GRFIOCGSPRITEMAX:
1785 		return(rh_getspritemax (gp, (struct grf_position *) data));
1786 #else /* RH_HARDWARECURSOR */
1787 	    case GRFIOCGSPRITEPOS:
1788 	    case GRFIOCSSPRITEPOS:
1789 	    case GRFIOCSSPRITEINF:
1790 	    case GRFIOCGSPRITEMAX:
1791 		break;
1792 #endif /* RH_HARDWARECURSOR */
1793 
1794 	    case GRFIOCGETCMAP:
1795 		return(rh_getcmap (gp, (struct grf_colormap *) data));
1796 
1797 	    case GRFIOCPUTCMAP:
1798 		return(rh_putcmap (gp, (struct grf_colormap *) data));
1799 
1800 	    case GRFIOCBITBLT:
1801 		return(rh_bitblt (gp, (struct grf_bitblt *) data));
1802 
1803 	    case GRFIOCBLANK:
1804 		return (rh_blank(gp, (int *)data));
1805 	}
1806 
1807 	return(EINVAL);
1808 }
1809 
1810 
1811 int
1812 rh_getcmap (gfp, cmap)
1813 	struct grf_softc *gfp;
1814 	struct grf_colormap *cmap;
1815 {
1816 	volatile unsigned char *ba;
1817 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1818 	short x;
1819 	int error;
1820 
1821 	if (cmap->count == 0 || cmap->index >= 256)
1822 		return 0;
1823 
1824 	if (cmap->index + cmap->count > 256)
1825 		cmap->count = 256 - cmap->index;
1826 
1827 	ba = gfp->g_regkva;
1828 	/* first read colors out of the chip, then copyout to userspace */
1829 	vgaw (ba, VDAC_ADDRESS_W, cmap->index);
1830 	x = cmap->count - 1;
1831 	rp = red + cmap->index;
1832 	gp = green + cmap->index;
1833 	bp = blue + cmap->index;
1834 	do {
1835 		*rp++ = vgar (ba, VDAC_DATA) << 2;
1836 		*gp++ = vgar (ba, VDAC_DATA) << 2;
1837 		*bp++ = vgar (ba, VDAC_DATA) << 2;
1838 	} while (x-- > 0);
1839 
1840 	if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
1841 	    && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
1842 	    && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
1843 		return(0);
1844 
1845 	return(error);
1846 }
1847 
1848 int
1849 rh_putcmap (gfp, cmap)
1850 	struct grf_softc *gfp;
1851 	struct grf_colormap *cmap;
1852 {
1853 	volatile unsigned char *ba;
1854 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1855 	short x;
1856 	int error;
1857 
1858 	if (cmap->count == 0 || cmap->index >= 256)
1859 		return(0);
1860 
1861 	if (cmap->index + cmap->count > 256)
1862 		cmap->count = 256 - cmap->index;
1863 
1864 	/* first copy the colors into kernelspace */
1865 	if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
1866 	    && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
1867 	    && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
1868 		/* argl.. LoadPalette wants a different format, so do it like with
1869 		* Retina2.. */
1870 		ba = gfp->g_regkva;
1871 		vgaw (ba, VDAC_ADDRESS_W, cmap->index);
1872 		x = cmap->count - 1;
1873 		rp = red + cmap->index;
1874 		gp = green + cmap->index;
1875 		bp = blue + cmap->index;
1876 		do {
1877 			vgaw (ba, VDAC_DATA, *rp++ >> 2);
1878 			vgaw (ba, VDAC_DATA, *gp++ >> 2);
1879 			vgaw (ba, VDAC_DATA, *bp++ >> 2);
1880 		} while (x-- > 0);
1881 		return(0);
1882 	}
1883 	else
1884 		return(error);
1885 }
1886 
1887 int
1888 rh_getspritepos (gp, pos)
1889 	struct grf_softc *gp;
1890 	struct grf_position *pos;
1891 {
1892 	volatile unsigned char *acm = gp->g_regkva + ACM_OFFSET;
1893 
1894 	pos->x = acm[ACM_CURSOR_POSITION + 0] +
1895 	    (acm[ACM_CURSOR_POSITION + 1] << 8);
1896 	pos->y = acm[ACM_CURSOR_POSITION + 2] +
1897 	    (acm[ACM_CURSOR_POSITION + 3] << 8);
1898 
1899 	pos->x += xpan;
1900 	pos->y += ypan;
1901 
1902 	return(0);
1903 }
1904 
1905 int
1906 rh_setspritepos (gp, pos)
1907 	struct grf_softc *gp;
1908 	struct grf_position *pos;
1909 {
1910 	RZ3SetHWCloc (gp, pos->x, pos->y);
1911 	return(0);
1912 }
1913 
1914 int
1915 rh_getspriteinfo (gp, info)
1916 	struct grf_softc *gp;
1917 	struct grf_spriteinfo *info;
1918 {
1919 	volatile unsigned char *ba, *fb;
1920 
1921 	ba = gp->g_regkva;
1922 	fb = gp->g_fbkva;
1923 	if (info->set & GRFSPRSET_ENABLE)
1924 		info->enable = RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
1925 	if (info->set & GRFSPRSET_POS)
1926 		rh_getspritepos (gp, &info->pos);
1927 	if (info->set & GRFSPRSET_HOT) {
1928 		info->hot.x = RSeq (ba, SEQ_ID_CURSOR_X_INDEX) & 0x3f;
1929 		info->hot.y = RSeq (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
1930 	}
1931 	if (info->set & GRFSPRSET_CMAP) {
1932 		struct grf_colormap cmap;
1933 		int index;
1934 		cmap.index = 0;
1935 		cmap.count = 256;
1936 		rh_getcmap (gp, &cmap);
1937 		index = RSeq (ba, SEQ_ID_CURSOR_COLOR0);
1938 		info->cmap.red[0] = cmap.red[index];
1939 		info->cmap.green[0] = cmap.green[index];
1940 		info->cmap.blue[0] = cmap.blue[index];
1941 		index = RSeq (ba, SEQ_ID_CURSOR_COLOR1);
1942 		info->cmap.red[1] = cmap.red[index];
1943 		info->cmap.green[1] = cmap.green[index];
1944 		info->cmap.blue[1] = cmap.blue[index];
1945 	}
1946 	if (info->set & GRFSPRSET_SHAPE) {
1947 		u_char image[128], mask[128];
1948 		volatile u_long *hwp;
1949 		u_char *imp, *mp;
1950 		short row;
1951 
1952 		/* sprite bitmap is WEIRD in this chip.. see grf_rhvar.h
1953 		 * for an explanation. To convert to "our" format, the
1954 		 * following holds:
1955 		 *   col2   = !image & mask
1956 		 *   col1   = image & mask
1957 		 *   transp = !mask
1958 		 * and thus:
1959 		 *   image  = col1
1960 		 *   mask   = col1 | col2
1961 		 * hope I got these bool-eqs right below..
1962 		 */
1963 
1964 #ifdef RH_64BIT_SPRITE
1965 		info->size.x = 64;
1966 		info->size.y = 64;
1967 		for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
1968 		    mp = mask, imp = image;
1969 		    row < 64;
1970 		    row++) {
1971 			u_long bp10, bp20, bp11, bp21;
1972 			bp10 = *hwp++;
1973 			bp20 = *hwp++;
1974 			bp11 = *hwp++;
1975 			bp21 = *hwp++;
1976 			M2I (bp10);
1977 			M2I (bp20);
1978 			M2I (bp11);
1979 			M2I (bp21);
1980 			*imp++ = (~bp10) & bp11;
1981 			*imp++ = (~bp20) & bp21;
1982 			*mp++  = (~bp10) | (bp10 & ~bp11);
1983 			*mp++  = (~bp20) & (bp20 & ~bp21);
1984 		}
1985 #else
1986                 info->size.x = 32;
1987                 info->size.y = 32;
1988                 for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
1989                     mp = mask, imp = image;
1990                     row < 32;
1991                     row++) {
1992                         u_long bp10, bp11;
1993                         bp10 = *hwp++;
1994                         bp11 = *hwp++;
1995                         M2I (bp10);
1996                         M2I (bp11);
1997                         *imp++ = (~bp10) & bp11;
1998                         *mp++  = (~bp10) | (bp10 & ~bp11);
1999                 }
2000 #endif
2001 		copyout (image, info->image, sizeof (image));
2002 		copyout (mask, info->mask, sizeof (mask));
2003 	}
2004 	return(0);
2005 }
2006 
2007 int
2008 rh_setspriteinfo (gp, info)
2009 	struct grf_softc *gp;
2010 	struct grf_spriteinfo *info;
2011 {
2012 	volatile unsigned char *ba, *fb;
2013 #if 0
2014 	u_char control;
2015 #endif
2016 
2017 	ba = gp->g_regkva;
2018 	fb = gp->g_fbkva;
2019 
2020 	if (info->set & GRFSPRSET_SHAPE) {
2021 		/*
2022 		 * For an explanation of these weird actions here, see above
2023 		 * when reading the shape.  We set the shape directly into
2024 		 * the video memory, there's no reason to keep 1k on the
2025 		 * kernel stack just as template
2026 		 */
2027 		u_char *image, *mask;
2028 		volatile u_long *hwp;
2029 		u_char *imp, *mp;
2030 		short row;
2031 
2032 #ifdef RH_64BIT_SPRITE
2033 		if (info->size.y > 64)
2034 			info->size.y = 64;
2035 		if (info->size.x > 64)
2036 			info->size.x = 64;
2037 #else
2038                 if (info->size.y > 32)
2039                         info->size.y = 32;
2040                 if (info->size.x > 32)
2041                         info->size.x = 32;
2042 #endif
2043 
2044 		if (info->size.x < 32)
2045 			info->size.x = 32;
2046 
2047 		image = malloc(HWC_MEM_SIZE, M_TEMP, M_WAITOK);
2048 		mask  = image + HWC_MEM_SIZE/2;
2049 
2050 		copyin(info->image, image, info->size.y * info->size.x / 8);
2051 		copyin(info->mask, mask, info->size.y * info->size.x / 8);
2052 
2053 		hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF);
2054 
2055 		/*
2056 		 * setting it is slightly more difficult, because we can't
2057 		 * force the application to not pass a *smaller* than
2058 		 * supported bitmap
2059 		 */
2060 
2061 		for (row = 0, mp = mask, imp = image;
2062 		    row < info->size.y;
2063 		    row++) {
2064 			u_long im1, im2, m1, m2;
2065 
2066 			im1 = *(unsigned long *)imp;
2067 			imp += 4;
2068 			m1  = *(unsigned long *)mp;
2069 			mp  += 4;
2070 #ifdef RH_64BIT_SPRITE
2071 			if (info->size.x > 32) {
2072 	      			im2 = *(unsigned long *)imp;
2073 				imp += 4;
2074 				m2  = *(unsigned long *)mp;
2075 				mp  += 4;
2076 			}
2077 			else
2078 #endif
2079 				im2 = m2 = 0;
2080 
2081 			M2I(im1);
2082 			M2I(im2);
2083 			M2I(m1);
2084 			M2I(m2);
2085 
2086 			*hwp++ = ~m1;
2087 #ifdef RH_64BIT_SPRITE
2088 			*hwp++ = ~m2;
2089 #endif
2090 			*hwp++ = m1 & im1;
2091 #ifdef RH_64BIT_SPRITE
2092 			*hwp++ = m2 & im2;
2093 #endif
2094 		}
2095 #ifdef RH_64BIT_SPRITE
2096 		for (; row < 64; row++) {
2097 			*hwp++ = 0xffffffff;
2098 			*hwp++ = 0xffffffff;
2099 			*hwp++ = 0x00000000;
2100 			*hwp++ = 0x00000000;
2101 		}
2102 #else
2103                 for (; row < 32; row++) {
2104                         *hwp++ = 0xffffffff;
2105                         *hwp++ = 0x00000000;
2106                 }
2107 #endif
2108 
2109 		free(image, M_TEMP);
2110 		RZ3SetupHWC(gp, 1, 0, 0, 0, 0);
2111 	}
2112 	if (info->set & GRFSPRSET_CMAP) {
2113 		/* hey cheat a bit here.. XXX */
2114 		WSeq(ba, SEQ_ID_CURSOR_COLOR0, 0);
2115 		WSeq(ba, SEQ_ID_CURSOR_COLOR1, 1);
2116 	}
2117 	if (info->set & GRFSPRSET_ENABLE) {
2118 #if 0
2119 		if (info->enable)
2120 			control = 0x85;
2121 		else
2122 			control = 0;
2123 		WSeq(ba, SEQ_ID_CURSOR_CONTROL, control);
2124 #endif
2125 	}
2126 	if (info->set & GRFSPRSET_POS)
2127 		rh_setspritepos(gp, &info->pos);
2128 	if (info->set & GRFSPRSET_HOT) {
2129 		WSeq(ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x3f);
2130 		WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
2131 	}
2132 
2133 	return(0);
2134 }
2135 
2136 int
2137 rh_getspritemax (gp, pos)
2138 	struct grf_softc *gp;
2139 	struct grf_position *pos;
2140 {
2141 #ifdef RH_64BIT_SPRITE
2142 	pos->x = 64;
2143 	pos->y = 64;
2144 #else
2145         pos->x = 32;
2146         pos->y = 32;
2147 #endif
2148 
2149 	return(0);
2150 }
2151 
2152 
2153 int
2154 rh_bitblt (gp, bb)
2155 	struct grf_softc *gp;
2156 	struct grf_bitblt *bb;
2157 {
2158 	struct MonDef *md = (struct MonDef *)gp->g_data;
2159         if (md->DEP <= 8)
2160 		RZ3BitBlit(gp, bb);
2161         else if (md->DEP <= 16)
2162 		RZ3BitBlit16(gp, bb);
2163         else
2164                 RZ3BitBlit24(gp, bb);
2165 
2166 	return(0);
2167 }
2168 
2169 
2170 int
2171 rh_blank(gp, on)
2172 	struct grf_softc *gp;
2173 	int *on;
2174 {
2175 	struct MonDef *md = (struct MonDef *)gp->g_data;
2176 	int r;
2177 
2178 	r = 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8);
2179 
2180 	WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? r : 0x21);
2181 
2182 	return(0);
2183 }
2184 
2185 #endif	/* NGRF */
2186