Home | History | Annotate | Line # | Download | only in dev
grf_et.c revision 1.7
      1 /*	$NetBSD: grf_et.c,v 1.7 1996/10/13 03:07:04 christos 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 *, const char *));
    104 void	et_memset __P((unsigned char *d, unsigned char c, int l));
    105 
    106 /*
    107  * Graphics display definitions.
    108  * These are filled by 'grfconfig' using GRFIOCSETMON.
    109  */
    110 #define monitor_def_max 8
    111 static struct grfvideo_mode monitor_def[8] = {
    112 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
    113 };
    114 static struct grfvideo_mode *monitor_current = &monitor_def[0];
    115 
    116 /* Console display definition.
    117  *   Default hardcoded text mode.  This grf_et is set up to
    118  *   use one text mode only, and this is it.  You may use
    119  *   grfconfig to change the mode after boot.
    120  */
    121 /* Console font */
    122 #ifdef KFONT_8X11
    123 #define TSENGFONT kernel_font_8x11
    124 #define TSENGFONTY 11
    125 #else
    126 #define TSENGFONT kernel_font_8x8
    127 #define TSENGFONTY 8
    128 #endif
    129 extern unsigned char TSENGFONT[];
    130 
    131 struct grfettext_mode etconsole_mode = {
    132 	{255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8,
    133 	 481, 521, 491, 493, 525},
    134 	8, TSENGFONTY, 640 / 8, 480 / TSENGFONTY, TSENGFONT, 32, 255
    135 };
    136 
    137 /* Console colors */
    138 unsigned char etconscolors[3][3] = {	/* background, foreground, hilite */
    139 	{0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
    140 };
    141 
    142 int ettype = 0;		/* oMniBus, Domino or Merlin */
    143 int etctype = 0;	/* ET4000 or ETW32 */
    144 int etdtype = 0;	/* Type of DAC (see grf_etregs.h) */
    145 
    146 char etcmap_shift = 0;	/* 6 or 8 bit cmap entries */
    147 unsigned char pass_toggle;	/* passthru status tracker */
    148 
    149 unsigned char Merlin_switch = 0;
    150 
    151 /*
    152  * Because all Tseng-boards have 2 configdev entries, one for
    153  * framebuffer mem and the other for regs, we have to hold onto
    154  * the pointers globally until we match on both.  This and 'ettype'
    155  * are the primary obsticles to multiple board support, but if you
    156  * have multiple boards you have bigger problems than grf_et.
    157  */
    158 static void *et_fbaddr = 0;	/* framebuffer */
    159 static void *et_regaddr = 0;	/* registers */
    160 static int et_fbsize;		/* framebuffer size */
    161 
    162 /* current sprite info, if you add support for multiple boards
    163  * make this an array or something
    164  */
    165 struct grf_spriteinfo et_cursprite;
    166 
    167 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if
    168  * you add multiple board support
    169  */
    170 static unsigned char et_imageptr[8 * 64], et_maskptr[8 * 64];
    171 static unsigned char et_sprred[2], et_sprgreen[2], et_sprblue[2];
    172 
    173 /* standard driver stuff */
    174 struct cfattach grfet_ca = {
    175 	sizeof(struct grf_softc), grfetmatch, grfetattach
    176 };
    177 
    178 struct cfdriver grfet_cd = {
    179 	NULL, "grfet", DV_DULL, NULL, 0
    180 };
    181 
    182 static struct cfdata *cfdata;
    183 
    184 int
    185 grfetmatch(pdp, 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 	const 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 > 0 ? 0x01 : 0x21);
    603         return(0);
    604 }
    605 
    606 
    607 /*
    608  * Change the mode of the display.
    609  * Return a UNIX error number or 0 for success.
    610  */
    611 int
    612 et_mode(gp, cmd, arg, a2, a3)
    613 	register struct grf_softc *gp;
    614 	u_long cmd;
    615 	void *arg;
    616 	u_long a2;
    617 	int a3;
    618 {
    619 	int error;
    620 
    621 	switch (cmd) {
    622 	    case GM_GRFON:
    623 		error = et_load_mon(gp,
    624 		    (struct grfettext_mode *) monitor_current) ? 0 : EINVAL;
    625 		return (error);
    626 
    627 	    case GM_GRFOFF:
    628 #ifndef TSENGCONSOLE
    629 		et_off(gp);
    630 #else
    631 		et_load_mon(gp, &etconsole_mode);
    632 #endif
    633 		return (0);
    634 
    635 	    case GM_GRFCONFIG:
    636 		return (0);
    637 
    638 	    case GM_GRFGETVMODE:
    639 		return (et_getvmode(gp, (struct grfvideo_mode *) arg));
    640 
    641 	    case GM_GRFSETVMODE:
    642 		error = et_setvmode(gp, *(unsigned *) arg);
    643 		if (!error && (gp->g_flags & GF_GRFON))
    644 			et_load_mon(gp,
    645 			    (struct grfettext_mode *) monitor_current);
    646 		return (error);
    647 
    648 	    case GM_GRFGETNUMVM:
    649 		*(int *) arg = monitor_def_max;
    650 		return (0);
    651 
    652 	    case GM_GRFIOCTL:
    653 		return (et_ioctl(gp, a2, arg));
    654 
    655 	    default:
    656 		break;
    657 	}
    658 
    659 	return (EINVAL);
    660 }
    661 
    662 
    663 int
    664 et_ioctl(gp, cmd, data)
    665 	register struct grf_softc *gp;
    666 	u_long cmd;
    667 	void   *data;
    668 {
    669 	switch (cmd) {
    670 	    case GRFIOCGSPRITEPOS:
    671 		return (et_getmousepos(gp, (struct grf_position *) data));
    672 
    673 	    case GRFIOCSSPRITEPOS:
    674 		return (et_setmousepos(gp, (struct grf_position *) data));
    675 
    676 	    case GRFIOCSSPRITEINF:
    677 		return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data));
    678 
    679 	    case GRFIOCGSPRITEINF:
    680 		return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data));
    681 
    682 	    case GRFIOCGSPRITEMAX:
    683 		return (et_getspritemax(gp, (struct grf_position *) data));
    684 
    685 	    case GRFIOCGETCMAP:
    686 		return (et_getcmap(gp, (struct grf_colormap *) data));
    687 
    688 	    case GRFIOCPUTCMAP:
    689 		return (et_putcmap(gp, (struct grf_colormap *) data));
    690 
    691 	    case GRFIOCBITBLT:
    692 		break;
    693 
    694 	    case GRFTOGGLE:
    695 		return (et_toggle(gp, 0));
    696 
    697 	    case GRFIOCSETMON:
    698 		return (et_setmonitor(gp, (struct grfvideo_mode *) data));
    699 
    700 	    case GRFIOCBLANK:
    701 		return (et_blank(gp, (int *)data));
    702 	}
    703 	return (EINVAL);
    704 }
    705 
    706 
    707 int
    708 et_getmousepos(gp, data)
    709 	struct grf_softc *gp;
    710 	struct grf_position *data;
    711 {
    712 	data->x = et_cursprite.pos.x;
    713 	data->y = et_cursprite.pos.y;
    714 
    715 	return (0);
    716 }
    717 
    718 
    719 void
    720 et_writesprpos(ba, x, y)
    721 	volatile char *ba;
    722 	short   x;
    723 	short   y;
    724 {
    725 }
    726 
    727 
    728 int
    729 et_setmousepos(gp, data)
    730 	struct grf_softc *gp;
    731 	struct grf_position *data;
    732 {
    733 	volatile char *ba = gp->g_regkva;
    734 	short rx, ry, prx, pry;
    735 
    736 	/* no movement */
    737 	if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y)
    738 		return (0);
    739 
    740 	/* current and previous real coordinates */
    741 	rx = data->x - et_cursprite.hot.x;
    742 	ry = data->y - et_cursprite.hot.y;
    743 	prx = et_cursprite.pos.x - et_cursprite.hot.x;
    744 	pry = et_cursprite.pos.y - et_cursprite.hot.y;
    745 
    746 	/* if we are/were on an edge, create (un)shifted bitmap --
    747 	 * ripped out optimization (not extremely worthwhile,
    748 	 * and kind of buggy anyhow).
    749 	 */
    750 
    751 	/* do movement, save position */
    752 	et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
    753 	et_cursprite.pos.x = data->x;
    754 	et_cursprite.pos.y = data->y;
    755 
    756 	return (0);
    757 }
    758 
    759 
    760 int
    761 et_getspriteinfo(gp, data)
    762 	struct grf_softc *gp;
    763 	struct grf_spriteinfo *data;
    764 {
    765 
    766 	return(EINVAL);
    767 }
    768 
    769 
    770 static int
    771 et_setspriteinfo(gp, data)
    772 	struct grf_softc *gp;
    773 	struct grf_spriteinfo *data;
    774 {
    775 
    776 	return(EINVAL);
    777 }
    778 
    779 
    780 static int
    781 et_getspritemax(gp, data)
    782 	struct grf_softc *gp;
    783 	struct grf_position *data;
    784 {
    785 
    786 	return(EINVAL);
    787 }
    788 
    789 
    790 int
    791 et_setmonitor(gp, gv)
    792 	struct grf_softc *gp;
    793 	struct grfvideo_mode *gv;
    794 {
    795 	struct grfvideo_mode *md;
    796 
    797 	if (!et_mondefok(gv))
    798 		return(EINVAL);
    799 
    800 #ifdef TSENGCONSOLE
    801 	/* handle interactive setting of console mode */
    802 	if (gv->mode_num == 255) {
    803 		bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode));
    804 		etconsole_mode.gv.hblank_start /= 8;
    805 		etconsole_mode.gv.hblank_stop /= 8;
    806 		etconsole_mode.gv.hsync_start /= 8;
    807 		etconsole_mode.gv.hsync_stop /= 8;
    808 		etconsole_mode.gv.htotal /= 8;
    809 		etconsole_mode.rows = gv->disp_height / etconsole_mode.fy;
    810 		etconsole_mode.cols = gv->disp_width / etconsole_mode.fx;
    811 		if (!(gp->g_flags & GF_GRFON))
    812 			et_load_mon(gp, &etconsole_mode);
    813 		ite_reinit(gp->g_itedev);
    814 		return (0);
    815 	}
    816 #endif
    817 
    818 	md = monitor_def + (gv->mode_num - 1);
    819 	bcopy(gv, md, sizeof(struct grfvideo_mode));
    820 
    821 	/* adjust pixel oriented values to internal rep. */
    822 
    823 	md->hblank_start /= 8;
    824 	md->hblank_stop /= 8;
    825 	md->hsync_start /= 8;
    826 	md->hsync_stop /= 8;
    827 	md->htotal /= 8;
    828 
    829 	return (0);
    830 }
    831 
    832 
    833 int
    834 et_getcmap(gfp, cmap)
    835 	struct grf_softc *gfp;
    836 	struct grf_colormap *cmap;
    837 {
    838 	volatile unsigned char *ba;
    839 	u_char	red[256], green[256], blue[256], *rp, *gp, *bp;
    840 	short	x;
    841 	int	error;
    842 
    843 	if (cmap->count == 0 || cmap->index >= 256)
    844 		return 0;
    845 
    846 	if (cmap->index + cmap->count > 256)
    847 		cmap->count = 256 - cmap->index;
    848 
    849 	ba = gfp->g_regkva;
    850 	/* first read colors out of the chip, then copyout to userspace */
    851 	x = cmap->count - 1;
    852 
    853 	rp = red + cmap->index;
    854 	gp = green + cmap->index;
    855 	bp = blue + cmap->index;
    856 
    857 	switch(ettype) {
    858 	    case MERLIN:
    859 		vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
    860 		do {
    861 			*rp++ = vgar(ba, MERLIN_VDAC_COLORS);
    862 			*gp++ = vgar(ba, MERLIN_VDAC_COLORS);
    863 			*bp++ = vgar(ba, MERLIN_VDAC_COLORS);
    864 		} while (x-- > 0);
    865 		break;
    866 	    default:
    867 		vgaw(ba, VDAC_ADDRESS_R+((ettype==DOMINO)?0x0fff:0), cmap->index);
    868 		do {
    869 			*rp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
    870 			*gp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
    871 			*bp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
    872 		} while (x-- > 0);
    873 		break;
    874 	}
    875 
    876 	error = copyout(red + cmap->index, cmap->red, cmap->count);
    877 	if (!error)
    878 		error = copyout(green + cmap->index, cmap->green, cmap->count);
    879 	if (!error)
    880 		error = copyout(blue + cmap->index, cmap->blue, cmap->count);
    881 
    882 	return (error);
    883 }
    884 
    885 
    886 int
    887 et_putcmap(gfp, cmap)
    888 	struct grf_softc *gfp;
    889 	struct grf_colormap *cmap;
    890 {
    891 	volatile unsigned char *ba;
    892 	u_char	red[256], green[256], blue[256], *rp, *gp, *bp;
    893 	short	x;
    894 	int	error;
    895 
    896 	if (cmap->count == 0 || cmap->index >= 256)
    897 		return (0);
    898 
    899 	if (cmap->index + cmap->count > 256)
    900 		cmap->count = 256 - cmap->index;
    901 
    902 	/* first copy the colors into kernelspace */
    903 	if ((error = copyin(cmap->red, red + cmap->index, cmap->count)))
    904 		return (error);
    905 
    906 	if ((error = copyin(cmap->green, green + cmap->index, cmap->count)))
    907 		return (error);
    908 
    909 	if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count)))
    910 		return (error);
    911 
    912 	ba = gfp->g_regkva;
    913 	x = cmap->count - 1;
    914 
    915 	rp = red + cmap->index;
    916 	gp = green + cmap->index;
    917 	bp = blue + cmap->index;
    918 
    919 	switch(ettype){
    920 	    case MERLIN:
    921 		vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
    922 		do {
    923 			vgaw(ba, MERLIN_VDAC_COLORS, *rp++);
    924 			vgaw(ba, MERLIN_VDAC_COLORS, *gp++);
    925 			vgaw(ba, MERLIN_VDAC_COLORS, *bp++);
    926 		} while (x-- > 0);
    927 		break;
    928 	    default:
    929 		vgaw(ba, VDAC_ADDRESS_W, cmap->index);
    930 		do {
    931 			vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
    932 			    *rp++ >> etcmap_shift);
    933 			vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
    934 			    *gp++ >> etcmap_shift);
    935 			vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
    936 			    *bp++ >> etcmap_shift);
    937 		} while (x-- > 0);
    938 		break;
    939 	}
    940 
    941 	return (0);
    942 }
    943 
    944 
    945 int
    946 et_toggle(gp, wopp)
    947 	struct grf_softc *gp;
    948 	unsigned short wopp;	/* don't need that one yet, ill */
    949 {
    950 	volatile unsigned char *ba;
    951 
    952 	ba = gp->g_regkva;
    953 
    954 	if (pass_toggle) {
    955 		RegOffpass(ba);
    956 	} else {
    957 		RegOnpass(ba);
    958 	}
    959 	return (0);
    960 }
    961 
    962 
    963 #define ET_NUMCLOCKS 32
    964 
    965 static u_char et_clocks[ET_NUMCLOCKS] = {
    966 	0, 1, 6, 2, 3, 7, 4, 5,
    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 };
    971 
    972 static u_char et_clockdividers[ET_NUMCLOCKS] = {
    973 	3, 3, 3, 3, 3, 3, 3, 3,
    974 	2, 2, 2, 2, 2, 2, 2, 2,
    975 	1, 1, 1, 1, 1, 1, 1, 1,
    976 	0, 0, 0, 0, 0, 0, 0, 0
    977 };
    978 
    979 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
    980 	 6293750,  7080500,  7875000,  8125000,
    981 	 9000000,  9375000, 10000000, 11225000,
    982 	12587500, 14161000, 15750000, 16250000,
    983 	18000000, 18750000, 20000000, 22450000,
    984 	25175000, 28322000, 31500000, 32500000,
    985 	36000000, 37500000, 40000000, 44900000,
    986 	50350000, 56644000, 63000000, 65000000,
    987 	72000000, 75000000, 80000000, 89800000
    988 };
    989 
    990 
    991 static void
    992 et_CompFQ(fq, num, denom)
    993 	u_int   fq;
    994 	u_char *num;
    995 	u_char *denom;
    996 {
    997 	int i;
    998 
    999 	for (i=0; i < ET_NUMCLOCKS;) {
   1000 		if (fq <= et_clockfreqs[i++]) {
   1001 			break;
   1002 		}
   1003 	}
   1004 
   1005 	*num = et_clocks[--i];
   1006 	*denom = et_clockdividers[i];
   1007 
   1008 	return;
   1009 }
   1010 
   1011 
   1012 int
   1013 et_mondefok(gv)
   1014 	struct grfvideo_mode *gv;
   1015 {
   1016 
   1017 	if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
   1018 		if (gv->mode_num != 255 || gv->depth != 4)
   1019 			return(0);
   1020 
   1021 	switch (gv->depth) {
   1022 	    case 4:
   1023 		if (gv->mode_num != 255)
   1024 			return(0);
   1025 	    case 1:
   1026 	    case 8:
   1027 	    case 15:
   1028 	    case 16:
   1029 	    case 24:
   1030 		break;
   1031 	    default:
   1032 		return (0);
   1033 	}
   1034 	return (1);
   1035 }
   1036 
   1037 
   1038 int
   1039 et_load_mon(gp, md)
   1040 	struct grf_softc *gp;
   1041 	struct grfettext_mode *md;
   1042 {
   1043 	struct grfvideo_mode *gv;
   1044 	struct grfinfo *gi;
   1045 	volatile unsigned char *ba;
   1046 	unsigned char num0, denom0;
   1047 	unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
   1048 	        VSE, VT;
   1049 	char    LACE, DBLSCAN, TEXT;
   1050 	unsigned char seq;
   1051 	int     uplim, lowlim;
   1052 
   1053 	/* identity */
   1054 	gv = &md->gv;
   1055 	TEXT = (gv->depth == 4);
   1056 
   1057 	if (!et_mondefok(gv)) {
   1058 		printf("mondef not ok\n");
   1059 		return (0);
   1060 	}
   1061 	ba = gp->g_regkva;
   1062 
   1063 	/* provide all needed information in grf device-independant locations */
   1064 	gp->g_data = (caddr_t) gv;
   1065 	gi = &gp->g_display;
   1066 	gi->gd_regaddr = (caddr_t) ztwopa(ba);
   1067 	gi->gd_regsize = 64 * 1024;
   1068 	gi->gd_fbaddr = (caddr_t) kvtop(gp->g_fbkva);
   1069 	gi->gd_fbsize = et_fbsize;
   1070 	gi->gd_colors = 1 << gv->depth;
   1071 	gi->gd_planes = gv->depth;
   1072 	gi->gd_fbwidth = gv->disp_width;
   1073 	gi->gd_fbheight = gv->disp_height;
   1074 	gi->gd_fbx = 0;
   1075 	gi->gd_fby = 0;
   1076 	if (TEXT) {
   1077 		gi->gd_dwidth = md->fx * md->cols;
   1078 		gi->gd_dheight = md->fy * md->rows;
   1079 	} else {
   1080 		gi->gd_dwidth = gv->disp_width;
   1081 		gi->gd_dheight = gv->disp_height;
   1082 	}
   1083 	gi->gd_dx = 0;
   1084 	gi->gd_dy = 0;
   1085 
   1086 	/* get display mode parameters */
   1087 
   1088 	HBS = gv->hblank_start;
   1089 	HBE = gv->hblank_stop;
   1090 	HSS = gv->hsync_start;
   1091 	HSE = gv->hsync_stop;
   1092 	HT  = gv->htotal;
   1093 	VBS = gv->vblank_start;
   1094 	VSS = gv->vsync_start;
   1095 	VSE = gv->vsync_stop;
   1096 	VBE = gv->vblank_stop;
   1097 	VT  = gv->vtotal;
   1098 
   1099 	if (TEXT)
   1100 		HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
   1101 	else
   1102 		HDE = (gv->disp_width + 3) / 8 - 1;	/* HBS; */
   1103 	VDE = gv->disp_height - 1;
   1104 
   1105 	/* figure out whether lace or dblscan is needed */
   1106 
   1107 	uplim = gv->disp_height + (gv->disp_height / 4);
   1108 	lowlim = gv->disp_height - (gv->disp_height / 4);
   1109 	LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
   1110 	DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
   1111 
   1112 	/* adjustments */
   1113 
   1114 	if (LACE)
   1115 		VDE /= 2;
   1116 
   1117 	WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
   1118 
   1119 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
   1120 	WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
   1121 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
   1122 
   1123 	/* Set clock */
   1124 
   1125 	et_CompFQ( gv->pixel_clock, &num0, &denom0);
   1126 
   1127 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2));
   1128 	WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08);
   1129 	seq=RSeq(ba, SEQ_ID_CLOCKING_MODE);
   1130 	switch(denom0) {
   1131 	    case 0:
   1132 		WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4);
   1133 		WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
   1134  		break;
   1135 	    case 1:
   1136 		WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
   1137 		WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
   1138 		break;
   1139 	    case 2:
   1140 		WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
   1141 		WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
   1142 		break;
   1143 	    case 3:
   1144 		WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
   1145 		WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08);
   1146 		break;
   1147 	}
   1148 	/* load display parameters into board */
   1149 
   1150 	WCrt(ba, CRT_ID_HOR_TOTAL, HT);
   1151 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
   1152 	WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
   1153 	WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80);	/* | 0x80? */
   1154 	WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
   1155 	WCrt(ba, CRT_ID_END_HOR_RETR,
   1156 	    (HSE & 0x1f) |
   1157 	    ((HBE & 0x20) ? 0x80 : 0x00));
   1158 	WCrt(ba, CRT_ID_VER_TOTAL, VT);
   1159 	WCrt(ba, CRT_ID_OVERFLOW,
   1160 	    0x10 |
   1161 	    ((VT  & 0x100) ? 0x01 : 0x00) |
   1162 	    ((VDE & 0x100) ? 0x02 : 0x00) |
   1163 	    ((VSS & 0x100) ? 0x04 : 0x00) |
   1164 	    ((VBS & 0x100) ? 0x08 : 0x00) |
   1165 	    ((VT  & 0x200) ? 0x20 : 0x00) |
   1166 	    ((VDE & 0x200) ? 0x40 : 0x00) |
   1167 	    ((VSS & 0x200) ? 0x80 : 0x00));
   1168 
   1169 	WCrt(ba, CRT_ID_MAX_ROW_ADDRESS,
   1170 	    0x40 |		/* TEXT ? 0x00 ??? */
   1171 	    (DBLSCAN ? 0x80 : 0x00) |
   1172 	    ((VBS & 0x200) ? 0x20 : 0x00) |
   1173 	    (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
   1174 
   1175 	WCrt(ba, CRT_ID_MODE_CONTROL,
   1176 	    ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab));
   1177 
   1178 	/* text cursor */
   1179 
   1180 	if (TEXT) {
   1181 #if ET_ULCURSOR
   1182 		WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
   1183 		WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
   1184 #else
   1185 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
   1186 		WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
   1187 #endif
   1188 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
   1189 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
   1190 	}
   1191 
   1192 	WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f)
   1193 		| ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60));
   1194 
   1195 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
   1196 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
   1197 
   1198 	WCrt(ba, CRT_ID_START_VER_RETR, VSS);
   1199 	WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
   1200 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
   1201 	WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
   1202 	WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
   1203 
   1204 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
   1205 
   1206 	WCrt(ba, CRT_ID_OVERFLOW_HIGH,
   1207 	    ((VBS & 0x400) ? 0x01 : 0x00) |
   1208 	    ((VT  & 0x400) ? 0x02 : 0x00) |
   1209 	    ((VDE & 0x400) ? 0x04 : 0x00) |
   1210 	    ((VSS & 0x400) ? 0x08 : 0x00) |
   1211 	    0x10 |
   1212 	    (LACE ? 0x80 : 0x00));
   1213 
   1214 	WCrt(ba, CRT_ID_HOR_OVERFLOW,
   1215 	    ((HT  & 0x100) ? 0x01 : 0x00) |
   1216 	    ((HBS & 0x100) ? 0x04 : 0x00) |
   1217 	    ((HSS & 0x100) ? 0x10 : 0x00)
   1218 	);
   1219 
   1220 	/* depth dependent stuff */
   1221 
   1222 	WGfx(ba, GCT_ID_GRAPHICS_MODE,
   1223 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
   1224 	WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
   1225 
   1226 	vgaw(ba, VDAC_MASK, 0xff);
   1227 	vgar(ba, VDAC_MASK);
   1228 	vgar(ba, VDAC_MASK);
   1229 	vgar(ba, VDAC_MASK);
   1230 	vgar(ba, VDAC_MASK);
   1231 	switch (gv->depth) {
   1232 	    case 1:
   1233 	    case 4:	/* text */
   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 / 16;
   1245 		break;
   1246 	    case 8:
   1247 		switch(etdtype) {
   1248 		    case SIERRA11483:
   1249 		    case SIERRA15025:
   1250 		    case MUSICDAC:
   1251 			vgaw(ba, VDAC_MASK, 0);
   1252 			break;
   1253 		    case MERLINDAC:
   1254 			setMerlinDACmode(ba, 0);
   1255 			break;
   1256 		}
   1257 		HDE = gv->disp_width / 8;
   1258 		break;
   1259 	    case 15:
   1260 		switch(etdtype) {
   1261 		    case SIERRA11483:
   1262 		    case SIERRA15025:
   1263 		    case MUSICDAC:
   1264 			vgaw(ba, VDAC_MASK, 0xa0);
   1265 			break;
   1266 		    case MERLINDAC:
   1267 			setMerlinDACmode(ba, 0xa0);
   1268 			break;
   1269 		}
   1270 		HDE = gv->disp_width / 4;
   1271 		break;
   1272 	    case 16:
   1273 		switch(etdtype) {
   1274 		    case SIERRA11483:
   1275 			vgaw(ba, VDAC_MASK, 0);	/* illegal mode! */
   1276 			break;
   1277 		    case SIERRA15025:
   1278 			vgaw(ba, VDAC_MASK, 0xe0);
   1279 			break;
   1280 		    case MUSICDAC:
   1281 			vgaw(ba, VDAC_MASK, 0xc0);
   1282 			break;
   1283 		    case MERLINDAC:
   1284 			setMerlinDACmode(ba, 0xe0);
   1285 			break;
   1286 		}
   1287 		HDE = gv->disp_width / 4;
   1288 		break;
   1289 	    case 24:
   1290 		switch(etdtype) {
   1291 		    case SIERRA11483:
   1292 			vgaw(ba, VDAC_MASK, 0);	/* illegal mode! */
   1293 			break;
   1294 		    case SIERRA15025:
   1295 			vgaw(ba, VDAC_MASK, 0xe1);
   1296 			break;
   1297 		    case MUSICDAC:
   1298 			vgaw(ba, VDAC_MASK, 0xe0);
   1299 			break;
   1300 		    case MERLINDAC:
   1301 			setMerlinDACmode(ba, 0xf0);
   1302 			break;
   1303 		}
   1304 		HDE = (gv->disp_width / 8) * 3;
   1305 		break;
   1306 	    case 32:
   1307 		switch(etdtype) {
   1308 		    case SIERRA11483:
   1309 		    case MUSICDAC:
   1310 			vgaw(ba, VDAC_MASK, 0);	/* illegal mode! */
   1311 			break;
   1312 		    case SIERRA15025:
   1313 			vgaw(ba, VDAC_MASK, 0x61);
   1314 			break;
   1315 		    case MERLINDAC:
   1316 			setMerlinDACmode(ba, 0xb0);
   1317 			break;
   1318 		}
   1319 		HDE = gv->disp_width / 2;
   1320 		break;
   1321 	}
   1322 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
   1323 	WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
   1324 	    (gv->depth == 1) ? 0x01 : 0x0f);
   1325 
   1326 	WCrt(ba, CRT_ID_OFFSET, HDE);
   1327 
   1328 	/* text initialization */
   1329 	if (TEXT) {
   1330 		et_inittextmode(gp);
   1331 	}
   1332 
   1333 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
   1334 
   1335 	/* Pass-through */
   1336 	RegOffpass(ba);
   1337 
   1338 	return (1);
   1339 }
   1340 
   1341 
   1342 void
   1343 et_inittextmode(gp)
   1344 	struct grf_softc *gp;
   1345 {
   1346 	struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data;
   1347 	volatile unsigned char *ba = gp->g_regkva;
   1348 	unsigned char *fb = gp->g_fbkva;
   1349 	unsigned char *c, *f, y;
   1350 	unsigned short z;
   1351 
   1352 
   1353 	/*
   1354 	 * load text font into beginning of display memory. Each character
   1355 	 * cell is 32 bytes long (enough for 4 planes)
   1356 	 */
   1357 
   1358 	SetTextPlane(ba, 0x02);
   1359         et_memset(fb, 0, 256 * 32);
   1360 	c = (unsigned char *) (fb) + (32 * tm->fdstart);
   1361 	f = tm->fdata;
   1362 	for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
   1363 		for (y = 0; y < tm->fy; y++)
   1364 			*c++ = *f++;
   1365 
   1366 	/* clear out text/attr planes (three screens worth) */
   1367 
   1368 	SetTextPlane(ba, 0x01);
   1369 	et_memset(fb, 0x07, tm->cols * tm->rows * 3);
   1370 	SetTextPlane(ba, 0x00);
   1371 	et_memset(fb, 0x20, tm->cols * tm->rows * 3);
   1372 
   1373 	/* print out a little init msg */
   1374 
   1375 	c = (unsigned char *) (fb) + (tm->cols - 16);
   1376 	strcpy(c, "TSENG");
   1377 	c[6] = 0x20;
   1378 
   1379 	/* set colors (B&W) */
   1380 
   1381 	switch(ettype) {
   1382 	    case MERLIN:
   1383 		vgaw(ba, MERLIN_VDAC_INDEX, 0);
   1384 		for (z = 0; z < 256; z++) {
   1385 			y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
   1386 
   1387 			vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]);
   1388 			vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]);
   1389 			vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]);
   1390 		}
   1391 		break;
   1392 	    default:
   1393 		vgaw(ba, VDAC_ADDRESS_W, 0);
   1394 		for (z = 0; z < 256; z++) {
   1395 			y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
   1396 
   1397 			vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
   1398 			    etconscolors[y][0] >> etcmap_shift);
   1399 			vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
   1400 			    etconscolors[y][1] >> etcmap_shift);
   1401 			vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
   1402 			    etconscolors[y][2] >> etcmap_shift);
   1403 		}
   1404 		break;
   1405 	}
   1406 }
   1407 
   1408 
   1409 void
   1410 et_memset(d, c, l)
   1411 	unsigned char *d;
   1412 	unsigned char c;
   1413 	int     l;
   1414 {
   1415 	for (; l > 0; l--)
   1416 		*d++ = c;
   1417 }
   1418 
   1419 
   1420 static int
   1421 et_getControllerType(gp)
   1422 	struct grf_softc * gp;
   1423 {
   1424 	unsigned char *ba = gp->g_regkva; /* register base */
   1425 	unsigned char *mem = gp->g_fbkva; /* memory base */
   1426 	unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */
   1427 
   1428 	*mem = 0;
   1429 
   1430 	/* make ACL visible */
   1431 	WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb);
   1432 	WIma(ba, IMA_PORTCONTROL, 0x01);
   1433 
   1434 	*((unsigned long *)mmu) = 0;
   1435 	*(mem + 0x13) = 0x38;
   1436 
   1437 	*mmu = 0xff;
   1438 
   1439 	/* hide ACL */
   1440 	WIma(ba, IMA_PORTCONTROL, 0x00);
   1441 	WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
   1442 
   1443 	return((*mem == 0xff) ? ETW32 : ET4000);
   1444 }
   1445 
   1446 
   1447 static int
   1448 et_getDACType(gp)
   1449 	struct grf_softc * gp;
   1450 {
   1451 	unsigned char *ba = gp->g_regkva;
   1452 	union {
   1453 		int  tt;
   1454 		char cc[4];
   1455 	} check;
   1456 
   1457 	/* check for Sierra SC 15025 */
   1458 
   1459 	/* We MUST do 4 HW reads to switch into command mode */
   1460 	if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
   1461 		vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
   1462 
   1463 	vgaw(ba, VDAC_XINDEX, 9);
   1464 	check.cc[0] = vgar(ba, VDAC_XDATA);
   1465 	vgaw(ba, VDAC_XINDEX, 10);
   1466 	check.cc[1] = vgar(ba, VDAC_XDATA);
   1467 	vgaw(ba, VDAC_XINDEX, 11);
   1468 	check.cc[2] = vgar(ba, VDAC_XDATA);
   1469 	vgaw(ba, VDAC_XINDEX, 12);
   1470 	check.cc[3] = vgar(ba, VDAC_XDATA);
   1471 
   1472 	if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
   1473 		vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
   1474 
   1475 	if (check.tt == 0x533ab141) {
   1476 		if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
   1477 			vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
   1478 
   1479 		/* switch to 8 bits per color */
   1480 		vgaw(ba, VDAC_XINDEX, 8);
   1481 		vgaw(ba, VDAC_XDATA, 1);
   1482 		/* do not shift color values */
   1483 		etcmap_shift = 0;
   1484 
   1485 		if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
   1486 			vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
   1487 
   1488 		vgaw(ba, VDAC_MASK, 0xff);
   1489 		return (SIERRA15025);
   1490 	}
   1491 
   1492 	/* check for MUSIC DAC */
   1493 
   1494 	if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
   1495 		vgaw(ba, VDAC_COMMAND, 0x02);	/* set some strange MUSIC mode (???) */
   1496 
   1497 	vgaw(ba, VDAC_XINDEX, 0x01);
   1498 	if (vgar(ba, VDAC_XDATA) == 0x01) {
   1499 		/* shift color values by 2 */
   1500 		etcmap_shift = 2;
   1501 
   1502 		vgaw(ba, VDAC_MASK, 0xff);
   1503 		return (MUSICDAC);
   1504 }
   1505 
   1506 	/*
   1507 	 * nothing else found, so let us pretend it is a stupid
   1508 	 * Sierra SC 11483
   1509 	 */
   1510 
   1511 	/* shift color values by 2 */
   1512 	etcmap_shift = 2;
   1513 
   1514 	vgaw(ba, VDAC_MASK, 0xff);
   1515 	return (SIERRA11483);
   1516 }
   1517 
   1518 #endif /* NGRFET */
   1519