Home | History | Annotate | Line # | Download | only in dev
grf_rh.c revision 1.10
      1 /*	$NetBSD: grf_rh.c,v 1.10 1996/01/28 19:19:05 chopps 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 || zap->prodid != 16)
   1448 		return(0);
   1449 #ifdef RETINACONSOLE
   1450 	if (amiga_realconfig == 0 || rhconunit != cfp->cf_unit) {
   1451 #endif
   1452 		if ((unsigned)rh_default_mon >= rh_mon_max ||
   1453 		    monitor_defs[rh_default_mon].DEP == 8)
   1454 			rh_default_mon = 0;
   1455 		current_mon = monitor_defs + rh_default_mon;
   1456 		if (rh_mondefok(current_mon) == 0)
   1457 			return(0);
   1458 #ifdef RETINACONSOLE
   1459 		if (amiga_realconfig == 0) {
   1460 			rhconunit = cfp->cf_unit;
   1461 			cfdata = cfp;
   1462 		}
   1463 	}
   1464 #endif
   1465 	return(1);
   1466 }
   1467 
   1468 void
   1469 grfrhattach(pdp, dp, auxp)
   1470 	struct device *pdp, *dp;
   1471 	void *auxp;
   1472 {
   1473 	static struct grf_softc congrf;
   1474 	static int coninited;
   1475 	struct zbus_args *zap;
   1476 	struct grf_softc *gp;
   1477 
   1478 	zap = auxp;
   1479 
   1480 	if (dp == NULL)
   1481 		gp = &congrf;
   1482 	else
   1483 		gp = (struct grf_softc *)dp;
   1484 	if (dp != NULL && congrf.g_regkva != 0) {
   1485 		/*
   1486 		 * inited earlier, just copy (not device struct)
   1487 		 */
   1488 		bcopy(&congrf.g_display, &gp->g_display,
   1489 		    (char *)&gp[1] - (char *)&gp->g_display);
   1490 	} else {
   1491 		gp->g_regkva = (volatile caddr_t)zap->va;
   1492 		gp->g_fbkva = (volatile caddr_t)zap->va + LM_OFFSET;
   1493 		gp->g_unit = GRF_RETINAIII_UNIT;
   1494 		gp->g_mode = rh_mode;
   1495 		gp->g_conpri = grfrh_cnprobe();
   1496 		gp->g_flags = GF_ALIVE;
   1497 		grfrh_iteinit(gp);
   1498 		(void)rh_load_mon(gp, current_mon);
   1499 	}
   1500 	if (dp != NULL)
   1501 		printf("\n");
   1502 	/*
   1503 	 * attach grf
   1504 	 */
   1505 	amiga_config_found(cfdata, &gp->g_device, gp, grfrhprint);
   1506 }
   1507 
   1508 int
   1509 grfrhprint(auxp, pnp)
   1510 	void *auxp;
   1511 	char *pnp;
   1512 {
   1513 	if (pnp)
   1514 		printf("ite at %s", pnp);
   1515 	return(UNCONF);
   1516 }
   1517 
   1518 int
   1519 rh_getvmode(gp, vm)
   1520 	struct grf_softc *gp;
   1521 	struct grfvideo_mode *vm;
   1522 {
   1523 	struct MonDef *md;
   1524 
   1525 	if (vm->mode_num && vm->mode_num > rh_mon_max)
   1526 		return(EINVAL);
   1527 
   1528 	if (! vm->mode_num)
   1529 		vm->mode_num = (current_mon - monitor_defs) + 1;
   1530 
   1531 	md = monitor_defs + (vm->mode_num - 1);
   1532 	strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
   1533 	   sizeof (vm->mode_descr));
   1534 	vm->pixel_clock  = md->FQ;
   1535         vm->disp_width   = (md->DEP == 4) ? md->MW : md->TX;
   1536         vm->disp_height  = (md->DEP == 4) ? md->MH : md->TY;
   1537 	vm->depth        = md->DEP;
   1538 
   1539 	/*
   1540 	 * From observation of the monitor definition table above, I guess
   1541 	 * that the horizontal timings are in units of longwords. Hence, I
   1542 	 * get the pixels by multiplication with 32 and division by the depth.
   1543 	 * The text modes, apparently marked by depth == 4, are even more
   1544 	 * wierd. According to a comment above, they are computed from a
   1545 	 * depth==8 mode thats for us: * 32 / 8) by applying another factor
   1546 	 * of 4 / font width.
   1547 	 * Reverse applying the latter formula most of the constants cancel
   1548 	 * themselves and we are left with a nice (* font width).
   1549 	 * That is, internal timings are in units of longwords for graphics
   1550 	 * modes, or in units of characters widths for text modes.
   1551 	 * We better don't WRITE modes until this has been real live checked.
   1552 	 *                    - Ignatios Souvatzis
   1553 	 */
   1554 
   1555 	if (md->DEP == 4) {
   1556 		vm->hblank_start = md->HBS * 32 / md->DEP;
   1557 		vm->hblank_stop  = md->HBE * 32 / md->DEP;
   1558 		vm->hsync_start  = md->HSS * 32 / md->DEP;
   1559 		vm->hsync_stop   = md->HSE * 32 / md->DEP;
   1560 		vm->htotal       = md->HT * 32 / md->DEP;
   1561 	} else {
   1562 		vm->hblank_start = md->HBS * md->FX;
   1563 		vm->hblank_stop  = md->HBE * md->FX;
   1564 		vm->hsync_start  = md->HSS * md->FX;
   1565 		vm->hsync_stop   = md->HSE * md->FX;
   1566 		vm->htotal       = md->HT * md->FX;
   1567 	}
   1568 
   1569 	vm->vblank_start = md->VBS;
   1570 	vm->vblank_stop  = md->VBE;
   1571 	vm->vsync_start  = md->VSS;
   1572 	vm->vsync_stop   = md->VSE;
   1573 	vm->vtotal       = md->VT;
   1574 
   1575 	return(0);
   1576 }
   1577 
   1578 
   1579 int
   1580 rh_setvmode(gp, mode, type)
   1581 	struct grf_softc *gp;
   1582 	unsigned mode;
   1583         enum mode_type type;
   1584 {
   1585 	struct MonDef *md;
   1586 	int error;
   1587 
   1588 	if (!mode || mode > rh_mon_max)
   1589 		return(EINVAL);
   1590 
   1591         if ((type == MT_TXTONLY && monitor_defs[mode-1].DEP != 4)
   1592             || (type == MT_GFXONLY && monitor_defs[mode-1].DEP == 4))
   1593 		return(EINVAL);
   1594 
   1595 	current_mon = monitor_defs + (mode - 1);
   1596 
   1597 	error = rh_load_mon (gp, current_mon) ? 0 : EINVAL;
   1598 
   1599 	return(error);
   1600 }
   1601 
   1602 
   1603 /*
   1604  * Change the mode of the display.
   1605  * Return a UNIX error number or 0 for success.
   1606  */
   1607 rh_mode(gp, cmd, arg, a2, a3)
   1608 	register struct grf_softc *gp;
   1609 	int cmd;
   1610 	void *arg;
   1611 	int a2, a3;
   1612 {
   1613 	switch (cmd) {
   1614 	case GM_GRFON:
   1615                 rh_setvmode (gp, rh_default_gfx + 1, MT_GFXONLY);
   1616 		return(0);
   1617 
   1618 	case GM_GRFOFF:
   1619                 rh_setvmode (gp, rh_default_mon + 1, MT_TXTONLY);
   1620 		return(0);
   1621 
   1622 	case GM_GRFCONFIG:
   1623 		return(0);
   1624 
   1625 	case GM_GRFGETVMODE:
   1626 		return(rh_getvmode (gp, (struct grfvideo_mode *) arg));
   1627 
   1628 	case GM_GRFSETVMODE:
   1629                 return(rh_setvmode (gp, *(unsigned *) arg,
   1630                                     (gp->g_flags & GF_GRFON) ? MT_GFXONLY : MT_TXTONLY));
   1631 
   1632 	case GM_GRFGETNUMVM:
   1633 		*(int *)arg = rh_mon_max;
   1634 		return(0);
   1635 
   1636 #ifdef BANKEDDEVPAGER
   1637 	case GM_GRFGETBANK:
   1638 	case GM_GRFGETCURBANK:
   1639 	case GM_GRFSETBANK:
   1640 		return(EINVAL);
   1641 #endif
   1642 	case GM_GRFIOCTL:
   1643 		return(rh_ioctl (gp, (u_long) arg, (caddr_t) a2));
   1644 
   1645 	default:
   1646 		break;
   1647 	}
   1648 
   1649 	return(EINVAL);
   1650 }
   1651 
   1652 int
   1653 rh_ioctl (gp, cmd, data)
   1654 	register struct grf_softc *gp;
   1655 	u_long cmd;
   1656 	void *data;
   1657 {
   1658 	switch (cmd) {
   1659 	case GRFIOCGSPRITEPOS:
   1660 		return(rh_getspritepos (gp, (struct grf_position *) data));
   1661 
   1662 	case GRFIOCSSPRITEPOS:
   1663 		return(rh_setspritepos (gp, (struct grf_position *) data));
   1664 
   1665 	case GRFIOCSSPRITEINF:
   1666 		return(rh_setspriteinfo (gp, (struct grf_spriteinfo *) data));
   1667 
   1668 	case GRFIOCGSPRITEINF:
   1669 		return(rh_getspriteinfo (gp, (struct grf_spriteinfo *) data));
   1670 
   1671 	case GRFIOCGSPRITEMAX:
   1672 		return(rh_getspritemax (gp, (struct grf_position *) data));
   1673 
   1674 	case GRFIOCGETCMAP:
   1675 		return(rh_getcmap (gp, (struct grf_colormap *) data));
   1676 
   1677 	case GRFIOCPUTCMAP:
   1678 		return(rh_putcmap (gp, (struct grf_colormap *) data));
   1679 
   1680 	case GRFIOCBITBLT:
   1681 		return(rh_bitblt (gp, (struct grf_bitblt *) data));
   1682 	}
   1683 
   1684 	return(EINVAL);
   1685 }
   1686 
   1687 
   1688 int
   1689 rh_getcmap (gfp, cmap)
   1690 	struct grf_softc *gfp;
   1691 	struct grf_colormap *cmap;
   1692 {
   1693 	volatile unsigned char *ba;
   1694 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1695 	short x;
   1696 	int error;
   1697 
   1698 	if (cmap->count == 0 || cmap->index >= 256)
   1699 		return 0;
   1700 
   1701 	if (cmap->index + cmap->count > 256)
   1702 		cmap->count = 256 - cmap->index;
   1703 
   1704 	ba = gfp->g_regkva;
   1705 	/* first read colors out of the chip, then copyout to userspace */
   1706 	vgaw (ba, VDAC_ADDRESS_W, cmap->index);
   1707 	x = cmap->count - 1;
   1708 	rp = red + cmap->index;
   1709 	gp = green + cmap->index;
   1710 	bp = blue + cmap->index;
   1711 	do {
   1712 		*rp++ = vgar (ba, VDAC_DATA) << 2;
   1713 		*gp++ = vgar (ba, VDAC_DATA) << 2;
   1714 		*bp++ = vgar (ba, VDAC_DATA) << 2;
   1715 	} while (x-- > 0);
   1716 
   1717 	if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
   1718 	    && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
   1719 	    && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
   1720 		return(0);
   1721 
   1722 	return(error);
   1723 }
   1724 
   1725 int
   1726 rh_putcmap (gfp, cmap)
   1727 	struct grf_softc *gfp;
   1728 	struct grf_colormap *cmap;
   1729 {
   1730 	volatile unsigned char *ba;
   1731 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1732 	short x;
   1733 	int error;
   1734 
   1735 	if (cmap->count == 0 || cmap->index >= 256)
   1736 		return(0);
   1737 
   1738 	if (cmap->index + cmap->count > 256)
   1739 		cmap->count = 256 - cmap->index;
   1740 
   1741 	/* first copy the colors into kernelspace */
   1742 	if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
   1743 	    && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
   1744 	    && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
   1745 		/* argl.. LoadPalette wants a different format, so do it like with
   1746 		* Retina2.. */
   1747 		ba = gfp->g_regkva;
   1748 		vgaw (ba, VDAC_ADDRESS_W, cmap->index);
   1749 		x = cmap->count - 1;
   1750 		rp = red + cmap->index;
   1751 		gp = green + cmap->index;
   1752 		bp = blue + cmap->index;
   1753 		do {
   1754 			vgaw (ba, VDAC_DATA, *rp++ >> 2);
   1755 			vgaw (ba, VDAC_DATA, *gp++ >> 2);
   1756 			vgaw (ba, VDAC_DATA, *bp++ >> 2);
   1757 		} while (x-- > 0);
   1758 		return(0);
   1759 	}
   1760 	else
   1761 		return(error);
   1762 }
   1763 
   1764 int
   1765 rh_getspritepos (gp, pos)
   1766 	struct grf_softc *gp;
   1767 	struct grf_position *pos;
   1768 {
   1769 	volatile unsigned char *acm = gp->g_regkva + ACM_OFFSET;
   1770 
   1771 	pos->x = acm[ACM_CURSOR_POSITION + 0] +
   1772 	    (acm[ACM_CURSOR_POSITION + 1] << 8);
   1773 	pos->y = acm[ACM_CURSOR_POSITION + 2] +
   1774 	    (acm[ACM_CURSOR_POSITION + 3] << 8);
   1775 
   1776 	pos->x += xpan;
   1777 	pos->y += ypan;
   1778 
   1779 	return(0);
   1780 }
   1781 
   1782 int
   1783 rh_setspritepos (gp, pos)
   1784 	struct grf_softc *gp;
   1785 	struct grf_position *pos;
   1786 {
   1787 	RZ3SetHWCloc (gp, pos->x, pos->y);
   1788 	return(0);
   1789 }
   1790 
   1791 int
   1792 rh_getspriteinfo (gp, info)
   1793 	struct grf_softc *gp;
   1794 	struct grf_spriteinfo *info;
   1795 {
   1796 	volatile unsigned char *ba, *fb;
   1797 
   1798 	ba = gp->g_regkva;
   1799 	fb = gp->g_fbkva;
   1800 	if (info->set & GRFSPRSET_ENABLE)
   1801 		info->enable = RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
   1802 	if (info->set & GRFSPRSET_POS)
   1803 		rh_getspritepos (gp, &info->pos);
   1804 	if (info->set & GRFSPRSET_HOT) {
   1805 		info->hot.x = RSeq (ba, SEQ_ID_CURSOR_X_INDEX) & 0x3f;
   1806 		info->hot.y = RSeq (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
   1807 	}
   1808 	if (info->set & GRFSPRSET_CMAP) {
   1809 		struct grf_colormap cmap;
   1810 		int index;
   1811 		cmap.index = 0;
   1812 		cmap.count = 256;
   1813 		rh_getcmap (gp, &cmap);
   1814 		index = RSeq (ba, SEQ_ID_CURSOR_COLOR0);
   1815 		info->cmap.red[0] = cmap.red[index];
   1816 		info->cmap.green[0] = cmap.green[index];
   1817 		info->cmap.blue[0] = cmap.blue[index];
   1818 		index = RSeq (ba, SEQ_ID_CURSOR_COLOR1);
   1819 		info->cmap.red[1] = cmap.red[index];
   1820 		info->cmap.green[1] = cmap.green[index];
   1821 		info->cmap.blue[1] = cmap.blue[index];
   1822 	}
   1823 	if (info->set & GRFSPRSET_SHAPE) {
   1824 		u_char image[128], mask[128];
   1825 		volatile u_long *hwp;
   1826 		u_char *imp, *mp;
   1827 		short row;
   1828 
   1829 		/* sprite bitmap is WEIRD in this chip.. see grf_rhvar.h
   1830 		 * for an explanation. To convert to "our" format, the
   1831 		 * following holds:
   1832 		 *   col2   = !image & mask
   1833 		 *   col1   = image & mask
   1834 		 *   transp = !mask
   1835 		 * and thus:
   1836 		 *   image  = col1
   1837 		 *   mask   = col1 | col2
   1838 		 * hope I got these bool-eqs right below..
   1839 		 */
   1840 
   1841 #ifdef RH_64BIT_SPRITE
   1842 		info->size.x = 64;
   1843 		info->size.y = 64;
   1844 		for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
   1845 		    mp = mask, imp = image;
   1846 		    row < 64;
   1847 		    row++) {
   1848 			u_long bp10, bp20, bp11, bp21;
   1849 			bp10 = *hwp++;
   1850 			bp20 = *hwp++;
   1851 			bp11 = *hwp++;
   1852 			bp21 = *hwp++;
   1853 			M2I (bp10);
   1854 			M2I (bp20);
   1855 			M2I (bp11);
   1856 			M2I (bp21);
   1857 			*imp++ = (~bp10) & bp11;
   1858 			*imp++ = (~bp20) & bp21;
   1859 			*mp++  = (~bp10) | (bp10 & ~bp11);
   1860 			*mp++  = (~bp20) & (bp20 & ~bp21);
   1861 		}
   1862 #else
   1863                 info->size.x = 32;
   1864                 info->size.y = 32;
   1865                 for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
   1866                     mp = mask, imp = image;
   1867                     row < 32;
   1868                     row++) {
   1869                         u_long bp10, bp11;
   1870                         bp10 = *hwp++;
   1871                         bp11 = *hwp++;
   1872                         M2I (bp10);
   1873                         M2I (bp11);
   1874                         *imp++ = (~bp10) & bp11;
   1875                         *mp++  = (~bp10) | (bp10 & ~bp11);
   1876                 }
   1877 #endif
   1878 		copyout (image, info->image, sizeof (image));
   1879 		copyout (mask, info->mask, sizeof (mask));
   1880 	}
   1881 	return(0);
   1882 }
   1883 
   1884 int
   1885 rh_setspriteinfo (gp, info)
   1886 	struct grf_softc *gp;
   1887 	struct grf_spriteinfo *info;
   1888 {
   1889 	volatile unsigned char *ba, *fb;
   1890 	u_char control;
   1891 
   1892 	ba = gp->g_regkva;
   1893 	fb = gp->g_fbkva;
   1894 
   1895 	if (info->set & GRFSPRSET_SHAPE) {
   1896 		/*
   1897 		 * For an explanation of these weird actions here, see above
   1898 		 * when reading the shape.  We set the shape directly into
   1899 		 * the video memory, there's no reason to keep 1k on the
   1900 		 * kernel stack just as template
   1901 		 */
   1902 		u_char *image, *mask;
   1903 		volatile u_long *hwp;
   1904 		u_char *imp, *mp;
   1905 		short row;
   1906 
   1907 #ifdef RH_64BIT_SPRITE
   1908 		if (info->size.y > 64)
   1909 			info->size.y = 64;
   1910 		if (info->size.x > 64)
   1911 			info->size.x = 64;
   1912 #else
   1913                 if (info->size.y > 32)
   1914                         info->size.y = 32;
   1915                 if (info->size.x > 32)
   1916                         info->size.x = 32;
   1917 #endif
   1918 
   1919 		if (info->size.x < 32)
   1920 			info->size.x = 32;
   1921 
   1922 		image = malloc(HWC_MEM_SIZE, M_TEMP, M_WAITOK);
   1923 		mask  = image + HWC_MEM_SIZE/2;
   1924 
   1925 		copyin(info->image, image, info->size.y * info->size.x / 8);
   1926 		copyin(info->mask, mask, info->size.y * info->size.x / 8);
   1927 
   1928 		hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF);
   1929 
   1930 		/*
   1931 		 * setting it is slightly more difficult, because we can't
   1932 		 * force the application to not pass a *smaller* than
   1933 		 * supported bitmap
   1934 		 */
   1935 
   1936 		for (row = 0, mp = mask, imp = image;
   1937 		    row < info->size.y;
   1938 		    row++) {
   1939 			u_long im1, im2, m1, m2;
   1940 
   1941 			im1 = *(unsigned long *)imp;
   1942 			imp += 4;
   1943 			m1  = *(unsigned long *)mp;
   1944 			mp  += 4;
   1945 #ifdef RH_64BIT_SPRITE
   1946 			if (info->size.x > 32) {
   1947 	      			im2 = *(unsigned long *)imp;
   1948 				imp += 4;
   1949 				m2  = *(unsigned long *)mp;
   1950 				mp  += 4;
   1951 			}
   1952 			else
   1953 #endif
   1954 				im2 = m2 = 0;
   1955 
   1956 			M2I(im1);
   1957 			M2I(im2);
   1958 			M2I(m1);
   1959 			M2I(m2);
   1960 
   1961 			*hwp++ = ~m1;
   1962 #ifdef RH_64BIT_SPRITE
   1963 			*hwp++ = ~m2;
   1964 #endif
   1965 			*hwp++ = m1 & im1;
   1966 #ifdef RH_64BIT_SPRITE
   1967 			*hwp++ = m2 & im2;
   1968 #endif
   1969 		}
   1970 #ifdef RH_64BIT_SPRITE
   1971 		for (; row < 64; row++) {
   1972 			*hwp++ = 0xffffffff;
   1973 			*hwp++ = 0xffffffff;
   1974 			*hwp++ = 0x00000000;
   1975 			*hwp++ = 0x00000000;
   1976 		}
   1977 #else
   1978                 for (; row < 32; row++) {
   1979                         *hwp++ = 0xffffffff;
   1980                         *hwp++ = 0x00000000;
   1981                 }
   1982 #endif
   1983 
   1984 		free(image, M_TEMP);
   1985 		RZ3SetupHWC(gp, 1, 0, 0, 0, 0);
   1986 	}
   1987 	if (info->set & GRFSPRSET_CMAP) {
   1988 		/* hey cheat a bit here.. XXX */
   1989 		WSeq(ba, SEQ_ID_CURSOR_COLOR0, 0);
   1990 		WSeq(ba, SEQ_ID_CURSOR_COLOR1, 1);
   1991 	}
   1992 	if (info->set & GRFSPRSET_ENABLE) {
   1993 #if 0
   1994 		if (info->enable)
   1995 			control = 0x85;
   1996 		else
   1997 			control = 0;
   1998 		WSeq(ba, SEQ_ID_CURSOR_CONTROL, control);
   1999 #endif
   2000 	}
   2001 	if (info->set & GRFSPRSET_POS)
   2002 		rh_setspritepos(gp, &info->pos);
   2003 	if (info->set & GRFSPRSET_HOT) {
   2004 		WSeq(ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x3f);
   2005 		WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
   2006 	}
   2007 
   2008 	return(0);
   2009 }
   2010 
   2011 int
   2012 rh_getspritemax (gp, pos)
   2013 	struct grf_softc *gp;
   2014 	struct grf_position *pos;
   2015 {
   2016 #ifdef RH_64BIT_SPRITE
   2017 	pos->x = 64;
   2018 	pos->y = 64;
   2019 #else
   2020         pos->x = 32;
   2021         pos->y = 32;
   2022 #endif
   2023 
   2024 	return(0);
   2025 }
   2026 
   2027 
   2028 int
   2029 rh_bitblt (gp, bb)
   2030 	struct grf_softc *gp;
   2031 	struct grf_bitblt *bb;
   2032 {
   2033 	struct MonDef *md = (struct MonDef *)gp->g_data;
   2034         if (md->DEP <= 8)
   2035 		RZ3BitBlit(gp, bb);
   2036         else if (md->DEP <= 16)
   2037 		RZ3BitBlit16(gp, bb);
   2038         else
   2039                 RZ3BitBlit24(gp, bb);
   2040 }
   2041 #endif	/* NGRF */
   2042