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