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