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