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