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