Home | History | Annotate | Line # | Download | only in dev
grf_cv3d.c revision 1.32
      1 /*	$NetBSD: grf_cv3d.c,v 1.32 2015/11/12 12:01:53 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.32 2015/11/12 12:01:53 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  * the 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 for 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/grfvar.h>
    103 #include <amiga/dev/grf_cv3dreg.h>
    104 #include <amiga/dev/zbusvar.h>
    105 
    106 
    107 /*
    108  * finish all bus operations, flush pipelines
    109  */
    110 #if defined(__m68k__)
    111 #define cpu_sync() __asm volatile ("nop")
    112 #elif defined(__powerpc__)
    113 #define cpu_sync() __asm volatile ("sync; isync")
    114 #endif
    115 
    116 int	grfcv3dmatch(device_t, cfdata_t, void *);
    117 void	grfcv3dattach(device_t, device_t, void *);
    118 int	grfcv3dprint(void *, const char *);
    119 
    120 static int cv3d_has_4mb(volatile void *);
    121 static unsigned short cv3d_compute_clock(unsigned long);
    122 void	cv3d_boardinit(struct grf_softc *);
    123 int	cv3d_getvmode(struct grf_softc *, struct grfvideo_mode *);
    124 int	cv3d_setvmode(struct grf_softc *, unsigned int);
    125 int	cv3d_blank(struct grf_softc *, int);
    126 int	cv3d_isblank(struct grf_softc *);
    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 int	cv3d_wsioctl(void *, void *, u_long, void *, int, struct lwp *);
    294 static int	cv3d_get_fbinfo(struct grf_softc *, struct wsdisplayio_fbinfo *);
    295 
    296 static void	cv3d_wscursor(void *, int, int, int);
    297 static void	cv3d_wsputchar(void *, int, int, u_int, long);
    298 static void	cv3d_wscopycols(void *, int, int, int, int);
    299 static void	cv3d_wserasecols(void *, int, int, int, long);
    300 static void	cv3d_wscopyrows(void *, int, int, int);
    301 static void	cv3d_wseraserows(void *, int, int, long);
    302 static int	cv3d_wsallocattr(void *, int, int, int, long *);
    303 static int	cv3d_wsmapchar(void *, int, unsigned int *);
    304 
    305 struct wsdisplay_accessops cv3d_accessops = {
    306 	.ioctl		= cv3d_wsioctl,
    307 	.mmap		= grf_wsmmap
    308 };
    309 
    310 static struct wsdisplay_emulops cv3d_textops = {
    311 	.cursor		= cv3d_wscursor,
    312 	.mapchar	= cv3d_wsmapchar,
    313 	.putchar	= cv3d_wsputchar,
    314 	.copycols	= cv3d_wscopycols,
    315 	.copyrows	= cv3d_wscopyrows,
    316 	.erasecols	= cv3d_wserasecols,
    317 	.eraserows	= cv3d_wseraserows,
    318 	.allocattr	= cv3d_wsallocattr
    319 };
    320 
    321 static struct wsscreen_descr cv3d_defaultscreen = {
    322 	.name		= "default",
    323 	.textops	= &cv3d_textops,
    324 	.fontwidth	= 8,
    325 	.fontheight	= S3FONTY,
    326 	.capabilities	= WSSCREEN_HILIT | WSSCREEN_BLINK |
    327 			  WSSCREEN_REVERSE | WSSCREEN_UNDERLINE
    328 };
    329 
    330 static const struct wsscreen_descr *cv3d_screens[] = {
    331 	&cv3d_defaultscreen,
    332 };
    333 
    334 static struct wsscreen_list cv3d_screenlist = {
    335 	sizeof(cv3d_screens) / sizeof(struct wsscreen_descr *), cv3d_screens
    336 };
    337 #endif /* NWSDISPLAY > 0 */
    338 
    339 /* standard driver stuff */
    340 CFATTACH_DECL_NEW(grfcv3d, sizeof(struct grf_softc),
    341     grfcv3dmatch, grfcv3dattach, NULL, NULL);
    342 
    343 static struct cfdata *cfdata;
    344 
    345 #define CV3D_ULCURSOR	1	/* Underlined Cursor in textmode */
    346 
    347 /*
    348  * Get frambuffer memory size.
    349  * phase5 didn't provide the bit in CR36,
    350  * so we have to do it this way.
    351  * Return 0 for 2MB, 1 for 4MB
    352  */
    353 static int
    354 cv3d_has_4mb(volatile void *fb)
    355 {
    356 #if 0	/* XXX */
    357 	volatile unsigned long *testfbw, *testfbr;
    358 
    359 	/* write patterns in memory and test if they can be read */
    360 	testfbw = (volatile unsigned long *)fb;
    361 	testfbr = (volatile unsigned long *)(fb + 0x02000000);
    362 	*testfbw = 0x87654321;
    363 	if (*testfbr != 0x87654321)
    364 		return (0);
    365 
    366 	/* upper memory region */
    367 	testfbw = (volatile unsigned long *)(fb + 0x00200000);
    368 	testfbr = (volatile unsigned long *)(fb + 0x02200000);
    369 	*testfbw = 0x87654321;
    370 	if (*testfbr != 0x87654321)
    371 		return (0);
    372 	*testfbw = 0xAAAAAAAA;
    373 	if (*testfbr != 0xAAAAAAAA)
    374 		return (0);
    375 	*testfbw = 0x55555555;
    376 	if (*testfbr != 0x55555555)
    377 		return (0);
    378 #endif
    379 	return (1);
    380 }
    381 
    382 int
    383 grfcv3dmatch(device_t parent, cfdata_t cf, void *aux)
    384 {
    385 #ifdef CV3DCONSOLE
    386 	static int cv3dcons_unit = -1;
    387 #endif
    388 	struct zbus_args *zap;
    389 
    390 	zap = aux;
    391 
    392 	if (amiga_realconfig == 0)
    393 #ifdef CV3DCONSOLE
    394 		if (cv3dcons_unit != -1)
    395 #endif
    396 			 return (0);
    397 
    398 	/*
    399 	 * Distinct between ZorroII or ZorroIII mode.
    400 	 * Note that iszthreepa(x) is true for the Z2 bus on the DraCo;
    401 	 * therefore we check for the size instead.
    402 	 */
    403 	cv3d_zorroIII = zap->size > 4*1024*1024;
    404 
    405 	/* Lets be Paranoid: Test man and prod id */
    406 	if (zap->manid != 8512 || zap->prodid != 67)
    407 		return (0);
    408 
    409 	cv3d_boardaddr = zap->va;
    410 
    411 #ifdef CV3DCONSOLE
    412 	if (amiga_realconfig == 0) {
    413 		cv3dcons_unit = cf->cf_unit;
    414 		cfdata = cf;
    415 	}
    416 #endif
    417 
    418 	return (1);
    419 }
    420 
    421 void
    422 grfcv3dattach(device_t parent, device_t self, void *aux)
    423 {
    424 	static struct grf_softc congrf;
    425 	static char attachflag = 0;
    426 	struct device temp;
    427 	struct grf_softc *gp;
    428 
    429 	printf("\n");
    430 
    431 	/*
    432 	 * This function is called twice, once on console init (self == NULL)
    433 	 * and once on "normal" grf7 init.
    434 	 */
    435 
    436 	if (self == NULL) {
    437 		gp = &congrf;
    438 		gp->g_device = &temp;
    439 		temp.dv_private = gp;
    440 	} else {
    441 		gp = device_private(self);
    442 		gp->g_device = self;
    443 	}
    444 
    445 	if (self != NULL && congrf.g_regkva != 0) {
    446 		/*
    447 		 * inited earlier, just copy (not device struct)
    448 		 */
    449 
    450 		memcpy(&gp->g_display, &congrf.g_display,
    451 			(char *) &gp[1] - (char *) &gp->g_display);
    452 	} else {
    453 		if (cv3d_zorroIII) {
    454 			gp->g_fbkva =
    455 			    (volatile char *)cv3d_boardaddr + 0x04800000;
    456 			cv3d_memory_io_base =
    457 			    (volatile char *)cv3d_boardaddr + 0x05000000;
    458 			cv3d_register_base =
    459 			    (volatile char *)cv3d_boardaddr + 0x05008000;
    460 			cv3d_vcode_switch_base =
    461 			    (volatile char *)cv3d_boardaddr + 0x08000000;
    462 			cv3d_special_register_base =
    463 			    (volatile char *)cv3d_boardaddr + 0x0C000000;
    464 		} else {
    465 			gp->g_fbkva =
    466 			    (volatile char *)cv3d_boardaddr + 0x00000000;
    467 			cv3d_memory_io_base =
    468 			    (volatile char *)cv3d_boardaddr + 0x003E0000;
    469 			cv3d_register_base =
    470 			    (volatile char *)cv3d_boardaddr + 0x003C8000;
    471 			cv3d_vcode_switch_base =
    472 			    (volatile char *)cv3d_boardaddr + 0x003A0000;
    473 			cv3d_special_register_base =
    474 			    (volatile char *)cv3d_boardaddr + 0x003C0000;
    475 		}
    476 
    477 		gp->g_regkva = (volatile void *)cv3d_register_base;
    478 
    479 		gp->g_unit = GRF_CV3D_UNIT;
    480 		gp->g_mode = cv3d_mode;
    481 #if NITE > 0
    482 		gp->g_conpri = grfcv3d_cnprobe();
    483 #endif
    484 		gp->g_flags = GF_ALIVE;
    485 
    486 		/* wakeup the board */
    487 		cv3d_boardinit(gp);
    488 
    489 #ifdef CV3DCONSOLE
    490 #if NWSDISPLAY > 0
    491 		gp->g_accessops = &cv3d_accessops;
    492 		gp->g_emulops = &cv3d_textops;
    493 		gp->g_defaultscr = &cv3d_defaultscreen;
    494 		gp->g_scrlist = &cv3d_screenlist;
    495 #else
    496 		grfcv3d_iteinit(gp);
    497 #endif /* NWSDISPLAY > 0 */
    498 		(void)cv3d_load_mon(gp, &cv3dconsole_mode);
    499 #endif
    500 	}
    501 
    502 	/*
    503 	 * attach grf
    504 	 */
    505 	if (amiga_config_found(cfdata, gp->g_device, gp, grfcv3dprint)) {
    506 		if (self != NULL)
    507 			printf("%s: CyberVision64/3D with %dMB being used\n",
    508 			    device_xname(self), cv3d_fbsize / 0x100000);
    509 		attachflag = 1;
    510 	} else {
    511 		if (!attachflag)
    512 			/*printf("grfcv3d unattached!!\n")*/;
    513 	}
    514 }
    515 
    516 int
    517 grfcv3dprint(void *aux, const char *pnp)
    518 {
    519 	if (pnp)
    520 		aprint_normal("ite at %s: ", pnp);
    521 	return (UNCONF);
    522 }
    523 
    524 
    525 /*
    526  * Computes M, N, and R values from
    527  * given input frequency. It uses a table of
    528  * precomputed values, to keep CPU time low.
    529  *
    530  * The return value consist of:
    531  * lower byte:  Bits 4-0: N Divider Value
    532  *	        Bits 5-6: R Value          for e.g. SR10 or SR12
    533  * higher byte: Bits 0-6: M divider value  for e.g. SR11 or SR13
    534  */
    535 
    536 static unsigned short
    537 cv3d_compute_clock(unsigned long freq)
    538 {
    539 	static unsigned char *mnr, *save;	/* M, N + R vals */
    540 	unsigned long work_freq, r;
    541 	unsigned short erg;
    542 	long diff, d2;
    543 
    544 	if (freq < 12500000 || freq > MAXPIXELCLOCK) {
    545 		printf("grfcv3d: Illegal clock frequency: %ldMHz\n", freq/1000000);
    546 		printf("grfcv3d: Using default frequency: 25MHz\n");
    547 		printf("grfcv3d: See the manpage of grfconfig for more informations.\n");
    548 		freq = 25000000;
    549 	}
    550 
    551 	mnr = clocks;	/* there the vals are stored */
    552 	d2 = 0x7fffffff;
    553 
    554 	while (*mnr) {	/* mnr vals are 0-terminated */
    555 		work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
    556 
    557 		r = (mnr[1] >> 5) & 0x03;
    558 		if (r != 0)
    559 			work_freq=work_freq >> r;	/* r is the freq divider */
    560 
    561 		work_freq *= 0x3E8;	/* 2nd part of OSC */
    562 
    563 		diff = abs(freq - work_freq);
    564 
    565 		if (d2 >= diff) {
    566 			d2 = diff;
    567 			/* In save are the vals for minimal diff */
    568 			save = mnr;
    569 		}
    570 		mnr += 2;
    571 	}
    572 	erg = *((unsigned short *)save);
    573 
    574 	return (erg);
    575 }
    576 
    577 
    578 void
    579 cv3d_boardinit(struct grf_softc *gp)
    580 {
    581 	volatile void *ba;
    582 	volatile char *special;
    583 	unsigned char test;
    584 	unsigned int clockpar;
    585 	int i;
    586 	struct grfinfo *gi;
    587 
    588 	ba = gp->g_regkva;
    589 
    590 	/* PCI config */
    591 	if (cv3d_zorroIII) {
    592 		special = ((volatile char*)cv3d_special_register_base +
    593 			0x000E0000);
    594 	} else {
    595 		special = ((volatile char*)cv3d_special_register_base);
    596 	}
    597 	*((volatile short *)(special + 0x10)) = 0;
    598 	*((volatile long *)(special + 0x4)) = 0x02000003;
    599 
    600 	/* Wakeup Chip */
    601 	vgawio(cv3d_boardaddr, SREG_VIDEO_SUBS_ENABLE, 1);
    602 
    603 	vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x01);
    604 
    605 	vgaw(ba, GREG_MISC_OUTPUT_W, 0x03);
    606 
    607 	WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48);	/* unlock S3 VGA regs */
    608 	WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5);	/* unlock syscontrol */
    609 
    610 	WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x02);
    611 	WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x00);
    612 
    613 	WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x06);	/* Unlock extensions */
    614 
    615 	/*
    616 	 * bit 0=1: enable enhanced mode functions
    617 	 * bit 4=1: enable linear addressing
    618 	 */
    619 	vgaw32(cv3d_memory_io_base, MR_ADVANCED_FUNCTION_CONTROL, 0x00000011);
    620 
    621 	/* -hsync and -vsync */
    622 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xC3);
    623 
    624 	/* Reset. This does nothing, but everyone does it:) */
    625 	WSeq(ba, SEQ_ID_RESET, 0x03);
    626 
    627 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);	/* 8 Dot Clock */
    628 	WSeq(ba, SEQ_ID_MAP_MASK, 0x0F);	/* Enable write planes */
    629 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);	/* Character Font */
    630 
    631 	WSeq(ba, SEQ_ID_MEMORY_MODE, 0x02);	/* Complete mem access */
    632 	WSeq(ba, SEQ_ID_MMIO_SELECT, 0x00);
    633 
    634 	test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL);	/* Bus Request */
    635 
    636 	/* enable 4MB fast Page Mode */
    637 	test = test | 0xC0;
    638 	WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test);
    639 
    640 #if 0	/* XXX */
    641 	/* faster LUT write */
    642 	WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0);
    643 #else
    644 	WSeq(ba, SEQ_ID_UNKNOWN6, 0x00);
    645 	WSeq(ba, SEQ_ID_SIGNAL_SELECT, 0x02);
    646 #endif
    647 
    648 	test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);	/* Clksyn2 read */
    649 
    650 	/* immediately Clkload bit clear */
    651 	test = test & 0xDF;
    652 
    653 	/* 2 MCLK Memory Write.... */
    654 	if (cv3d_memclk >= 55000000)
    655 		test |= 0x80;
    656 
    657 	WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test);
    658 
    659 	/* Memory CLK */
    660 	clockpar = cv3d_compute_clock(cv3d_memclk);
    661 	test = (clockpar & 0xFF00) >> 8;
    662 	WSeq(ba, SEQ_ID_MCLK_HI, test);		/* PLL N-Divider Value */
    663 
    664 	test = clockpar & 0xFF;
    665 	WSeq(ba, SEQ_ID_MCLK_LO, test);		/* PLL M-Divider Value */
    666 
    667 	/* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */
    668 	/* DCLK */
    669 	WSeq(ba, SEQ_ID_DCLK_HI, 0x13);
    670 	WSeq(ba, SEQ_ID_DCLK_LO, 0x41);
    671 
    672 	test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2);
    673 	test = test | 0x22;
    674 
    675 	/* DCLK + MCLK Clock immediate load! */
    676 	WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test);
    677 
    678 	/* DCLK load */
    679 	test = vgar(ba, 0x3cc);
    680 	test = test | 0x0c;
    681 	vgaw(ba, 0x3c2, test);
    682 
    683 	/* Clear bit 5 again, prevent further loading. */
    684 	WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x02);
    685 
    686 	WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F);
    687 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F);
    688 	WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50);
    689 	WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82);
    690 	WCrt(ba, CRT_ID_START_HOR_RETR, 0x54);
    691 	WCrt(ba, CRT_ID_END_HOR_RETR, 0x80);
    692 	WCrt(ba, CRT_ID_VER_TOTAL, 0xBF);
    693 
    694 	WCrt(ba, CRT_ID_OVERFLOW, 0x1F);	/* overflow reg */
    695 
    696 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);	/* no panning */
    697 
    698 	WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40);	/* vscan */
    699 
    700 	WCrt(ba, CRT_ID_CURSOR_START, 0x00);
    701 	WCrt(ba, CRT_ID_CURSOR_END, 0x00);
    702 
    703 	/* Display start address */
    704 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
    705 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
    706 
    707 	/* Cursor location */
    708 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
    709 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
    710 
    711 	/* Vertical retrace */
    712 	WCrt(ba, CRT_ID_START_VER_RETR, 0x9C);
    713 	WCrt(ba, CRT_ID_END_VER_RETR, 0x0E);
    714 
    715 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F);
    716 	WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50);
    717 
    718 	WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00);
    719 
    720 	WCrt(ba, CRT_ID_START_VER_BLANK, 0x96);
    721 	WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9);
    722 
    723 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
    724 
    725 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF);
    726 
    727 	WCrt(ba, CRT_ID_SYSTEM_CONFIG, 0x21);
    728 	WCrt(ba, CRT_ID_MEMORY_CONF, 0x04);
    729 	WCrt(ba, CRT_ID_BACKWAD_COMP_1, 0x00);
    730 	WCrt(ba, CRT_ID_BACKWAD_COMP_2, 0x02);
    731 	WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10);	/* FIFO enabled */
    732 
    733 	/* Refresh count 1, High speed text font, enhanced color mode */
    734 	WCrt(ba, CRT_ID_MISC_1, 0x35);
    735 
    736 	/* start fifo position */
    737 	WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5A);
    738 
    739 	WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x02);
    740 
    741 	WCrt(ba, CRT_ID_LAW_POS_LO, 0x40);
    742 
    743 	WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x81);
    744 	WCrt(ba, CRT_ID_MISC_1, 0xB5);
    745 	WCrt(ba, CRT_ID_CONFIG_1, 0x0E);
    746 
    747 	WGfx(ba, GCT_ID_SET_RESET, 0x00);
    748 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
    749 	WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
    750 	WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
    751 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
    752 	WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
    753 	WGfx(ba, GCT_ID_MISC, 0x01);
    754 	WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F);
    755 	WGfx(ba, GCT_ID_BITMASK, 0xFF);
    756 
    757 	/* colors for text mode */
    758 	for (i = 0; i <= 0xf; i++)
    759 		WAttr (ba, i, i);
    760 
    761 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41);
    762 	WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01);
    763 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F);
    764 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
    765 	WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
    766 
    767 	vgawio(cv3d_boardaddr, VDAC_MASK, 0xFF);	/* DAC Mask */
    768 
    769 	/* colors initially set to greyscale */
    770 
    771 	vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, 0);
    772 
    773 	for (i = 255; i >= 0 ; i--) {
    774 		vgawio(cv3d_boardaddr, VDAC_DATA, i);
    775 		vgawio(cv3d_boardaddr, VDAC_DATA, i);
    776 		vgawio(cv3d_boardaddr, VDAC_DATA, i);
    777 	}
    778 
    779 	/* GFx hardware cursor off */
    780 	WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
    781 
    782 	/* Set first to 4 MB, so test will work */
    783 	WCrt(ba, CRT_ID_LAW_CNTL, 0x13);
    784 
    785 	/* find *correct* fbsize of z3 board */
    786 	if (cv3d_has_4mb(gp->g_fbkva)) {
    787 		cv3d_fbsize = 1024 * 1024 * 4;
    788 		WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */
    789 	} else {
    790 		cv3d_fbsize = 1024 * 1024 * 2;
    791 		WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */
    792 	}
    793 
    794 	/* Initialize graphics engine */
    795 	GfxBusyWait(cv3d_memory_io_base);
    796 	vgaw32(cv3d_memory_io_base, BLT_COMMAND_SET, CMD_NOP);
    797 	vgaw32(cv3d_memory_io_base, BLT_CLIP_LEFT_RIGHT, 0x000007ff);
    798 	vgaw32(cv3d_memory_io_base, BLT_CLIP_TOP_BOTTOM, 0x000007ff);
    799 	vgaw32(cv3d_memory_io_base, L2D_COMMAND_SET, CMD_NOP);
    800 	vgaw32(cv3d_memory_io_base, L2D_CLIP_LEFT_RIGHT, 0x000007ff);
    801 	vgaw32(cv3d_memory_io_base, L2D_CLIP_TOP_BOTTOM, 0x000007ff);
    802 	vgaw32(cv3d_memory_io_base, P2D_COMMAND_SET, CMD_NOP);
    803 	vgaw32(cv3d_memory_io_base, P2D_CLIP_LEFT_RIGHT, 0x000007ff);
    804 	vgaw32(cv3d_memory_io_base, P2D_CLIP_TOP_BOTTOM, 0x000007ff);
    805 
    806 	/* Enable Video Display (Set Bit 5) */
    807 	WAttr(ba, 0x33, 0);
    808 
    809 
    810 	gi = &gp->g_display;
    811 	gi->gd_regaddr	= (void *) kvtop (__UNVOLATILE(ba));
    812 	gi->gd_regsize	= 64 * 1024;
    813 	gi->gd_fbaddr	= (void *) kvtop (__UNVOLATILE(gp->g_fbkva));
    814 	gi->gd_fbsize	= cv3d_fbsize;
    815 }
    816 
    817 
    818 int
    819 cv3d_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
    820 {
    821 	struct grfvideo_mode *gv;
    822 
    823 #ifdef CV3DCONSOLE
    824 	/* Handle grabbing console mode */
    825 	if (vm->mode_num == 255) {
    826 		memcpy(vm, &cv3dconsole_mode, sizeof(struct grfvideo_mode));
    827 		/* XXX so grfconfig can tell us the correct text dimensions. */
    828 		vm->depth = cv3dconsole_mode.fy;
    829 	} else
    830 #endif
    831 	{
    832 		if (vm->mode_num == 0)
    833 			vm->mode_num = (monitor_current - monitor_def) + 1;
    834 		if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
    835 			return (EINVAL);
    836 		gv = monitor_def + (vm->mode_num - 1);
    837 		if (gv->mode_num == 0)
    838 			return (EINVAL);
    839 
    840 		memcpy(vm, gv, sizeof(struct grfvideo_mode));
    841 	}
    842 
    843 	/* adjust internal values to pixel values */
    844 
    845 	vm->hblank_start *= 8;
    846 	vm->hsync_start *= 8;
    847 	vm->hsync_stop *= 8;
    848 	vm->htotal *= 8;
    849 
    850 	return (0);
    851 }
    852 
    853 
    854 int
    855 cv3d_setvmode(struct grf_softc *gp, unsigned mode)
    856 {
    857 
    858 	if (!mode || (mode > monitor_def_max) ||
    859 	    monitor_def[mode - 1].mode_num == 0)
    860 		return (EINVAL);
    861 
    862 	monitor_current = monitor_def + (mode - 1);
    863 
    864 	return (0);
    865 }
    866 
    867 
    868 int
    869 cv3d_blank(struct grf_softc *gp, int on)
    870 {
    871 	volatile void *ba;
    872 
    873 	ba = gp->g_regkva;
    874 	cv3d_gfx_on_off(on > 0 ? 0 : 1, ba);
    875 	return (0);
    876 }
    877 
    878 
    879 int
    880 cv3d_isblank(struct grf_softc *gp)
    881 {
    882 	volatile void *ba;
    883 	int r;
    884 
    885 	ba = gp->g_regkva;
    886 	r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
    887 	return (r & 0x20) != 0;
    888 }
    889 
    890 
    891 /*
    892  * Change the mode of the display.
    893  * Return a UNIX error number or 0 for success.
    894  */
    895 int
    896 cv3d_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2,
    897           int a3)
    898 {
    899 	int error;
    900 
    901 	switch (cmd) {
    902 	    case GM_GRFON:
    903 		error = cv3d_load_mon (gp,
    904 		    (struct grfcv3dtext_mode *) monitor_current) ? 0 : EINVAL;
    905 		return (error);
    906 
    907 	    case GM_GRFOFF:
    908 #ifndef CV3DCONSOLE
    909 		cv3dscreen(1, cv3d_vcode_switch_base);
    910 #else
    911 		cv3d_load_mon(gp, &cv3dconsole_mode);
    912 #if NITE > 0
    913 		ite_reinit(gp->g_itedev);
    914 #endif
    915 #endif
    916 		return (0);
    917 
    918 	    case GM_GRFCONFIG:
    919 		return (0);
    920 
    921 	    case GM_GRFGETVMODE:
    922 		return (cv3d_getvmode (gp, (struct grfvideo_mode *) arg));
    923 
    924 	    case GM_GRFSETVMODE:
    925 		error = cv3d_setvmode (gp, *(unsigned *) arg);
    926 		if (!error && (gp->g_flags & GF_GRFON))
    927 			cv3d_load_mon(gp,
    928 			    (struct grfcv3dtext_mode *) monitor_current);
    929 		return (error);
    930 
    931 	    case GM_GRFGETNUMVM:
    932 		*(int *)arg = monitor_def_max;
    933 		return (0);
    934 
    935 	    case GM_GRFIOCTL:
    936 		return (cv3d_ioctl (gp, a2, arg));
    937 
    938 	    default:
    939 		break;
    940 	}
    941 
    942 	return (EPASSTHROUGH);
    943 }
    944 
    945 
    946 int
    947 cv3d_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
    948 {
    949 	switch (cmd) {
    950 #ifdef CV3D_HARDWARE_CURSOR
    951 	    case GRFIOCGSPRITEPOS:
    952 		return(cv3d_getspritepos (gp, (struct grf_position *) data));
    953 
    954 	    case GRFIOCSSPRITEPOS:
    955 		return(cv3d_setspritepos (gp, (struct grf_position *) data));
    956 
    957 	    case GRFIOCSSPRITEINF:
    958 		return(cv3d_setspriteinfo (gp, (struct grf_spriteinfo *) data));
    959 
    960 	    case GRFIOCGSPRITEINF:
    961 		return(cv3d_getspriteinfo (gp, (struct grf_spriteinfo *) data));
    962 
    963 	    case GRFIOCGSPRITEMAX:
    964 		return(cv3d_getspritemax (gp, (struct grf_position *) data));
    965 #else	/* CV3D_HARDWARE_CURSOR */
    966 	    case GRFIOCGSPRITEPOS:
    967 	    case GRFIOCSSPRITEPOS:
    968 	    case GRFIOCSSPRITEINF:
    969 	    case GRFIOCGSPRITEINF:
    970 	    case GRFIOCGSPRITEMAX:
    971 		break;
    972 #endif	/* CV3D_HARDWARE_CURSOR */
    973 
    974 	    case GRFIOCGETCMAP:
    975 		return (cv3d_getcmap (gp, (struct grf_colormap *) data));
    976 
    977 	    case GRFIOCPUTCMAP:
    978 		return (cv3d_putcmap (gp, (struct grf_colormap *) data));
    979 
    980 	    case GRFIOCBITBLT:
    981 		break;
    982 
    983 	    case GRFTOGGLE:
    984 		return (cv3d_toggle (gp));
    985 
    986 	    case GRFIOCSETMON:
    987 		return (cv3d_setmonitor (gp, (struct grfvideo_mode *)data));
    988 
    989 	    case GRFIOCBLANK:
    990 		return (cv3d_blank (gp, *(int *)data));
    991 	}
    992 	return (EPASSTHROUGH);
    993 }
    994 
    995 
    996 int
    997 cv3d_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv)
    998 {
    999 	struct grfvideo_mode *md;
   1000 
   1001 	if (!cv3d_mondefok(gv))
   1002 		return (EINVAL);
   1003 
   1004 #ifdef CV3DCONSOLE
   1005 	/* handle interactive setting of console mode */
   1006 	if (gv->mode_num == 255) {
   1007 		memcpy(&cv3dconsole_mode.gv, gv, sizeof(struct grfvideo_mode));
   1008 		cv3dconsole_mode.gv.hblank_start /= 8;
   1009 		cv3dconsole_mode.gv.hsync_start /= 8;
   1010 		cv3dconsole_mode.gv.hsync_stop /= 8;
   1011 		cv3dconsole_mode.gv.htotal /= 8;
   1012 		cv3dconsole_mode.rows = gv->disp_height / cv3dconsole_mode.fy;
   1013 		cv3dconsole_mode.cols = gv->disp_width / cv3dconsole_mode.fx;
   1014 		if (!(gp->g_flags & GF_GRFON))
   1015 			cv3d_load_mon(gp, &cv3dconsole_mode);
   1016 #if NITE > 0
   1017 		ite_reinit(gp->g_itedev);
   1018 #endif
   1019 		return (0);
   1020 	}
   1021 #endif
   1022 
   1023 	md = monitor_def + (gv->mode_num - 1);
   1024 
   1025 	/*
   1026 	 * Prevent user from crashing the system by using
   1027 	 * grfconfig while in X
   1028 	 */
   1029 	if (gp->g_flags & GF_GRFON)
   1030 		if (md == monitor_current) {
   1031 			printf("grfcv3d: Changing the used mode not allowed!\n");
   1032 			return (EINVAL);
   1033 		}
   1034 
   1035 	memcpy(md, gv, sizeof(struct grfvideo_mode));
   1036 
   1037 	/* adjust pixel oriented values to internal rep. */
   1038 
   1039 	md->hblank_start /= 8;
   1040 	md->hsync_start /= 8;
   1041 	md->hsync_stop /= 8;
   1042 	md->htotal /= 8;
   1043 
   1044 	return (0);
   1045 }
   1046 
   1047 
   1048 int
   1049 cv3d_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
   1050 {
   1051 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1052 	short x;
   1053 	int error;
   1054 
   1055 	if (cmap->count == 0 || cmap->index >= 256)
   1056 		return (0);
   1057 
   1058 	if (cmap->count > 256 - cmap->index)
   1059 		cmap->count = 256 - cmap->index;
   1060 
   1061 	/* first read colors out of the chip, then copyout to userspace */
   1062 	vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, cmap->index);
   1063 	x = cmap->count - 1;
   1064 
   1065 	rp = red + cmap->index;
   1066 	gp = green + cmap->index;
   1067 	bp = blue + cmap->index;
   1068 
   1069 	do {
   1070 		*rp++ = vgario(cv3d_special_register_base, VDAC_DATA) << 2;
   1071 		*gp++ = vgario(cv3d_special_register_base, VDAC_DATA) << 2;
   1072 		*bp++ = vgario(cv3d_special_register_base, VDAC_DATA) << 2;
   1073 	} while (x-- > 0);
   1074 
   1075 	if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
   1076 	    && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
   1077 	    && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
   1078 		return (0);
   1079 
   1080 	return (error);
   1081 }
   1082 
   1083 
   1084 int
   1085 cv3d_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
   1086 {
   1087 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1088 	short x;
   1089 	int error;
   1090 
   1091 	if (cmap->count == 0 || cmap->index >= 256)
   1092 		return (0);
   1093 
   1094 	if (cmap->index + cmap->count > 256)
   1095 		cmap->count = 256 - cmap->index;
   1096 
   1097 	/* first copy the colors into kernelspace */
   1098 	if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
   1099 	    && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
   1100 	    && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
   1101 		vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, cmap->index);
   1102 		x = cmap->count - 1;
   1103 
   1104 		rp = red + cmap->index;
   1105 		gp = green + cmap->index;
   1106 		bp = blue + cmap->index;
   1107 
   1108 		do {
   1109 			vgawio(cv3d_boardaddr, VDAC_DATA, *rp++ >> 2);
   1110 			vgawio(cv3d_boardaddr, VDAC_DATA, *gp++ >> 2);
   1111 			vgawio(cv3d_boardaddr, VDAC_DATA, *bp++ >> 2);
   1112 		} while (x-- > 0);
   1113 		return (0);
   1114 	} else
   1115 		return (error);
   1116 }
   1117 
   1118 
   1119 int
   1120 cv3d_toggle(struct grf_softc *gp)
   1121 {
   1122 #ifndef CV3DCONSOLE
   1123 	cv3d_pass_toggle = 1;
   1124 #endif /* !CV3DCONSOLE */
   1125 
   1126 	if (cv3d_pass_toggle) {
   1127 		cv3dscreen(0, cv3d_vcode_switch_base);
   1128 		cv3d_pass_toggle = 0;
   1129 	} else {
   1130 		cv3dscreen(1, cv3d_vcode_switch_base);
   1131 		cv3d_pass_toggle = 1;
   1132 	}
   1133 
   1134 	return (0);
   1135 }
   1136 
   1137 
   1138 int
   1139 cv3d_mondefok(struct grfvideo_mode *gv)
   1140 {
   1141 	unsigned long maxpix;
   1142 
   1143 	if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) {
   1144 		if (gv->mode_num != 255 || gv->depth != 4)
   1145 			return (0);
   1146 	}
   1147 
   1148 	switch(gv->depth) {
   1149 	   case 4:
   1150 		maxpix = MAXPIXELCLOCK - 55000000;
   1151 		break;
   1152 	   case 8:
   1153 		maxpix = MAXPIXELCLOCK;
   1154 		break;
   1155 	   case 15:
   1156 	   case 16:
   1157 #ifdef	CV3D_AGGRESSIVE_TIMING
   1158 		maxpix = MAXPIXELCLOCK - 35000000;
   1159 #else
   1160 		maxpix = MAXPIXELCLOCK - 55000000;
   1161 #endif
   1162 		break;
   1163 	   case 24:
   1164 	   case 32:
   1165 #ifdef	CV3D_AGGRESSIVE_TIMING
   1166 		maxpix = MAXPIXELCLOCK - 75000000;
   1167 #else
   1168 		maxpix = MAXPIXELCLOCK - 85000000;
   1169 #endif
   1170 		break;
   1171 	   default:
   1172 		printf("grfcv3d: Illegal depth in mode %d\n",
   1173 			(int) gv->mode_num);
   1174 		return (0);
   1175 	}
   1176 
   1177 	if (gv->pixel_clock > maxpix) {
   1178 		printf("grfcv3d: Pixelclock too high in mode %d\n",
   1179 			(int) gv->mode_num);
   1180 		return (0);
   1181 	}
   1182 
   1183 	if (gv->mode_num == 255) { /* console mode */
   1184 		if ((gv->disp_width / 8) > MAXCOLS) {
   1185 			printf ("grfcv3d: Too many columns for console\n");
   1186 			return (0);
   1187 		} else if ((gv->disp_height / S3FONTY) > MAXROWS) {
   1188 			printf ("grfcv3d: Too many rows for console\n");
   1189 			return (0);
   1190 		}
   1191 	}
   1192 
   1193 	if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) {
   1194 		printf("grfcv3d: sync-on-green is not supported\n");
   1195 		return (0);
   1196 	}
   1197 
   1198 	return (1);
   1199 }
   1200 
   1201 
   1202 int
   1203 cv3d_load_mon(struct grf_softc *gp, struct grfcv3dtext_mode *md)
   1204 {
   1205 	struct grfvideo_mode *gv;
   1206 	struct grfinfo *gi;
   1207 	volatile void *ba;
   1208 	unsigned short mnr;
   1209 	unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
   1210 		VSE, VT;
   1211 	int cr50, cr66, sr15, sr18, clock_mode, test;
   1212 	int hmul;	/* Multiplier for hor. Values */
   1213 	int fb_flag = 2;	/* default value for 8bit memory access */
   1214 	unsigned char hvsync_pulse;
   1215 	char TEXT, CONSOLE;
   1216 
   1217 	/* identity */
   1218 	gv = &md->gv;
   1219 
   1220 	TEXT = (gv->depth == 4);
   1221 	CONSOLE = (gv->mode_num == 255);
   1222 
   1223 	if (!cv3d_mondefok(gv)) {
   1224 		printf("grfcv3d: Monitor definition not ok\n");
   1225 		return (0);
   1226 	}
   1227 
   1228 	ba = gp->g_regkva;
   1229 
   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 *fb;
   1577 	volatile unsigned char *c;
   1578 	unsigned char *f, y;
   1579 	unsigned short z;
   1580 
   1581 	fb = gp->g_fbkva;
   1582 
   1583 	/* load text font into beginning of display memory.
   1584 	 * Each character cell is 32 bytes long (enough for 4 planes)
   1585 	 * In linear addressing text mode, the memory is organized
   1586 	 * so, that the Bytes of all 4 planes are interleaved.
   1587 	 * 1st byte plane 0, 1st byte plane 1, 1st byte plane 2,
   1588 	 * 1st byte plane 3, 2nd byte plane 0, 2nd byte plane 1,...
   1589 	 * The font is loaded in plane 2.
   1590 	 */
   1591 
   1592 	c = (volatile unsigned char *) fb;
   1593 
   1594 	/* clear screen */
   1595 	for (z = 0; z < tm->cols * tm->rows * 3; z++) {
   1596 		*c++ = 0x20;
   1597 		*c++ = 0x07;
   1598 		*c++ = 0;
   1599 		*c++ = 0;
   1600 	}
   1601 
   1602 	c = (volatile unsigned char *)fb + (32 * tm->fdstart * 4 + 2);
   1603 	f = tm->fdata;
   1604 	for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy) * 4)
   1605 		for (y = 0; y < tm->fy; y++) {
   1606 			*c = *f++;
   1607 			c += 4;
   1608 		}
   1609 
   1610 	/* print out a little init msg */
   1611 	c = (volatile unsigned char *)fb + (tm->cols - 9) * 4;
   1612 	*c++ = 'C';
   1613 	*c++ = 0x0c;
   1614 	c +=2;
   1615 	*c++ = 'V';
   1616 	*c++ = 0x0c;
   1617 	c +=2;
   1618 	*c++ = '6';
   1619 	*c++ = 0x0b;
   1620 	c +=2;
   1621 	*c++ = '4';
   1622 	*c++ = 0x0f;
   1623 	c +=2;
   1624 	*c++ = '/';
   1625 	*c++ = 0x0e;
   1626 	c +=2;
   1627 	*c++ = '3';
   1628 	*c++ = 0x0a;
   1629 	c +=2;
   1630 	*c++ = 'D';
   1631 	*c++ = 0x0a;
   1632 }
   1633 
   1634 /*
   1635  *  Monitor Switch
   1636  *  0 = CyberVision Signal
   1637  *  1 = Amiga Signal,
   1638  * ba = boardaddr
   1639  */
   1640 static inline void
   1641 cv3dscreen(int toggle, volatile void *ba)
   1642 {
   1643 	*((volatile short *)(ba)) = (toggle & 1);
   1644 }
   1645 
   1646 
   1647 /* 0 = on, 1= off */
   1648 /* ba= registerbase */
   1649 static inline void
   1650 cv3d_gfx_on_off(int toggle, volatile void *ba)
   1651 {
   1652 	int r;
   1653 
   1654 	toggle &= 0x1;
   1655 	toggle = toggle << 5;
   1656 
   1657 	r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
   1658 	r &= ~0x20;	/* set Bit 5 to 0 */
   1659 
   1660 	WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle);
   1661 }
   1662 
   1663 
   1664 #ifdef CV3D_HARDWARE_CURSOR
   1665 
   1666 static unsigned char cv3d_hotx = 0, cv3d_hoty = 0;
   1667 static char cv_cursor_on = 0;
   1668 
   1669 #define HWC_OFF (cv3d_fbsize - 1024*2)
   1670 #define HWC_SIZE 1024
   1671 
   1672 /* Hardware Cursor handling routines */
   1673 
   1674 int
   1675 cv3d_getspritepos(struct grf_softc *gp, struct grf_position *pos)
   1676 {
   1677 	int hi,lo;
   1678 	volatile void *ba = gp->g_regkva;
   1679 
   1680 	hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI);
   1681 	lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO);
   1682 
   1683 	pos->y = (hi << 8) + lo;
   1684 	hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI);
   1685 	lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO);
   1686 	pos->x = (hi << 8) + lo;
   1687 	return (0);
   1688 }
   1689 
   1690 
   1691 int
   1692 cv3d_setspritepos(struct grf_softc *gp, struct grf_position *pos)
   1693 {
   1694 	volatile void *ba = gp->g_regkva;
   1695 	short x, y;
   1696 	static short savex, savey;
   1697 	short xoff, yoff;
   1698 
   1699 	if (pos) {
   1700 		x = pos->x;
   1701 		y = pos->y;
   1702 		savex = x;
   1703 		savey= y;
   1704 	} else { /* restore cursor */
   1705 		x = savex;
   1706 		y = savey;
   1707 	}
   1708 	x -= cv3d_hotx;
   1709 	y -= cv3d_hoty;
   1710 	if (x < 0) {
   1711 		xoff = ((-x) & 0xFE);
   1712 		x = 0;
   1713 	} else {
   1714 		xoff = 0;
   1715 	}
   1716 
   1717 	if (y < 0) {
   1718 		yoff = ((-y) & 0xFE);
   1719 		y = 0;
   1720 	} else {
   1721 		yoff = 0;
   1722 	}
   1723 
   1724 	WCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8));
   1725 	WCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff));
   1726 
   1727 	WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff));
   1728 	WCrt(ba, CRT_ID_HWGC_DSTART_X, xoff);
   1729 	WCrt(ba, CRT_ID_HWGC_DSTART_Y, yoff);
   1730 	WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8));
   1731 
   1732 	return(0);
   1733 }
   1734 
   1735 static inline short
   1736 M2I(short val)
   1737 {
   1738 	return ( ((val & 0xff00) >> 8) | ((val & 0xff) << 8));
   1739 }
   1740 
   1741 int
   1742 cv3d_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
   1743 {
   1744 	volatile void *ba, fb;
   1745 
   1746 	ba = gp->g_regkva;
   1747 	fb = gp->g_fbkva;
   1748 
   1749 	if (info->set & GRFSPRSET_ENABLE)
   1750 		info->enable = RCrt(ba, CRT_ID_HWGC_MODE) & 0x01;
   1751 
   1752 	if (info->set & GRFSPRSET_POS)
   1753 		cv3d_getspritepos (gp, &info->pos);
   1754 
   1755 #if 0	/* XXX */
   1756 	if (info->set & GRFSPRSET_SHAPE) {
   1757 		u_char image[512], mask[512];
   1758 		volatile u_long *hwp;
   1759 		u_char *imp, *mp;
   1760 		short row;
   1761 		info->size.x = 64;
   1762 		info->size.y = 64;
   1763 		for (row = 0, hwp = (u_long *)(fb + HWC_OFF),
   1764 		    mp = mask, imp = image;
   1765 		    row < 64;
   1766 		    row++) {
   1767 			u_long bp10, bp20, bp11, bp21;
   1768 			bp10 = *hwp++;
   1769 			bp20 = *hwp++;
   1770 			bp11 = *hwp++;
   1771 			bp21 = *hwp++;
   1772 			M2I (bp10);
   1773 			M2I (bp20);
   1774 			M2I (bp11);
   1775 			M2I (bp21);
   1776 			*imp++ = (~bp10) & bp11;
   1777 			*imp++ = (~bp20) & bp21;
   1778 			*mp++  = (~bp10) | (bp10 & ~bp11);
   1779 			*mp++  = (~bp20) & (bp20 & ~bp21);
   1780 		}
   1781 		copyout (image, info->image, sizeof (image));
   1782 		copyout (mask, info->mask, sizeof (mask));
   1783 	}
   1784 #endif
   1785 	return(0);
   1786 }
   1787 
   1788 
   1789 void
   1790 cv3d_setup_hwc(struct grf_softc *gp)
   1791 {
   1792 	volatile void *ba = gp->g_regkva;
   1793 	volatile void *hwc;
   1794 	int test;
   1795 
   1796 	if (gp->g_display.gd_planes <= 4)
   1797 		cv3d_cursor_on = 0;	/* don't enable hwc in text modes */
   1798 	if (cv3d_cursor_on == 0)
   1799 		return;
   1800 
   1801 	/* reset colour stack */
   1802 #if !defined(__m68k__)
   1803 	test = RCrt(ba, CRT_ID_HWGC_MODE);
   1804 	cpu_sync();
   1805 #else
   1806 	/* do it in assembler, the above does't seem to work */
   1807 	__asm volatile ("moveb #0x45, %1@(0x3d4); \
   1808 		moveb %1@(0x3d5),%0" : "=r" (test) : "a" (ba));
   1809 #endif
   1810 
   1811 	WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
   1812 
   1813 	hwc = ba + CRT_ADDRESS_W;
   1814 	*hwc = 0;
   1815 	*hwc = 0;
   1816 
   1817 #if !defined(__m68k__)
   1818 	test = RCrt(ba, CRT_ID_HWGC_MODE);
   1819 	cpu_sync();
   1820 #else
   1821 	/* do it in assembler, the above does't seem to work */
   1822 	__asm volatile ("moveb #0x45, %1@(0x3d4); \
   1823 		moveb %1@(0x3d5),%0" : "=r" (test) : "a" (ba));
   1824 #endif
   1825 	switch (gp->g_display.gd_planes) {
   1826 	    case 8:
   1827 		WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1);
   1828 		*hwc = 1;
   1829 		break;
   1830 	    default:
   1831 		WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
   1832 		*hwc = 0xff;
   1833 		*hwc = 0xff;
   1834 	}
   1835 
   1836 	test = HWC_OFF / HWC_SIZE;
   1837 	WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8));
   1838 	WCrt (ba, CRT_ID_HWGC_START_AD_LO, (test & 0xff));
   1839 
   1840 	WCrt (ba, CRT_ID_HWGC_DSTART_X , 0);
   1841 	WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0);
   1842 
   1843 	WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10);	/* Cursor X11 Mode */
   1844 	/*
   1845 	 * Put it into Windoze Mode or you'll see sometimes a white stripe
   1846 	 * on the right side (in double clocking modes with a screen bigger
   1847 	 * > 1023 pixels).
   1848 	 */
   1849 	WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x00);	/* Cursor Windoze Mode */
   1850 
   1851 	WCrt (ba, CRT_ID_HWGC_MODE, 0x01);
   1852 }
   1853 
   1854 
   1855 /*
   1856  * This was the reason why you shouldn't use the HWC in the Kernel:(
   1857  * Obsoleted now by use of interrupts :-)
   1858  */
   1859 
   1860 #define VerticalRetraceWait(ba) \
   1861 { \
   1862 	while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \
   1863 	while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x08) ; \
   1864 	while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x00) ; \
   1865 }
   1866 
   1867 
   1868 int
   1869 cv3d_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
   1870 {
   1871 	volatile void *ba, fb;
   1872 	int depth = gp->g_display.gd_planes;
   1873 
   1874 	ba = gp->g_regkva;
   1875 	fb = gp->g_fbkva;
   1876 
   1877 	if (info->set & GRFSPRSET_SHAPE) {
   1878 		/*
   1879 		 * For an explanation of these weird actions here, see above
   1880 		 * when reading the shape.  We set the shape directly into
   1881 		 * the video memory, there's no reason to keep 1k on the
   1882 		 * kernel stack just as template
   1883 		 */
   1884 		u_char *image, *mask;
   1885 		volatile u_short *hwp;
   1886 		u_char *imp, *mp;
   1887 		unsigned short row;
   1888 
   1889 		/* Cursor off */
   1890 		WCrt (ba, CRT_ID_HWGC_MODE, 0x00);
   1891 
   1892 		/*
   1893 		 * The Trio64 crashes if the cursor data is written
   1894 		 * while the cursor is displayed.
   1895 		 * Sadly, turning the cursor off is not enough.
   1896 		 * What we have to do is:
   1897 		 * 1. Wait for vertical retrace, to make sure no-one
   1898 		 * has moved the cursor in this sync period (because
   1899 		 * another write then would have no effect, argh!).
   1900 		 * 2. Move the cursor off-screen
   1901 		 * 3. Another wait for v. retrace to make sure the cursor
   1902 		 * is really off.
   1903 		 * 4. Write the data, finally.
   1904 		 * (thanks to Harald Koenig for this tip!)
   1905 		 */
   1906 
   1907 		/*
   1908 		 * Remark 06/06/96: Update in interrupt obsoletes this,
   1909 		 * but the warning should stay there!
   1910 		 */
   1911 
   1912 		VerticalRetraceWait(ba);
   1913 
   1914 		WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7);
   1915 		WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO,  0xff);
   1916 		WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, 0xff);
   1917 		WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f);
   1918 		WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f);
   1919 		WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7);
   1920 
   1921 		if (info->size.y > 64)
   1922 			info->size.y = 64;
   1923 		if (info->size.x > 64)
   1924 			info->size.x = 64;
   1925 		if (info->size.x < 32)
   1926 			info->size.x = 32;
   1927 
   1928 		image = malloc(HWC_SIZE, M_TEMP, M_WAITOK);
   1929 		mask  = image + HWC_SIZE/2;
   1930 
   1931 		copyin(info->image, image, info->size.y * info->size.x / 8);
   1932 		copyin(info->mask, mask, info->size.y * info->size.x / 8);
   1933 
   1934 		hwp = (u_short *)(fb  +HWC_OFF);
   1935 
   1936 		/* This is necessary in order not to crash the board */
   1937 		VerticalRetraceWait(ba);
   1938 
   1939 		/*
   1940 		 * setting it is slightly more difficult, because we can't
   1941 		 * force the application to not pass a *smaller* than
   1942 		 * supported bitmap
   1943 		 */
   1944 
   1945 		for (row = 0, mp = mask, imp = image;
   1946 		    row < info->size.y; row++) {
   1947 			u_short im1, im2, im3, im4, m1, m2, m3, m4;
   1948 
   1949 			m1  = ~(*(unsigned short *)mp);
   1950 			im1 = *(unsigned short *)imp & *(unsigned short *)mp;
   1951 			mp  += 2;
   1952 			imp += 2;
   1953 
   1954 			m2  = ~(*(unsigned short *)mp);
   1955 			im2 = *(unsigned short *)imp & *(unsigned short *)mp;
   1956 			mp  += 2;
   1957 			imp += 2;
   1958 
   1959 			if (info->size.x > 32) {
   1960 				m3  = ~(*(unsigned short *)mp);
   1961 				im3 = *(unsigned short *)imp & *(unsigned short *)mp;
   1962 				mp  += 2;
   1963 				imp += 2;
   1964 				m4  = ~(*(unsigned short *)mp);
   1965 				im4 = *(unsigned short *)imp & *(unsigned short *)mp;
   1966 				mp  += 2;
   1967 				imp += 2;
   1968 			} else {
   1969 				m3  = 0xffff;
   1970 				im3 = 0;
   1971 				m4  = 0xffff;
   1972 				im4 = 0;
   1973 			}
   1974 
   1975 			switch (depth) {
   1976 			    case 8:
   1977 				*hwp++ = m1;
   1978 				*hwp++ = im1;
   1979 				*hwp++ = m2;
   1980 				*hwp++ = im2;
   1981 				*hwp++ = m3;
   1982 				*hwp++ = im3;
   1983 				*hwp++ = m4;
   1984 				*hwp++ = im4;
   1985 				break;
   1986 			    case 15:
   1987 			    case 16:
   1988 				*hwp++ = M2I(m1);
   1989 				*hwp++ = M2I(im1);
   1990 				*hwp++ = M2I(m2);
   1991 				*hwp++ = M2I(im2);
   1992 				*hwp++ = M2I(m3);
   1993 				*hwp++ = M2I(im3);
   1994 				*hwp++ = M2I(m4);
   1995 				*hwp++ = M2I(im4);
   1996 				break;
   1997 			    case 24:
   1998 			    case 32:
   1999 				*hwp++ = M2I(im1);
   2000 				*hwp++ = M2I(m1);
   2001 				*hwp++ = M2I(im2);
   2002 				*hwp++ = M2I(m2);
   2003 				*hwp++ = M2I(im3);
   2004 				*hwp++ = M2I(m3);
   2005 				*hwp++ = M2I(im4);
   2006 				*hwp++ = M2I(m4);
   2007 				break;
   2008 			}
   2009 		}
   2010 
   2011 		if (depth < 24) {
   2012 			for (; row < 64; row++) {
   2013 				*hwp++ = 0xffff;
   2014 				*hwp++ = 0x0000;
   2015 				*hwp++ = 0xffff;
   2016 				*hwp++ = 0x0000;
   2017 				*hwp++ = 0xffff;
   2018 				*hwp++ = 0x0000;
   2019 				*hwp++ = 0xffff;
   2020 				*hwp++ = 0x0000;
   2021 			}
   2022 		} else {
   2023 			for (; row < 64; row++) {
   2024 				*hwp++ = 0x0000;
   2025 				*hwp++ = 0xffff;
   2026 				*hwp++ = 0x0000;
   2027 				*hwp++ = 0xffff;
   2028 				*hwp++ = 0x0000;
   2029 				*hwp++ = 0xffff;
   2030 				*hwp++ = 0x0000;
   2031 				*hwp++ = 0xffff;
   2032 			}
   2033 		}
   2034 
   2035 		free(image, M_TEMP);
   2036 		/* cv3d_setup_hwc(gp); */
   2037 		cv3d_hotx = info->hot.x;
   2038 		cv3d_hoty = info->hot.y;
   2039 
   2040 		/* One must not write twice per vertical blank :-( */
   2041 		VerticalRetraceWait(ba);
   2042 		cv3d_setspritepos(gp, &info->pos);
   2043 	}
   2044 	if (info->set & GRFSPRSET_CMAP) {
   2045 		volatile void *hwc;
   2046 		int test;
   2047 
   2048 		/* reset colour stack */
   2049 		test = RCrt(ba, CRT_ID_HWGC_MODE);
   2050 		cpu_sync();
   2051 		switch (depth) {
   2052 		    case 8:
   2053 		    case 15:
   2054 		    case 16:
   2055 			WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
   2056 			hwc = ba + CRT_ADDRESS_W;
   2057 			*hwc = 0;
   2058 			break;
   2059 		    case 32:
   2060 		    case 24:
   2061 			WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
   2062 			hwc = ba + CRT_ADDRESS_W;
   2063 			*hwc = 0;
   2064 			*hwc = 0;
   2065 			break;
   2066 		}
   2067 
   2068 		test = RCrt(ba, CRT_ID_HWGC_MODE);
   2069 		cpu_sync();
   2070 		switch (depth) {
   2071 		    case 8:
   2072 			WCrt (ba, CRT_ID_HWGC_BG_STACK, 1);
   2073 			hwc = ba + CRT_ADDRESS_W;
   2074 			*hwc = 1;
   2075 			break;
   2076 		    case 15:
   2077 		    case 16:
   2078 			WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
   2079 			hwc = ba + CRT_ADDRESS_W;
   2080 			*hwc = 0xff;
   2081 			break;
   2082 		    case 32:
   2083 		    case 24:
   2084 			WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
   2085 			hwc = ba + CRT_ADDRESS_W;
   2086 			*hwc = 0xff;
   2087 			*hwc = 0xff;
   2088 			break;
   2089 		}
   2090 	}
   2091 
   2092 	if (info->set & GRFSPRSET_ENABLE) {
   2093 		if (info->enable) {
   2094 			cv3d_cursor_on = 1;
   2095 			cv3d_setup_hwc(gp);
   2096 			/* WCrt(ba, CRT_ID_HWGC_MODE, 0x01); */
   2097 		} else
   2098 			WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
   2099 	}
   2100 	if (info->set & GRFSPRSET_POS)
   2101 		cv3d_setspritepos(gp, &info->pos);
   2102 	if (info->set & GRFSPRSET_HOT) {
   2103 
   2104 		cv3d_hotx = info->hot.x;
   2105 		cv3d_hoty = info->hot.y;
   2106 		cv3d_setspritepos (gp, &info->pos);
   2107 	}
   2108 	return(0);
   2109 }
   2110 
   2111 
   2112 int
   2113 cv3d_getspritemax(struct grf_softc *gp, struct grf_position *pos)
   2114 {
   2115 
   2116 	pos->x = 64;
   2117 	pos->y = 64;
   2118 	return(0);
   2119 }
   2120 
   2121 #endif /* CV3D_HARDWARE_CURSOR */
   2122 
   2123 #if NWSDISPLAY > 0
   2124 
   2125 static void
   2126 cv3d_wscursor(void *c, int on, int row, int col)
   2127 {
   2128 	struct rasops_info *ri;
   2129 	struct vcons_screen *scr;
   2130 	struct grf_softc *gp;
   2131 	volatile void *ba;
   2132 	int offs;
   2133 
   2134 	ri = c;
   2135 	scr = ri->ri_hw;
   2136 	gp = scr->scr_cookie;
   2137 	ba = gp->g_regkva;
   2138 
   2139 	if ((ri->ri_flg & RI_CURSOR) && !on) {
   2140 		/* cursor was visible, but we want to remove it */
   2141 		/*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
   2142 		ri->ri_flg &= ~RI_CURSOR;
   2143 	}
   2144 
   2145 	ri->ri_crow = row;
   2146 	ri->ri_ccol = col;
   2147 
   2148 	if (on) {
   2149 		/* move cursor to new location */
   2150 		if (!(ri->ri_flg & RI_CURSOR)) {
   2151 			/*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
   2152 			ri->ri_flg |= RI_CURSOR;
   2153 		}
   2154 		offs = gp->g_rowoffset[row] + col;
   2155 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, offs & 0xff);
   2156 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, offs >> 8);
   2157 	}
   2158 }
   2159 
   2160 static void
   2161 cv3d_wsputchar(void *cookie, int row, int col, u_int ch, long attr)
   2162 {
   2163 	struct rasops_info *ri;
   2164 	struct vcons_screen *scr;
   2165 	struct grf_softc *gp;
   2166 	volatile unsigned char *cp;
   2167 
   2168 	ri = cookie;
   2169 	scr = ri->ri_hw;
   2170 	gp = scr->scr_cookie;
   2171 	cp = gp->g_fbkva;
   2172 	cp += (gp->g_rowoffset[row] + col) << 2;
   2173 	*cp++ = ch;
   2174 	*cp = attr;
   2175 }
   2176 
   2177 static void
   2178 cv3d_wscopycols(void *c, int row, int srccol, int dstcol, int ncols)
   2179 {
   2180 	struct rasops_info *ri;
   2181 	struct vcons_screen *scr;
   2182 	struct grf_softc *gp;
   2183 	volatile uint16_t *src, *dst;
   2184 
   2185 	KASSERT(ncols > 0);
   2186 	ri = c;
   2187 	scr = ri->ri_hw;
   2188 	gp = scr->scr_cookie;
   2189 	src = dst = gp->g_fbkva;
   2190 	src += (gp->g_rowoffset[row] + srccol) << 1;
   2191 	dst += (gp->g_rowoffset[row] + dstcol) << 1;
   2192 	if (src < dst) {
   2193 		/* need to copy backwards */
   2194 		src += (ncols - 1) << 1;
   2195 		dst += (ncols - 1) << 1;
   2196 		while (ncols--) {
   2197 			*dst = *src;
   2198 			src -= 2;
   2199 			dst -= 2;
   2200 		}
   2201 	} else
   2202 		while (ncols--) {
   2203 			*dst = *src;
   2204 			src += 2;
   2205 			dst += 2;
   2206 		}
   2207 }
   2208 
   2209 static void
   2210 cv3d_wserasecols(void *c, int row, int startcol, int ncols, long fillattr)
   2211 {
   2212 	struct rasops_info *ri;
   2213 	struct vcons_screen *scr;
   2214 	struct grf_softc *gp;
   2215 	volatile uint16_t *cp;
   2216 	uint16_t val;
   2217 
   2218 	ri = c;
   2219 	scr = ri->ri_hw;
   2220 	gp = scr->scr_cookie;
   2221 	cp = gp->g_fbkva;
   2222 	val = 0x2000 | fillattr;
   2223 	cp += (gp->g_rowoffset[row] + startcol) << 1;
   2224 	while (ncols--) {
   2225 		*cp = val;
   2226 		cp += 2;
   2227 	}
   2228 }
   2229 
   2230 static void
   2231 cv3d_wscopyrows(void *c, int srcrow, int dstrow, int nrows)
   2232 {
   2233 	struct rasops_info *ri;
   2234 	struct vcons_screen *scr;
   2235 	struct grf_softc *gp;
   2236 	volatile uint16_t *src, *dst;
   2237 	int n;
   2238 
   2239 	KASSERT(nrows > 0);
   2240 	ri = c;
   2241 	scr = ri->ri_hw;
   2242 	gp = scr->scr_cookie;
   2243 	src = dst = gp->g_fbkva;
   2244 	n = ri->ri_cols * nrows;
   2245 	if (src < dst) {
   2246 		/* need to copy backwards */
   2247 		src += gp->g_rowoffset[srcrow + nrows] << 1;
   2248 		dst += gp->g_rowoffset[dstrow + nrows] << 1;
   2249 		while (n--) {
   2250 			src -= 2;
   2251 			dst -= 2;
   2252 			*dst = *src;
   2253 		}
   2254 	} else {
   2255 		src += gp->g_rowoffset[srcrow] << 1;
   2256 		dst += gp->g_rowoffset[dstrow] << 1;
   2257 		while (n--) {
   2258 			*dst = *src;
   2259 			src += 2;
   2260 			dst += 2;
   2261 		}
   2262 	}
   2263 }
   2264 
   2265 static void
   2266 cv3d_wseraserows(void *c, int row, int nrows, long fillattr)
   2267 {
   2268 	struct rasops_info *ri;
   2269 	struct vcons_screen *scr;
   2270 	struct grf_softc *gp;
   2271 	volatile uint16_t *cp;
   2272 	int n;
   2273 	uint16_t val;
   2274 
   2275 	ri = c;
   2276 	scr = ri->ri_hw;
   2277 	gp = scr->scr_cookie;
   2278 	cp = gp->g_fbkva;
   2279 	val = 0x2000 | fillattr;
   2280 	cp += gp->g_rowoffset[row] << 1;
   2281 	n = ri->ri_cols * nrows;
   2282 	while (n--) {
   2283 		*cp = val;
   2284 		cp += 2;
   2285 	}
   2286 }
   2287 
   2288 /* our font does not support unicode extensions */
   2289 static int
   2290 cv3d_wsmapchar(void *c, int ch, unsigned int *cp)
   2291 {
   2292 
   2293 	if (ch > 0 && ch < 256) {
   2294 		*cp = ch;
   2295 		return 5;
   2296 	}
   2297 	*cp = ' ';
   2298 	return 0;
   2299 }
   2300 
   2301 static int
   2302 cv3d_wsallocattr(void *c, int fg, int bg, int flg, long *attr)
   2303 {
   2304 
   2305 	/* XXX color support? */
   2306 	*attr = (flg & WSATTR_REVERSE) ? 0x70 : 0x07;
   2307 	if (flg & WSATTR_UNDERLINE)	*attr = 0x01;
   2308 	if (flg & WSATTR_HILIT)		*attr |= 0x08;
   2309 	if (flg & WSATTR_BLINK)		*attr |= 0x80;
   2310 	return 0;
   2311 }
   2312 
   2313 static int
   2314 cv3d_wsioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
   2315 {
   2316 	struct vcons_data *vd;
   2317 	struct grf_softc *gp;
   2318 
   2319 	vd = v;
   2320 	gp = vd->cookie;
   2321 
   2322 	switch (cmd) {
   2323 	case WSDISPLAYIO_GETCMAP:
   2324 		/* Note: wsdisplay_cmap and grf_colormap have same format */
   2325 		if (gp->g_display.gd_planes == 8)
   2326 			return cv3d_getcmap(gp, (struct grf_colormap *)data);
   2327 		return EINVAL;
   2328 
   2329 	case WSDISPLAYIO_PUTCMAP:
   2330 		/* Note: wsdisplay_cmap and grf_colormap have same format */
   2331 		if (gp->g_display.gd_planes == 8)
   2332 			return cv3d_putcmap(gp, (struct grf_colormap *)data);
   2333 		return EINVAL;
   2334 
   2335 	case WSDISPLAYIO_GVIDEO:
   2336 		if (cv3d_isblank(gp))
   2337 			*(u_int *)data = WSDISPLAYIO_VIDEO_OFF;
   2338 		else
   2339 			*(u_int *)data = WSDISPLAYIO_VIDEO_ON;
   2340 		return 0;
   2341 
   2342 	case WSDISPLAYIO_SVIDEO:
   2343 		return cv3d_blank(gp, *(u_int *)data == WSDISPLAYIO_VIDEO_OFF);
   2344 
   2345 	case WSDISPLAYIO_SMODE:
   2346 		if ((*(int *)data) != gp->g_wsmode) {
   2347 			if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
   2348 				/* load console text mode, redraw screen */
   2349 				(void)cv3d_load_mon(gp, &cv3dconsole_mode);
   2350 				if (vd->active != NULL)
   2351 					vcons_redraw_screen(vd->active);
   2352 			} else {
   2353 				/* switch to current graphics mode */
   2354 				if (!cv3d_load_mon(gp,
   2355 				    (struct grfcv3dtext_mode *)monitor_current))
   2356 					return EINVAL;
   2357 			}
   2358 			gp->g_wsmode = *(int *)data;
   2359 		}
   2360 		return 0;
   2361 
   2362 	case WSDISPLAYIO_GET_FBINFO:
   2363 		return cv3d_get_fbinfo(gp, data);
   2364 	}
   2365 
   2366 	/* handle this command hw-independant in grf(4) */
   2367 	return grf_wsioctl(v, vs, cmd, data, flag, l);
   2368 }
   2369 
   2370 /*
   2371  * Fill the wsdisplayio_fbinfo structure with information from the current
   2372  * graphics mode. Even when text mode is active.
   2373  */
   2374 static int
   2375 cv3d_get_fbinfo(struct grf_softc *gp, struct wsdisplayio_fbinfo *fbi)
   2376 {
   2377 	struct grfvideo_mode *md;
   2378 	uint32_t rbits, gbits, bbits, abits;
   2379 
   2380 	md = monitor_current;
   2381 	abits = 0;
   2382 
   2383 	fbi->fbi_width = md->disp_width;
   2384 	fbi->fbi_height = md->disp_height;
   2385 	fbi->fbi_bitsperpixel = md->depth;
   2386 
   2387 	switch (md->depth) {
   2388 	case 8:
   2389 		fbi->fbi_stride = md->disp_width;
   2390 		rbits = gbits = bbits = 6;  /* keep gcc happy */
   2391 		break;
   2392 	case 15:
   2393 		fbi->fbi_stride = md->disp_width * 2;
   2394 		rbits = gbits = bbits = 5;
   2395 		break;
   2396 	case 16:
   2397 		fbi->fbi_stride = md->disp_width * 2;
   2398 		rbits = bbits = 5;
   2399 		gbits = 6;
   2400 		break;
   2401 	case 32:
   2402 		abits = 8;
   2403 	case 24:
   2404 		fbi->fbi_stride = md->disp_width * 4;
   2405 		rbits = gbits = bbits = 8;
   2406 		break;
   2407 	default:
   2408 		return EINVAL;
   2409 	}
   2410 
   2411 	if (md->depth > 8) {
   2412 		fbi->fbi_pixeltype = WSFB_RGB;
   2413 		fbi->fbi_subtype.fbi_rgbmasks.red_offset = bbits + gbits;
   2414 		fbi->fbi_subtype.fbi_rgbmasks.red_size = rbits;
   2415 		fbi->fbi_subtype.fbi_rgbmasks.green_offset = bbits;
   2416 		fbi->fbi_subtype.fbi_rgbmasks.green_size = gbits;
   2417 		fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
   2418 		fbi->fbi_subtype.fbi_rgbmasks.blue_size = bbits;
   2419 		fbi->fbi_subtype.fbi_rgbmasks.alpha_offset =
   2420 		    bbits + gbits + rbits;
   2421 		fbi->fbi_subtype.fbi_rgbmasks.alpha_size = abits;
   2422 	} else {
   2423 		fbi->fbi_pixeltype = WSFB_CI;
   2424 		fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = 1 << md->depth;
   2425 	}
   2426 
   2427 	fbi->fbi_flags = 0;
   2428 	fbi->fbi_fbsize = fbi->fbi_stride * fbi->fbi_height;
   2429 	fbi->fbi_fboffset = 0;
   2430 	return 0;
   2431 }
   2432 #endif	/* NWSDISPLAY > 0 */
   2433 
   2434 #endif	/* NGRFCV3D */
   2435