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