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