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