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