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