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