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