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