1/*	$NetBSD: grf_et.c,v 1.28 2009/10/26 19:16:54 cegger 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.28 2009/10/26 19:16:54 cegger 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
84int	et_mondefok(struct grfvideo_mode *gv);
85void	et_boardinit(struct grf_softc *gp);
86static void et_CompFQ(u_int fq, u_char *num, u_char *denom);
87int	et_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm);
88int	et_setvmode(struct grf_softc *gp, unsigned int mode);
89int	et_toggle(struct grf_softc *gp, unsigned short);
90int	et_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap);
91int	et_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap);
92#ifndef TSENGCONSOLE
93void	et_off(struct grf_softc *gp);
94#endif
95void	et_inittextmode(struct grf_softc *gp);
96int	et_ioctl(register struct grf_softc *gp, u_long cmd, void *data);
97int	et_getmousepos(struct grf_softc *gp, struct grf_position *data);
98void	et_writesprpos(volatile char *ba, short x, short y);
99int	et_setmousepos(struct grf_softc *gp, struct grf_position *data);
100static int et_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data);
101int	et_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data);
102static int et_getspritemax(struct grf_softc *gp, struct grf_position *data);
103int	et_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv);
104int	et_blank(struct grf_softc *gp, int *on);
105static int et_getControllerType(struct grf_softc *gp);
106static int et_getDACType(struct grf_softc *gp);
107
108int	grfetmatch(struct device *, struct cfdata *, void *);
109void	grfetattach(struct device *, struct device *, void *);
110int	grfetprint(void *, const char *);
111void	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
118static 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};
123static 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
138extern unsigned char TSENGFONT[];
139
140struct 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 */
147unsigned char etconscolors[3][3] = {	/* background, foreground, hilite */
148	{0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
149};
150
151int ettype = 0;		/* oMniBus, Domino or Merlin */
152int etctype = 0;	/* ET4000 or ETW32 */
153int etdtype = 0;	/* Type of DAC (see grf_etregs.h) */
154
155char etcmap_shift = 0;	/* 6 or 8 bit cmap entries */
156unsigned char pass_toggle;	/* passthru status tracker */
157
158unsigned 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 */
167static void *et_fbaddr = 0;	/* framebuffer */
168static void *et_regaddr = 0;	/* registers */
169static 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 */
174struct 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 */
179static unsigned char et_imageptr[8 * 64], et_maskptr[8 * 64];
180static unsigned char et_sprred[2], et_sprgreen[2], et_sprblue[2];
181
182/* standard driver stuff */
183CFATTACH_DECL(grfet, sizeof(struct grf_softc),
184    grfetmatch, grfetattach, NULL, NULL);
185
186static struct cfdata *cfdata;
187
188int
189grfetmatch(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
270void
271grfetattach(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
372int
373grfetprint(void *auxp, const char *pnp)
374{
375	if (pnp)
376		aprint_normal("ite at %s: ", pnp);
377	return (UNCONF);
378}
379
380
381void
382et_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
560int
561et_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
596int
597et_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
610void
611et_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
621int
622et_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 */
633int
634et_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
681int
682et_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
722int
723et_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
732void
733et_writesprpos(volatile char *ba, short x, short y)
734{
735}
736
737
738int
739et_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
768int
769et_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
770{
771
772	return(EINVAL);
773}
774
775
776static int
777et_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
778{
779
780	return(EINVAL);
781}
782
783
784static int
785et_getspritemax(struct grf_softc *gp, struct grf_position *data)
786{
787
788	return(EINVAL);
789}
790
791
792int
793et_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
833int
834et_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
884int
885et_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
941int
942et_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
960static 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
967static 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
974static 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
986static void
987et_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
1004int
1005et_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
1052int
1053et_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
1404void
1405et_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
1471void
1472et_memset(volatile unsigned char *d, unsigned char c, int l)
1473{
1474	for (; l > 0; l--)
1475		*d++ = c;
1476}
1477
1478
1479static int
1480et_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
1514static int
1515et_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