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