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