Home | History | Annotate | Line # | Download | only in dev
grf_cv3d.c revision 1.8
      1 /*	$NetBSD: grf_cv3d.c,v 1.8 2002/01/26 13:40:54 aymeric Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1995 Michael Teske
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *      This product includes software developed by Ezra Story, by Kari
     18  *      Mettinen, and Michael Teske.
     19  * 4. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 #include "opt_amigacons.h"
     34 #include "grfcv3d.h"
     35 #if NGRFCV3D > 0
     36 
     37 /*
     38  * Graphics routines for the CyberVision 64/3D board, using the S3 ViRGE.
     39  *
     40  * Modified for CV64/3D from Michael Teske's CV driver by Tobias Abt 10/97.
     41  * Bugfixes by Bernd Ernesti 10/97.
     42  * Many thanks to Richard Hartmann who gave us his board so we could make
     43  * driver.
     44  *
     45  * TODO:
     46  *	- ZorroII support
     47  *	- Blitter support
     48  *	- Memcheck for 2MB boards (if they exists)
     49  */
     50 
     51 /* Thanks to Frank Mariak for these infos
     52 BOARDBASE
     53         +0x4000000      Memorybase start
     54         +0x4ffffff      Memorybase end
     55         +0x5000000      Img TransPort start
     56         +0x5007fff      Img TransPort end
     57         +0x5008000      MMIO Regbase start
     58         +0x500ffff      MMIO Regbase end
     59         +0x5800000      Img TransPort (rot) start
     60         +0x5807fff      Img TransPort (rot) end
     61         +0x7000000      Img TransPort (rot) start
     62         +0x7007fff      Img TransPort (rot) end
     63         +0x8000000      VCodeSwitch start
     64         +0x8000fff      VCodeSwitch end
     65         +0xc000000      IO Regbase start
     66         +0xc00ffff      IO Regbase end
     67         +0xc0e0000      PCI Cfg Base start
     68         +0xc0e0fff      PCI Cfg Base end
     69 
     70 Note: IO Regbase is needed fo wakeup of the board otherwise use
     71       MMIO Regbase
     72 */
     73 
     74 #include <sys/param.h>
     75 #include <sys/errno.h>
     76 #include <sys/ioctl.h>
     77 #include <sys/device.h>
     78 #include <sys/malloc.h>
     79 #include <sys/systm.h>
     80 #include <machine/cpu.h>
     81 #include <dev/cons.h>
     82 #include <amiga/dev/itevar.h>
     83 #include <amiga/amiga/device.h>
     84 #include <amiga/dev/grfioctl.h>
     85 #include <amiga/dev/grfvar.h>
     86 #include <amiga/dev/grf_cv3dreg.h>
     87 #include <amiga/dev/zbusvar.h>
     88 
     89 int	grfcv3dmatch(struct device *, struct cfdata *, void *);
     90 void	grfcv3dattach(struct device *, struct device *, void *);
     91 int	grfcv3dprint(void *, const char *);
     92 
     93 static int cv3d_has_4mb(volatile caddr_t);
     94 static unsigned short cv3d_compute_clock(unsigned long);
     95 void	cv3d_boardinit(struct grf_softc *);
     96 int	cv3d_getvmode(struct grf_softc *, struct grfvideo_mode *);
     97 int	cv3d_setvmode(struct grf_softc *, unsigned int);
     98 int	cv3d_blank(struct grf_softc *, int *);
     99 int	cv3d_mode(register struct grf_softc *, u_long, void *, u_long, int);
    100 int	cv3d_ioctl(register struct grf_softc *gp, u_long cmd, void *data);
    101 int	cv3d_setmonitor(struct grf_softc *, struct grfvideo_mode *);
    102 int	cv3d_getcmap(struct grf_softc *, struct grf_colormap *);
    103 int	cv3d_putcmap(struct grf_softc *, struct grf_colormap *);
    104 int	cv3d_toggle(struct grf_softc *);
    105 int	cv3d_mondefok(struct grfvideo_mode *);
    106 int	cv3d_load_mon(struct grf_softc *, struct grfcv3dtext_mode *);
    107 void	cv3d_inittextmode(struct grf_softc *);
    108 static	__inline void cv3dscreen(int, volatile caddr_t);
    109 static	__inline void cv3d_gfx_on_off(int, volatile caddr_t);
    110 
    111 #ifdef CV3D_HARDWARE_CURSOR
    112 int	cv3d_getspritepos(struct grf_softc *, struct grf_position *);
    113 int	cv3d_setspritepos(struct grf_softc *, struct grf_position *);
    114 int	cv3d_getspriteinfo(struct grf_softc *,struct grf_spriteinfo *);
    115 void	cv3d_setup_hwc(struct grf_softc *);
    116 int	cv3d_setspriteinfo(struct grf_softc *,struct grf_spriteinfo *);
    117 int	cv3d_getspritemax(struct grf_softc *,struct grf_position *);
    118 #endif	/* CV3D_HARDWARE_CURSOR */
    119 
    120 /* Graphics display definitions.
    121  * These are filled by 'grfconfig' using GRFIOCSETMON.
    122  */
    123 #define monitor_def_max 24
    124 static struct grfvideo_mode monitor_def[24] = {
    125 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
    126 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
    127 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
    128 };
    129 static struct grfvideo_mode *monitor_current = &monitor_def[0];
    130 #define MAXPIXELCLOCK 135000000 /* safety */
    131 
    132 int	cv3d_zorroIII = 0;	/* CV64/3D in ZorroII or ZorroIII mode */
    133 unsigned char cv3d_pass_toggle;	/* passthru status tracker */
    134 
    135 /* Console display definition.
    136  *   Default hardcoded text mode.  This grf_cv3d is set up to
    137  *   use one text mode only, and this is it.  You may use
    138  *   grfconfig to change the mode after boot.
    139  */
    140 
    141 /* Console font */
    142 #ifdef KFONT_8X11
    143 #define S3FONT kernel_font_8x11
    144 #define S3FONTY 11
    145 #else
    146 #define S3FONT kernel_font_8x8
    147 #define S3FONTY 8
    148 #endif
    149 extern unsigned char S3FONT[];
    150 
    151 /*
    152  * Define default console mode
    153  * (Internally, we still have to use hvalues/8!)
    154  */
    155 struct grfcv3dtext_mode cv3dconsole_mode = {
    156 	{255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8,
    157 	 481, 491, 493, 525, 0},
    158 	8, S3FONTY, 80, 480 / S3FONTY, S3FONT, 32, 255
    159 };
    160 
    161 /* Console colors */
    162 unsigned char cv3dconscolors[16][3] = {	/* background, foreground, hilite */
    163 	/*  R     G     B  */
    164 	{0x30, 0x30, 0x30},
    165 	{0x00, 0x00, 0x00},
    166 	{0x80, 0x00, 0x00},
    167 	{0x00, 0x80, 0x00},
    168 	{0x00, 0x00, 0x80},
    169 	{0x80, 0x80, 0x00},
    170 	{0x00, 0x80, 0x80},
    171 	{0x80, 0x00, 0x80},
    172 	{0xff, 0xff, 0xff},
    173 	{0x40, 0x40, 0x40},
    174 	{0xff, 0x00, 0x00},
    175 	{0x00, 0xff, 0x00},
    176 	{0x00, 0x00, 0xff},
    177 	{0xff, 0xff, 0x00},
    178 	{0x00, 0xff, 0xff},
    179 	{0x00, 0x00, 0xff}
    180 };
    181 
    182 static unsigned char clocks[]={
    183 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
    184 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
    185 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
    186 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
    187 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
    188 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
    189 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
    190 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
    191 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
    192 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
    193 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
    194 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
    195 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
    196 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
    197 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
    198 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
    199 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
    200 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
    201 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
    202 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
    203 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
    204 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
    205 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
    206 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
    207 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
    208 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
    209 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
    210 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
    211 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
    212 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
    213 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
    214 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
    215 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
    216 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
    217 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
    218 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
    219 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
    220 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
    221 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
    222 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
    223 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
    224 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
    225 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
    226 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
    227 0x13, 0x1,  0x13, 0x1,  0x7d, 0x27, 0x4c, 0x9,
    228 0x37, 0x22, 0x5b, 0xb,  0x71, 0x26, 0x5c, 0xb,
    229 0x6b, 0xd,  0x47, 0x23, 0x14, 0x1,  0x4f, 0x9,
    230 0x23, 0x3,  0x75, 0x26, 0x7d, 0xf,  0x1c, 0x2,
    231 0x51, 0x9,  0x59, 0x24, 0x61, 0xb,  0x69, 0x25,
    232 0x79, 0x26, 0x34, 0x5,  0x1d, 0x2,  0x6b, 0x25,
    233 0x54, 0x9,  0x35, 0x5,  0x45, 0x7,  0x6d, 0x25,
    234 0x7d, 0x26, 0x16, 0x1,  0x7f, 0x26, 0x77, 0xd,
    235 0x4f, 0x23, 0x78, 0xd,  0x2f, 0x21, 0x27, 0x3,
    236 0x1f, 0x2,  0x59, 0x9,  0x6a, 0xb,  0x73, 0x25,
    237 0x6b, 0xb,  0x63, 0x24, 0x5b, 0x9,  0x20, 0x2,
    238 0x7e, 0xd,  0x4b, 0x7,  0x65, 0x24, 0x43, 0x22,
    239 0x18, 0x1,  0x6f, 0xb,  0x5e, 0x9,  0x70, 0xb,
    240 0x2a, 0x3,  0x33, 0x4,  0x45, 0x6,  0x60, 0x9,
    241 0x7b, 0xc,  0x19, 0x1,  0x19, 0x1,  0x7d, 0xc,
    242 0x74, 0xb,  0x50, 0x7,  0x75, 0xb,  0x63, 0x9,
    243 0x51, 0x7,  0x23, 0x2,  0x3f, 0x5,  0x1a, 0x1,
    244 0x65, 0x9,  0x2d, 0x3,  0x40, 0x5,  0x0,  0x0,
    245 };
    246 
    247 
    248 /* Board Address of CV64/3D */
    249 static volatile caddr_t cv3d_boardaddr;
    250 static int cv3d_fbsize;
    251 
    252 static volatile caddr_t cv3d_memory_io_base;
    253 static volatile caddr_t cv3d_register_base;
    254 static volatile caddr_t cv3d_vcode_switch_base;
    255 static volatile caddr_t cv3d_special_register_base;
    256 
    257 /*
    258  * Memory clock (binpatchable).
    259  */
    260 long cv3d_memclk = 55000000;
    261 
    262 /* standard driver stuff */
    263 struct cfattach grfcv3d_ca = {
    264 	sizeof(struct grf_softc), grfcv3dmatch, grfcv3dattach
    265 };
    266 
    267 static struct cfdata *cfdata;
    268 
    269 #define CV3D_ULCURSOR	1	/* Underlined Cursor in textmode */
    270 
    271 /*
    272  * Get frambuffer memory size.
    273  * phase5 didn't provide the bit in CR36,
    274  * so we have to do it this way.
    275  * Return 0 for 2MB, 1 for 4MB
    276  */
    277 static int
    278 cv3d_has_4mb(volatile caddr_t fb)
    279 {
    280 #if 0	/* XXX */
    281 	volatile unsigned long *testfbw, *testfbr;
    282 
    283 	/* write patterns in memory and test if they can be read */
    284 	testfbw = (volatile unsigned long *)fb;
    285 	testfbr = (volatile unsigned long *)(fb + 0x02000000);
    286 	*testfbw = 0x87654321;
    287 	if (*testfbr != 0x87654321)
    288 		return (0);
    289 
    290 	/* upper memory region */
    291 	testfbw = (volatile unsigned long *)(fb + 0x00200000);
    292 	testfbr = (volatile unsigned long *)(fb + 0x02200000);
    293 	*testfbw = 0x87654321;
    294 	if (*testfbr != 0x87654321)
    295 		return (0);
    296 	*testfbw = 0xAAAAAAAA;
    297 	if (*testfbr != 0xAAAAAAAA)
    298 		return (0);
    299 	*testfbw = 0x55555555;
    300 	if (*testfbr != 0x55555555)
    301 		return (0);
    302 #endif
    303 	return (1);
    304 }
    305 
    306 int
    307 grfcv3dmatch(struct device *pdp, struct cfdata *cfp, void *auxp)
    308 {
    309 #ifdef CV3DCONSOLE
    310 	static int cv3dcons_unit = -1;
    311 #endif
    312 	struct zbus_args *zap;
    313 
    314 	zap = auxp;
    315 
    316 	if (amiga_realconfig == 0)
    317 #ifdef CV3DCONSOLE
    318 		if (cv3dcons_unit != -1)
    319 #endif
    320 			 return (0);
    321 
    322 	/*
    323 	 * Distinct between ZorroII or ZorroIII mode.
    324 	 * Note that iszthreepa(x) is true for the Z2 bus on the DraCo;
    325 	 * therefore we check for the size instead.
    326 	 */
    327 	cv3d_zorroIII = zap->size > 4*1024*1024;
    328 
    329 	/* Lets be Paranoid: Test man and prod id */
    330 	if (zap->manid != 8512 || zap->prodid != 67)
    331 		return (0);
    332 
    333 #ifndef CV3DONZORRO2
    334 	if (!cv3d_zorroIII) {
    335 		return (0);
    336 	}
    337 #endif
    338 
    339 	cv3d_boardaddr = zap->va;
    340 
    341 #ifdef CV3DCONSOLE
    342 	if (amiga_realconfig == 0) {
    343 		cv3dcons_unit = cfp->cf_unit;
    344 		cfdata = cfp;
    345 	}
    346 #endif
    347 
    348 	return (1);
    349 }
    350 
    351 void
    352 grfcv3dattach(struct device *pdp, struct device *dp, void *auxp)
    353 {
    354 	static struct grf_softc congrf;
    355 	struct zbus_args *zap;
    356 	struct grf_softc *gp;
    357 	static char attachflag = 0;
    358 
    359 	zap = auxp;
    360 
    361 	printf("\n");
    362 
    363 	/*
    364 	 * This function is called twice, once on console init (dp == NULL)
    365 	 * and once on "normal" grf7 init.
    366 	 */
    367 
    368 	if (dp == NULL) /* console init */
    369 		gp = &congrf;
    370 	else
    371 		gp = (struct grf_softc *)dp;
    372 
    373 	if (dp != NULL && congrf.g_regkva != 0) {
    374 		/*
    375 		 * inited earlier, just copy (not device struct)
    376 		 */
    377 
    378 		bcopy(&congrf.g_display, &gp->g_display,
    379 			(char *) &gp[1] - (char *) &gp->g_display);
    380 	} else {
    381 		if (cv3d_zorroIII) {
    382 			gp->g_fbkva =
    383 			    (volatile caddr_t)cv3d_boardaddr + 0x04800000;
    384 			cv3d_memory_io_base =
    385 			    (volatile caddr_t)cv3d_boardaddr + 0x05000000;
    386 			cv3d_register_base =
    387 			    (volatile caddr_t)cv3d_boardaddr + 0x05008000;
    388 			cv3d_vcode_switch_base =
    389 			    (volatile caddr_t)cv3d_boardaddr + 0x08000000;
    390 			cv3d_special_register_base =
    391 			    (volatile caddr_t)cv3d_boardaddr + 0x0C000000;
    392 		} else {
    393 			gp->g_fbkva =
    394 			    (volatile caddr_t)cv3d_boardaddr + 0x00000000;
    395 			cv3d_memory_io_base =
    396 			    (volatile caddr_t)cv3d_boardaddr + 0x003E0000;
    397 			cv3d_register_base =
    398 			    (volatile caddr_t)cv3d_boardaddr + 0x003C8000;
    399 			cv3d_vcode_switch_base =
    400 			    (volatile caddr_t)cv3d_boardaddr + 0x003A0000;
    401 			cv3d_special_register_base =
    402 			    (volatile caddr_t)cv3d_boardaddr + 0x003C0000;
    403 		}
    404 
    405 		gp->g_regkva = (volatile caddr_t)cv3d_register_base;
    406 
    407 		gp->g_unit = GRF_CV3D_UNIT;
    408 		gp->g_mode = cv3d_mode;
    409 		gp->g_conpri = grfcv3d_cnprobe();
    410 		gp->g_flags = GF_ALIVE;
    411 
    412 		/* wakeup the board */
    413 		cv3d_boardinit(gp);
    414 
    415 #ifdef CV3DCONSOLE
    416 		grfcv3d_iteinit(gp);
    417 		(void)cv3d_load_mon(gp, &cv3dconsole_mode);
    418 #endif
    419 	}
    420 
    421 	/*
    422 	 * attach grf
    423 	 */
    424 	if (amiga_config_found(cfdata, &gp->g_device, gp, grfcv3dprint)) {
    425 		if (dp != NULL)
    426 			printf("%s: CyberVision64/3D with %dMB being used\n",
    427 			    dp->dv_xname, cv3d_fbsize / 0x100000);
    428 		attachflag = 1;
    429 	} else {
    430 		if (!attachflag)
    431 			/*printf("grfcv3d unattached!!\n")*/;
    432 	}
    433 }
    434 
    435 int
    436 grfcv3dprint(void *auxp, const char *pnp)
    437 {
    438 	if (pnp)
    439 		printf("ite at %s: ", pnp);
    440 	return (UNCONF);
    441 }
    442 
    443 
    444 /*
    445  * Computes M, N, and R values from
    446  * given input frequency. It uses a table of
    447  * precomputed values, to keep CPU time low.
    448  *
    449  * The return value consist of:
    450  * lower byte:  Bits 4-0: N Divider Value
    451  *	        Bits 5-6: R Value          for e.g. SR10 or SR12
    452  * higher byte: Bits 0-6: M divider value  for e.g. SR11 or SR13
    453  */
    454 
    455 static unsigned short
    456 cv3d_compute_clock(unsigned long freq)
    457 {
    458 	static unsigned char *mnr, *save;	/* M, N + R vals */
    459 	unsigned long work_freq, r;
    460 	unsigned short erg;
    461 	long diff, d2;
    462 
    463 	if (freq < 12500000 || freq > MAXPIXELCLOCK) {
    464 		printf("grfcv3d: Illegal clock frequency: %ldMHz\n", freq/1000000);
    465 		printf("grfcv3d: Using default frequency: 25MHz\n");
    466 		printf("grfcv3d: See the manpage of grfconfig for more informations.\n");
    467 		freq = 25000000;
    468 	}
    469 
    470 	mnr = clocks;	/* there the vals are stored */
    471 	d2 = 0x7fffffff;
    472 
    473 	while (*mnr) {	/* mnr vals are 0-terminated */
    474 		work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
    475 
    476 		r = (mnr[1] >> 5) & 0x03;
    477 		if (r != 0)
    478 			work_freq=work_freq >> r;	/* r is the freq divider */
    479 
    480 		work_freq *= 0x3E8;	/* 2nd part of OSC */
    481 
    482 		diff = abs(freq - work_freq);
    483 
    484 		if (d2 >= diff) {
    485 			d2 = diff;
    486 			/* In save are the vals for minimal diff */
    487 			save = mnr;
    488 		}
    489 		mnr += 2;
    490 	}
    491 	erg = *((unsigned short *)save);
    492 
    493 	return (erg);
    494 }
    495 
    496 
    497 void
    498 cv3d_boardinit(struct grf_softc *gp)
    499 {
    500 	volatile caddr_t ba, special;
    501 	unsigned char test;
    502 	unsigned int clockpar;
    503 	int i;
    504 	struct grfinfo *gi;
    505 
    506 	ba = gp->g_regkva;
    507 
    508 	/* PCI config */
    509 	if (cv3d_zorroIII) {
    510 		special = (cv3d_special_register_base + 0x000E0000);
    511 	} else {
    512 		special = (cv3d_special_register_base);
    513 	}
    514 	*((short *)(special + 0x10)) = 0;
    515 	*((long *)(special + 0x4)) = 0x02000003;
    516 
    517 	/* Wakeup Chip */
    518 	vgawio(cv3d_boardaddr, SREG_VIDEO_SUBS_ENABLE, 1);
    519 
    520 	vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x01);
    521 
    522 	vgaw(ba, GREG_MISC_OUTPUT_W, 0x03);
    523 
    524 	WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48);	/* unlock S3 VGA regs */
    525 	WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5);	/* unlock syscontrol */
    526 
    527 	WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x02);
    528 	WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x00);
    529 
    530 	WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x06);	/* Unlock extensions */
    531 
    532 	/*
    533 	 * bit 0=1: enable enhanced mode functions
    534 	 * bit 4=1: enable linear adressing
    535 	 */
    536 	vgaw32(cv3d_memory_io_base, MR_ADVANCED_FUNCTION_CONTROL, 0x00000011);
    537 
    538 	/* -hsync and -vsync */
    539 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xC3);
    540 
    541 	/* Reset. This does nothing, but everyone does it:) */
    542 	WSeq(ba, SEQ_ID_RESET, 0x03);
    543 
    544 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);	/* 8 Dot Clock */
    545 	WSeq(ba, SEQ_ID_MAP_MASK, 0x0F);	/* Enable write planes */
    546 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);	/* Character Font */
    547 
    548 	WSeq(ba, SEQ_ID_MEMORY_MODE, 0x02);	/* Complete mem access */
    549 	WSeq(ba, SEQ_ID_MMIO_SELECT, 0x00);
    550 
    551 	test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL);	/* Bus Request */
    552 
    553 	/* enable 4MB fast Page Mode */
    554 	test = test | 0xC0;
    555 	WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test);
    556 
    557 #if 0	/* XXX */
    558 	/* faster LUT write */
    559 	WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0);
    560 #else
    561 	WSeq(ba, SEQ_ID_UNKNOWN6, 0x00);
    562 	WSeq(ba, SEQ_ID_SIGNAL_SELECT, 0x02);
    563 #endif
    564 
    565 	test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);	/* Clksyn2 read */
    566 
    567 	/* immediately Clkload bit clear */
    568 	test = test & 0xDF;
    569 
    570 	/* 2 MCLK Memory Write.... */
    571 	if (cv3d_memclk >= 55000000)
    572 		test |= 0x80;
    573 
    574 	WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test);
    575 
    576 	/* Memory CLK */
    577 	clockpar = cv3d_compute_clock(cv3d_memclk);
    578 	test = (clockpar & 0xFF00) >> 8;
    579 	WSeq(ba, SEQ_ID_MCLK_HI, test);		/* PLL N-Divider Value */
    580 
    581 	test = clockpar & 0xFF;
    582 	WSeq(ba, SEQ_ID_MCLK_LO, test);		/* PLL M-Divider Value */
    583 
    584 	/* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */
    585 	/* DCLK */
    586 	WSeq(ba, SEQ_ID_DCLK_HI, 0x13);
    587 	WSeq(ba, SEQ_ID_DCLK_LO, 0x41);
    588 
    589 	test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2);
    590 	test = test | 0x22;
    591 
    592 	/* DCLK + MCLK Clock immediate load! */
    593 	WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test);
    594 
    595 	/* DCLK load */
    596 	test = vgar(ba, 0x3cc);
    597 	test = test | 0x0c;
    598 	vgaw(ba, 0x3c2, test);
    599 
    600 	/* Clear bit 5 again, prevent further loading. */
    601 	WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x02);
    602 
    603 	WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F);
    604 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F);
    605 	WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50);
    606 	WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82);
    607 	WCrt(ba, CRT_ID_START_HOR_RETR, 0x54);
    608 	WCrt(ba, CRT_ID_END_HOR_RETR, 0x80);
    609 	WCrt(ba, CRT_ID_VER_TOTAL, 0xBF);
    610 
    611 	WCrt(ba, CRT_ID_OVERFLOW, 0x1F);	/* overflow reg */
    612 
    613 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);	/* no panning */
    614 
    615 	WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40);	/* vscan */
    616 
    617 	WCrt(ba, CRT_ID_CURSOR_START, 0x00);
    618 	WCrt(ba, CRT_ID_CURSOR_END, 0x00);
    619 
    620 	/* Display start adress */
    621 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
    622 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
    623 
    624 	/* Cursor location */
    625 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
    626 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
    627 
    628 	/* Vertical retrace */
    629 	WCrt(ba, CRT_ID_START_VER_RETR, 0x9C);
    630 	WCrt(ba, CRT_ID_END_VER_RETR, 0x0E);
    631 
    632 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F);
    633 	WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50);
    634 
    635 	WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00);
    636 
    637 	WCrt(ba, CRT_ID_START_VER_BLANK, 0x96);
    638 	WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9);
    639 
    640 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
    641 
    642 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF);
    643 
    644 	WCrt(ba, CRT_ID_SYSTEM_CONFIG, 0x21);
    645 	WCrt(ba, CRT_ID_MEMORY_CONF, 0x04);
    646 	WCrt(ba, CRT_ID_BACKWAD_COMP_1, 0x00);
    647 	WCrt(ba, CRT_ID_BACKWAD_COMP_2, 0x02);
    648 	WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10);	/* FIFO enabled */
    649 
    650 	/* Refresh count 1, High speed text font, enhanced color mode */
    651 	WCrt(ba, CRT_ID_MISC_1, 0x35);
    652 
    653 	/* start fifo position */
    654 	WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5A);
    655 
    656 	WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x02);
    657 
    658 	WCrt(ba, CRT_ID_LAW_POS_LO, 0x40);
    659 
    660 	WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x81);
    661 	WCrt(ba, CRT_ID_MISC_1, 0xB5);
    662 	WCrt(ba, CRT_ID_CONFIG_1, 0x0E);
    663 
    664 	WGfx(ba, GCT_ID_SET_RESET, 0x00);
    665 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
    666 	WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
    667 	WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
    668 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
    669 	WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
    670 	WGfx(ba, GCT_ID_MISC, 0x01);
    671 	WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F);
    672 	WGfx(ba, GCT_ID_BITMASK, 0xFF);
    673 
    674 	/* colors for text mode */
    675 	for (i = 0; i <= 0xf; i++)
    676 		WAttr (ba, i, i);
    677 
    678 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41);
    679 	WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01);
    680 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F);
    681 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
    682 	WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
    683 
    684 	vgawio(cv3d_boardaddr, VDAC_MASK, 0xFF);	/* DAC Mask */
    685 
    686 	/* colors initially set to greyscale */
    687 
    688 	vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, 0);
    689 
    690 	for (i = 255; i >= 0 ; i--) {
    691 		vgawio(cv3d_boardaddr, VDAC_DATA, i);
    692 		vgawio(cv3d_boardaddr, VDAC_DATA, i);
    693 		vgawio(cv3d_boardaddr, VDAC_DATA, i);
    694 	}
    695 
    696 	/* GFx hardware cursor off */
    697 	WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
    698 
    699 	/* Set first to 4 MB, so test will work */
    700 	WCrt(ba, CRT_ID_LAW_CNTL, 0x13);
    701 
    702 	/* find *correct* fbsize of z3 board */
    703 	if (cv3d_has_4mb(gp->g_fbkva)) {
    704 		cv3d_fbsize = 1024 * 1024 * 4;
    705 		WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */
    706 	} else {
    707 		cv3d_fbsize = 1024 * 1024 * 2;
    708 		WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */
    709 	}
    710 
    711 	/* Initialize graphics engine */
    712 	GfxBusyWait(cv3d_memory_io_base);
    713 	vgaw32(cv3d_memory_io_base, BLT_COMMAND_SET, CMD_NOP);
    714 	vgaw32(cv3d_memory_io_base, BLT_CLIP_LEFT_RIGHT, 0x000007ff);
    715 	vgaw32(cv3d_memory_io_base, BLT_CLIP_TOP_BOTTOM, 0x000007ff);
    716 	vgaw32(cv3d_memory_io_base, L2D_COMMAND_SET, CMD_NOP);
    717 	vgaw32(cv3d_memory_io_base, L2D_CLIP_LEFT_RIGHT, 0x000007ff);
    718 	vgaw32(cv3d_memory_io_base, L2D_CLIP_TOP_BOTTOM, 0x000007ff);
    719 	vgaw32(cv3d_memory_io_base, P2D_COMMAND_SET, CMD_NOP);
    720 	vgaw32(cv3d_memory_io_base, P2D_CLIP_LEFT_RIGHT, 0x000007ff);
    721 	vgaw32(cv3d_memory_io_base, P2D_CLIP_TOP_BOTTOM, 0x000007ff);
    722 
    723 	/* Enable Video Display (Set Bit 5) */
    724 	WAttr(ba, 0x33, 0);
    725 
    726 
    727 	gi = &gp->g_display;
    728 	gi->gd_regaddr	= (caddr_t) kvtop (ba);
    729 	gi->gd_regsize	= 64 * 1024;
    730 	gi->gd_fbaddr	= (caddr_t) kvtop (gp->g_fbkva);
    731 	gi->gd_fbsize	= cv3d_fbsize;
    732 }
    733 
    734 
    735 int
    736 cv3d_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
    737 {
    738 	struct grfvideo_mode *gv;
    739 
    740 #ifdef CV3DCONSOLE
    741 	/* Handle grabbing console mode */
    742 	if (vm->mode_num == 255) {
    743 		bcopy(&cv3dconsole_mode, vm, sizeof(struct grfvideo_mode));
    744 		/* XXX so grfconfig can tell us the correct text dimensions. */
    745 		vm->depth = cv3dconsole_mode.fy;
    746 	} else
    747 #endif
    748 	{
    749 		if (vm->mode_num == 0)
    750 			vm->mode_num = (monitor_current - monitor_def) + 1;
    751 		if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
    752 			return (EINVAL);
    753 		gv = monitor_def + (vm->mode_num - 1);
    754 		if (gv->mode_num == 0)
    755 			return (EINVAL);
    756 
    757 		bcopy(gv, vm, sizeof(struct grfvideo_mode));
    758 	}
    759 
    760 	/* adjust internal values to pixel values */
    761 
    762 	vm->hblank_start *= 8;
    763 	vm->hsync_start *= 8;
    764 	vm->hsync_stop *= 8;
    765 	vm->htotal *= 8;
    766 
    767 	return (0);
    768 }
    769 
    770 
    771 int
    772 cv3d_setvmode(struct grf_softc *gp, unsigned mode)
    773 {
    774 
    775 	if (!mode || (mode > monitor_def_max) ||
    776 	    monitor_def[mode - 1].mode_num == 0)
    777 		return (EINVAL);
    778 
    779 	monitor_current = monitor_def + (mode - 1);
    780 
    781 	return (0);
    782 }
    783 
    784 
    785 int
    786 cv3d_blank(struct grf_softc *gp, int *on)
    787 {
    788 	volatile caddr_t ba;
    789 
    790 	ba = gp->g_regkva;
    791 	cv3d_gfx_on_off(*on > 0 ? 0 : 1, ba);
    792 	return (0);
    793 }
    794 
    795 
    796 /*
    797  * Change the mode of the display.
    798  * Return a UNIX error number or 0 for success.
    799  */
    800 int
    801 cv3d_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2,
    802           int a3)
    803 {
    804 	int error;
    805 
    806 	switch (cmd) {
    807 	    case GM_GRFON:
    808 		error = cv3d_load_mon (gp,
    809 		    (struct grfcv3dtext_mode *) monitor_current) ? 0 : EINVAL;
    810 		return (error);
    811 
    812 	    case GM_GRFOFF:
    813 #ifndef CV3DCONSOLE
    814 		cv3dscreen(1, cv3d_vcode_switch_base);
    815 #else
    816 		cv3d_load_mon(gp, &cv3dconsole_mode);
    817 		ite_reinit(gp->g_itedev);
    818 #endif
    819 		return (0);
    820 
    821 	    case GM_GRFCONFIG:
    822 		return (0);
    823 
    824 	    case GM_GRFGETVMODE:
    825 		return (cv3d_getvmode (gp, (struct grfvideo_mode *) arg));
    826 
    827 	    case GM_GRFSETVMODE:
    828 		error = cv3d_setvmode (gp, *(unsigned *) arg);
    829 		if (!error && (gp->g_flags & GF_GRFON))
    830 			cv3d_load_mon(gp,
    831 			    (struct grfcv3dtext_mode *) monitor_current);
    832 		return (error);
    833 
    834 	    case GM_GRFGETNUMVM:
    835 		*(int *)arg = monitor_def_max;
    836 		return (0);
    837 
    838 	    case GM_GRFIOCTL:
    839 		return (cv3d_ioctl (gp, a2, arg));
    840 
    841 	    default:
    842 		break;
    843 	}
    844 
    845 	return (EINVAL);
    846 }
    847 
    848 
    849 int
    850 cv3d_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
    851 {
    852 	switch (cmd) {
    853 #ifdef CV3D_HARDWARE_CURSOR
    854 	    case GRFIOCGSPRITEPOS:
    855 		return(cv3d_getspritepos (gp, (struct grf_position *) data));
    856 
    857 	    case GRFIOCSSPRITEPOS:
    858 		return(cv3d_setspritepos (gp, (struct grf_position *) data));
    859 
    860 	    case GRFIOCSSPRITEINF:
    861 		return(cv3d_setspriteinfo (gp, (struct grf_spriteinfo *) data));
    862 
    863 	    case GRFIOCGSPRITEINF:
    864 		return(cv3d_getspriteinfo (gp, (struct grf_spriteinfo *) data));
    865 
    866 	    case GRFIOCGSPRITEMAX:
    867 		return(cv3d_getspritemax (gp, (struct grf_position *) data));
    868 #else	/* CV3D_HARDWARE_CURSOR */
    869 	    case GRFIOCGSPRITEPOS:
    870 	    case GRFIOCSSPRITEPOS:
    871 	    case GRFIOCSSPRITEINF:
    872 	    case GRFIOCGSPRITEINF:
    873 	    case GRFIOCGSPRITEMAX:
    874 		break;
    875 #endif	/* CV3D_HARDWARE_CURSOR */
    876 
    877 	    case GRFIOCGETCMAP:
    878 		return (cv3d_getcmap (gp, (struct grf_colormap *) data));
    879 
    880 	    case GRFIOCPUTCMAP:
    881 		return (cv3d_putcmap (gp, (struct grf_colormap *) data));
    882 
    883 	    case GRFIOCBITBLT:
    884 		break;
    885 
    886 	    case GRFTOGGLE:
    887 		return (cv3d_toggle (gp));
    888 
    889 	    case GRFIOCSETMON:
    890 		return (cv3d_setmonitor (gp, (struct grfvideo_mode *)data));
    891 
    892 	    case GRFIOCBLANK:
    893 		return (cv3d_blank (gp, (int *)data));
    894 	}
    895 	return (EINVAL);
    896 }
    897 
    898 
    899 int
    900 cv3d_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv)
    901 {
    902 	struct grfvideo_mode *md;
    903 
    904 	if (!cv3d_mondefok(gv))
    905 		return (EINVAL);
    906 
    907 #ifdef CV3DCONSOLE
    908 	/* handle interactive setting of console mode */
    909 	if (gv->mode_num == 255) {
    910 		bcopy(gv, &cv3dconsole_mode.gv, sizeof(struct grfvideo_mode));
    911 		cv3dconsole_mode.gv.hblank_start /= 8;
    912 		cv3dconsole_mode.gv.hsync_start /= 8;
    913 		cv3dconsole_mode.gv.hsync_stop /= 8;
    914 		cv3dconsole_mode.gv.htotal /= 8;
    915 		cv3dconsole_mode.rows = gv->disp_height / cv3dconsole_mode.fy;
    916 		cv3dconsole_mode.cols = gv->disp_width / cv3dconsole_mode.fx;
    917 		if (!(gp->g_flags & GF_GRFON))
    918 			cv3d_load_mon(gp, &cv3dconsole_mode);
    919 		ite_reinit(gp->g_itedev);
    920 		return (0);
    921 	}
    922 #endif
    923 
    924 	md = monitor_def + (gv->mode_num - 1);
    925 
    926 	/*
    927 	 * Prevent user from crashing the system by using
    928 	 * grfconfig while in X
    929 	 */
    930 	if (gp->g_flags & GF_GRFON)
    931 		if (md == monitor_current) {
    932 			printf("grfcv3d: Changing the used mode not allowed!\n");
    933 			return (EINVAL);
    934 		}
    935 
    936 	bcopy(gv, md, sizeof(struct grfvideo_mode));
    937 
    938 	/* adjust pixel oriented values to internal rep. */
    939 
    940 	md->hblank_start /= 8;
    941 	md->hsync_start /= 8;
    942 	md->hsync_stop /= 8;
    943 	md->htotal /= 8;
    944 
    945 	return (0);
    946 }
    947 
    948 
    949 int
    950 cv3d_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
    951 {
    952 	volatile caddr_t ba;
    953 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    954 	short x;
    955 	int error;
    956 
    957 	ba = gfp->g_regkva;
    958 	if (cmap->count == 0 || cmap->index >= 256)
    959 		return (0);
    960 
    961 	if (cmap->index + cmap->count > 256)
    962 		cmap->count = 256 - cmap->index;
    963 
    964 	/* first read colors out of the chip, then copyout to userspace */
    965 	vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, cmap->index);
    966 	x = cmap->count - 1;
    967 
    968 	rp = red + cmap->index;
    969 	gp = green + cmap->index;
    970 	bp = blue + cmap->index;
    971 
    972 	do {
    973 		*rp++ = vgario(cv3d_special_register_base, VDAC_DATA) << 2;
    974 		*gp++ = vgario(cv3d_special_register_base, VDAC_DATA) << 2;
    975 		*bp++ = vgario(cv3d_special_register_base, VDAC_DATA) << 2;
    976 	} while (x-- > 0);
    977 
    978 	if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
    979 	    && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
    980 	    && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
    981 		return (0);
    982 
    983 	return (error);
    984 }
    985 
    986 
    987 int
    988 cv3d_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
    989 {
    990 	volatile caddr_t ba;
    991 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    992 	short x;
    993 	int error;
    994 
    995 	ba = gfp->g_regkva;
    996 	if (cmap->count == 0 || cmap->index >= 256)
    997 		return (0);
    998 
    999 	if (cmap->index + cmap->count > 256)
   1000 		cmap->count = 256 - cmap->index;
   1001 
   1002 	/* first copy the colors into kernelspace */
   1003 	if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
   1004 	    && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
   1005 	    && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
   1006 		vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, cmap->index);
   1007 		x = cmap->count - 1;
   1008 
   1009 		rp = red + cmap->index;
   1010 		gp = green + cmap->index;
   1011 		bp = blue + cmap->index;
   1012 
   1013 		do {
   1014 			vgawio(cv3d_boardaddr, VDAC_DATA, *rp++ >> 2);
   1015 			vgawio(cv3d_boardaddr, VDAC_DATA, *gp++ >> 2);
   1016 			vgawio(cv3d_boardaddr, VDAC_DATA, *bp++ >> 2);
   1017 		} while (x-- > 0);
   1018 		return (0);
   1019 	} else
   1020 		return (error);
   1021 }
   1022 
   1023 
   1024 int
   1025 cv3d_toggle(struct grf_softc *gp)
   1026 {
   1027 	volatile caddr_t ba;
   1028 
   1029 	ba = gp->g_regkva;
   1030 #ifndef CV3DCONSOLE
   1031 	cv3d_pass_toggle = 1;
   1032 #endif /* !CV3DCONSOLE */
   1033 
   1034 	if (cv3d_pass_toggle) {
   1035 		cv3dscreen(0, cv3d_vcode_switch_base);
   1036 		cv3d_pass_toggle = 0;
   1037 	} else {
   1038 		cv3dscreen(1, cv3d_vcode_switch_base);
   1039 		cv3d_pass_toggle = 1;
   1040 	}
   1041 
   1042 	return (0);
   1043 }
   1044 
   1045 
   1046 int
   1047 cv3d_mondefok(struct grfvideo_mode *gv)
   1048 {
   1049 	unsigned long maxpix;
   1050 
   1051 	if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) {
   1052 		if (gv->mode_num != 255 || gv->depth != 4)
   1053 			return (0);
   1054 	}
   1055 
   1056 	switch(gv->depth) {
   1057 	   case 4:
   1058 		maxpix = MAXPIXELCLOCK - 55000000;
   1059 		break;
   1060 	   case 8:
   1061 		maxpix = MAXPIXELCLOCK;
   1062 		break;
   1063 	   case 15:
   1064 	   case 16:
   1065 #ifdef	CV3D_AGGRESSIVE_TIMING
   1066 		maxpix = MAXPIXELCLOCK - 35000000;
   1067 #else
   1068 		maxpix = MAXPIXELCLOCK - 55000000;
   1069 #endif
   1070 		break;
   1071 	   case 24:
   1072 	   case 32:
   1073 #ifdef	CV3D_AGGRESSIVE_TIMING
   1074 		maxpix = MAXPIXELCLOCK - 75000000;
   1075 #else
   1076 		maxpix = MAXPIXELCLOCK - 85000000;
   1077 #endif
   1078 		break;
   1079 	   default:
   1080 		printf("grfcv3d: Illegal depth in mode %d\n",
   1081 			(int) gv->mode_num);
   1082 		return (0);
   1083 	}
   1084 
   1085 	if (gv->pixel_clock > maxpix) {
   1086 		printf("grfcv3d: Pixelclock too high in mode %d\n",
   1087 			(int) gv->mode_num);
   1088 		return (0);
   1089 	}
   1090 
   1091 	if (gv->mode_num == 255) { /* console mode */
   1092 		if ((gv->disp_width / 8) > MAXCOLS) {
   1093 			printf ("grfcv3d: Too many columns for console\n");
   1094 			return (0);
   1095 		} else if ((gv->disp_height / S3FONTY) > MAXROWS) {
   1096 			printf ("grfcv3d: Too many rows for console\n");
   1097 			return (0);
   1098 		}
   1099 	}
   1100 
   1101 	if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) {
   1102 		printf("grfcv3d: sync-on-green is not supported\n");
   1103 		return (0);
   1104 	}
   1105 
   1106 	return (1);
   1107 }
   1108 
   1109 
   1110 int
   1111 cv3d_load_mon(struct grf_softc *gp, struct grfcv3dtext_mode *md)
   1112 {
   1113 	struct grfvideo_mode *gv;
   1114 	struct grfinfo *gi;
   1115 	volatile caddr_t ba, fb;
   1116 	unsigned short mnr;
   1117 	unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
   1118 		VSE, VT;
   1119 	int cr50, cr66, sr15, sr18, clock_mode, test;
   1120 	int hmul;	/* Multiplier for hor. Values */
   1121 	int fb_flag = 2;	/* default value for 8bit memory access */
   1122 	unsigned char hvsync_pulse;
   1123 	char TEXT, CONSOLE;
   1124 
   1125 	/* identity */
   1126 	gv = &md->gv;
   1127 
   1128 	TEXT = (gv->depth == 4);
   1129 	CONSOLE = (gv->mode_num == 255);
   1130 
   1131 	if (!cv3d_mondefok(gv)) {
   1132 		printf("grfcv3d: Monitor definition not ok\n");
   1133 		return (0);
   1134 	}
   1135 
   1136 	ba = gp->g_regkva;
   1137 	fb = gp->g_fbkva;
   1138 
   1139 	/* turn gfx off, don't mess up the display */
   1140 	cv3d_gfx_on_off(1, ba);
   1141 
   1142 	/* provide all needed information in grf device-independant locations */
   1143 	gp->g_data		= (caddr_t) gv;
   1144 	gi = &gp->g_display;
   1145 	gi->gd_colors		= 1 << gv->depth;
   1146 	gi->gd_planes		= gv->depth;
   1147 	gi->gd_fbwidth		= gv->disp_width;
   1148 	gi->gd_fbheight		= gv->disp_height;
   1149 	gi->gd_fbx		= 0;
   1150 	gi->gd_fby		= 0;
   1151 	if (CONSOLE) {
   1152 		gi->gd_dwidth	= md->fx * md->cols;
   1153 		gi->gd_dheight	= md->fy * md->rows;
   1154 	} else {
   1155 		gi->gd_dwidth	= gv->disp_width;
   1156 		gi->gd_dheight	= gv->disp_height;
   1157 	}
   1158 	gi->gd_dx		= 0;
   1159 	gi->gd_dy		= 0;
   1160 
   1161 	/* get display mode parameters */
   1162 	switch (gv->depth) {
   1163 	    case 15:
   1164 	    case 16:
   1165 		hmul = 2;
   1166 		break;
   1167 	    default:
   1168 		hmul = 1;
   1169 		break;
   1170 	}
   1171 
   1172 	HBS = gv->hblank_start * hmul;
   1173 	HSS = gv->hsync_start * hmul;
   1174 	HSE = gv->hsync_stop * hmul;
   1175 	HBE = gv->htotal * hmul - 6;
   1176 	HT  = gv->htotal * hmul - 5;
   1177 	VBS = gv->vblank_start - 1;
   1178 	VSS = gv->vsync_start;
   1179 	VSE = gv->vsync_stop;
   1180 	VBE = gv->vtotal - 3;
   1181 	VT  = gv->vtotal - 2;
   1182 
   1183 	/*
   1184 	 * Disable enhanced Mode for text display
   1185 	 *
   1186 	 * XXX You need to set this bit in CRT_ID_EXT_MISC_CNTL_1
   1187 	 * _and_ MR_ADVANCED_FUNCTION_CONTROL, because the same
   1188 	 * function exists in both registers.
   1189 	 */
   1190 	cr66 = RCrt(ba, CRT_ID_EXT_MISC_CNTL_1);
   1191 	if (TEXT) {
   1192 		cr66 &= ~0x01;
   1193 		vgaw32(cv3d_memory_io_base, MR_ADVANCED_FUNCTION_CONTROL,
   1194 			0x00000010);
   1195 	} else {
   1196 		cr66 |= 0x01;
   1197 		vgaw32(cv3d_memory_io_base, MR_ADVANCED_FUNCTION_CONTROL,
   1198 			0x00000011);
   1199 	}
   1200 	WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, cr66);
   1201 
   1202 	if (TEXT)
   1203 		HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
   1204 	else
   1205 		HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/
   1206 	VDE = gv->disp_height - 1;
   1207 
   1208 	/* adjustments */
   1209 
   1210 	if (gv->disp_flags & GRF_FLAGS_LACE) {
   1211 		VDE = VDE / 2;
   1212 		VBS = VBS / 2;
   1213 		VSS = VSS / 2;
   1214 		VSE = VSE / 2;
   1215 		VBE = VBE / 2;
   1216 		VT  = VT / 2;
   1217 	}
   1218 
   1219 	/* Horizontal/Vertical Sync Pulse */
   1220 	/*
   1221 	 * GREG_MISC_OUTPUT_W Register:
   1222 	 * bit	description (0/1)
   1223 	 *  0	Monochrome/Color emulation
   1224 	 *  1	Disable/Enable access of the display memory from the CPU
   1225 	 *  5	Select the low/high 64K page of memory
   1226 	 *  6	Select a positive/negative horizontal retrace sync pulse
   1227 	 *  7	Select a positive/negative vertical retrace sync pulse
   1228 	 */
   1229 	hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R);
   1230 	if (gv->disp_flags & GRF_FLAGS_PHSYNC)
   1231 		hvsync_pulse &= ~0x40;
   1232 	else
   1233 		hvsync_pulse |= 0x40;
   1234 	if (gv->disp_flags & GRF_FLAGS_PVSYNC)
   1235 		hvsync_pulse &= ~0x80;
   1236 	else
   1237 		hvsync_pulse |= 0x80;
   1238 	vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse);
   1239 
   1240 	/* GFX hardware cursor off */
   1241 	WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
   1242 	WCrt(ba, CRT_ID_EXT_DAC_CNTL, 0x00);
   1243 
   1244 	WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
   1245 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
   1246 	WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
   1247 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
   1248 
   1249 	/* Set clock */
   1250 
   1251 	mnr = cv3d_compute_clock(gv->pixel_clock);
   1252 	WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
   1253 	WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF));
   1254 
   1255 	/* load display parameters into board */
   1256 
   1257 	WCrt(ba, CRT_ID_EXT_HOR_OVF,
   1258 	   ((HT & 0x100) ? 0x01 : 0x00) |
   1259 	   ((HDE & 0x100) ? 0x02 : 0x00) |
   1260 	   ((HBS & 0x100) ? 0x04 : 0x00) |
   1261 	/* ((HBE & 0x40) ? 0x08 : 0x00) | */  /* Later... */
   1262 	   ((HSS & 0x100) ? 0x10 : 0x00) |
   1263 	/* ((HSE & 0x20) ? 0x20 : 0x00) | */
   1264 	   (((HT-5) & 0x100) ? 0x40 : 0x00) );
   1265 
   1266 	WCrt(ba, CRT_ID_EXT_VER_OVF,
   1267 	    0x40 |	/* Line compare */
   1268 	    ((VT  & 0x400) ? 0x01 : 0x00) |
   1269 	    ((VDE & 0x400) ? 0x02 : 0x00) |
   1270 	    ((VBS & 0x400) ? 0x04 : 0x00) |
   1271 	    ((VSS & 0x400) ? 0x10 : 0x00) );
   1272 
   1273 	WCrt(ba, CRT_ID_HOR_TOTAL, HT);
   1274 	WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5);
   1275 
   1276 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
   1277 	WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
   1278 	WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80));
   1279 	WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
   1280 	WCrt(ba, CRT_ID_END_HOR_RETR,
   1281 	    (HSE & 0x1f) |
   1282 	    ((HBE & 0x20) ? 0x80 : 0x00) );
   1283 	WCrt(ba, CRT_ID_VER_TOTAL, VT);
   1284 	WCrt(ba, CRT_ID_OVERFLOW,
   1285 	    0x10 |
   1286 	    ((VT  & 0x100) ? 0x01 : 0x00) |
   1287 	    ((VDE & 0x100) ? 0x02 : 0x00) |
   1288 	    ((VSS & 0x100) ? 0x04 : 0x00) |
   1289 	    ((VBS & 0x100) ? 0x08 : 0x00) |
   1290 	    ((VT  & 0x200) ? 0x20 : 0x00) |
   1291 	    ((VDE & 0x200) ? 0x40 : 0x00) |
   1292 	    ((VSS & 0x200) ? 0x80 : 0x00) );
   1293 
   1294 	WCrt(ba, CRT_ID_MAX_SCAN_LINE,
   1295 	    0x40 |  /* TEXT ? 0x00 ??? */
   1296 	    ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) |
   1297 	    ((VBS & 0x200) ? 0x20 : 0x00) |
   1298 	    (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
   1299 
   1300 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
   1301 
   1302 	/* text cursor */
   1303 
   1304 	if (TEXT) {
   1305 #if CV3D_ULCURSOR
   1306 		WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
   1307 		WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
   1308 #else
   1309 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
   1310 		WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
   1311 #endif
   1312 		WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
   1313 
   1314 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
   1315 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
   1316 	}
   1317 
   1318 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
   1319 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
   1320 
   1321 	WCrt(ba, CRT_ID_START_VER_RETR, VSS);
   1322 	WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f));
   1323 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
   1324 	WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
   1325 	WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
   1326 
   1327 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
   1328 	WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2);
   1329 	WCrt(ba, CRT_ID_LACE_CONTROL,
   1330 	    ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x20 : 0x00));
   1331 
   1332 	WGfx(ba, GCT_ID_GRAPHICS_MODE,
   1333 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
   1334 	WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
   1335 
   1336 	WSeq (ba, SEQ_ID_MEMORY_MODE,
   1337 	    ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02));
   1338 
   1339 	vgawio(cv3d_boardaddr, VDAC_MASK, 0xff);
   1340 
   1341 	/* Blank border */
   1342 	test = RCrt(ba, CRT_ID_BACKWAD_COMP_2);
   1343 	WCrt(ba, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
   1344 
   1345 	sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);
   1346 	sr15 &= ~0x10;
   1347 	sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL);
   1348 	sr18 &= ~0x80;
   1349 	clock_mode = 0x00;
   1350 	cr50 = 0x00;
   1351 
   1352 	test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2);
   1353 	test &= 0xd;
   1354 
   1355 	switch (gv->depth) {
   1356 	   case 1:
   1357 	   case 4: /* text */
   1358 		fb_flag = 2;
   1359 		HDE = gv->disp_width / 16;
   1360 		break;
   1361 	   case 8:
   1362 		fb_flag = 2;
   1363 		if (gv->pixel_clock > 80000000) {
   1364 			/*
   1365 			 * CR67 bit 1 is undocumented but needed to prevent
   1366 			 * a white line on the left side of the screen.
   1367 			 */
   1368 			clock_mode = 0x10 | 0x02;
   1369 			sr15 |= 0x10;
   1370 			sr18 |= 0x80;
   1371 		}
   1372 		HDE = gv->disp_width / 8;
   1373 		cr50 |= 0x00;
   1374 		break;
   1375 	   case 15:
   1376 		fb_flag = 1;
   1377 		clock_mode = 0x30;
   1378 		HDE = gv->disp_width / 4;
   1379 		cr50 |= 0x10;
   1380 		break;
   1381 	   case 16:
   1382 		fb_flag = 1;
   1383 		clock_mode = 0x50;
   1384 		HDE = gv->disp_width / 4;
   1385 		cr50 |= 0x10;
   1386 		break;
   1387 	   case 24: /* this is really 32 Bit on CV64/3D */
   1388 	   case 32:
   1389 		fb_flag = 0;
   1390 		clock_mode = 0xd0;
   1391 		HDE = (gv->disp_width / 2);
   1392 		cr50 |= 0x30;
   1393 		break;
   1394 	}
   1395 
   1396 	if (cv3d_zorroIII) {
   1397 		gp->g_fbkva = (volatile caddr_t)cv3d_boardaddr + 0x04000000 +
   1398 				(0x00400000 * fb_flag);
   1399 	} else {
   1400 		/* XXX This is totaly untested */
   1401 		Select_Zorro2_FrameBuffer(fb_flag);
   1402 	}
   1403 
   1404 	WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
   1405 	WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15);
   1406 	WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18);
   1407 	WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE);
   1408 
   1409 	WCrt(ba, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
   1410 
   1411 	test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2);
   1412 	test &= ~0x30;
   1413 	/* HDE Overflow in bits 4-5 */
   1414 	test |= (HDE >> 4) & 0x30;
   1415 	WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test);
   1416 
   1417 #if 0	/* XXX */
   1418 	/* Set up graphics engine */
   1419 	switch (gv->disp_width) {
   1420 	   case 1024:
   1421 		cr50 |= 0x00;
   1422 		break;
   1423 	   case 640:
   1424 		cr50 |= 0x40;
   1425 		break;
   1426 	   case 800:
   1427 		cr50 |= 0x80;
   1428 		break;
   1429 	   case 1280:
   1430 		cr50 |= 0xc0;
   1431 		break;
   1432 	   case 1152:
   1433 		cr50 |= 0x01;
   1434 		break;
   1435 	   case 1600:
   1436 		cr50 |= 0x81;
   1437 		break;
   1438 	   default: /* XXX The Xserver has to handle this */
   1439 		break;
   1440 	}
   1441 
   1442 	WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50);
   1443 #endif
   1444 
   1445 	delay(100000);
   1446 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
   1447 	delay(100000);
   1448 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA,
   1449 	    (gv->depth == 1) ? 0x01 : 0x0f);
   1450 	delay(100000);
   1451 
   1452 	/* text initialization */
   1453 
   1454 	if (TEXT) {
   1455 		cv3d_inittextmode(gp);
   1456 	}
   1457 
   1458 	if (CONSOLE) {
   1459 		int i;
   1460 		vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, 0);
   1461 		for (i = 0; i < 16; i++) {
   1462 			vgawio(cv3d_boardaddr, VDAC_DATA, cv3dconscolors[i][0]);
   1463 			vgawio(cv3d_boardaddr, VDAC_DATA, cv3dconscolors[i][1]);
   1464 			vgawio(cv3d_boardaddr, VDAC_DATA, cv3dconscolors[i][2]);
   1465 		}
   1466 	}
   1467 
   1468 	/* Set display enable flag */
   1469 	WAttr(ba, 0x33, 0);
   1470 
   1471 	/* turn gfx on again */
   1472 	cv3d_gfx_on_off(0, ba);
   1473 
   1474 	/* Pass-through */
   1475 	cv3dscreen(0, cv3d_vcode_switch_base);
   1476 
   1477 	return (1);
   1478 }
   1479 
   1480 
   1481 void
   1482 cv3d_inittextmode(struct grf_softc *gp)
   1483 {
   1484 	struct grfcv3dtext_mode *tm = (struct grfcv3dtext_mode *)gp->g_data;
   1485 	volatile caddr_t ba, fb;
   1486 	unsigned char *c, *f, y;
   1487 	unsigned short z;
   1488 
   1489 	ba = gp->g_regkva;
   1490 	fb = gp->g_fbkva;
   1491 
   1492 	/* load text font into beginning of display memory.
   1493 	 * Each character cell is 32 bytes long (enough for 4 planes)
   1494 	 * In linear adressing text mode, the memory is organized
   1495 	 * so, that the Bytes of all 4 planes are interleaved.
   1496 	 * 1st byte plane 0, 1st byte plane 1, 1st byte plane 2,
   1497 	 * 1st byte plane 3, 2nd byte plane 0, 2nd byte plane 1,...
   1498 	 * The font is loaded in plane 2.
   1499 	 */
   1500 
   1501 	c = (unsigned char *) fb;
   1502 
   1503 	/* clear screen */
   1504 	for (z = 0; z < tm->cols * tm->rows * 3; z++) {
   1505 		*c++ = 0x20;
   1506 		*c++ = 0x07;
   1507 		*c++ = 0;
   1508 		*c++ = 0;
   1509 	}
   1510 
   1511 	c = (unsigned char *) (fb) + (32 * tm->fdstart * 4 + 2);
   1512 	f = tm->fdata;
   1513 	for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy) * 4)
   1514 		for (y = 0; y < tm->fy; y++) {
   1515 			*c = *f++;
   1516 			c += 4;
   1517 		}
   1518 
   1519 	/* print out a little init msg */
   1520 	c = (unsigned char *)(fb) + (tm->cols - 9) * 4;
   1521 	*c++ = 'C';
   1522 	*c++ = 0x0c;
   1523 	c +=2;
   1524 	*c++ = 'V';
   1525 	*c++ = 0x0c;
   1526 	c +=2;
   1527 	*c++ = '6';
   1528 	*c++ = 0x0b;
   1529 	c +=2;
   1530 	*c++ = '4';
   1531 	*c++ = 0x0f;
   1532 	c +=2;
   1533 	*c++ = '/';
   1534 	*c++ = 0x0e;
   1535 	c +=2;
   1536 	*c++ = '3';
   1537 	*c++ = 0x0a;
   1538 	c +=2;
   1539 	*c++ = 'D';
   1540 	*c++ = 0x0a;
   1541 }
   1542 
   1543 /*
   1544  *  Monitor Switch
   1545  *  0 = CyberVision Signal
   1546  *  1 = Amiga Signal,
   1547  * ba = boardaddr
   1548  */
   1549 static __inline void
   1550 cv3dscreen(int toggle, volatile caddr_t ba)
   1551 {
   1552 	*((short *)(ba)) = (toggle & 1);
   1553 }
   1554 
   1555 
   1556 /* 0 = on, 1= off */
   1557 /* ba= registerbase */
   1558 static __inline void
   1559 cv3d_gfx_on_off(int toggle, volatile caddr_t ba)
   1560 {
   1561 	int r;
   1562 
   1563 	toggle &= 0x1;
   1564 	toggle = toggle << 5;
   1565 
   1566 	r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
   1567 	r &= ~0x20;	/* set Bit 5 to 0 */
   1568 
   1569 	WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle);
   1570 }
   1571 
   1572 
   1573 #ifdef CV3D_HARDWARE_CURSOR
   1574 
   1575 static unsigned char cv3d_hotx = 0, cv3d_hoty = 0;
   1576 static char cv_cursor_on = 0;
   1577 
   1578 #define HWC_OFF (cv3d_fbsize - 1024*2)
   1579 #define HWC_SIZE 1024
   1580 
   1581 /* Hardware Cursor handling routines */
   1582 
   1583 int
   1584 cv3d_getspritepos(struct grf_softc *gp, struct grf_position *pos)
   1585 {
   1586 	int hi,lo;
   1587 	volatile caddr_t ba = gp->g_regkva;
   1588 
   1589 	hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI);
   1590 	lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO);
   1591 
   1592 	pos->y = (hi << 8) + lo;
   1593 	hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI);
   1594 	lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO);
   1595 	pos->x = (hi << 8) + lo;
   1596 	return (0);
   1597 }
   1598 
   1599 
   1600 int
   1601 cv3d_setspritepos(struct grf_softc *gp, struct grf_position *pos)
   1602 {
   1603 	volatile caddr_t ba = gp->g_regkva;
   1604 	short x, y;
   1605 	static short savex, savey;
   1606 	short xoff, yoff;
   1607 
   1608 	if (pos) {
   1609 		x = pos->x;
   1610 		y = pos->y;
   1611 		savex = x;
   1612 		savey= y;
   1613 	} else { /* restore cursor */
   1614 		x = savex;
   1615 		y = savey;
   1616 	}
   1617 	x -= cv3d_hotx;
   1618 	y -= cv3d_hoty;
   1619 	if (x < 0) {
   1620 		xoff = ((-x) & 0xFE);
   1621 		x = 0;
   1622 	} else {
   1623 		xoff = 0;
   1624 	}
   1625 
   1626 	if (y < 0) {
   1627 		yoff = ((-y) & 0xFE);
   1628 		y = 0;
   1629 	} else {
   1630 		yoff = 0;
   1631 	}
   1632 
   1633 	WCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8));
   1634 	WCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff));
   1635 
   1636 	WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff));
   1637 	WCrt(ba, CRT_ID_HWGC_DSTART_X, xoff);
   1638 	WCrt(ba, CRT_ID_HWGC_DSTART_Y, yoff);
   1639 	WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8));
   1640 
   1641 	return(0);
   1642 }
   1643 
   1644 static __inline short
   1645 M2I(short val)
   1646 {
   1647 	return ( ((val & 0xff00) >> 8) | ((val & 0xff) << 8));
   1648 }
   1649 
   1650 int
   1651 cv3d_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
   1652 {
   1653 	volatile caddr_t ba, fb;
   1654 
   1655 	ba = gp->g_regkva;
   1656 	fb = gp->g_fbkva;
   1657 
   1658 	if (info->set & GRFSPRSET_ENABLE)
   1659 		info->enable = RCrt(ba, CRT_ID_HWGC_MODE) & 0x01;
   1660 
   1661 	if (info->set & GRFSPRSET_POS)
   1662 		cv3d_getspritepos (gp, &info->pos);
   1663 
   1664 #if 0	/* XXX */
   1665 	if (info->set & GRFSPRSET_SHAPE) {
   1666 		u_char image[512], mask[512];
   1667 		volatile u_long *hwp;
   1668 		u_char *imp, *mp;
   1669 		short row;
   1670 		info->size.x = 64;
   1671 		info->size.y = 64;
   1672 		for (row = 0, hwp = (u_long *)(fb + HWC_OFF),
   1673 		    mp = mask, imp = image;
   1674 		    row < 64;
   1675 		    row++) {
   1676 			u_long bp10, bp20, bp11, bp21;
   1677 			bp10 = *hwp++;
   1678 			bp20 = *hwp++;
   1679 			bp11 = *hwp++;
   1680 			bp21 = *hwp++;
   1681 			M2I (bp10);
   1682 			M2I (bp20);
   1683 			M2I (bp11);
   1684 			M2I (bp21);
   1685 			*imp++ = (~bp10) & bp11;
   1686 			*imp++ = (~bp20) & bp21;
   1687 			*mp++  = (~bp10) | (bp10 & ~bp11);
   1688 			*mp++  = (~bp20) & (bp20 & ~bp21);
   1689 		}
   1690 		copyout (image, info->image, sizeof (image));
   1691 		copyout (mask, info->mask, sizeof (mask));
   1692 	}
   1693 #endif
   1694 	return(0);
   1695 }
   1696 
   1697 
   1698 void
   1699 cv3d_setup_hwc(struct grf_softc *gp)
   1700 {
   1701 	volatile caddr_t ba = gp->g_regkva;
   1702 	volatile caddr_t hwc;
   1703 	int test;
   1704 
   1705 	if (gp->g_display.gd_planes <= 4)
   1706 		cv3d_cursor_on = 0;	/* don't enable hwc in text modes */
   1707 	if (cv3d_cursor_on == 0)
   1708 		return;
   1709 
   1710 	/* reset colour stack */
   1711 #if 0
   1712 	test = RCrt(ba, CRT_ID_HWGC_MODE);
   1713 	asm volatile("nop");
   1714 #else
   1715 	/* do it in assembler, the above does't seem to work */
   1716 	asm volatile ("moveb #0x45, %1@(0x3d4); \
   1717 		moveb %1@(0x3d5),%0" : "=r" (test) : "a" (ba));
   1718 #endif
   1719 
   1720 	WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
   1721 
   1722 	hwc = ba + CRT_ADDRESS_W;
   1723 	*hwc = 0;
   1724 	*hwc = 0;
   1725 
   1726 #if 0
   1727 	test = RCrt(ba, CRT_ID_HWGC_MODE);
   1728 	asm volatile("nop");
   1729 #else
   1730 	/* do it in assembler, the above does't seem to work */
   1731 	asm volatile ("moveb #0x45, %1@(0x3d4); \
   1732 		moveb %1@(0x3d5),%0" : "=r" (test) : "a" (ba));
   1733 #endif
   1734 	switch (gp->g_display.gd_planes) {
   1735 	    case 8:
   1736 		WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1);
   1737 		*hwc = 1;
   1738 		break;
   1739 	    default:
   1740 		WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
   1741 		*hwc = 0xff;
   1742 		*hwc = 0xff;
   1743 	}
   1744 
   1745 	test = HWC_OFF / HWC_SIZE;
   1746 	WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8));
   1747 	WCrt (ba, CRT_ID_HWGC_START_AD_LO, (test & 0xff));
   1748 
   1749 	WCrt (ba, CRT_ID_HWGC_DSTART_X , 0);
   1750 	WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0);
   1751 
   1752 	WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10);	/* Cursor X11 Mode */
   1753 	/*
   1754 	 * Put it into Windoze Mode or you'll see sometimes a white stripe
   1755 	 * on the right side (in double clocking modes with a screen bigger
   1756 	 * > 1023 pixels).
   1757 	 */
   1758 	WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x00);	/* Cursor Windoze Mode */
   1759 
   1760 	WCrt (ba, CRT_ID_HWGC_MODE, 0x01);
   1761 }
   1762 
   1763 
   1764 /*
   1765  * This was the reason why you shouldn't use the HWC in the Kernel:(
   1766  * Obsoleted now by use of interrupts :-)
   1767  */
   1768 
   1769 #define VerticalRetraceWait(ba) \
   1770 { \
   1771 	while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \
   1772 	while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x08) ; \
   1773 	while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x00) ; \
   1774 }
   1775 
   1776 
   1777 int
   1778 cv3d_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
   1779 {
   1780 	volatile caddr_t ba, fb;
   1781 	int depth = gp->g_display.gd_planes;
   1782 
   1783 	ba = gp->g_regkva;
   1784 	fb = gp->g_fbkva;
   1785 
   1786 	if (info->set & GRFSPRSET_SHAPE) {
   1787 		/*
   1788 		 * For an explanation of these weird actions here, see above
   1789 		 * when reading the shape.  We set the shape directly into
   1790 		 * the video memory, there's no reason to keep 1k on the
   1791 		 * kernel stack just as template
   1792 		 */
   1793 		u_char *image, *mask;
   1794 		volatile u_short *hwp;
   1795 		u_char *imp, *mp;
   1796 		unsigned short row;
   1797 
   1798 		/* Cursor off */
   1799 		WCrt (ba, CRT_ID_HWGC_MODE, 0x00);
   1800 
   1801 		/*
   1802 		 * The Trio64 crashes if the cursor data is written
   1803 		 * while the cursor is displayed.
   1804 		 * Sadly, turning the cursor off is not enough.
   1805 		 * What we have to do is:
   1806 		 * 1. Wait for vertical retrace, to make sure no-one
   1807 		 * has moved the cursor in this sync period (because
   1808 		 * another write then would have no effect, argh!).
   1809 		 * 2. Move the cursor off-screen
   1810 		 * 3. Another wait for v. retrace to make sure the cursor
   1811 		 * is really off.
   1812 		 * 4. Write the data, finally.
   1813 		 * (thanks to Harald Koenig for this tip!)
   1814 		 */
   1815 
   1816 		/*
   1817 		 * Remark 06/06/96: Update in interrupt obsoletes this,
   1818 		 * but the warning should stay there!
   1819 		 */
   1820 
   1821 		VerticalRetraceWait(ba);
   1822 
   1823 		WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7);
   1824 		WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO,  0xff);
   1825 		WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, 0xff);
   1826 		WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f);
   1827 		WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f);
   1828 		WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7);
   1829 
   1830 		if (info->size.y > 64)
   1831 			info->size.y = 64;
   1832 		if (info->size.x > 64)
   1833 			info->size.x = 64;
   1834 		if (info->size.x < 32)
   1835 			info->size.x = 32;
   1836 
   1837 		image = malloc(HWC_SIZE, M_TEMP, M_WAITOK);
   1838 		mask  = image + HWC_SIZE/2;
   1839 
   1840 		copyin(info->image, image, info->size.y * info->size.x / 8);
   1841 		copyin(info->mask, mask, info->size.y * info->size.x / 8);
   1842 
   1843 		hwp = (u_short *)(fb  +HWC_OFF);
   1844 
   1845 		/* This is necessary in order not to crash the board */
   1846 		VerticalRetraceWait(ba);
   1847 
   1848 		/*
   1849 		 * setting it is slightly more difficult, because we can't
   1850 		 * force the application to not pass a *smaller* than
   1851 		 * supported bitmap
   1852 		 */
   1853 
   1854 		for (row = 0, mp = mask, imp = image;
   1855 		    row < info->size.y; row++) {
   1856 			u_short im1, im2, im3, im4, m1, m2, m3, m4;
   1857 
   1858 			m1  = ~(*(unsigned short *)mp);
   1859 			im1 = *(unsigned short *)imp & *(unsigned short *)mp;
   1860 			mp  += 2;
   1861 			imp += 2;
   1862 
   1863 			m2  = ~(*(unsigned short *)mp);
   1864 			im2 = *(unsigned short *)imp & *(unsigned short *)mp;
   1865 			mp  += 2;
   1866 			imp += 2;
   1867 
   1868 			if (info->size.x > 32) {
   1869 				m3  = ~(*(unsigned short *)mp);
   1870 				im3 = *(unsigned short *)imp & *(unsigned short *)mp;
   1871 				mp  += 2;
   1872 				imp += 2;
   1873 				m4  = ~(*(unsigned short *)mp);
   1874 				im4 = *(unsigned short *)imp & *(unsigned short *)mp;
   1875 				mp  += 2;
   1876 				imp += 2;
   1877 			} else {
   1878 				m3  = 0xffff;
   1879 				im3 = 0;
   1880 				m4  = 0xffff;
   1881 				im4 = 0;
   1882 			}
   1883 
   1884 			switch (depth) {
   1885 			    case 8:
   1886 				*hwp++ = m1;
   1887 				*hwp++ = im1;
   1888 				*hwp++ = m2;
   1889 				*hwp++ = im2;
   1890 				*hwp++ = m3;
   1891 				*hwp++ = im3;
   1892 				*hwp++ = m4;
   1893 				*hwp++ = im4;
   1894 				break;
   1895 			    case 15:
   1896 			    case 16:
   1897 				*hwp++ = M2I(m1);
   1898 				*hwp++ = M2I(im1);
   1899 				*hwp++ = M2I(m2);
   1900 				*hwp++ = M2I(im2);
   1901 				*hwp++ = M2I(m3);
   1902 				*hwp++ = M2I(im3);
   1903 				*hwp++ = M2I(m4);
   1904 				*hwp++ = M2I(im4);
   1905 				break;
   1906 			    case 24:
   1907 			    case 32:
   1908 				*hwp++ = M2I(im1);
   1909 				*hwp++ = M2I(m1);
   1910 				*hwp++ = M2I(im2);
   1911 				*hwp++ = M2I(m2);
   1912 				*hwp++ = M2I(im3);
   1913 				*hwp++ = M2I(m3);
   1914 				*hwp++ = M2I(im4);
   1915 				*hwp++ = M2I(m4);
   1916 				break;
   1917 			}
   1918 		}
   1919 
   1920 		if (depth < 24) {
   1921 			for (; row < 64; row++) {
   1922 				*hwp++ = 0xffff;
   1923 				*hwp++ = 0x0000;
   1924 				*hwp++ = 0xffff;
   1925 				*hwp++ = 0x0000;
   1926 				*hwp++ = 0xffff;
   1927 				*hwp++ = 0x0000;
   1928 				*hwp++ = 0xffff;
   1929 				*hwp++ = 0x0000;
   1930 			}
   1931 		} else {
   1932 			for (; row < 64; row++) {
   1933 				*hwp++ = 0x0000;
   1934 				*hwp++ = 0xffff;
   1935 				*hwp++ = 0x0000;
   1936 				*hwp++ = 0xffff;
   1937 				*hwp++ = 0x0000;
   1938 				*hwp++ = 0xffff;
   1939 				*hwp++ = 0x0000;
   1940 				*hwp++ = 0xffff;
   1941 			}
   1942 		}
   1943 
   1944 		free(image, M_TEMP);
   1945 		/* cv3d_setup_hwc(gp); */
   1946 		cv3d_hotx = info->hot.x;
   1947 		cv3d_hoty = info->hot.y;
   1948 
   1949 		/* One must not write twice per vertical blank :-( */
   1950 		VerticalRetraceWait(ba);
   1951 		cv3d_setspritepos(gp, &info->pos);
   1952 	}
   1953 	if (info->set & GRFSPRSET_CMAP) {
   1954 		volatile caddr_t hwc;
   1955 		int test;
   1956 
   1957 		/* reset colour stack */
   1958 		test = RCrt(ba, CRT_ID_HWGC_MODE);
   1959 		asm volatile("nop");
   1960 		switch (depth) {
   1961 		    case 8:
   1962 		    case 15:
   1963 		    case 16:
   1964 			WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
   1965 			hwc = ba + CRT_ADDRESS_W;
   1966 			*hwc = 0;
   1967 			break;
   1968 		    case 32:
   1969 		    case 24:
   1970 			WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
   1971 			hwc = ba + CRT_ADDRESS_W;
   1972 			*hwc = 0;
   1973 			*hwc = 0;
   1974 			break;
   1975 		}
   1976 
   1977 		test = RCrt(ba, CRT_ID_HWGC_MODE);
   1978 		asm volatile("nop");
   1979 		switch (depth) {
   1980 		    case 8:
   1981 			WCrt (ba, CRT_ID_HWGC_BG_STACK, 1);
   1982 			hwc = ba + CRT_ADDRESS_W;
   1983 			*hwc = 1;
   1984 			break;
   1985 		    case 15:
   1986 		    case 16:
   1987 			WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
   1988 			hwc = ba + CRT_ADDRESS_W;
   1989 			*hwc = 0xff;
   1990 			break;
   1991 		    case 32:
   1992 		    case 24:
   1993 			WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
   1994 			hwc = ba + CRT_ADDRESS_W;
   1995 			*hwc = 0xff;
   1996 			*hwc = 0xff;
   1997 			break;
   1998 		}
   1999 	}
   2000 
   2001 	if (info->set & GRFSPRSET_ENABLE) {
   2002 		if (info->enable) {
   2003 			cv3d_cursor_on = 1;
   2004 			cv3d_setup_hwc(gp);
   2005 			/* WCrt(ba, CRT_ID_HWGC_MODE, 0x01); */
   2006 		} else
   2007 			WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
   2008 	}
   2009 	if (info->set & GRFSPRSET_POS)
   2010 		cv3d_setspritepos(gp, &info->pos);
   2011 	if (info->set & GRFSPRSET_HOT) {
   2012 
   2013 		cv3d_hotx = info->hot.x;
   2014 		cv3d_hoty = info->hot.y;
   2015 		cv3d_setspritepos (gp, &info->pos);
   2016 	}
   2017 	return(0);
   2018 }
   2019 
   2020 
   2021 int
   2022 cv3d_getspritemax(struct grf_softc *gp, struct grf_position *pos)
   2023 {
   2024 
   2025 	pos->x = 64;
   2026 	pos->y = 64;
   2027 	return(0);
   2028 }
   2029 
   2030 #endif /* CV3D_HARDWARE_CURSOR */
   2031 
   2032 #endif  /* NGRFCV3D */
   2033