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