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