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