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