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