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