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