Home | History | Annotate | Line # | Download | only in dev
grf_cv.c revision 1.8
      1 /*	$NetBSD: grf_cv.c,v 1.8 1996/03/04 20:36:56 is 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) dice2.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  *    Hardware Cursor support
     49  */
     50 
     51 #include <sys/param.h>
     52 #include <sys/errno.h>
     53 #include <sys/ioctl.h>
     54 #include <sys/device.h>
     55 #include <sys/malloc.h>
     56 #include <sys/systm.h>
     57 #include <machine/cpu.h>
     58 #include <dev/cons.h>
     59 #include <amiga/dev/itevar.h>
     60 #include <amiga/amiga/device.h>
     61 #include <amiga/dev/grfioctl.h>
     62 #include <amiga/dev/grfvar.h>
     63 #include <amiga/dev/grf_cvreg.h>
     64 #include <amiga/dev/zbusvar.h>
     65 
     66 int	grfcvmatch  __P((struct device *, struct cfdata *, void *));
     67 void	grfcvattach __P((struct device *, struct device *, void *));
     68 int	grfcvprint  __P((void *, char *));
     69 
     70 static int cv_has_4mb __P((volatile caddr_t));
     71 static unsigned short compute_clock __P((unsigned long));
     72 void	cv_boardinit __P((struct grf_softc *));
     73 int	cv_getvmode __P((struct grf_softc *, struct grfvideo_mode *));
     74 int	cv_setvmode __P((struct grf_softc *, unsigned int));
     75 int	cv_blank __P((struct grf_softc *, int *));
     76 int	cv_mode __P((register struct grf_softc *, int, void *, int, int));
     77 int	cv_ioctl __P((register struct grf_softc *gp, int cmd, void *data));
     78 int	cv_setmonitor __P((struct grf_softc *, struct grfvideo_mode *));
     79 int	cv_getcmap __P((struct grf_softc *, struct grf_colormap *));
     80 int	cv_putcmap __P((struct grf_softc *, struct grf_colormap *));
     81 int	cv_toggle __P((struct grf_softc *));
     82 int	cv_mondefok __P((struct grfvideo_mode *));
     83 int	cv_load_mon __P((struct grf_softc *, struct grfcvtext_mode *));
     84 void	cv_inittextmode __P((struct grf_softc *));
     85 void	cv_memset __P((unsigned char *, unsigned char, int));
     86 static	inline void cv_write_port __P((unsigned short, volatile caddr_t));
     87 static	inline void cvscreen __P((int, volatile caddr_t));
     88 static	inline void gfx_on_off __P((int, volatile caddr_t));
     89 
     90 /* Graphics display definitions.
     91  * These are filled by 'grfconfig' using GRFIOCSETMON.
     92  */
     93 #define monitor_def_max 24
     94 static struct grfvideo_mode monitor_def[24] = {
     95 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
     96 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
     97 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
     98 };
     99 static struct grfvideo_mode *monitor_current = &monitor_def[0];
    100 #define MAXPIXELCLOCK 135000000 /* safety */
    101 
    102 
    103 /* Console display definition.
    104  *   Default hardcoded text mode.  This grf_cv is set up to
    105  *   use one text mode only, and this is it.  You may use
    106  *   grfconfig to change the mode after boot.
    107  */
    108 
    109 /* Console font */
    110 #ifdef KFONT_8X11
    111 #define S3FONT kernel_font_8x11
    112 #define S3FONTY 11
    113 #else
    114 #define S3FONT kernel_font_8x8
    115 #define S3FONTY 8
    116 #endif
    117 extern unsigned char S3FONT[];
    118 
    119 /*
    120  * Define default console mode
    121  * (Internally, we still have to use hvalues/8!)
    122  */
    123 struct grfcvtext_mode cvconsole_mode = {
    124 	{255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8,
    125 	 481, 521, 491, 493, 525},
    126 	8, S3FONTY, 80, 480 / S3FONTY, S3FONT, 32, 255
    127 };
    128 
    129 /* Console colors */
    130 unsigned char cvconscolors[4][3] = {	/* background, foreground, hilite */
    131 	{0x30, 0x30, 0x30}, {0, 0, 0}, {0x18, 0x20, 0x34}, {0x2a, 0x2a, 0x2a}
    132 };
    133 
    134 static unsigned char clocks[]={
    135 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
    136 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
    137 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
    138 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
    139 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
    140 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
    141 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
    142 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
    143 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
    144 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
    145 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
    146 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
    147 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
    148 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
    149 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
    150 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
    151 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
    152 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
    153 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
    154 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
    155 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
    156 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
    157 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
    158 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
    159 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
    160 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
    161 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
    162 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
    163 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
    164 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
    165 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
    166 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
    167 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
    168 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
    169 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
    170 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
    171 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
    172 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
    173 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
    174 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
    175 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
    176 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
    177 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
    178 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
    179 0x13, 0x1,  0x13, 0x1,  0x7d, 0x27, 0x4c, 0x9,
    180 0x37, 0x22, 0x5b, 0xb,  0x71, 0x26, 0x5c, 0xb,
    181 0x6b, 0xd,  0x47, 0x23, 0x14, 0x1,  0x4f, 0x9,
    182 0x23, 0x3,  0x75, 0x26, 0x7d, 0xf,  0x1c, 0x2,
    183 0x51, 0x9,  0x59, 0x24, 0x61, 0xb,  0x69, 0x25,
    184 0x79, 0x26, 0x34, 0x5,  0x1d, 0x2,  0x6b, 0x25,
    185 0x54, 0x9,  0x35, 0x5,  0x45, 0x7,  0x6d, 0x25,
    186 0x7d, 0x26, 0x16, 0x1,  0x7f, 0x26, 0x77, 0xd,
    187 0x4f, 0x23, 0x78, 0xd,  0x2f, 0x21, 0x27, 0x3,
    188 0x1f, 0x2,  0x59, 0x9,  0x6a, 0xb,  0x73, 0x25,
    189 0x6b, 0xb,  0x63, 0x24, 0x5b, 0x9,  0x20, 0x2,
    190 0x7e, 0xd,  0x4b, 0x7,  0x65, 0x24, 0x43, 0x22,
    191 0x18, 0x1,  0x6f, 0xb,  0x5e, 0x9,  0x70, 0xb,
    192 0x2a, 0x3,  0x33, 0x4,  0x45, 0x6,  0x60, 0x9,
    193 0x7b, 0xc,  0x19, 0x1,  0x19, 0x1,  0x7d, 0xc,
    194 0x74, 0xb,  0x50, 0x7,  0x75, 0xb,  0x63, 0x9,
    195 0x51, 0x7,  0x23, 0x2,  0x3f, 0x5,  0x1a, 0x1,
    196 0x65, 0x9,  0x2d, 0x3,  0x40, 0x5,  0x0,  0x0,
    197 };
    198 
    199 
    200 /* Board Address of CV64 */
    201 static volatile caddr_t cv_boardaddr;
    202 static int cv_fbsize;
    203 
    204 /*
    205  * Memory clock (binpatchable).
    206  * Let's be defensive: 45 MHz runs on all boards I know of.
    207  * 55 MHz runs on most boards. But you should know what you're doing
    208  * if you set this flag. Again: This flag may destroy your CV Board.
    209  * Use it at your own risk!!!
    210  * Anyway, this doesn't imply that I'm responsible if your board breaks
    211  * without setting this flag :-).
    212  */
    213 #ifdef CV_AGGRESSIVE_TIMING
    214 long cv_memclk = 55000000;
    215 #else
    216 long cv_memclk = 45000000;
    217 #endif
    218 
    219 /* standard driver stuff */
    220 struct cfdriver grfcvcd = {
    221 	NULL, "grfcv", (cfmatch_t)grfcvmatch, grfcvattach,
    222 	DV_DULL, sizeof(struct grf_softc), NULL, 0
    223 };
    224 static struct cfdata *cfdata;
    225 
    226 
    227 /*
    228  * Get frambuffer memory size.
    229  * phase5 didn't provide the bit in CR36,
    230  * so we have to do it this way.
    231  * Return 0 for 2MB, 1 for 4MB
    232  */
    233 static int
    234 cv_has_4mb(fb)
    235 	volatile caddr_t fb;
    236 {
    237 	volatile unsigned long *testfbw, *testfbr;
    238 
    239 	/* write patterns in memory and test if they can be read */
    240 	testfbw = (volatile unsigned long *)fb;
    241 	testfbr = (volatile unsigned long *)(fb + 0x02000000);
    242 	*testfbw = 0x87654321;
    243 	if (*testfbr != 0x87654321)
    244 		return (0);
    245 
    246 	/* upper memory region */
    247 	testfbw = (volatile unsigned long *)(fb + 0x00200000);
    248 	testfbr = (volatile unsigned long *)(fb + 0x02200000);
    249 	*testfbw = 0x87654321;
    250 	if (*testfbr != 0x87654321)
    251 		return (0);
    252 	*testfbw = 0xAAAAAAAA;
    253 	if (*testfbr != 0xAAAAAAAA)
    254 		return (0);
    255 	*testfbw = 0x55555555;
    256 	if (*testfbr != 0x55555555)
    257 		return (0);
    258 	return (1);
    259 }
    260 
    261 int
    262 grfcvmatch(pdp, cfp, auxp)
    263 	struct device *pdp;
    264 	struct cfdata *cfp;
    265 	void *auxp;
    266 {
    267 	struct zbus_args *zap;
    268 	static int cvcons_unit = -1;
    269 
    270 	zap = auxp;
    271 
    272 	if (amiga_realconfig == 0)
    273 #ifdef CV64CONSOLE
    274 		if (cvcons_unit != -1)
    275 #endif
    276 			 return (0);
    277 
    278 	/* Lets be Paranoid: Test man and prod id */
    279 	if (zap->manid != 8512 || zap->prodid != 34)
    280 		return (0);
    281 
    282 	cv_boardaddr = zap->va;
    283 
    284 #ifdef CV64CONSOLE
    285 	if (amiga_realconfig == 0) {
    286 		cvcons_unit = cfp->cf_unit;
    287 		cfdata = cfp;
    288 	}
    289 #endif
    290 
    291 	return (1);
    292 }
    293 
    294 void
    295 grfcvattach(pdp, dp, auxp)
    296 	struct device *pdp, *dp;
    297 	void *auxp;
    298 {
    299 	static struct grf_softc congrf;
    300 	struct zbus_args *zap;
    301 	struct grf_softc *gp;
    302 	static char attachflag = 0;
    303 
    304 	zap = auxp;
    305 
    306 	/*
    307 	 * This function is called twice, once on console init (dp == NULL)
    308 	 * and once on "normal" grf5 init.
    309 	 */
    310 
    311 	if (dp == NULL) /* console init */
    312 		gp = &congrf;
    313 	else
    314 		gp = (struct grf_softc *)dp;
    315 
    316 	if (dp != NULL && congrf.g_regkva != 0) {
    317 		/*
    318 		 * inited earlier, just copy (not device struct)
    319 		 */
    320 
    321 		printf("\n");
    322 #ifdef CV64CONSOLE
    323 		bcopy(&congrf.g_display, &gp->g_display,
    324 			(char *) &gp[1] - (char *) &gp->g_display);
    325 #else
    326 		gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000;
    327 		gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000;
    328 
    329 		gp->g_unit = GRF_CV64_UNIT;
    330 		gp->g_mode = cv_mode;
    331 		gp->g_conpri = grfcv_cnprobe();
    332 		gp->g_flags = GF_ALIVE;
    333 #endif
    334 	} else {
    335 		gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000;
    336 		gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000;
    337 
    338 		gp->g_unit = GRF_CV64_UNIT;
    339 		gp->g_mode = cv_mode;
    340 		gp->g_conpri = grfcv_cnprobe();
    341 		gp->g_flags = GF_ALIVE;
    342 
    343 		/* wakeup the board */
    344 		cv_boardinit(gp);
    345 
    346 #ifdef CV64CONSOLE
    347 		grfcv_iteinit(gp);
    348 		(void)cv_load_mon(gp, &cvconsole_mode);
    349 #endif
    350 	}
    351 
    352 	/*
    353 	 * attach grf
    354 	 */
    355 	if (amiga_config_found(cfdata, &gp->g_device, gp, grfcvprint)) {
    356 		if (dp != NULL)
    357 			printf("grfcv: CyberVision64 with %dMB being used\n", cv_fbsize/0x100000);
    358 		attachflag = 1;
    359 	} else {
    360 		if (!attachflag)
    361 			/*printf("grfcv unattached!!\n")*/;
    362 	}
    363 }
    364 
    365 int
    366 grfcvprint(auxp, pnp)
    367 	void *auxp;
    368 	char *pnp;
    369 {
    370 	if (pnp)
    371 		printf("ite at %s: ", pnp);
    372 	return (UNCONF);
    373 }
    374 
    375 
    376 /*
    377  * Computes M, N, and R values from
    378  * given input frequency. It uses a table of
    379  * precomputed values, to keep CPU time low.
    380  *
    381  * The return value consist of:
    382  * lower byte:  Bits 4-0: N Divider Value
    383  *	        Bits 5-6: R Value          for e.g. SR10 or SR12
    384  * higher byte: Bits 0-6: M divider value  for e.g. SR11 or SR13
    385  */
    386 
    387 static unsigned short
    388 compute_clock(freq)
    389 	unsigned long freq;
    390 {
    391 	static unsigned char *mnr, *save;	/* M, N + R vals */
    392 	unsigned long work_freq, r;
    393 	unsigned short erg;
    394 	long diff, d2;
    395 
    396 	if (freq < 12500000 || freq > MAXPIXELCLOCK) {
    397 		printf("grfcv: Illegal clock frequency: %ldMHz\n", freq/1000000);
    398 		printf("grfcv: Using default frequency: 25MHz\n");
    399 		printf("grfcv: See the manpage of grfconfig for more informations.\n");
    400 		freq = 25000000;
    401 	}
    402 
    403 	mnr = clocks;	/* there the vals are stored */
    404 	d2 = 0x7fffffff;
    405 
    406 	while (*mnr) {	/* mnr vals are 0-terminated */
    407 		work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
    408 
    409 		r = (mnr[1] >> 5) & 0x03;
    410 		if (r != 0)
    411 			work_freq=work_freq >> r;	/* r is the freq divider */
    412 
    413 		work_freq *= 0x3E8;	/* 2nd part of OSC */
    414 
    415 		diff = abs(freq - work_freq);
    416 
    417 		if (d2 >= diff) {
    418 			d2 = diff;
    419 			/* In save are the vals for minimal diff */
    420 			save = mnr;
    421 		}
    422 		mnr += 2;
    423 	}
    424 	erg = *((unsigned short *)save);
    425 
    426 	return (erg);
    427 }
    428 
    429 
    430 void
    431 cv_boardinit(gp)
    432 	struct grf_softc *gp;
    433 {
    434 	volatile caddr_t ba;
    435 	unsigned char test;
    436 	unsigned int clockpar;
    437 	int i;
    438 	struct grfinfo *gi;
    439 
    440 	ba = gp->g_regkva;
    441 	/* Reset board */
    442 	for (i = 0; i < 6; i++)
    443 		cv_write_port (0xff, ba - 0x02000000);	/* Clear all bits */
    444 
    445 	/* Return to operational Mode */
    446 	cv_write_port(0x8004, ba - 0x02000000);
    447 
    448 	/* Wakeup Chip */
    449 	vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x10);
    450 	vgaw(ba, SREG_OPTION_SELECT, 0x1);
    451 	vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x8);
    452 
    453 	vgaw(ba, GREG_MISC_OUTPUT_W, 0x23);
    454 
    455 	WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48);	/* unlock S3 VGA regs */
    456 	WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5);	/* unlock syscontrol */
    457 
    458 	test = RCrt(ba, CRT_ID_SYSTEM_CONFIG);
    459 	test = test | 0x01;	/* enable enhaced register access */
    460 	test = test & 0xEF;	/* clear bit 4, 0 wait state */
    461 	WCrt(ba, CRT_ID_SYSTEM_CONFIG, test);
    462 
    463 	/*
    464 	 * bit 1=1: enable enhanced mode functions
    465 	 * bit 4=1: enable linear adressing
    466 	 * bit 5=1: enable MMIO
    467  	 */
    468 	vgaw(ba, ECR_ADV_FUNC_CNTL, 0x31);
    469 
    470 	/* enable cpu acess, color mode, high 64k page */
    471 	vgaw(ba, GREG_MISC_OUTPUT_W, 0x23);
    472 
    473 	/* Cpu base addr */
    474 	WCrt(ba, CRT_ID_EXT_SYS_CNTL_4, 0x0);
    475 
    476 	/* Reset. This does nothing, but everyone does it:) */
    477 	WSeq(ba, SEQ_ID_RESET, 0x3);
    478 
    479 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x1);	/* 8 Dot Clock */
    480 	WSeq(ba, SEQ_ID_MAP_MASK, 0xF);		/* Enable write planes */
    481 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x0);	/* Character Font */
    482 
    483 	WSeq(ba, SEQ_ID_MEMORY_MODE, 0x2);	/* Complete mem access */
    484 
    485 	WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x6);	/* Unlock extensions */
    486 	test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL);	/* Bus Request */
    487 
    488 	/* enable 4MB fast Page Mode */
    489 	test = test | 1 << 6;
    490 	WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test);
    491 	/* faster LUT write */
    492 	WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0);
    493 
    494 	test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);	/* Clksyn2 read */
    495 
    496 	/* immediately Clkload bit clear */
    497 	test = test & 0xDF;
    498 
    499 	/* 2 MCLK Memory Write.... */
    500 	if (cv_memclk >= 55000000)
    501 		test |= 0x80;
    502 
    503 	WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test);
    504 
    505 	/* Memory CLK */
    506 	clockpar = compute_clock(cv_memclk);
    507 	test = (clockpar & 0xFF00) >> 8;
    508 
    509 	if (RCrt(ba, CRT_ID_REVISION) == 0x10) {
    510 		WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */
    511 
    512 		test = clockpar & 0xFF;
    513 		WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */
    514 
    515 		test = (clockpar & 0xFF00) >> 8;
    516 		WSeq(ba, SEQ_ID_MORE_MAGIC, test);
    517 	} else {
    518                WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */
    519 
    520                test = clockpar & 0xFF;
    521                WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */
    522 	}
    523 
    524 	/* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */
    525 	/* DCLK */
    526 	WSeq(ba, SEQ_ID_DCLK_HI, 0x13);
    527 	WSeq(ba, SEQ_ID_DCLK_LO, 0x41);
    528 
    529 	test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2);
    530 	test = test | 0x22;
    531 
    532 	/* DCLK + MCLK Clock immediate load! */
    533 	WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test);
    534 
    535 	/* DCLK load */
    536 	test = vgar(ba, 0x3cc);
    537 	test = test | 0x0c;
    538 	vgaw(ba, 0x3c2, test);
    539 
    540 	/* Clear bit 5 again, prevent further loading. */
    541 	WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x2);
    542 
    543 	WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F);
    544 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F);
    545 	WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50);
    546 	WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82);
    547 	WCrt(ba, CRT_ID_START_HOR_RETR, 0x54);
    548 	WCrt(ba, CRT_ID_END_HOR_RETR, 0x80);
    549 	WCrt(ba, CRT_ID_VER_TOTAL, 0xBF);
    550 
    551 	WCrt(ba, CRT_ID_OVERFLOW, 0x1F);	/* overflow reg */
    552 
    553 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x0);	/* no panning */
    554 
    555 	WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40);	/* vscan */
    556 
    557 	WCrt(ba, CRT_ID_CURSOR_START, 0x00);
    558 	WCrt(ba, CRT_ID_CURSOR_END, 0x00);
    559 
    560 	/* Display start adress */
    561 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
    562 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
    563 
    564 	/* Cursor location */
    565 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
    566 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
    567 
    568 	/* Vertical retrace */
    569 	WCrt(ba, CRT_ID_START_VER_RETR, 0x9C);
    570 	WCrt(ba, CRT_ID_END_VER_RETR, 0x0E);
    571 
    572 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F);
    573 	WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50);
    574 
    575 	WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00);
    576 
    577 	WCrt(ba, CRT_ID_START_VER_BLANK, 0x96);
    578 	WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9);
    579 
    580 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
    581 
    582 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF);
    583 
    584 	WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10);	/* FIFO enabled */
    585 
    586 	/* Refresh count 1, High speed text font, enhanced color mode */
    587 	WCrt(ba, CRT_ID_MISC_1, 0x35);
    588 
    589 	/* start fifo position */
    590 	WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5a);
    591 
    592 	WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x70);
    593 
    594 	/* address window position */
    595 	WCrt(ba, CRT_ID_LAW_POS_LO, 0x40);
    596 
    597 	/* N Parameter for Display FIFO */
    598 	WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
    599 
    600 	WGfx(ba, GCT_ID_SET_RESET, 0x0);
    601 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x0);
    602 	WGfx(ba, GCT_ID_COLOR_COMPARE, 0x0);
    603 	WGfx(ba, GCT_ID_DATA_ROTATE, 0x0);
    604 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x0);
    605 	WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
    606 	WGfx(ba, GCT_ID_MISC, 0x01);
    607 	WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F);
    608 	WGfx(ba, GCT_ID_BITMASK, 0xFF);
    609 
    610 	/* colors for text mode */
    611 	for (i = 0; i <= 0xf; i++)
    612 		WAttr (ba, i, i);
    613 
    614 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41);
    615 	WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01);
    616 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F);
    617 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x0);
    618 	WAttr(ba, ACT_ID_COLOR_SELECT, 0x0);
    619 
    620 	vgaw(ba, VDAC_MASK, 0xFF);	/* DAC Mask */
    621 
    622 	*((unsigned long *)(ba + ECR_FRGD_COLOR)) = 0xFF;
    623 	*((unsigned long *)(ba + ECR_BKGD_COLOR)) = 0;
    624 
    625 	/* colors initially set to greyscale */
    626 
    627 	vgaw(ba, VDAC_ADDRESS_W, 0);
    628 	for (i = 255; i >= 0 ; i--) {
    629 		vgaw(ba, VDAC_DATA, i);
    630 		vgaw(ba, VDAC_DATA, i);
    631 		vgaw(ba, VDAC_DATA, i);
    632 	}
    633 
    634 	/* GFx hardware cursor off */
    635 	WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
    636 
    637 	/* Set first to 4 MB, so test will work */
    638 	WCrt(ba, CRT_ID_LAW_CNTL, 0x13);
    639 
    640 	/* find *correct* fbsize of z3 board */
    641 	if (cv_has_4mb((volatile caddr_t)cv_boardaddr + 0x01400000)) {
    642 		cv_fbsize = 1024 * 1024 * 4;
    643 		WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */
    644 	} else {
    645 		cv_fbsize = 1024 * 1024 * 2;
    646 		WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */
    647 	}
    648 
    649 	/* Enable Video Display (Set Bit 5) */
    650 	WAttr(ba, 0x33, 0);
    651 
    652 	gi = &gp->g_display;
    653 	gi->gd_regaddr	= (caddr_t) kvtop (ba);
    654 	gi->gd_regsize	= 64 * 1024;
    655 	gi->gd_fbaddr	= (caddr_t) kvtop (gp->g_fbkva);
    656 	gi->gd_fbsize	= cv_fbsize;
    657 }
    658 
    659 
    660 int
    661 cv_getvmode(gp, vm)
    662 	struct grf_softc *gp;
    663 	struct grfvideo_mode *vm;
    664 {
    665 	struct grfvideo_mode *gv;
    666 
    667 #ifdef CV64CONSOLE
    668 	/* Handle grabbing console mode */
    669 	if (vm->mode_num == 255) {
    670 		bcopy(&cvconsole_mode, vm, sizeof(struct grfvideo_mode));
    671 		/* XXX so grfconfig can tell us the correct text dimensions. */
    672 		vm->depth = cvconsole_mode.fy;
    673 	} else
    674 #endif
    675 	{
    676 		if (vm->mode_num == 0)
    677 			vm->mode_num = (monitor_current - monitor_def) + 1;
    678 		if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
    679 			return (EINVAL);
    680 		gv = monitor_def + (vm->mode_num - 1);
    681 		if (gv->mode_num == 0)
    682 			return (EINVAL);
    683 
    684 		bcopy(gv, vm, sizeof(struct grfvideo_mode));
    685 	}
    686 
    687 	/* adjust internal values to pixel values */
    688 
    689 	vm->hblank_start *= 8;
    690 	vm->hblank_stop *= 8;
    691 	vm->hsync_start *= 8;
    692 	vm->hsync_stop *= 8;
    693 	vm->htotal *= 8;
    694 
    695 	return (0);
    696 }
    697 
    698 
    699 int
    700 cv_setvmode(gp, mode)
    701 	struct grf_softc *gp;
    702 	unsigned mode;
    703 {
    704 
    705 	if (!mode || (mode > monitor_def_max) ||
    706 	    monitor_def[mode - 1].mode_num == 0)
    707 		return (EINVAL);
    708 
    709 	monitor_current = monitor_def + (mode - 1);
    710 
    711 	return (0);
    712 }
    713 
    714 
    715 int
    716 cv_blank(gp, on)
    717 	struct grf_softc *gp;
    718 	int *on;
    719 {
    720 	volatile caddr_t ba;
    721 
    722 	ba = gp->g_regkva;
    723 	gfx_on_off(*on ? 0 : 1, ba);
    724 	return (0);
    725 }
    726 
    727 
    728 /*
    729  * Change the mode of the display.
    730  * Return a UNIX error number or 0 for success.
    731  */
    732 int
    733 cv_mode(gp, cmd, arg, a2, a3)
    734 	register struct grf_softc *gp;
    735 	int cmd;
    736 	void *arg;
    737 	int a2, a3;
    738 {
    739 	int error;
    740 
    741 	switch (cmd) {
    742 	case GM_GRFON:
    743 		error = cv_load_mon (gp,
    744 		    (struct grfcvtext_mode *) monitor_current) ? 0 : EINVAL;
    745 		return (error);
    746 
    747 	case GM_GRFOFF:
    748 #ifndef CV64CONSOLE
    749 		(void)cv_toggle(gp);
    750 #else
    751 		cv_load_mon(gp, &cvconsole_mode);
    752 		ite_reinit(gp->g_itedev);
    753 #endif
    754 		return (0);
    755 
    756 	case GM_GRFCONFIG:
    757 		return (0);
    758 
    759 	case GM_GRFGETVMODE:
    760 		return (cv_getvmode (gp, (struct grfvideo_mode *) arg));
    761 
    762 	case GM_GRFSETVMODE:
    763 		error = cv_setvmode (gp, *(unsigned *) arg);
    764 		if (!error && (gp->g_flags & GF_GRFON))
    765 			cv_load_mon(gp,
    766 			    (struct grfcvtext_mode *) monitor_current);
    767 		return (error);
    768 
    769 	case GM_GRFGETNUMVM:
    770 		*(int *)arg = monitor_def_max;
    771 		return (0);
    772 
    773 	case GM_GRFIOCTL:
    774 		return (cv_ioctl (gp, (int) arg, (caddr_t) a2));
    775 
    776 	default:
    777 		break;
    778 	}
    779 
    780 	return (EINVAL);
    781 }
    782 
    783 int
    784 cv_ioctl (gp, cmd, data)
    785 	register struct grf_softc *gp;
    786 	int cmd;
    787 	void *data;
    788 {
    789 	switch (cmd) {
    790 	case GRFIOCGSPRITEPOS:
    791 	case GRFIOCSSPRITEPOS:
    792 	case GRFIOCSSPRITEINF:
    793 	case GRFIOCGSPRITEINF:
    794 	case GRFIOCGSPRITEMAX:
    795 		break;
    796 
    797 	case GRFIOCGETCMAP:
    798 		return (cv_getcmap (gp, (struct grf_colormap *) data));
    799 
    800 	case GRFIOCPUTCMAP:
    801 		return (cv_putcmap (gp, (struct grf_colormap *) data));
    802 
    803 	case GRFIOCBITBLT:
    804 		break;
    805 
    806 	case GRFTOGGLE:
    807 		return (cv_toggle (gp));
    808 
    809 	case GRFIOCSETMON:
    810 		return (cv_setmonitor (gp, (struct grfvideo_mode *)data));
    811 
    812 	case GRFIOCBLANK:
    813 		return (cv_blank (gp, (int *)data));
    814 	}
    815 	return (EINVAL);
    816 }
    817 
    818 int
    819 cv_setmonitor(gp, gv)
    820 	struct grf_softc *gp;
    821 	struct grfvideo_mode *gv;
    822 {
    823 	struct grfvideo_mode *md;
    824 
    825 	if (!cv_mondefok(gv))
    826 		return (EINVAL);
    827 
    828 #ifdef CV64CONSOLE
    829 	/* handle interactive setting of console mode */
    830 	if (gv->mode_num == 255) {
    831 		bcopy(gv, &cvconsole_mode.gv, sizeof(struct grfvideo_mode));
    832 		cvconsole_mode.gv.hblank_start /= 8;
    833 		cvconsole_mode.gv.hblank_stop /= 8;
    834 		cvconsole_mode.gv.hsync_start /= 8;
    835 		cvconsole_mode.gv.hsync_stop /= 8;
    836 		cvconsole_mode.gv.htotal /= 8;
    837 		cvconsole_mode.rows = gv->disp_height / cvconsole_mode.fy;
    838 		cvconsole_mode.cols = gv->disp_width / cvconsole_mode.fx;
    839 		if (!(gp->g_flags & GF_GRFON))
    840 			cv_load_mon(gp, &cvconsole_mode);
    841 		ite_reinit(gp->g_itedev);
    842 		return (0);
    843 	}
    844 #endif
    845 
    846 	md = monitor_def + (gv->mode_num - 1);
    847 	bcopy(gv, md, sizeof(struct grfvideo_mode));
    848 
    849 	/* adjust pixel oriented values to internal rep. */
    850 
    851 	md->hblank_start /= 8;
    852 	md->hblank_stop /= 8;
    853 	md->hsync_start /= 8;
    854 	md->hsync_stop /= 8;
    855 	md->htotal /= 8;
    856 
    857 	return (0);
    858 }
    859 
    860 int
    861 cv_getcmap(gfp, cmap)
    862 	struct grf_softc *gfp;
    863 	struct grf_colormap *cmap;
    864 {
    865 	volatile caddr_t ba;
    866 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    867 	short x;
    868 	int error;
    869 
    870 	ba = gfp->g_regkva;
    871 	if (cmap->count == 0 || cmap->index >= 256)
    872 		return (0);
    873 
    874 	if (cmap->index + cmap->count > 256)
    875 		cmap->count = 256 - cmap->index;
    876 
    877 	/* first read colors out of the chip, then copyout to userspace */
    878 	vgaw (ba, VDAC_ADDRESS_W, cmap->index);
    879 	x = cmap->count - 1;
    880 
    881 	rp = red + cmap->index;
    882 	gp = green + cmap->index;
    883 	bp = blue + cmap->index;
    884 
    885 	do {
    886 		*rp++ = vgar (ba, VDAC_DATA) << 2;
    887 		*gp++ = vgar (ba, VDAC_DATA) << 2;
    888 		*bp++ = vgar (ba, VDAC_DATA) << 2;
    889 	} while (x-- > 0);
    890 
    891 	if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
    892 	    && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
    893 	    && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
    894 		return (0);
    895 
    896 	return (error);
    897 }
    898 
    899 int
    900 cv_putcmap(gfp, cmap)
    901 	struct grf_softc *gfp;
    902 	struct grf_colormap *cmap;
    903 {
    904 	volatile caddr_t ba;
    905 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    906 	short x;
    907 	int error;
    908 
    909 	ba = gfp->g_regkva;
    910 	if (cmap->count == 0 || cmap->index >= 256)
    911 		return (0);
    912 
    913 	if (cmap->index + cmap->count > 256)
    914 		cmap->count = 256 - cmap->index;
    915 
    916 	/* first copy the colors into kernelspace */
    917 	if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
    918 	    && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
    919 	    && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
    920 		vgaw (ba, VDAC_ADDRESS_W, cmap->index);
    921 		x = cmap->count - 1;
    922 
    923 		rp = red + cmap->index;
    924 		gp = green + cmap->index;
    925 		bp = blue + cmap->index;
    926 
    927 		do {
    928 			vgaw (ba, VDAC_DATA, *rp++ >> 2);
    929 			vgaw (ba, VDAC_DATA, *gp++ >> 2);
    930 			vgaw (ba, VDAC_DATA, *bp++ >> 2);
    931 		} while (x-- > 0);
    932 		return (0);
    933 	} else
    934 		return (error);
    935 }
    936 
    937 
    938 int
    939 cv_toggle(gp)
    940 	struct grf_softc *gp;
    941 {
    942 	volatile caddr_t ba;
    943 
    944 	ba = gp->g_regkva;
    945 	cvscreen(1, ba - 0x02000000);
    946 
    947 	return (0);
    948 }
    949 
    950 
    951 int
    952 cv_mondefok(gv)
    953 	struct grfvideo_mode *gv;
    954 {
    955 	unsigned long maxpix;
    956 	int widthok = 0;
    957 
    958 	if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) {
    959 		if (gv->mode_num != 255 || (gv->depth != 4 && gv->depth != 8))
    960 			return (0);
    961 		else
    962 			/*
    963 			 * We have 8 bit console modes. This _is_
    964 			 * a hack but necessary to be compatible.
    965 			 */
    966 			gv->depth = 8;
    967 	}
    968 
    969 	switch(gv->depth) {
    970 	   case 1:
    971 	   case 4:
    972 		return (0);
    973 	   case 8:
    974 		maxpix = MAXPIXELCLOCK;
    975 		break;
    976 	   case 15:
    977 	   case 16:
    978 #ifdef CV_AGGRESSIVE_TIMING
    979 		maxpix = MAXPIXELCLOCK - 35000000;
    980 #else
    981 		maxpix = MAXPIXELCLOCK - 55000000;
    982 #endif
    983 		break;
    984 	   case 24:
    985 	   case 32:
    986 #ifdef CV_AGGRESSIVE_TIMING
    987 		maxpix = MAXPIXELCLOCK - 75000000;
    988 #else
    989 		maxpix = MAXPIXELCLOCK - 85000000;
    990 #endif
    991 		break;
    992 	   default:
    993 		return (0);
    994 	}
    995 
    996 	if (gv->pixel_clock > maxpix)
    997 		return (0);
    998 
    999 	/*
   1000 	 * These are the supported witdh values for the
   1001 	 * graphics engine. To Support other widths, one
   1002 	 * has to use one of these widths for memory alignment, i.e.
   1003 	 * one has to set CRT_ID_SCREEN_OFFSET to one of these values and
   1004 	 * CRT_ID_HOR_DISP_ENA_END to the desired width.
   1005 	 * Since a working graphics engine is essential
   1006 	 * for the console, console modes of other width are not supported.
   1007 	 * We could do that, though, but then you have to tell the Xserver
   1008 	 * about this strange configuration and I don't know how at the moment :-)
   1009 	 */
   1010 
   1011 	switch (gv->disp_width) {
   1012 	    case 1024:
   1013 	    case 640:
   1014 	    case 800:
   1015 	    case 1280:
   1016 	    case 1152:
   1017 	    case 1600:
   1018 		widthok = 1;
   1019 		break;
   1020 	    default: /* XXX*/
   1021 		widthok = 0;
   1022 		break;
   1023 	}
   1024 
   1025 	if (widthok) return (1);
   1026 	else {
   1027 		if (gv->mode_num == 255) { /* console mode */
   1028 			printf ("This display width is not supported by the CV64 console.\n");
   1029 			printf ("Use one of 640 800 1024 1152 1280 1600!\n");
   1030 			return (0);
   1031 		} else {
   1032 			printf ("Warning for mode %d:\n", (int) gv->mode_num);
   1033 			printf ("Don't use a blitter-suporting Xserver with this display width\n");
   1034 			printf ("Use one of 640 800 1024 1152 1280 1600!\n");
   1035 			return (1);
   1036 		}
   1037 	}
   1038 	return (1);
   1039 }
   1040 
   1041 int
   1042 cv_load_mon(gp, md)
   1043 	struct grf_softc *gp;
   1044 	struct grfcvtext_mode *md;
   1045 {
   1046 	struct grfvideo_mode *gv;
   1047 	struct grfinfo *gi;
   1048 	volatile caddr_t ba, fb;
   1049 	unsigned short mnr;
   1050 	unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
   1051 		VSE, VT;
   1052 	char LACE, DBLSCAN, TEXT, CONSOLE;
   1053 	int uplim, lowlim;
   1054 	int cr50, cr33, sr15, sr18, clock_mode, test;
   1055 	int m, n;	/* For calc'ing display FIFO */
   1056 	int tfillm, temptym;	/* FIFO fill and empty mclk's */
   1057 	int hmul;	/* Multiplier for hor. Values */
   1058 	/* identity */
   1059 	gv = &md->gv;
   1060 
   1061 	/*
   1062 	 * No way to get text modes to work.
   1063 	 * Blame phase5, not me!
   1064 	 */
   1065 	TEXT = 0; /* (gv->depth == 4); */
   1066 	CONSOLE = (gv->mode_num == 255);
   1067 
   1068 	if (!cv_mondefok(gv)) {
   1069 		printf("grfcv: The monitor definition is not okay.\n");
   1070 		printf("grfcv: See the manpage of grfconfig for more informations\n");
   1071 		return (0);
   1072 	}
   1073 	ba = gp->g_regkva;
   1074 	fb = gp->g_fbkva;
   1075 
   1076 	/* turn gfx off, don't mess up the display */
   1077 	gfx_on_off(1, ba);
   1078 
   1079 	/* provide all needed information in grf device-independant locations */
   1080 	gp->g_data		= (caddr_t) gv;
   1081 	gi = &gp->g_display;
   1082 	gi->gd_colors		= 1 << gv->depth;
   1083 	gi->gd_planes		= gv->depth;
   1084 	gi->gd_fbwidth		= gv->disp_width;
   1085 	gi->gd_fbheight		= gv->disp_height;
   1086 	gi->gd_fbx		= 0;
   1087 	gi->gd_fby		= 0;
   1088 	if (CONSOLE) {
   1089 		gi->gd_dwidth	= md->fx * md->cols;
   1090 		gi->gd_dheight	= md->fy * md->rows;
   1091 	} else {
   1092 		gi->gd_dwidth	= gv->disp_width;
   1093 		gi->gd_dheight	= gv->disp_height;
   1094 	}
   1095 	gi->gd_dx		= 0;
   1096 	gi->gd_dy		= 0;
   1097 
   1098 	/* get display mode parameters */
   1099 	switch (gv->depth) {
   1100 		case 15:
   1101 		case 16:
   1102 			hmul = 2;
   1103 			break;
   1104 		default:
   1105 			hmul = 1;
   1106         		break;
   1107 	}
   1108 
   1109 	HBS = gv->hblank_start * hmul;
   1110 	HBE = gv->hblank_stop * hmul;
   1111 	HSS = gv->hsync_start * hmul;
   1112 	HSE = gv->hsync_stop * hmul;
   1113 	HT  = gv->htotal*hmul - 5;
   1114 	VBS = gv->vblank_start - 1;
   1115 	VSS = gv->vsync_start;
   1116 	VSE = gv->vsync_stop;
   1117 	VBE = gv->vblank_stop;
   1118 	VT  = gv->vtotal - 2;
   1119 
   1120 	if (TEXT)
   1121 		HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
   1122 	else
   1123 		HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/
   1124 	VDE = gv->disp_height - 1;
   1125 
   1126 	/* figure out whether lace or dblscan is needed */
   1127 
   1128 	uplim = gv->disp_height + (gv->disp_height / 4);
   1129 	lowlim = gv->disp_height - (gv->disp_height / 4);
   1130 	LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
   1131 	DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
   1132 
   1133 	/* adjustments */
   1134 
   1135 	if (LACE)
   1136 		VDE /= 2;
   1137 
   1138 	WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
   1139 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
   1140 	WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
   1141 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
   1142 
   1143 	/* Set clock */
   1144 
   1145 	mnr = compute_clock(gv->pixel_clock);
   1146 	WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8) );
   1147 	WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF));
   1148 
   1149 	/* load display parameters into board */
   1150 
   1151 	WCrt(ba, CRT_ID_EXT_HOR_OVF,
   1152 	   ((HT & 0x100) ? 0x01 : 0x00) |
   1153 	   ((HDE & 0x100) ? 0x02 : 0x00) |
   1154 	   ((HBS & 0x100) ? 0x04 : 0x00) |
   1155 	/* ((HBE & 0x40) ? 0x08 : 0x00) | */  /* Later... */
   1156 	   ((HSS & 0x100) ? 0x10 : 0x00) |
   1157 	/* ((HSE & 0x20) ? 0x20 : 0x00) | */
   1158 	   (((HT-5) & 0x100) ? 0x40 : 0x00) );
   1159 
   1160 	WCrt(ba, CRT_ID_EXT_VER_OVF,
   1161 	    0x40 |	/* Line compare */
   1162 	    ((VT  & 0x400) ? 0x01 : 0x00) |
   1163 	    ((VDE & 0x400) ? 0x02 : 0x00) |
   1164 	    ((VBS & 0x400) ? 0x04 : 0x00) |
   1165 	    ((VSS & 0x400) ? 0x10 : 0x00) );
   1166 
   1167 	WCrt(ba, CRT_ID_HOR_TOTAL, HT);
   1168 	WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5);
   1169 
   1170 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
   1171 	WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
   1172 	WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80));
   1173 	WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
   1174 	WCrt(ba, CRT_ID_END_HOR_RETR,
   1175 	    (HSE & 0x1f) |
   1176 	    ((HBE & 0x20) ? 0x80 : 0x00) );
   1177 	WCrt(ba, CRT_ID_VER_TOTAL, VT);
   1178 	WCrt(ba, CRT_ID_OVERFLOW,
   1179 	    0x10 |
   1180 	    ((VT  & 0x100) ? 0x01 : 0x00) |
   1181 	    ((VDE & 0x100) ? 0x02 : 0x00) |
   1182 	    ((VSS & 0x100) ? 0x04 : 0x00) |
   1183 	    ((VBS & 0x100) ? 0x08 : 0x00) |
   1184 	    ((VT  & 0x200) ? 0x20 : 0x00) |
   1185 	    ((VDE & 0x200) ? 0x40 : 0x00) |
   1186 	    ((VSS & 0x200) ? 0x80 : 0x00) );
   1187 
   1188 	WCrt(ba, CRT_ID_MAX_SCAN_LINE,
   1189 	    0x40 |  /* TEXT ? 0x00 ??? */
   1190 	    (DBLSCAN ? 0x80 : 0x00) |
   1191 	    ((VBS & 0x200) ? 0x20 : 0x00) |
   1192 	    (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
   1193 
   1194 	WCrt(ba, CRT_ID_MODE_CONTROL,
   1195 	    ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xe3));
   1196 
   1197 	/* text cursor */
   1198 
   1199 	if (TEXT) {
   1200 #if 1
   1201 		WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
   1202 		WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
   1203 #else
   1204 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
   1205 		WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
   1206 #endif
   1207 		WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
   1208 
   1209 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
   1210 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
   1211 	}
   1212 
   1213 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
   1214 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
   1215 
   1216 	WCrt(ba, CRT_ID_START_VER_RETR, VSS);
   1217 	WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f));
   1218 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
   1219 	WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
   1220 	WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
   1221 
   1222 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
   1223 	WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2);
   1224 	WCrt(ba, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
   1225 
   1226 	WGfx(ba, GCT_ID_GRAPHICS_MODE,
   1227 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
   1228 	WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
   1229 
   1230 	WSeq (ba, SEQ_ID_MEMORY_MODE,
   1231 	    ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02));
   1232 
   1233 	vgaw(ba, VDAC_MASK, 0xff);
   1234 
   1235 	sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);
   1236 	sr15 &= 0xef;
   1237 	sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL);
   1238 	sr18 &= 0x7f;
   1239 	cr33 = RCrt(ba, CRT_ID_BACKWAD_COMP_2);
   1240 	cr33 &= 0xdf;
   1241 	clock_mode = 0x00;
   1242 	cr50 = 0x00;
   1243 
   1244 	test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2);
   1245 	test &= 0xd;
   1246 
   1247 	/* clear roxxler  byte-swapping... */
   1248 	cv_write_port(0x0040, cv_boardaddr);
   1249 	cv_write_port(0x0020, cv_boardaddr);
   1250 
   1251 	switch (gv->depth) {
   1252 	   case 1:
   1253 	   case 4: /* text */
   1254 		HDE = gv->disp_width / 16;
   1255 		break;
   1256 	   case 8:
   1257 		if (gv->pixel_clock > 80000000) {
   1258 			clock_mode = 0x10 | 0x02;
   1259 			sr15 |= 0x10;
   1260 			sr18 |= 0x80;
   1261 			cr33 |= 0x20;
   1262 		}
   1263 		HDE = gv->disp_width / 8;
   1264 		cr50 |= 0x00;
   1265 		break;
   1266 	   case 15:
   1267 		cv_write_port (0x8020, cv_boardaddr);
   1268 		clock_mode = 0x30;
   1269 		HDE = gv->disp_width / 4;
   1270 		cr50 |= 0x10;
   1271 		break;
   1272 	   case 16:
   1273 		cv_write_port (0x8020, cv_boardaddr);
   1274 		clock_mode = 0x50;
   1275 		HDE = gv->disp_width / 4;
   1276 		cr50 |= 0x10;
   1277 		break;
   1278 	   case 24: /* this is really 32 Bit on CV64 */
   1279 	   case 32:
   1280 		cv_write_port(0x8040, cv_boardaddr);
   1281 		clock_mode = 0xd0;
   1282 		HDE = (gv->disp_width / 2);
   1283 		cr50 |= 0x30;
   1284 		break;
   1285 	}
   1286 
   1287 	WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
   1288 	WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15);
   1289 	WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18);
   1290 	WCrt(ba, CRT_ID_BACKWAD_COMP_2, cr33);
   1291 	WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE);
   1292 
   1293 	test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2);
   1294 	test &= ~0x30;
   1295 	/* HDE Overflow in bits 4-5 */
   1296 	test |= (HDE >> 4) & 0x30;
   1297 	WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test);
   1298 
   1299 	/* Set up graphics engine */
   1300 	switch (gv->disp_width) {
   1301 	   case 1024:
   1302 		cr50 |= 0x00;
   1303 		break;
   1304 	   case 640:
   1305 		cr50 |= 0x40;
   1306 		break;
   1307 	   case 800:
   1308 		cr50 |= 0x80;
   1309 		break;
   1310 	   case 1280:
   1311 		cr50 |= 0xc0;
   1312 		break;
   1313 	   case 1152:
   1314 		cr50 |= 0x01;
   1315 		break;
   1316 	   case 1600:
   1317 		cr50 |= 0x81;
   1318 		break;
   1319 	   default: /* XXX*/
   1320 		break;
   1321 	}
   1322 
   1323 	WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50);
   1324 
   1325 	delay(100000);
   1326 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x41));
   1327 	delay(100000);
   1328 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA,
   1329 	    (gv->depth == 1) ? 0x01 : 0x0f);
   1330 	delay(100000);
   1331 
   1332 	/*
   1333 	 * M-Parameter of Display FIFO
   1334 	 * This is dependant on the pixel clock and the memory clock.
   1335 	 * The FIFO filling bandwidth is 240 MHz  and the FIFO is 96 Byte wide.
   1336 	 * Then the time to fill the FIFO is tfill = (96/240000000) sec, the time
   1337 	 * to empty the FIFO is tempty = (96/pixelclock) sec.
   1338 	 * Then the M parameter maximum is ((tempty-tfill)*cv_memclk-9)/2.
   1339 	 * This seems to be logical, ain't it?
   1340 	 * Remember: We have to use integer arithmetics :(
   1341 	 * Divide by 1000 to prevent overflows.
   1342 	 */
   1343 
   1344 	tfillm = (96 * (cv_memclk/1000))/240000;
   1345 
   1346 	switch(gv->depth) {
   1347 	   case 32:
   1348 	   case 24:
   1349 		temptym = (24 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
   1350 		break;
   1351 	   case 15:
   1352 	   case 16:
   1353 		temptym = (48 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
   1354 		break;
   1355 	   default:
   1356 		temptym = (96 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
   1357 		break;
   1358 	}
   1359 
   1360 	m = (temptym - tfillm - 9) / 2;
   1361 	m = (m & 0x1f) << 3;
   1362 	if (m < 0x18)
   1363 		m = 0x18;
   1364 	n = 0xff;
   1365 
   1366 	WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, m);
   1367 	WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, n);
   1368 	delay(10000);
   1369 
   1370 	/* text initialization */
   1371 
   1372 	if (TEXT) {
   1373 		cv_inittextmode(gp);
   1374 	}
   1375 
   1376 	if (CONSOLE) {
   1377 		int i;
   1378 		vgaw(ba, VDAC_ADDRESS_W, 0);
   1379 		for (i = 0; i < 4; i++) {
   1380 			vgaw(ba, VDAC_DATA, cvconscolors[i][0]);
   1381 			vgaw(ba, VDAC_DATA, cvconscolors[i][1]);
   1382 			vgaw(ba, VDAC_DATA, cvconscolors[i][2]);
   1383 		}
   1384 	}
   1385 
   1386 	/* Some kind of Magic */
   1387 	WAttr(ba, 0x33, 0);
   1388 
   1389 	/* turn gfx on again */
   1390 	gfx_on_off(0, ba);
   1391 
   1392 	/* Pass-through */
   1393 	cvscreen(0, ba - 0x02000000);
   1394 
   1395 	return (1);
   1396 }
   1397 
   1398 void
   1399 cv_inittextmode(gp)
   1400 	struct grf_softc *gp;
   1401 {
   1402 	struct grfcvtext_mode *tm = (struct grfcvtext_mode *)gp->g_data;
   1403 	volatile caddr_t ba, fb;
   1404 	unsigned char *c, *f, y;
   1405 	unsigned short z;
   1406 
   1407 	ba = gp->g_regkva;
   1408 	fb = gp->g_fbkva;
   1409 
   1410 	/* load text font into beginning of display memory.
   1411 	 * Each character cell is 32 bytes long (enough for 4 planes)
   1412 	 */
   1413 
   1414 	SetTextPlane(ba, 0x02);
   1415 	cv_memset(fb, 0, 256 * 32);
   1416 	c = (unsigned char *) (fb) + (32 * tm->fdstart);
   1417 	f = tm->fdata;
   1418 	for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
   1419 		for (y = 0; y < tm->fy; y++)
   1420 			*c++ = *f++;
   1421 
   1422 	/* clear out text/attr planes (three screens worth) */
   1423 
   1424 	SetTextPlane(ba, 0x01);
   1425 	cv_memset(fb, 0x07, tm->cols * tm->rows * 3);
   1426 	SetTextPlane(ba, 0x00);
   1427 	cv_memset(fb, 0x20, tm->cols * tm->rows * 3);
   1428 
   1429 	/* print out a little init msg */
   1430 
   1431 	c = (unsigned char *)(fb) + (tm->cols-16);
   1432 	strcpy(c, "CV64");
   1433 	c[6] = 0x20;
   1434 
   1435 	/* set colors (B&W) */
   1436 
   1437 	vgaw(ba, VDAC_ADDRESS_W, 0);
   1438 	for (z=0; z<256; z++) {
   1439 		unsigned char r, g, b;
   1440 
   1441 		y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
   1442 
   1443 		r = cvconscolors[y][0];
   1444 		g = cvconscolors[y][1];
   1445 		b = cvconscolors[y][2];
   1446 		vgaw(ba, VDAC_DATA, r >> 2);
   1447 		vgaw(ba, VDAC_DATA, g >> 2);
   1448 		vgaw(ba, VDAC_DATA, b >> 2);
   1449 	}
   1450 }
   1451 
   1452 void
   1453 cv_memset(d, c, l)
   1454 	unsigned char *d;
   1455 	unsigned char c;
   1456 	int l;
   1457 {
   1458 	for(; l > 0; l--)
   1459 		*d++ = c;
   1460 }
   1461 
   1462 
   1463 static inline void
   1464 cv_write_port(bits, BoardAddr)
   1465 	unsigned short bits;
   1466 	volatile caddr_t BoardAddr;
   1467 {
   1468 	volatile caddr_t addr;
   1469 	static unsigned char CVPortBits = 0;	/* mirror port bits here */
   1470 
   1471 	addr = BoardAddr + 0x40001;
   1472 	if (bits & 0x8000)
   1473 		CVPortBits |= bits & 0xFF;	/* Set bits */
   1474 	else {
   1475 		bits = bits & 0xFF;
   1476 		bits = (~bits) & 0xFF ;
   1477 		CVPortBits &= bits;	/* Clear bits */
   1478 	}
   1479 
   1480 	*addr = CVPortBits;
   1481 }
   1482 
   1483 
   1484 /*
   1485  *  Monitor Switch
   1486  *  0 = CyberVision Signal
   1487  *  1 = Amiga Signal,
   1488  * ba = boardaddr
   1489  */
   1490 static inline void
   1491 cvscreen(toggle, ba)
   1492 	int toggle;
   1493 	volatile caddr_t ba;
   1494 {
   1495 
   1496 	if (toggle == 1)
   1497 		cv_write_port (0x10, ba);
   1498 	else
   1499 		cv_write_port (0x8010, ba);
   1500 }
   1501 
   1502 /* 0 = on, 1= off */
   1503 /* ba= registerbase */
   1504 static inline void
   1505 gfx_on_off(toggle, ba)
   1506 	int toggle;
   1507 	volatile caddr_t ba;
   1508 {
   1509 	int r;
   1510 
   1511 	toggle &= 0x1;
   1512 	toggle = toggle << 5;
   1513 
   1514 	r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
   1515 	r &= 0xdf;	/* set Bit 5 to 0 */
   1516 
   1517 	WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle);
   1518 }
   1519 
   1520 #endif  /* NGRFCV */
   1521