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