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