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