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