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