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