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