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