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