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