Home | History | Annotate | Line # | Download | only in dev
grf_et.c revision 1.1
      1 /*	$NetBSD: grf_et.c,v 1.1 1996/05/19 21:05:32 veego Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1996 Tobias Abt
      5  * Copyright (c) 1995 Ezra Story
      6  * Copyright (c) 1995 Kari Mettinen
      7  * Copyright (c) 1994 Markus Wild
      8  * Copyright (c) 1994 Lutz Vieweg
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *      This product includes software developed by Lutz Vieweg.
     22  * 4. The name of the author may not be used to endorse or promote products
     23  *    derived from this software without specific prior written permission
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     26  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     28  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35  */
     36 #include "grfet.h"
     37 #if NGRFET > 0
     38 
     39 /*
     40  * Graphics routines for Tseng ET4000 (&W32) boards,
     41  *
     42  * This code offers low-level routines to access Tseng ET4000
     43  * graphics-boards from within NetBSD for the Amiga.
     44  * No warranties for any kind of function at all - this
     45  * code may crash your hardware and scratch your harddisk.  Use at your
     46  * own risk.  Freely distributable.
     47  *
     48  * Modified for Tseng ET4000 from
     49  * Kari Mettinen's Cirrus driver by Tobias Abt
     50  *
     51  *
     52  * TODO:
     53  *
     54  */
     55 
     56 #include <sys/param.h>
     57 #include <sys/systm.h>
     58 #include <sys/errno.h>
     59 #include <sys/ioctl.h>
     60 #include <sys/device.h>
     61 #include <sys/malloc.h>
     62 
     63 #include <machine/cpu.h>
     64 #include <dev/cons.h>
     65 #ifdef TSENGCONSOLE
     66 #include <amiga/dev/itevar.h>
     67 #endif
     68 #include <amiga/amiga/device.h>
     69 #include <amiga/dev/grfioctl.h>
     70 #include <amiga/dev/grfvar.h>
     71 #include <amiga/dev/grf_etreg.h>
     72 #include <amiga/dev/zbusvar.h>
     73 
     74 int	et_mondefok __P((struct grfvideo_mode * gv));
     75 void	et_boardinit __P((struct grf_softc * gp));
     76 static void et_CompFQ __P((u_int fq, u_char * num, u_char * denom));
     77 int	et_getvmode __P((struct grf_softc * gp, struct grfvideo_mode * vm));
     78 int	et_setvmode __P((struct grf_softc * gp, unsigned int mode));
     79 int	et_toggle __P((struct grf_softc * gp, unsigned short));
     80 int	et_getcmap __P((struct grf_softc * gfp, struct grf_colormap * cmap));
     81 int	et_putcmap __P((struct grf_softc * gfp, struct grf_colormap * cmap));
     82 #ifndef TSENGCONSOLE
     83 void	et_off __P((struct grf_softc * gp));
     84 #endif
     85 void	et_inittextmode __P((struct grf_softc * gp));
     86 int	et_ioctl __P((register struct grf_softc * gp, u_long cmd, void *data));
     87 int	et_getmousepos __P((struct grf_softc * gp, struct grf_position * data));
     88 void	et_writesprpos __P((volatile char *ba, short x, short y));
     89 #ifdef notyet
     90 void	et_writeshifted __P((unsigned char *to, char shiftx, char shifty));
     91 #endif
     92 int	et_setmousepos __P((struct grf_softc * gp, struct grf_position * data));
     93 static int et_setspriteinfo __P((struct grf_softc * gp, struct grf_spriteinfo * data));
     94 int	et_getspriteinfo __P((struct grf_softc * gp, struct grf_spriteinfo * data));
     95 static int et_getspritemax __P((struct grf_softc * gp, struct grf_position * data));
     96 int	et_setmonitor __P((struct grf_softc * gp, struct grfvideo_mode * gv));
     97 int	et_blank __P((struct grf_softc * gp, int * on));
     98 static int et_getControllerType __P((struct grf_softc * gp));
     99 static int et_getDACType __P((struct grf_softc * gp));
    100 
    101 int	grfetmatch __P((struct device *, void *, void *));
    102 void	grfetattach __P((struct device *, struct device *, void *));
    103 int	grfetprint __P((void *, char *));
    104 void	et_memset __P((unsigned char *d, unsigned char c, int l));
    105 
    106 /* Graphics display definitions.
    107  * These are filled by 'grfconfig' using GRFIOCSETMON.
    108  */
    109 #define monitor_def_max 8
    110 static struct grfvideo_mode monitor_def[8] = {
    111 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
    112 };
    113 static struct grfvideo_mode *monitor_current = &monitor_def[0];
    114 
    115 /* Console display definition.
    116  *   Default hardcoded text mode.  This grf_et is set up to
    117  *   use one text mode only, and this is it.  You may use
    118  *   grfconfig to change the mode after boot.
    119  */
    120 /* Console font */
    121 #ifdef KFONT_8X11
    122 #define TSENGFONT kernel_font_8x11
    123 #define TSENGFONTY 11
    124 #else
    125 #define TSENGFONT kernel_font_8x8
    126 #define TSENGFONTY 8
    127 #endif
    128 extern unsigned char TSENGFONT[];
    129 
    130 struct grfettext_mode etconsole_mode = {
    131 	{255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8,
    132 	 481, 521, 491, 493, 525},
    133 	8, TSENGFONTY, 640 / 8, 480 / TSENGFONTY, TSENGFONT, 32, 255
    134 };
    135 
    136 /* some modes
    137 # 640x480 256colors  41kHz  79Hz   active
    138 x 31500000 640 480 8 640 752 672 768 728 487 505 488 490 512
    139 # 31500000 640 480 8 80 94 84 96 91 487 505 488 490 512
    140 # 640x512 256colors  42kHz  76Hz   active
    141 x 32500000 640 512 8 640 760 664 760 736 519 536 520 522 543
    142 # 32500000 640 512 8 80 95 83 95 92 519 536 520 522 543
    143 # 720x540 256colors  43kHz  74Hz   active
    144 x 37500000 720 540 8 720 856 744 840 832 547 565 548 550 572
    145 # 37500000 720 540 8 90 107 93 105 104 547 565 548 550 572
    146 # 800x600 256colors  48kHz  73Hz   active
    147 x 50350000 800 600 8 792 1048 864 960 1016 599 648 615 617 647
    148 # 50350000 800 600 8 99 131 108 120 127 599 648 615 617 647
    149 # 912x684 256colors  57kHz  78Hz   active
    150 x 65000000 912 684 8 904 1136 944 1040 1104 683 725 693 695 724
    151 # 65000000 912 684 8 113 142 118 130 138 683 725 693 695 724
    152 # 1024x768 256colors  61kHz  75Hz   active
    153 x 80000000 1024 768 8 1024 1288 1072 1168 1264 775 806 780 782 813
    154 # 80000000 1024 768 8 128 161 134 146 158 775 806 780 782 813
    155 # 1120x832 256colors  56kHz  64Hz   active
    156 x 80000000 1120 832 8 1120 1424 1152 1248 1400 839 848 833 835 855
    157 # 80000000 1120 832 8 140 178 144 156 175 839 848 833 835 855
    158 */
    159 
    160 /* Console colors */
    161 unsigned char etconscolors[3][3] = {	/* background, foreground, hilite */
    162 	{0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
    163 };
    164 
    165 int ettype = 0;		/* oMniBus, Domino or Merlin */
    166 int etctype = 0;	/* ET4000 or ETW32 */
    167 int etdtype = 0;	/* Type of DAC (see grf_etregs.h) */
    168 
    169 char etcmap_shift = 0;	/* 6 or 8 bit cmap entries */
    170 unsigned char pass_toggle;	/* passthru status tracker */
    171 
    172 unsigned char Merlin_switch = 0;
    173 
    174 /* because all Tseng-boards have 2 configdev entries, one for
    175  * framebuffer mem and the other for regs, we have to hold onto
    176  * the pointers globally until we match on both.  This and 'ettype'
    177  * are the primary obsticles to multiple board support, but if you
    178  * have multiple boards you have bigger problems than grf_et.
    179  */
    180 static void *et_fbaddr = 0;	/* framebuffer */
    181 static void *et_regaddr = 0;	/* registers */
    182 static int et_fbsize;		/* framebuffer size */
    183 
    184 /* current sprite info, if you add support for multiple boards
    185  * make this an array or something
    186  */
    187 struct grf_spriteinfo et_cursprite;
    188 
    189 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if
    190  * you add multiple board support
    191  */
    192 static unsigned char et_imageptr[8 * 64], et_maskptr[8 * 64];
    193 static unsigned char et_sprred[2], et_sprgreen[2], et_sprblue[2];
    194 
    195 /* standard driver stuff */
    196 struct cfattach grfet_ca = {
    197 	sizeof(struct grf_softc), grfetmatch, grfetattach
    198 };
    199 
    200 struct cfdriver grfet_cd = {
    201 	NULL, "grfet", DV_DULL, NULL, 0
    202 };
    203 static struct cfdata *cfdata;
    204 
    205 
    206 int
    207 grfetmatch(pdp, match, auxp)
    208 	struct device *pdp;
    209 	void *match, *auxp;
    210 {
    211 #ifdef TSENGCONSOLE
    212 	struct cfdata *cfp = match;
    213 #endif
    214 	struct zbus_args *zap;
    215 	static int regprod, fbprod;
    216 
    217 	zap = auxp;
    218 
    219 #ifndef TSENGCONSOLE
    220 	if (amiga_realconfig == 0)
    221 		return (0);
    222 #endif
    223 
    224 	/* Grab the first board we encounter as the preferred one.  This will
    225 	 * allow one board to work in a multiple Tseng board system, but not
    226 	 * multiple boards at the same time.  */
    227 	if (ettype == 0) {
    228 		switch (zap->manid) {
    229 		    case OMNIBUS:
    230 			if (zap->prodid != 0)
    231 				return (0);
    232 			regprod = 0;
    233 			fbprod = 0;
    234 			break;
    235 		    case DOMINO:
    236 			if (zap->prodid != 2 && zap->prodid != 1)
    237 				return (0);
    238 			regprod = 2;
    239 			fbprod = 1;
    240 			break;
    241 		    case MERLIN:
    242 			if (zap->prodid != 3 && zap->prodid != 4)
    243 				return (0);
    244 			regprod = 4;
    245 			fbprod = 3;
    246 			/*
    247 			 * This card works only in ZorroII mode.
    248 			 * ZorroIII needs different initialisations,
    249 			 * which will be implemented later.
    250 			 */
    251 			if iszthreepa(zap->pa)
    252 				return (0);
    253 			break;
    254 		    default:
    255 			return (0);
    256 		}
    257 		ettype = zap->manid;
    258 	} else {
    259 		if (ettype != zap->manid) {
    260 			return (0);
    261 		}
    262 	}
    263 
    264 	/* Configure either registers or framebuffer in any order */
    265 	/* as said before, oMniBus does not support ProdID */
    266 	if (ettype == OMNIBUS) {
    267 		if (zap->size == 64 * 1024) {
    268 			/* register area */
    269 			et_regaddr = zap->va;
    270 		} else {
    271 			/* memory area */
    272 			et_fbaddr = zap->va;
    273 			et_fbsize = zap->size;
    274 		}
    275 	} else {
    276 		if (zap->prodid == regprod) {
    277 			et_regaddr = zap->va;
    278 		} else {
    279 			if (zap->prodid == fbprod) {
    280 				et_fbaddr = zap->va;
    281 				et_fbsize = zap->size;
    282 			} else {
    283 				return (0);
    284 			}
    285 		}
    286 	}
    287 
    288 #ifdef TSENGCONSOLE
    289 	if (amiga_realconfig == 0) {
    290 		cfdata = cfp;
    291 	}
    292 #endif
    293 
    294 	return (1);
    295 }
    296 
    297 
    298 void
    299 grfetattach(pdp, dp, auxp)
    300 	struct device *pdp, *dp;
    301 	void   *auxp;
    302 {
    303 	static struct grf_softc congrf;
    304 	struct zbus_args *zap;
    305 	struct grf_softc *gp;
    306 	static char attachflag = 0;
    307 
    308 	zap = auxp;
    309 
    310 	printf("\n");
    311 
    312 	/* make sure both halves have matched */
    313 	if (!et_regaddr || !et_fbaddr)
    314 		return;
    315 
    316 	if (zap->manid == MERLIN && iszthreepa(zap->pa)) {
    317 		printf("grfet: WARNING: It is not possible to use the Merlin in ZorroIII mode.\n");
    318 		printf("grfet: Switch the Jumper to use it in ZorroII mode.\n");
    319 		printf("grfet unattached!!\n");
    320 		return;
    321 	}
    322 
    323 	/* do all that messy console/grf stuff */
    324 	if (dp == NULL)
    325 		gp = &congrf;
    326 	else
    327 		gp = (struct grf_softc *) dp;
    328 
    329 	if (dp != NULL && congrf.g_regkva != 0) {
    330 		/*
    331 		 * inited earlier, just copy (not device struct)
    332 		 */
    333 		bcopy(&congrf.g_display, &gp->g_display,
    334 		    (char *) &gp[1] - (char *) &gp->g_display);
    335 	} else {
    336 		gp->g_regkva = (volatile caddr_t) et_regaddr;
    337 		gp->g_fbkva = (volatile caddr_t) et_fbaddr;
    338 
    339 		gp->g_unit = GRF_ET4000_UNIT;
    340 		gp->g_mode = et_mode;
    341 		gp->g_conpri = grfet_cnprobe();
    342 		gp->g_flags = GF_ALIVE;
    343 
    344 		/* wakeup the board */
    345 		et_boardinit(gp);
    346 
    347 #ifdef TSENGCONSOLE
    348 		grfet_iteinit(gp);
    349 		(void) et_load_mon(gp, &etconsole_mode);
    350 #endif
    351 	}
    352 
    353 	/*
    354 	 * attach grf (once)
    355 	 */
    356 	if (amiga_config_found(cfdata, &gp->g_device, gp, grfetprint)) {
    357 		attachflag = 1;
    358 		printf("grfet: %dMB ", et_fbsize / 0x100000);
    359 		switch (ettype) {
    360 		    case OMNIBUS:
    361 			printf("oMniBus");
    362 			break;
    363 		    case DOMINO:
    364 			printf("Domino");
    365 			break;
    366 		    case MERLIN:
    367 			printf("Merlin");
    368 			break;
    369 		}
    370 		printf(" with ");
    371 		switch (etctype) {
    372 		    case ET4000:
    373 			printf("Tseng ET4000");
    374 			break;
    375 		    case ETW32:
    376 			printf("Tseng ETW32");
    377 			break;
    378 		}
    379 		printf(" and ");
    380 		switch (etdtype) {
    381 		    case SIERRA11483:
    382 			printf("Sierra SC11483 DAC");
    383 			break;
    384 		    case SIERRA15025:
    385 			printf("Sierra SC15025 DAC");
    386 			break;
    387 		    case MUSICDAC:
    388 			printf("MUSIC DAC");
    389 			break;
    390 		    case MERLINDAC:
    391 			printf("BrookTree DAC");
    392 			break;
    393 		}
    394 		printf(" being used\n");
    395 	} else {
    396 		if (!attachflag)
    397 			printf("grfet unattached!!\n");
    398 	}
    399 }
    400 
    401 
    402 int
    403 grfetprint(auxp, pnp)
    404 	void   *auxp;
    405 	char   *pnp;
    406 {
    407 	if (pnp)
    408 		printf("ite at %s: ", pnp);
    409 	return (UNCONF);
    410 }
    411 
    412 
    413 void
    414 et_boardinit(gp)
    415 	struct grf_softc *gp;
    416 {
    417 	unsigned char *ba = gp->g_regkva;
    418 	int     x;
    419 
    420 	/* wakeup board and flip passthru OFF */
    421 
    422 	RegWakeup(ba);
    423 	RegOnpass(ba);
    424 
    425 	if (ettype == MERLIN) {
    426 	  /* Merlin needs some special initialisations */
    427 	  vgaw(ba, MERLIN_SWITCH_REG, 0);
    428 	  delay(20000);
    429 	  vgaw(ba, MERLIN_SWITCH_REG, 8);
    430 	  delay(20000);
    431 	  vgaw(ba, MERLIN_SWITCH_REG, 0);
    432 	  delay(20000);
    433 	  vgaw(ba, MERLIN_VDAC_DATA, 1);
    434 
    435 	  vgaw(ba, MERLIN_VDAC_INDEX, 0x00);
    436 	  vgaw(ba, MERLIN_VDAC_SPRITE,  0xff);
    437 	  vgaw(ba, MERLIN_VDAC_INDEX, 0x01);
    438 	  vgaw(ba, MERLIN_VDAC_SPRITE,  0x0f);
    439 	  vgaw(ba, MERLIN_VDAC_INDEX, 0x02);
    440 	  vgaw(ba, MERLIN_VDAC_SPRITE,  0x42);
    441 	  vgaw(ba, MERLIN_VDAC_INDEX, 0x03);
    442 	  vgaw(ba, MERLIN_VDAC_SPRITE,  0x00);
    443 
    444 	  vgaw(ba, MERLIN_VDAC_DATA, 0);
    445 	}
    446 
    447 
    448 	/* setup initial unchanging parameters */
    449 
    450 	vgaw(ba, GREG_HERCULESCOMPAT, 0x03);
    451 	vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
    452 	vgaw(ba, GREG_MISC_OUTPUT_W, 0x63);
    453 
    454 	WSeq(ba, SEQ_ID_RESET, 0x03);
    455 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);	/* 8 dot, Display off */
    456 	WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
    457 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
    458 	WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);
    459 /*	WSeq(ba, SEQ_ID_TS_STATE_CONTROL, 0x00);	*/
    460 	WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
    461 
    462 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
    463 	WCrt(ba, CRT_ID_CURSOR_START, 0x00);
    464 	WCrt(ba, CRT_ID_CURSOR_END, 0x08);
    465 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
    466 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
    467 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
    468 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
    469 
    470 	WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
    471 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3);	/* c3 */
    472 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);	/* ff */
    473 /*
    474 	WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22);
    475 */
    476 /* ET4000 special */
    477 	WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28);
    478 	WCrt(ba, CTR_ID_EXT_START, 0x00);
    479 	WCrt(ba, CRT_ID_6845_COMPAT, 0x08);
    480 	WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
    481 	WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f);
    482 	WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00);
    483 
    484 	WGfx(ba, GCT_ID_SET_RESET, 0x00);
    485 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
    486 	WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
    487 	WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
    488 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
    489 	WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
    490 	WGfx(ba, GCT_ID_MISC, 0x01);
    491 	WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
    492 	WGfx(ba, GCT_ID_BITMASK, 0xff);
    493 
    494 	vgaw(ba, GREG_SEGMENTSELECT, 0x00);
    495 
    496 	for (x = 0; x < 0x10; x++)
    497 		WAttr(ba, x, x);
    498 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
    499 	WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
    500 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
    501 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
    502 	WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
    503 	WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00);
    504 
    505 	vgaw(ba, VDAC_MASK, 0xff);
    506 	delay(200000);
    507 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3);	/* c3 */
    508 
    509 	/* colors initially set to greyscale */
    510 
    511 	switch(ettype) {
    512 	    case MERLIN:
    513 		vgaw(ba, MERLIN_VDAC_INDEX, 0);
    514 		for (x = 255; x >= 0; x--) {
    515 		    vgaw(ba, MERLIN_VDAC_COLORS, x);
    516 		    vgaw(ba, MERLIN_VDAC_COLORS, x);
    517 		    vgaw(ba, MERLIN_VDAC_COLORS, x);
    518 		}
    519 		break;
    520 	    default:
    521 		vgaw(ba, VDAC_ADDRESS_W, 0);
    522 		for (x = 255; x >= 0; x--) {
    523 		    vgaw(ba, VDAC_DATA, x);
    524 		    vgaw(ba, VDAC_DATA, x);
    525 		    vgaw(ba, VDAC_DATA, x);
    526 		}
    527 		break;
    528 	}
    529 	/* set sprite bitmap pointers */
    530 	/* should work like that */
    531 	et_cursprite.image = et_imageptr;
    532 	et_cursprite.mask = et_maskptr;
    533 	et_cursprite.cmap.red = et_sprred;
    534 	et_cursprite.cmap.green = et_sprgreen;
    535 	et_cursprite.cmap.blue = et_sprblue;
    536 
    537 	/* card spezific initialisations */
    538 	switch(ettype) {
    539 	    case OMNIBUS:
    540 		etctype = et_getControllerType(gp);
    541 		etdtype = et_getDACType(gp);
    542 		break;
    543 	    case MERLIN:
    544 		etctype = ETW32;
    545 		etdtype = MERLINDAC;
    546 	break;
    547 	    case DOMINO:
    548 		etctype = ET4000;
    549 		etdtype = SIERRA11483;
    550 		break;
    551 	}
    552 }
    553 
    554 
    555 int
    556 et_getvmode(gp, vm)
    557 	struct grf_softc *gp;
    558 	struct grfvideo_mode *vm;
    559 {
    560 	struct grfvideo_mode *gv;
    561 
    562 #ifdef TSENGCONSOLE
    563 	/* Handle grabbing console mode */
    564 	if (vm->mode_num == 255) {
    565 		bcopy(&etconsole_mode, vm, sizeof(struct grfvideo_mode));
    566 		/* XXX so grfconfig can tell us the correct text dimensions. */
    567 		vm->depth = etconsole_mode.fy;
    568 	} else
    569 #endif
    570         {
    571                 if (vm->mode_num == 0)
    572                         vm->mode_num = (monitor_current - monitor_def) + 1;
    573                 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
    574                         return (EINVAL);
    575                 gv = monitor_def + (vm->mode_num - 1);
    576                 if (gv->mode_num == 0)
    577                         return (EINVAL);
    578 
    579                 bcopy(gv, vm, sizeof(struct grfvideo_mode));
    580         }
    581 
    582         /* adjust internal values to pixel values */
    583 
    584         vm->hblank_start *= 8;
    585         vm->hblank_stop *= 8;
    586         vm->hsync_start *= 8;
    587         vm->hsync_stop *= 8;
    588         vm->htotal *= 8;
    589 
    590 	return (0);
    591 }
    592 
    593 
    594 int
    595 et_setvmode(gp, mode)
    596 	struct grf_softc *gp;
    597 	unsigned mode;
    598 {
    599 	if (!mode || (mode > monitor_def_max) ||
    600 	    monitor_def[mode - 1].mode_num == 0)
    601 		return (EINVAL);
    602 
    603 	monitor_current = monitor_def + (mode - 1);
    604 
    605 	return (0);
    606 }
    607 
    608 
    609 #ifndef TSENGCONSOLE
    610 void
    611 et_off(gp)
    612 	struct grf_softc *gp;
    613 {
    614 	char   *ba = gp->g_regkva;
    615 
    616 	/* we'll put the pass-through on for cc ite and set Full Bandwidth bit
    617 	 * on just in case it didn't work...but then it doesn't matter does
    618 	 * it? =) */
    619 	RegOnpass(ba);
    620 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
    621 }
    622 #endif
    623 
    624 
    625 int
    626 et_blank(gp, on)
    627         struct grf_softc *gp;
    628         int *on;
    629 {
    630         WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on ? 0x21 : 0x01);
    631         return(0);
    632 }
    633 
    634 
    635 /*
    636  * Change the mode of the display.
    637  * Return a UNIX error number or 0 for success.
    638  */
    639 int
    640 et_mode(gp, cmd, arg, a2, a3)
    641 	register struct grf_softc *gp;
    642 	u_long cmd;
    643 	void *arg;
    644 	u_long a2;
    645 	int a3;
    646 {
    647 	int     error;
    648 
    649 	switch (cmd) {
    650 	    case GM_GRFON:
    651 		error = et_load_mon(gp,
    652 		    (struct grfettext_mode *) monitor_current) ? 0 : EINVAL;
    653 		return (error);
    654 
    655 	    case GM_GRFOFF:
    656 #ifndef TSENGCONSOLE
    657 		et_off(gp);
    658 #else
    659 		et_load_mon(gp, &etconsole_mode);
    660 #endif
    661 		return (0);
    662 
    663 	    case GM_GRFCONFIG:
    664 		return (0);
    665 
    666 	    case GM_GRFGETVMODE:
    667 		return (et_getvmode(gp, (struct grfvideo_mode *) arg));
    668 
    669 	    case GM_GRFSETVMODE:
    670 		error = et_setvmode(gp, *(unsigned *) arg);
    671 		if (!error && (gp->g_flags & GF_GRFON))
    672 			et_load_mon(gp,
    673 			    (struct grfettext_mode *) monitor_current);
    674 		return (error);
    675 
    676 	    case GM_GRFGETNUMVM:
    677 		*(int *) arg = monitor_def_max;
    678 		return (0);
    679 
    680 	    case GM_GRFIOCTL:
    681 		return (et_ioctl(gp, a2, arg));
    682 
    683 	    default:
    684 		break;
    685 	}
    686 
    687 	return (EINVAL);
    688 }
    689 
    690 int
    691 et_ioctl(gp, cmd, data)
    692 	register struct grf_softc *gp;
    693 	u_long cmd;
    694 	void   *data;
    695 {
    696 	switch (cmd) {
    697 	    case GRFIOCGSPRITEPOS:
    698 		return (et_getmousepos(gp, (struct grf_position *) data));
    699 
    700 	    case GRFIOCSSPRITEPOS:
    701 		return (et_setmousepos(gp, (struct grf_position *) data));
    702 
    703 	    case GRFIOCSSPRITEINF:
    704 		return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data));
    705 
    706 	    case GRFIOCGSPRITEINF:
    707 		return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data));
    708 
    709 	    case GRFIOCGSPRITEMAX:
    710 		return (et_getspritemax(gp, (struct grf_position *) data));
    711 
    712 	    case GRFIOCGETCMAP:
    713 		return (et_getcmap(gp, (struct grf_colormap *) data));
    714 
    715 	    case GRFIOCPUTCMAP:
    716 		return (et_putcmap(gp, (struct grf_colormap *) data));
    717 
    718 	    case GRFIOCBITBLT:
    719 		break;
    720 
    721 	    case GRFTOGGLE:
    722 		return (et_toggle(gp, 0));
    723 
    724 	    case GRFIOCSETMON:
    725 		return (et_setmonitor(gp, (struct grfvideo_mode *) data));
    726 
    727             case GRFIOCBLANK:
    728 		return (et_blank(gp, (int *)data));
    729 	}
    730 	return (EINVAL);
    731 }
    732 
    733 
    734 int
    735 et_getmousepos(gp, data)
    736 	struct grf_softc *gp;
    737 	struct grf_position *data;
    738 {
    739 	data->x = et_cursprite.pos.x;
    740 	data->y = et_cursprite.pos.y;
    741 	return (0);
    742 }
    743 
    744 
    745 void
    746 et_writesprpos(ba, x, y)
    747 	volatile char *ba;
    748 	short   x;
    749 	short   y;
    750 {
    751 }
    752 
    753 
    754 #ifdef notyet
    755 void
    756 et_writeshifted(to, shiftx, shifty)
    757 	unsigned char *to;
    758 	char    shiftx;
    759 	char    shifty;
    760 {
    761 }
    762 #endif
    763 
    764 
    765 int
    766 et_setmousepos(gp, data)
    767 	struct grf_softc *gp;
    768 	struct grf_position *data;
    769 {
    770 	volatile char *ba = gp->g_regkva;
    771 #if 0
    772 	volatile char *fb = gp->g_fbkva;
    773 	volatile char *sprite = fb + (et_fbsize - 1024);
    774 #endif
    775 	short rx, ry, prx, pry;
    776 
    777 	/* no movement */
    778 	if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y)
    779 		return (0);
    780 
    781         /* current and previous real coordinates */
    782 	rx = data->x - et_cursprite.hot.x;
    783 	ry = data->y - et_cursprite.hot.y;
    784 	prx = et_cursprite.pos.x - et_cursprite.hot.x;
    785 	pry = et_cursprite.pos.y - et_cursprite.hot.y;
    786 
    787         /* if we are/were on an edge, create (un)shifted bitmap --
    788          * ripped out optimization (not extremely worthwhile,
    789          * and kind of buggy anyhow).
    790          */
    791 #ifdef notyet
    792         if (rx < 0 || ry < 0 || prx < 0 || pry < 0) {
    793                 et_writeshifted(sprite, rx < 0 ? -rx : 0, ry < 0 ? -ry : 0);
    794         }
    795 #endif
    796 
    797         /* do movement, save position */
    798         et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
    799 	et_cursprite.pos.x = data->x;
    800 	et_cursprite.pos.y = data->y;
    801 
    802 	return (0);
    803 }
    804 
    805 
    806 int
    807 et_getspriteinfo(gp, data)
    808 	struct grf_softc *gp;
    809 	struct grf_spriteinfo *data;
    810 {
    811 
    812 	return(EINVAL);
    813 }
    814 
    815 
    816 static int
    817 et_setspriteinfo(gp, data)
    818 	struct grf_softc *gp;
    819 	struct grf_spriteinfo *data;
    820 {
    821 
    822 	return(EINVAL);
    823 }
    824 
    825 
    826 static int
    827 et_getspritemax(gp, data)
    828 	struct grf_softc *gp;
    829 	struct grf_position *data;
    830 {
    831 
    832 	return(EINVAL);
    833 }
    834 
    835 
    836 int
    837 et_setmonitor(gp, gv)
    838 	struct grf_softc *gp;
    839 	struct grfvideo_mode *gv;
    840 {
    841 	struct grfvideo_mode *md;
    842 
    843         if (!et_mondefok(gv))
    844                 return(EINVAL);
    845 
    846 #ifdef TSENGCONSOLE
    847 	/* handle interactive setting of console mode */
    848 	if (gv->mode_num == 255) {
    849 		bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode));
    850                 etconsole_mode.gv.hblank_start /= 8;
    851                 etconsole_mode.gv.hblank_stop /= 8;
    852                 etconsole_mode.gv.hsync_start /= 8;
    853                 etconsole_mode.gv.hsync_stop /= 8;
    854                 etconsole_mode.gv.htotal /= 8;
    855 		etconsole_mode.rows = gv->disp_height / etconsole_mode.fy;
    856 		etconsole_mode.cols = gv->disp_width / etconsole_mode.fx;
    857 		if (!(gp->g_flags & GF_GRFON))
    858 			et_load_mon(gp, &etconsole_mode);
    859 		ite_reinit(gp->g_itedev);
    860 		return (0);
    861 	}
    862 #endif
    863 
    864 	md = monitor_def + (gv->mode_num - 1);
    865 	bcopy(gv, md, sizeof(struct grfvideo_mode));
    866 
    867         /* adjust pixel oriented values to internal rep. */
    868 
    869         md->hblank_start /= 8;
    870         md->hblank_stop /= 8;
    871         md->hsync_start /= 8;
    872         md->hsync_stop /= 8;
    873         md->htotal /= 8;
    874 
    875 	return (0);
    876 }
    877 
    878 
    879 int
    880 et_getcmap(gfp, cmap)
    881 	struct grf_softc *gfp;
    882 	struct grf_colormap *cmap;
    883 {
    884 	volatile unsigned char *ba;
    885 	u_char  red[256], green[256], blue[256], *rp, *gp, *bp;
    886 	short   x;
    887 	int     error;
    888 
    889 	if (cmap->count == 0 || cmap->index >= 256)
    890 		return 0;
    891 
    892 	if (cmap->index + cmap->count > 256)
    893 		cmap->count = 256 - cmap->index;
    894 
    895 	ba = gfp->g_regkva;
    896 	/* first read colors out of the chip, then copyout to userspace */
    897 	x = cmap->count - 1;
    898 
    899 	rp = red + cmap->index;
    900 	gp = green + cmap->index;
    901 	bp = blue + cmap->index;
    902 
    903 	switch(ettype) {
    904 	    case MERLIN:
    905 		vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
    906 		do {
    907 			*rp++ = vgar(ba, MERLIN_VDAC_COLORS);
    908 			*gp++ = vgar(ba, MERLIN_VDAC_COLORS);
    909 			*bp++ = vgar(ba, MERLIN_VDAC_COLORS);
    910 		} while (x-- > 0);
    911 		break;
    912 	    default:
    913 		vgaw(ba, VDAC_ADDRESS_W, cmap->index);
    914 		do {
    915 			*rp++ = vgar(ba, VDAC_DATA) << etcmap_shift;
    916 			*gp++ = vgar(ba, VDAC_DATA) << etcmap_shift;
    917 			*bp++ = vgar(ba, VDAC_DATA) << etcmap_shift;
    918 		} while (x-- > 0);
    919 		break;
    920 	}
    921 
    922 	if (!(error = copyout(red + cmap->index, cmap->red, cmap->count))
    923 	&& !(error = copyout(green + cmap->index, cmap->green, cmap->count))
    924 	&& !(error = copyout(blue + cmap->index, cmap->blue, cmap->count)))
    925 		return (0);
    926 
    927 	return (error);
    928 }
    929 
    930 
    931 int
    932 et_putcmap(gfp, cmap)
    933 	struct grf_softc *gfp;
    934 	struct grf_colormap *cmap;
    935 {
    936 	volatile unsigned char *ba;
    937 	u_char  red[256], green[256], blue[256], *rp, *gp, *bp;
    938 	short   x;
    939 	int     error;
    940 
    941 	if (cmap->count == 0 || cmap->index >= 256)
    942 		return (0);
    943 
    944 	if (cmap->index + cmap->count > 256)
    945 		cmap->count = 256 - cmap->index;
    946 
    947 	/* first copy the colors into kernelspace */
    948 	if (!(error = copyin(cmap->red, red + cmap->index, cmap->count))
    949 	    && !(error = copyin(cmap->green, green + cmap->index, cmap->count))
    950 	    && !(error = copyin(cmap->blue, blue + cmap->index, cmap->count))) {
    951 		ba = gfp->g_regkva;
    952 		x = cmap->count - 1;
    953 
    954 		rp = red + cmap->index;
    955 		gp = green + cmap->index;
    956 		bp = blue + cmap->index;
    957 
    958 		switch(ettype){
    959 		case MERLIN:
    960 		  vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
    961 		  do {
    962 		    vgaw(ba, MERLIN_VDAC_COLORS, *rp++);
    963 		    vgaw(ba, MERLIN_VDAC_COLORS, *gp++);
    964 		    vgaw(ba, MERLIN_VDAC_COLORS, *bp++);
    965 		  } while (x-- > 0);
    966 		  break;
    967 		default:
    968 		  vgaw(ba, VDAC_ADDRESS_W, cmap->index);
    969 		  do {
    970 		    vgaw(ba, VDAC_DATA, *rp++ >> etcmap_shift);
    971 		    vgaw(ba, VDAC_DATA, *gp++ >> etcmap_shift);
    972 		    vgaw(ba, VDAC_DATA, *bp++ >> etcmap_shift);
    973 		  } while (x-- > 0);
    974 		  break;
    975 		}
    976 
    977 		return (0);
    978 	} else
    979 		return (error);
    980 }
    981 
    982 
    983 int
    984 et_toggle(gp, wopp)
    985 	struct grf_softc *gp;
    986 	unsigned short wopp;	/* don't need that one yet, ill */
    987 {
    988 	volatile unsigned char *ba;
    989 
    990 	ba = gp->g_regkva;
    991 
    992 	if (pass_toggle) {
    993 		RegOffpass(ba);
    994 	} else {
    995 		RegOnpass(ba);
    996 	}
    997 	return (0);
    998 }
    999 
   1000 #define ET_NUMCLOCKS 32
   1001 
   1002 static u_char et_clocks[ET_NUMCLOCKS] = {
   1003 	0, 1, 6, 2, 3, 7, 4, 5,
   1004 	0, 1, 6, 2, 3, 7, 4, 5,
   1005 	0, 1, 6, 2, 3, 7, 4, 5,
   1006 	0, 1, 6, 2, 3, 7, 4, 5
   1007 };
   1008 
   1009 static u_char et_clockdividers[ET_NUMCLOCKS] = {
   1010 	3, 3, 3, 3, 3, 3, 3, 3,
   1011 	2, 2, 2, 2, 2, 2, 2, 2,
   1012 	1, 1, 1, 1, 1, 1, 1, 1,
   1013 	0, 0, 0, 0, 0, 0, 0, 0
   1014 };
   1015 
   1016 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
   1017 	  6293750,  7080500,  7875000,  8125000,
   1018 	  9000000,  9375000, 10000000, 11225000,
   1019 	 12587500, 14161000, 15750000, 16250000,
   1020 	 18000000, 18750000, 20000000, 22450000,
   1021 	 25175000, 28322000, 31500000, 32500000,
   1022 	 36000000, 37500000, 40000000, 44900000,
   1023 	 50350000, 56644000, 63000000, 65000000,
   1024 	 72000000, 75000000, 80000000, 89800000
   1025 };
   1026 
   1027 
   1028 static void
   1029 et_CompFQ(fq, num, denom)
   1030 	u_int   fq;
   1031 	u_char *num;
   1032 	u_char *denom;
   1033 {
   1034 	int i;
   1035 
   1036 	for (i=0; i < ET_NUMCLOCKS;) {
   1037 		if (fq <= et_clockfreqs[i++]) {
   1038 			break;
   1039 		}
   1040 	}
   1041 
   1042 	*num = et_clocks[--i];
   1043 	*denom = et_clockdividers[i];
   1044 
   1045 	return;
   1046 }
   1047 
   1048 
   1049 int
   1050 et_mondefok(gv)
   1051 	struct grfvideo_mode *gv;
   1052 {
   1053 
   1054 	if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
   1055                 if (gv->mode_num != 255 || gv->depth != 4)
   1056                         return(0);
   1057 
   1058 	switch (gv->depth) {
   1059 	    case 4:
   1060                 if (gv->mode_num != 255)
   1061                         return(0);
   1062 	    case 1:
   1063 	    case 8:
   1064 	    case 15:
   1065 	    case 16:
   1066 	    case 24:
   1067                 break;
   1068 	    default:
   1069 		return (0);
   1070 	}
   1071         return (1);
   1072 }
   1073 
   1074 
   1075 int
   1076 et_load_mon(gp, md)
   1077 	struct grf_softc *gp;
   1078 	struct grfettext_mode *md;
   1079 {
   1080 	struct grfvideo_mode *gv;
   1081 	struct grfinfo *gi;
   1082 	volatile unsigned char *ba;
   1083 	unsigned char num0, denom0;
   1084 	unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
   1085 	        VSE, VT;
   1086 	char    LACE, DBLSCAN, TEXT;
   1087 	unsigned char seq;
   1088 	int     uplim, lowlim;
   1089 
   1090 	/* identity */
   1091 	gv = &md->gv;
   1092 	TEXT = (gv->depth == 4);
   1093 
   1094 	if (!et_mondefok(gv)) {
   1095 		printf("mondef not ok\n");
   1096 		return (0);
   1097 	}
   1098 	ba = gp->g_regkva;
   1099 
   1100 	/* provide all needed information in grf device-independant locations */
   1101 	gp->g_data = (caddr_t) gv;
   1102 	gi = &gp->g_display;
   1103 	gi->gd_regaddr = (caddr_t) ztwopa(ba);
   1104 	gi->gd_regsize = 64 * 1024;
   1105 	gi->gd_fbaddr = (caddr_t) kvtop(gp->g_fbkva);
   1106 	gi->gd_fbsize = et_fbsize;
   1107 	gi->gd_colors = 1 << gv->depth;
   1108 	gi->gd_planes = gv->depth;
   1109 	gi->gd_fbwidth = gv->disp_width;
   1110 	gi->gd_fbheight = gv->disp_height;
   1111 	gi->gd_fbx = 0;
   1112 	gi->gd_fby = 0;
   1113 	if (TEXT) {
   1114 		gi->gd_dwidth = md->fx * md->cols;
   1115 		gi->gd_dheight = md->fy * md->rows;
   1116 	} else {
   1117 		gi->gd_dwidth = gv->disp_width;
   1118 		gi->gd_dheight = gv->disp_height;
   1119 	}
   1120 	gi->gd_dx = 0;
   1121 	gi->gd_dy = 0;
   1122 
   1123 	/* get display mode parameters */
   1124 
   1125 	HBS = gv->hblank_start;
   1126 	HBE = gv->hblank_stop;
   1127 	HSS = gv->hsync_start;
   1128 	HSE = gv->hsync_stop;
   1129 	HT  = gv->htotal;
   1130 	VBS = gv->vblank_start;
   1131 	VSS = gv->vsync_start;
   1132 	VSE = gv->vsync_stop;
   1133 	VBE = gv->vblank_stop;
   1134 	VT  = gv->vtotal;
   1135 
   1136 	if (TEXT)
   1137 		HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
   1138 	else
   1139 		HDE = (gv->disp_width + 3) / 8 - 1;	/* HBS; */
   1140 	VDE = gv->disp_height - 1;
   1141 
   1142 	/* figure out whether lace or dblscan is needed */
   1143 
   1144 	uplim = gv->disp_height + (gv->disp_height / 4);
   1145 	lowlim = gv->disp_height - (gv->disp_height / 4);
   1146 	LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
   1147 	DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
   1148 
   1149 	/* adjustments */
   1150 
   1151 	if (LACE)
   1152 		VDE /= 2;
   1153 
   1154 	WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
   1155 
   1156 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
   1157 	WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
   1158 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
   1159 
   1160 	/* Set clock */
   1161 
   1162 	et_CompFQ( gv->pixel_clock, &num0, &denom0);
   1163 
   1164 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2));
   1165 	WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08);
   1166 	seq=RSeq(ba, SEQ_ID_CLOCKING_MODE);
   1167 	switch(denom0) {
   1168 	    case 0:
   1169 		WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4);
   1170 		WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
   1171  		break;
   1172 	    case 1:
   1173 		WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
   1174 		WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
   1175 		break;
   1176 	    case 2:
   1177 		WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
   1178 		WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
   1179 		break;
   1180 	    case 3:
   1181 		WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
   1182 		WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08);
   1183 		break;
   1184 	}
   1185 	/* load display parameters into board */
   1186 
   1187 	WCrt(ba, CRT_ID_HOR_TOTAL, HT);
   1188 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
   1189 	WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
   1190 	WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80);	/* | 0x80? */
   1191 	WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
   1192 	WCrt(ba, CRT_ID_END_HOR_RETR,
   1193 	    (HSE & 0x1f) |
   1194 	    ((HBE & 0x20) ? 0x80 : 0x00));
   1195 	WCrt(ba, CRT_ID_VER_TOTAL, VT);
   1196 	WCrt(ba, CRT_ID_OVERFLOW,
   1197 	    0x10 |
   1198 	    ((VT  & 0x100) ? 0x01 : 0x00) |
   1199 	    ((VDE & 0x100) ? 0x02 : 0x00) |
   1200 	    ((VSS & 0x100) ? 0x04 : 0x00) |
   1201 	    ((VBS & 0x100) ? 0x08 : 0x00) |
   1202 	    ((VT  & 0x200) ? 0x20 : 0x00) |
   1203 	    ((VDE & 0x200) ? 0x40 : 0x00) |
   1204 	    ((VSS & 0x200) ? 0x80 : 0x00));
   1205 
   1206 	WCrt(ba, CRT_ID_MAX_ROW_ADDRESS,
   1207 	    0x40 |		/* TEXT ? 0x00 ??? */
   1208 	    (DBLSCAN ? 0x80 : 0x00) |
   1209 	    ((VBS & 0x200) ? 0x20 : 0x00) |
   1210 	    (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
   1211 
   1212 	WCrt(ba, CRT_ID_MODE_CONTROL,
   1213 	    ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab));
   1214 
   1215 	/* text cursor */
   1216 
   1217 	if (TEXT) {
   1218 #if ET_ULCURSOR
   1219 		WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
   1220 		WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
   1221 #else
   1222 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
   1223 		WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
   1224 #endif
   1225 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
   1226 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
   1227 	}
   1228 
   1229 	WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f)
   1230 		| ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60));
   1231 
   1232 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
   1233 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
   1234 
   1235 	WCrt(ba, CRT_ID_START_VER_RETR, VSS);
   1236 	WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
   1237 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
   1238 	WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
   1239 	WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
   1240 
   1241 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
   1242 
   1243 	WCrt(ba, CRT_ID_OVERFLOW_HIGH,
   1244 		((VBS & 0x400) ? 0x01 : 0x00) |
   1245 		((VT  & 0x400) ? 0x02 : 0x00) |
   1246 		((VDE & 0x400) ? 0x04 : 0x00) |
   1247 		((VSS & 0x400) ? 0x08 : 0x00) |
   1248 		0x10 |
   1249 		(LACE ? 0x80 : 0x00));
   1250 
   1251         WCrt(ba, CRT_ID_HOR_OVERFLOW,
   1252                 ((HT  & 0x100) ? 0x01 : 0x00) |
   1253                 ((HBS & 0x100) ? 0x04 : 0x00) |
   1254                 ((HSS & 0x100) ? 0x10 : 0x00)
   1255         );
   1256 
   1257 	/* depth dependent stuff */
   1258 
   1259 	WGfx(ba, GCT_ID_GRAPHICS_MODE,
   1260 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
   1261 	WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
   1262 
   1263 	vgaw(ba, VDAC_MASK, 0xff);
   1264 	vgar(ba, VDAC_MASK);
   1265 	vgar(ba, VDAC_MASK);
   1266 	vgar(ba, VDAC_MASK);
   1267 	vgar(ba, VDAC_MASK);
   1268 	switch (gv->depth) {
   1269 	    case 1:
   1270 	    case 4:	/* text */
   1271 		switch(etdtype) {
   1272 		    case SIERRA11483:
   1273 		    case SIERRA15025:
   1274 		    case MUSICDAC:
   1275 			vgaw(ba, VDAC_MASK, 0);
   1276 			break;
   1277 		    case MERLINDAC:
   1278 			setMerlinDACmode(ba, 0);
   1279 			break;
   1280 		}
   1281 		HDE = gv->disp_width / 16;
   1282 		break;
   1283 	    case 8:
   1284 		switch(etdtype) {
   1285 		    case SIERRA11483:
   1286 		    case SIERRA15025:
   1287 		    case MUSICDAC:
   1288 			vgaw(ba, VDAC_MASK, 0);
   1289 			break;
   1290 		    case MERLINDAC:
   1291 			setMerlinDACmode(ba, 0);
   1292 			break;
   1293 		}
   1294 		HDE = gv->disp_width / 8;
   1295 		break;
   1296 	    case 15:
   1297 		switch(etdtype) {
   1298 		    case SIERRA11483:
   1299 		    case SIERRA15025:
   1300 		    case MUSICDAC:
   1301 			vgaw(ba, VDAC_MASK, 0xa0);
   1302 			break;
   1303 		    case MERLINDAC:
   1304 			setMerlinDACmode(ba, 0xa0);
   1305 			break;
   1306 		}
   1307 		HDE = gv->disp_width / 4;
   1308 		break;
   1309 	    case 16:
   1310 		switch(etdtype) {
   1311 		    case SIERRA11483:
   1312 			vgaw(ba, VDAC_MASK, 0);	/* illegal mode! */
   1313 			break;
   1314 		    case SIERRA15025:
   1315 			vgaw(ba, VDAC_MASK, 0xe0);
   1316 			break;
   1317 		    case MUSICDAC:
   1318 			vgaw(ba, VDAC_MASK, 0xc0);
   1319 			break;
   1320 		    case MERLINDAC:
   1321 			setMerlinDACmode(ba, 0xe0);
   1322 			break;
   1323 		}
   1324 		HDE = gv->disp_width / 4;
   1325 		break;
   1326 	    case 24:
   1327 		switch(etdtype) {
   1328 		    case SIERRA11483:
   1329 			vgaw(ba, VDAC_MASK, 0);	/* illegal mode! */
   1330 			break;
   1331 		    case SIERRA15025:
   1332 			vgaw(ba, VDAC_MASK, 0xe1);
   1333 			break;
   1334 		    case MUSICDAC:
   1335 			vgaw(ba, VDAC_MASK, 0xe0);
   1336 			break;
   1337 		    case MERLINDAC:
   1338 			setMerlinDACmode(ba, 0xf0);
   1339 			break;
   1340 		}
   1341 		HDE = (gv->disp_width / 8) * 3;
   1342 		break;
   1343 	    case 32:
   1344 		switch(etdtype) {
   1345 		    case SIERRA11483:
   1346 		    case MUSICDAC:
   1347 			vgaw(ba, VDAC_MASK, 0);	/* illegal mode! */
   1348 			break;
   1349 		    case SIERRA15025:
   1350 			vgaw(ba, VDAC_MASK, 0x61);
   1351 			break;
   1352 		    case MERLINDAC:
   1353 			setMerlinDACmode(ba, 0xb0);
   1354 			break;
   1355 		}
   1356 		HDE = gv->disp_width / 2;
   1357 		break;
   1358 	}
   1359 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
   1360 	WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
   1361 	    (gv->depth == 1) ? 0x01 : 0x0f);
   1362 
   1363 	WCrt(ba, CRT_ID_OFFSET, HDE);
   1364 
   1365 	/* text initialization */
   1366 	if (TEXT) {
   1367 		et_inittextmode(gp);
   1368 	}
   1369 
   1370 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
   1371 
   1372 	/* Pass-through */
   1373 	RegOffpass(ba);
   1374 
   1375 	return (1);
   1376 }
   1377 
   1378 
   1379 void
   1380 et_inittextmode(gp)
   1381 	struct grf_softc *gp;
   1382 {
   1383 	struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data;
   1384 	volatile unsigned char *ba = gp->g_regkva;
   1385 	unsigned char *fb = gp->g_fbkva;
   1386 	unsigned char *c, *f, y;
   1387 	unsigned short z;
   1388 
   1389 
   1390 	/* load text font into beginning of display memory. Each character
   1391 	 * cell is 32 bytes long (enough for 4 planes) */
   1392 
   1393 	SetTextPlane(ba, 0x02);
   1394         et_memset(fb, 0, 256 * 32);
   1395 	c = (unsigned char *) (fb) + (32 * tm->fdstart);
   1396 	f = tm->fdata;
   1397 	for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
   1398 		for (y = 0; y < tm->fy; y++)
   1399 			*c++ = *f++;
   1400 
   1401 	/* clear out text/attr planes (three screens worth) */
   1402 
   1403 	SetTextPlane(ba, 0x01);
   1404 	et_memset(fb, 0x07, tm->cols * tm->rows * 3);
   1405 	SetTextPlane(ba, 0x00);
   1406 	et_memset(fb, 0x20, tm->cols * tm->rows * 3);
   1407 
   1408 	/* print out a little init msg */
   1409 
   1410 	c = (unsigned char *) (fb) + (tm->cols - 16);
   1411 	strcpy(c, "TSENG");
   1412 	c[6] = 0x20;
   1413 
   1414 	/* set colors (B&W) */
   1415 
   1416 	switch(ettype) {
   1417 	    case MERLIN:
   1418 		vgaw(ba, MERLIN_VDAC_INDEX, 0);
   1419 		for (z = 0; z < 256; z++) {
   1420 			y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
   1421 
   1422 			vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]);
   1423 			vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]);
   1424 			vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]);
   1425 		}
   1426 		break;
   1427 	    default:
   1428 		vgaw(ba, VDAC_ADDRESS_W, 0);
   1429 		for (z = 0; z < 256; z++) {
   1430 			y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
   1431 
   1432 			vgaw(ba, VDAC_DATA, etconscolors[y][0] >> etcmap_shift);
   1433 			vgaw(ba, VDAC_DATA, etconscolors[y][1] >> etcmap_shift);
   1434 			vgaw(ba, VDAC_DATA, etconscolors[y][2] >> etcmap_shift);
   1435 		}
   1436 		break;
   1437 	}
   1438 }
   1439 
   1440 
   1441 void
   1442 et_memset(d, c, l)
   1443 	unsigned char *d;
   1444 	unsigned char c;
   1445 	int     l;
   1446 {
   1447 	for (; l > 0; l--)
   1448 		*d++ = c;
   1449 }
   1450 
   1451 
   1452 static int
   1453 et_getControllerType(gp)
   1454 	struct grf_softc * gp;
   1455 {
   1456 	unsigned char *ba = gp->g_regkva; /* register base */
   1457 	unsigned char *mem = gp->g_fbkva; /* memory base */
   1458 	unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */
   1459 
   1460 	*mem = 0;
   1461 
   1462 	/* make ACL visible */
   1463 	WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb);
   1464 	WIma(ba, IMA_PORTCONTROL, 0x01);
   1465 
   1466 	*((unsigned long *)mmu) = 0;
   1467 	*(mem + 0x13) = 0x38;
   1468 
   1469 	*mmu = 0xff;
   1470 
   1471 	/* hide ACL */
   1472 	WIma(ba, IMA_PORTCONTROL, 0x00);
   1473 	WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
   1474 
   1475 	return((*mem == 0xff) ? ETW32 : ET4000);
   1476 }
   1477 
   1478 
   1479 static int
   1480 et_getDACType(gp)
   1481 	struct grf_softc * gp;
   1482 {
   1483 	unsigned char *ba = gp->g_regkva;
   1484 	union {
   1485 		int  tt;
   1486 		char cc[4];
   1487 	} check;
   1488 
   1489 	/* check for Sierra SC 15025 */
   1490 
   1491   if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
   1492   vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
   1493 
   1494   vgaw(ba, VDAC_XINDEX, 9);
   1495   check.cc[0]=vgar(ba, VDAC_XDATA);
   1496   vgaw(ba, VDAC_XINDEX, 10);
   1497   check.cc[1]=vgar(ba, VDAC_XDATA);
   1498   vgaw(ba, VDAC_XINDEX, 11);
   1499   check.cc[2]=vgar(ba, VDAC_XDATA);
   1500   vgaw(ba, VDAC_XINDEX, 12);
   1501   check.cc[3]=vgar(ba, VDAC_XDATA);
   1502 
   1503   if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
   1504   vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
   1505 
   1506   if(check.tt == 0x533ab141){
   1507     if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
   1508     vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
   1509 
   1510     /* switch to 8 bits per color */
   1511     vgaw(ba, VDAC_XINDEX, 8);
   1512     vgaw(ba, VDAC_XDATA, 1);
   1513     /* do not shift color values */
   1514     etcmap_shift = 0;
   1515 
   1516     if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
   1517     vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
   1518 
   1519     vgaw(ba, VDAC_MASK, 0xff);
   1520     return(SIERRA15025);
   1521   }
   1522 
   1523   /* check for MUSIC DAC */
   1524 
   1525   if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
   1526   vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */
   1527 
   1528   vgaw(ba, VDAC_XINDEX, 0x01);
   1529   if(vgar(ba, VDAC_XDATA) == 0x01){
   1530     /* shift color values by 2 */
   1531     etcmap_shift = 2;
   1532 
   1533     vgaw(ba, VDAC_MASK, 0xff);
   1534     return(MUSICDAC);
   1535   }
   1536 
   1537 	/* nothing else found, so let us pretend it is a stupid Sierra SC 11483 */
   1538 	/* shift color values by 2 */
   1539 	etcmap_shift = 2;
   1540 
   1541 	vgaw(ba, VDAC_MASK, 0xff);
   1542 	return(SIERRA11483);
   1543 }
   1544 
   1545 #endif /* NGRFET */
   1546