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