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