xref: /netbsd-src/sys/arch/atari/dev/grfabs_et.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
1 /*	$NetBSD: grfabs_et.c,v 1.4 1996/10/13 04:10:57 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1996 Leo Weppelman.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Leo Weppelman.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Most of the lower-level et4000 stuff was derived from:
35  *	.../amiga/dev/grf_et.c
36  *
37  * Which was copyrighted by:
38  *	Copyright (c) 1996 Tobias Abt
39  *	Copyright (c) 1995 Ezra Story
40  *	Copyright (c) 1995 Kari Mettinen
41  *	Copyright (c) 1994 Markus Wild
42  *	Copyright (c) 1994 Lutz Vieweg
43  *
44  * Thanks guys!
45  *
46  */
47 #include <sys/param.h>
48 #include <sys/queue.h>
49 #include <sys/malloc.h>
50 #include <sys/device.h>
51 #include <sys/systm.h>
52 
53 /*
54  * For PCI probing...
55  */
56 #include <dev/pci/pcireg.h>
57 #include <dev/pci/pcivar.h>
58 
59 #include <machine/iomap.h>
60 #include <machine/video.h>
61 #include <machine/mfp.h>
62 #include <atari/atari/device.h>
63 #include <atari/dev/grfioctl.h>
64 #include <atari/dev/grfabs_reg.h>
65 #include <atari/dev/grfabs_et.h>
66 #include <atari/dev/grf_etreg.h>
67 
68 #define	SAVEBUF_SIZE	(32*1024 + sizeof(save_area_t))
69 
70 /*
71  * Function decls
72  */
73 static void       init_view __P((view_t *, bmap_t *, dmode_t *, box_t *));
74 static colormap_t *alloc_colormap __P((dmode_t *));
75 static void	  et_display_view __P((view_t *));
76 static view_t	  *et_alloc_view __P((dmode_t *, dimen_t *, u_char));
77 static void	  et_boardinit __P((void));
78 static void	  et_free_view __P((view_t *));
79 static void	  et_loadmode __P((struct grfvideo_mode *, et_sv_reg_t *));
80 static void	  et_remove_view __P((view_t *));
81 static void	  et_save_view __P((view_t *));
82 static int	  et_use_colormap __P((view_t *, colormap_t *));
83 
84 /*
85  * Our function switch table
86  */
87 struct grfabs_sw et_vid_sw = {
88 	et_display_view,
89 	et_alloc_view,
90 	et_free_view,
91 	et_remove_view,
92 	et_save_view,
93 	et_use_colormap
94 };
95 
96 static struct grfvideo_mode hw_modes[] = {
97     {
98 	0, "", 25175000,		/* num, descr, pix-clock	*/
99 	640, 400, 4,			/* width, height, depth		*/
100 	640/8, 672/8, 688/8, 752/8, 768/8,/* HBS, HBE, HSS, HSE, HT	*/
101 	399, 450, 408, 413, 449		/* VBS, VBE, VSS, VSE, VT	*/
102     },
103     {
104 	0, "", 25175000,		/* num, descr, pix-clock	*/
105 	640, 480, 4,			/* width, height, depth		*/
106 	640/8, 672/8, 704/8, 752/8, 760/8,/* HBS, HBE, HSS, HSE, HT	*/
107 	481, 522, 490, 498, 522		/* VBS, VBE, VSS, VSE, VT	*/
108     }
109 };
110 
111 static dmode_t vid_modes[] = {
112     { { NULL, NULL },
113 	"640x400", { 640, 400 }, 1, (void*)&hw_modes[0], &et_vid_sw },
114     { { NULL, NULL },
115 	"640x480", { 640, 480 }, 1, (void*)&hw_modes[1], &et_vid_sw },
116     { { NULL, NULL }, NULL,  }
117 };
118 
119 #define	ET_NUMCLOCKS	32
120 
121 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
122 	 6293750,  7080500,  7875000,  8125000,
123 	 9000000,  9375000, 10000000, 11225000,
124 	12587500, 14161000, 15750000, 16250000,
125 	18000000, 18750000, 20000000, 22450000,
126 	25175000, 28322000, 31500000, 32500000,
127 	36000000, 37500000, 40000000, 44900000,
128 	50350000, 56644000, 63000000, 65000000,
129 	72000000, 75000000, 80000000, 89800000
130 };
131 
132 static bmap_t	con_bm; /* XXX */
133 
134 struct grfabs_et_priv {
135 	pcitag_t		pci_tag;
136 	volatile caddr_t	regkva;
137 	volatile caddr_t	memkva;
138 	int			regsz;
139 	int			memsz;
140 } et_priv;
141 
142 /*
143  * XXX: called from ite console init routine.
144  * Initialize list of posible video modes.
145  */
146 void
147 et_probe_video(modelp)
148 MODES	*modelp;
149 {
150 	dmode_t	*dm;
151 	int	i;
152 
153 	for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) {
154 		LIST_INSERT_HEAD(modelp, dm, link);
155 	}
156 }
157 
158 static void
159 et_display_view(v)
160 view_t *v;
161 {
162 	dmode_t		*dm = v->mode;
163 	bmap_t		*bm = v->bitmap;
164 	int		sv_size;
165 	u_short		*src, *dst;
166 	save_area_t	*sa;
167 
168 	if (dm->current_view && (dm->current_view != v)) {
169 		/*
170 		 * Mark current view for this mode as no longer displayed
171 		 */
172 		dm->current_view->flags &= ~VF_DISPLAY;
173 	}
174 	dm->current_view = v;
175 	v->flags |= VF_DISPLAY;
176 
177 	if ((sa = (save_area_t*)v->save_area) == NULL)
178 		return; /* XXX: Can't happen.... */
179 
180 	/*
181 	 * Restore register settings and turn the plane pointer
182 	 * to the card-memory
183 	 */
184 	et_hwrest(&sa->sv_regs);
185 	bm->plane = et_priv.memkva;
186 
187 	et_use_colormap(v, v->colormap);
188 
189 	/*
190 	 * Copy the backing store to card-memory
191 	 */
192 	sv_size = sa->fb_size;
193 	src     = sa->sv_fb;
194 	dst     = (u_short *)bm->plane;
195 	while (sv_size--)
196 		*dst++ = *src++;
197 }
198 
199 void
200 et_remove_view(v)
201 view_t *v;
202 {
203 	dmode_t *mode = v->mode;
204 
205 	if (mode->current_view == v) {
206 #if 0
207 		if (v->flags & VF_DISPLAY)
208 			panic("Cannot shutdown display\n"); /* XXX */
209 #endif
210 		mode->current_view = NULL;
211 	}
212 	v->flags &= ~VF_DISPLAY;
213 }
214 
215 void
216 et_save_view(v)
217 view_t *v;
218 {
219 	bmap_t		*bm = v->bitmap;
220 	u_char		font_height;
221 	int		sv_size;
222 	u_short		*src, *dst;
223 	save_area_t	*sa;
224 
225 	if (!atari_realconfig)
226 		return;
227 
228 	if (RGfx(et_priv.regkva, GCT_ID_MISC) & 1) {
229 #if 0 /* XXX: Can't use printf here.... */
230 		printf("et_save_view: Don't know how to save"
231 			" a graphics mode\n");
232 #endif
233 		return;
234 	}
235 	if (v->save_area == NULL)
236 		v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_WAITOK);
237 
238 	/*
239 	 * Calculate the size of the copy
240 	 */
241 	font_height = RCrt(et_priv.regkva, CRT_ID_MAX_ROW_ADDRESS) & 0x1f;
242 	sv_size = bm->bytes_per_row * (bm->rows / (font_height + 1));
243 	sv_size = min(SAVEBUF_SIZE, sv_size);
244 
245 	/*
246 	 * Save all we need to know....
247 	 */
248 	sa  = (save_area_t *)v->save_area;
249 	et_hwsave(&sa->sv_regs);
250 	sa->fb_size = sv_size;
251 	src = (u_short *)bm->plane;
252 	dst = sa->sv_fb;
253 	while (sv_size--)
254 		*dst++ = *src++;
255 	bm->plane = (u_char *)sa->sv_fb;
256 }
257 
258 void
259 et_free_view(v)
260 view_t *v;
261 {
262 	if(v) {
263 		et_remove_view(v);
264 		if (v->colormap != &gra_con_cmap)
265 			free(v->colormap, M_DEVBUF);
266 		if (v->save_area != NULL)
267 			free(v->save_area, M_DEVBUF);
268 		if (v != &gra_con_view) {
269 			free(v->bitmap, M_DEVBUF);
270 			free(v, M_DEVBUF);
271 		}
272 	}
273 }
274 
275 static int
276 et_use_colormap(v, cm)
277 view_t		*v;
278 colormap_t	*cm;
279 {
280 	return (0); /* XXX: Nothing here for now... */
281 }
282 
283 static view_t *
284 et_alloc_view(mode, dim, depth)
285 dmode_t	*mode;
286 dimen_t	*dim;
287 u_char   depth;
288 {
289 	view_t		*v;
290 	bmap_t		*bm;
291 	box_t		box;
292 	save_area_t	*sa;
293 
294 	if (!atari_realconfig) {
295 		v  = &gra_con_view;
296 		bm = &con_bm;
297 	}
298 	else {
299 		v  = malloc(sizeof(*v), M_DEVBUF, M_WAITOK);
300 		bm = malloc(sizeof(*bm), M_DEVBUF, M_WAITOK);
301 	}
302 	v->bitmap = bm;
303 
304 	/*
305 	 * Initialize the bitmap
306 	 */
307 	bm->plane         = et_priv.memkva;
308 	bm->hw_address    = et_priv.memkva; /* XXX: kvtop? */
309 	bm->regs          = et_priv.regkva;
310 	bm->hw_regs       = et_priv.regkva; /* XXX: kvtop? */
311 	bm->reg_size      = et_priv.regsz;
312 
313 	bm->bytes_per_row = (mode->size.width * depth) / NBBY;
314 	bm->rows          = mode->size.height;
315 	bm->depth         = depth;
316 
317 	/*
318 	 * Allocate a save_area.
319 	 * Note: If atari_realconfig is false, no save area is (can be)
320 	 * allocated. This means that the plane is the video memory,
321 	 * which is what's wanted in this case.
322 	 */
323 	if (atari_realconfig) {
324 		v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_WAITOK);
325 		sa           = (save_area_t*)v->save_area;
326 		sa->fb_size  = 0;
327 		bm->plane    = (u_char *)sa->sv_fb;
328 		et_loadmode(mode->data, &sa->sv_regs);
329 	}
330 	else v->save_area = NULL;
331 
332 	v->colormap = alloc_colormap(mode);
333 	if (v->colormap) {
334 		INIT_BOX(&box,0,0,mode->size.width,mode->size.height);
335 		init_view(v, bm, mode, &box);
336 		return (v);
337 	}
338 	if (v != &gra_con_view) {
339 		free(v, M_DEVBUF);
340 		free(bm, M_DEVBUF);
341 	}
342 	return (NULL);
343 }
344 
345 static void
346 init_view(v, bm, mode, dbox)
347 view_t	*v;
348 bmap_t	*bm;
349 dmode_t	*mode;
350 box_t	*dbox;
351 {
352 	v->bitmap    = bm;
353 	v->mode      = mode;
354 	v->flags     = 0;
355 	bcopy(dbox, &v->display, sizeof(box_t));
356 }
357 
358 /* XXX: No more than a stub... */
359 static colormap_t *
360 alloc_colormap(dm)
361 dmode_t		*dm;
362 {
363 	colormap_t	*cm;
364 	int		i;
365 
366 	cm = &gra_con_cmap;
367 	cm->entry = gra_con_colors;
368 
369 	cm->first = 0;
370 	cm->size  = 2;
371 
372 	for (i = 0; i < 2; i++)
373 		cm->entry[i] = gra_def_color16[i % 16];
374 	return (cm);
375 }
376 
377 /*
378  * Go look for a VGA card on the PCI-bus. This search is a
379  * stripped down version of the PCI-probe. It only looks on
380  * bus0 for simple cards.
381  */
382 int
383 et_probe_card()
384 {
385 	pci_chipset_tag_t	pc = NULL; /* XXX */
386 	pcitag_t		tag;
387 	int			class, device, found, id, maxndevs;
388 
389 	found    = 0;
390 	tag      = 0;
391 	maxndevs = pci_bus_maxdevs(pc, 0);
392 
393 	for (device = 0; device < maxndevs; device++) {
394 
395 		tag = pci_make_tag(pc, 0, device, 0);
396 		id  = pci_conf_read(pc, tag, PCI_ID_REG);
397 		if (id == 0 || id == 0xffffffff)
398 			continue;
399 		class = pci_conf_read(pc, tag, PCI_CLASS_REG);
400 		if (PCI_CLASS(class) == PCI_CLASS_PREHISTORIC
401 		    && PCI_SUBCLASS(class) == PCI_SUBCLASS_PREHISTORIC_VGA) {
402 			found = 1;
403 			break;
404 		}
405 		if (PCI_CLASS(class) == PCI_CLASS_DISPLAY
406 		    && PCI_SUBCLASS(class) == PCI_SUBCLASS_DISPLAY_VGA) {
407 			found = 1;
408 			break;
409 		}
410 	}
411 	if (!found)
412 		return (0);
413 
414 	et_priv.pci_tag = tag;
415 
416 	/*
417 	 * The things below are setup in atari_init.c
418 	 */
419 	et_priv.regkva  = (volatile caddr_t)pci_io_addr;
420 	et_priv.memkva  = (volatile caddr_t)pci_mem_addr;
421 	et_priv.memsz   = 4 * NBPG;
422 	et_priv.regsz   = NBPG;
423 
424 	if (found && !atari_realconfig) {
425 		et_boardinit();
426 		et_loadmode(&hw_modes[0], NULL);
427 		return (1);
428 	}
429 
430 	return (1);
431 }
432 
433 static void
434 et_loadmode(mode, regs)
435 struct grfvideo_mode	*mode;
436 et_sv_reg_t		*regs;
437 {
438 	unsigned short	HDE, VDE;
439 	int	    	lace, dblscan;
440 	int     	uplim, lowlim;
441 	int		i;
442 	unsigned char	clock, tmp;
443 	volatile u_char	*ba;
444 	et_sv_reg_t	loc_regs;
445 
446 	if (regs == NULL)
447 		regs = &loc_regs;
448 
449 	ba  = et_priv.regkva;
450 	HDE = mode->disp_width / 8 - 1;
451 	VDE = mode->disp_height - 1;
452 
453 	/* figure out whether lace or dblscan is needed */
454 
455 	uplim   = mode->disp_height + (mode->disp_height / 4);
456 	lowlim  = mode->disp_height - (mode->disp_height / 4);
457 	lace    = (((mode->vtotal * 2) > lowlim)
458 		   && ((mode->vtotal * 2) < uplim)) ? 1 : 0;
459 	dblscan = (((mode->vtotal / 2) > lowlim)
460 		   && ((mode->vtotal / 2) < uplim)) ? 1 : 0;
461 
462 	/* adjustments */
463 	if (lace)
464 		VDE /= 2;
465 
466 	regs->misc_output = 0x23; /* Page 0, Color mode */
467 	regs->seg_sel     = 0x00;
468 	regs->state_ctl   = 0x00;
469 
470 	regs->seq[SEQ_ID_RESET]           = 0x03; /* reset off		*/
471 	regs->seq[SEQ_ID_CLOCKING_MODE]   = 0x21; /* Turn off screen	*/
472 	regs->seq[SEQ_ID_MAP_MASK]        = 0xff; /* Cpu writes all planes*/
473 	regs->seq[SEQ_ID_CHAR_MAP_SELECT] = 0x00; /* Char. generator 0	*/
474 	regs->seq[SEQ_ID_MEMORY_MODE]     = 0x0e; /* Seq. Memory mode	*/
475 
476 	/*
477 	 * Set the clock...
478 	 */
479 	for(clock = ET_NUMCLOCKS-1; clock > 0; clock--) {
480 		if (et_clockfreqs[clock] <= mode->pixel_clock)
481 			break;
482 	}
483 	regs->misc_output |= (clock & 3) << 2;
484 	regs->aux_mode     = 0xb4 | ((clock & 8) << 3);
485 	regs->compat_6845  = (clock & 4) ? 0x0a : 0x08;
486 
487 	/*
488 	 * The display parameters...
489 	 */
490 	regs->crt[CRT_ID_HOR_TOTAL]        =  mode->htotal;
491 	regs->crt[CRT_ID_HOR_DISP_ENA_END] = ((HDE >= mode->hblank_start)
492 						? mode->hblank_stop - 1
493 						: HDE);
494 	regs->crt[CRT_ID_START_HOR_BLANK]  = mode->hblank_start;
495 	regs->crt[CRT_ID_END_HOR_BLANK]    = (mode->hblank_stop & 0x1f) | 0x80;
496 	regs->crt[CRT_ID_START_HOR_RETR]   = mode->hsync_start;
497 	regs->crt[CRT_ID_END_HOR_RETR]     = (mode->hsync_stop & 0x1f)
498 						| ((mode->hblank_stop & 0x20)
499 							? 0x80 : 0x00);
500 	regs->crt[CRT_ID_VER_TOTAL]        = mode->vtotal;
501 	regs->crt[CRT_ID_START_VER_RETR]   = mode->vsync_start;
502 	regs->crt[CRT_ID_END_VER_RETR]     = (mode->vsync_stop & 0x0f) | 0x30;
503 	regs->crt[CRT_ID_VER_DISP_ENA_END] = VDE;
504 	regs->crt[CRT_ID_START_VER_BLANK]  = mode->vblank_start;
505 	regs->crt[CRT_ID_END_VER_BLANK]    = mode->vblank_stop;
506 	regs->crt[CRT_ID_MODE_CONTROL]     = 0xab;
507 	regs->crt[CRT_ID_START_ADDR_HIGH]  = 0x00;
508 	regs->crt[CRT_ID_START_ADDR_LOW]   = 0x00;
509 	regs->crt[CRT_ID_LINE_COMPARE]     = 0xff;
510 	regs->crt[CRT_ID_UNDERLINE_LOC]    = 0x00;
511 	regs->crt[CRT_ID_OFFSET]           = mode->disp_width/16;
512 	regs->crt[CRT_ID_MAX_ROW_ADDRESS]  =
513 		0x40 |
514 		(dblscan ? 0x80 : 0x00) |
515 		((mode->vblank_start & 0x200) ? 0x20 : 0x00);
516 	regs->crt[CRT_ID_OVERFLOW] =
517 		0x10 |
518 		((mode->vtotal       & 0x100) ? 0x01 : 0x00) |
519 		((VDE                & 0x100) ? 0x02 : 0x00) |
520 		((mode->vsync_start  & 0x100) ? 0x04 : 0x00) |
521 		((mode->vblank_start & 0x100) ? 0x08 : 0x00) |
522 		((mode->vtotal       & 0x200) ? 0x20 : 0x00) |
523 		((VDE                & 0x200) ? 0x40 : 0x00) |
524 		((mode->vsync_start  & 0x200) ? 0x80 : 0x00);
525 	regs->overfl_high =
526 		0x10 |
527 		((mode->vblank_start & 0x400) ? 0x01 : 0x00) |
528 		((mode->vtotal       & 0x400) ? 0x02 : 0x00) |
529 		((VDE                & 0x400) ? 0x04 : 0x00) |
530 		((mode->vsync_start  & 0x400) ? 0x08 : 0x00) |
531 		(lace ? 0x80 : 0x00);
532 	regs->hor_overfl =
533 		((mode->htotal       & 0x100) ? 0x01 : 0x00) |
534 		((mode->hblank_start & 0x100) ? 0x04 : 0x00) |
535 		((mode->hsync_start  & 0x100) ? 0x10 : 0x00);
536 
537 	regs->grf[GCT_ID_SET_RESET]        = 0x00;
538 	regs->grf[GCT_ID_ENABLE_SET_RESET] = 0x00;
539 	regs->grf[GCT_ID_COLOR_COMPARE]    = 0x00;
540 	regs->grf[GCT_ID_DATA_ROTATE]      = 0x00;
541 	regs->grf[GCT_ID_READ_MAP_SELECT]  = 0x00;
542 	regs->grf[GCT_ID_GRAPHICS_MODE]    = mode->depth == 1 ? 0x00: 0x40;
543 	regs->grf[GCT_ID_MISC]             = 0x01;
544 	regs->grf[GCT_ID_COLOR_XCARE]      = 0x0f;
545 	regs->grf[GCT_ID_BITMASK]          = 0xff;
546 
547 	for (i = 0; i < 0x10; i++)
548 		regs->attr[i] = i;
549 	regs->attr[ACT_ID_ATTR_MODE_CNTL]  = 0x01;
550 	regs->attr[ACT_ID_OVERSCAN_COLOR]  = 0x00;
551 	regs->attr[ACT_ID_COLOR_PLANE_ENA] = 0x0f;
552 	regs->attr[ACT_ID_HOR_PEL_PANNING] = 0x00;
553 	regs->attr[ACT_ID_COLOR_SELECT]    = 0x00;
554 	regs->attr[ACT_ID_MISCELLANEOUS]   = 0x00;
555 
556 	/*
557 	 * XXX: This works for depth == 4. I need some better docs
558 	 * to fix the other modes....
559 	 */
560 	vgaw(ba, VDAC_MASK, 0xff);
561 	vgar(ba, VDAC_MASK);
562 	vgar(ba, VDAC_MASK);
563 	vgar(ba, VDAC_MASK);
564 	vgar(ba, VDAC_MASK);
565 
566 	vgaw(ba, VDAC_MASK, 0);
567 	/*
568 	 * End of depth stuff
569 	 */
570 
571 	/*
572 	 * Compute Hsync & Vsync polarity
573 	 * Note: This seems to be some kind of a black art :-(
574 	 */
575 	tmp = regs->misc_output & 0x3f;
576 #if 0 /* This is according to my BW monitor & Xfree... */
577 	if (VDE < 400)
578 		tmp |= 0x40;	/* -hsync +vsync */
579 	else if (VDE < 480)
580 		tmp |= 0xc0;	/* -hsync -vsync */
581 #else /* This is according to my color monitor.... */
582 	if (VDE < 400)
583 		tmp |= 0x00;	/* +hsync +vsync */
584 	else if (VDE < 480)
585 		tmp |= 0x80;	/* +hsync -vsync */
586 #endif
587 	/* I'm unable to try the rest.... */
588 	regs->misc_output = tmp;
589 
590 	if(regs == &loc_regs)
591 		et_hwrest(regs);
592 }
593 
594 static void
595 et_boardinit()
596 {
597 	volatile u_char *ba;
598 	int		i, j;
599 
600 	ba = et_priv.regkva;
601 
602 	vgaw(ba, GREG_HERCULESCOMPAT,     0x03);
603 	vgaw(ba, GREG_DISPMODECONTROL,    0xa0);
604 	vgaw(ba, GREG_MISC_OUTPUT_W,      0x23);
605 
606 	WSeq(ba, SEQ_ID_RESET,            0x03);
607 	WSeq(ba, SEQ_ID_CLOCKING_MODE,    0x21);	/* 8 dot, Display off */
608 	WSeq(ba, SEQ_ID_MAP_MASK,         0x0f);
609 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT,  0x00);
610 	WSeq(ba, SEQ_ID_MEMORY_MODE,      0x0e);
611 	WSeq(ba, SEQ_ID_AUXILIARY_MODE,   0xf4);
612 
613 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN,  0x00);
614 	WCrt(ba, CRT_ID_CURSOR_START,     0x00);
615 	WCrt(ba, CRT_ID_CURSOR_END,       0x08);
616 	WCrt(ba, CRT_ID_START_ADDR_HIGH,  0x00);
617 	WCrt(ba, CRT_ID_START_ADDR_LOW,   0x00);
618 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH,  0x00);
619 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW,   0x00);
620 
621 	WCrt(ba, CRT_ID_UNDERLINE_LOC,    0x07);
622 	WCrt(ba, CRT_ID_MODE_CONTROL,     0xa3);
623 	WCrt(ba, CRT_ID_LINE_COMPARE,     0xff);
624 	/*
625 	 * ET4000 special
626 	 */
627 	WCrt(ba, CRT_ID_RASCAS_CONFIG,    0x28);
628 	WCrt(ba, CTR_ID_EXT_START,        0x00);
629 	WCrt(ba, CRT_ID_6845_COMPAT,      0x08);
630 	WCrt(ba, CRT_ID_VIDEO_CONFIG1,    0x73);
631 	WCrt(ba, CRT_ID_VIDEO_CONFIG2,    0x09);
632 
633 	WCrt(ba, CRT_ID_HOR_OVERFLOW,     0x00);
634 
635 	WGfx(ba, GCT_ID_SET_RESET,        0x00);
636 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
637 	WGfx(ba, GCT_ID_COLOR_COMPARE,    0x00);
638 	WGfx(ba, GCT_ID_DATA_ROTATE,      0x00);
639 	WGfx(ba, GCT_ID_READ_MAP_SELECT,  0x00);
640 	WGfx(ba, GCT_ID_GRAPHICS_MODE,    0x00);
641 	WGfx(ba, GCT_ID_MISC,             0x01);
642 	WGfx(ba, GCT_ID_COLOR_XCARE,      0x0f);
643 	WGfx(ba, GCT_ID_BITMASK,          0xff);
644 
645 	vgaw(ba, GREG_SEGMENTSELECT,      0x00);
646 
647 	for (i = 0; i < 0x10; i++)
648 		WAttr(ba, i, i);
649 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL,  0x01);
650 	WAttr(ba, ACT_ID_OVERSCAN_COLOR,  0x00);
651 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
652 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
653 	WAttr(ba, ACT_ID_COLOR_SELECT,    0x00);
654 	WAttr(ba, ACT_ID_MISCELLANEOUS,   0x00);
655 
656 	vgaw(ba, VDAC_MASK, 0xff);
657 
658 #if 0 /* XXX: We like to do this: */
659 	delay(200000);
660 #else /* But because we run before the delay is initialized: */
661 	for(i = 0; i < 4000; i++)
662 		for(j =  0; j < 400; j++);
663 #endif
664 
665 	/*
666 	 * colors initially set to greyscale
667 	 */
668 	vgaw(ba, VDAC_ADDRESS_W, 0);
669 	for (i = 255; i >= 0; i--) {
670 		vgaw(ba, VDAC_DATA, i);
671 		vgaw(ba, VDAC_DATA, i);
672 		vgaw(ba, VDAC_DATA, i);
673 	}
674 }
675 
676 void
677 et_hwsave(et_regs)
678 et_sv_reg_t	*et_regs;
679 {
680 	volatile u_char *ba;
681 	int		i, s;
682 
683 	ba = et_priv.regkva;
684 
685 	s = splhigh();
686 
687 	/*
688 	 * General VGA registers
689 	 */
690 	et_regs->misc_output = vgar(ba, GREG_MISC_OUTPUT_R);
691 	for(i = 0; i < 25; i++)
692 		et_regs->crt[i]  = RCrt(ba, i);
693 	for(i = 0; i < 21; i++)
694 		et_regs->attr[i] = RAttr(ba, i | 0x20);
695 	for(i = 0; i < 9; i++)
696 		et_regs->grf[i]  = RGfx(ba, i);
697 	for(i = 0; i < 5; i++)
698 		et_regs->seq[i]  = RSeq(ba, i);
699 
700 	/*
701 	 * ET4000 extensions
702 	 */
703 	et_regs->ext_start   = RCrt(ba, CTR_ID_EXT_START);
704 	et_regs->compat_6845 = RCrt(ba, CRT_ID_6845_COMPAT);
705 	et_regs->overfl_high = RCrt(ba, CRT_ID_OVERFLOW_HIGH);
706 	et_regs->hor_overfl  = RCrt(ba, CRT_ID_HOR_OVERFLOW);
707 	et_regs->state_ctl   = RSeq(ba, SEQ_ID_STATE_CONTROL);
708 	et_regs->aux_mode    = RSeq(ba, SEQ_ID_AUXILIARY_MODE);
709 	et_regs->seg_sel     = vgar(ba, GREG_SEGMENTSELECT);
710 
711 	s = splx(s);
712 }
713 
714 void
715 et_hwrest(et_regs)
716 et_sv_reg_t	*et_regs;
717 {
718 	volatile u_char *ba;
719 	int		i, s;
720 
721 	ba = et_priv.regkva;
722 
723 	s = splhigh();
724 
725 	vgaw(ba, GREG_SEGMENTSELECT, 0);
726 	vgaw(ba, GREG_MISC_OUTPUT_W, et_regs->misc_output);
727 
728 	/*
729 	 * General VGA registers
730 	 */
731 	for(i = 0; i < 5; i++)
732 		WSeq(ba, i, et_regs->seq[i]);
733 
734 	/*
735 	 * Make sure we're allowed to write all crt-registers
736 	 */
737 	WCrt(ba, CRT_ID_END_VER_RETR,
738 		et_regs->crt[CRT_ID_END_VER_RETR] & 0x7f);
739 	for(i = 0; i < 25; i++)
740 		WCrt(ba, i, et_regs->crt[i]);
741 	for(i = 0; i < 9; i++)
742 		WGfx(ba, i, et_regs->grf[i]);
743 	for(i = 0; i < 21; i++)
744 		WAttr(ba, i | 0x20, et_regs->attr[i]);
745 
746 	/*
747 	 * ET4000 extensions
748 	 */
749 	WSeq(ba, SEQ_ID_STATE_CONTROL, et_regs->state_ctl);
750 	WSeq(ba, SEQ_ID_AUXILIARY_MODE, et_regs->aux_mode);
751 	WCrt(ba, CTR_ID_EXT_START, et_regs->ext_start);
752 	WCrt(ba, CRT_ID_6845_COMPAT, et_regs->compat_6845);
753 	WCrt(ba, CRT_ID_OVERFLOW_HIGH, et_regs->overfl_high);
754 	WCrt(ba, CRT_ID_HOR_OVERFLOW, et_regs->hor_overfl);
755 	vgaw(ba, GREG_SEGMENTSELECT, et_regs->seg_sel);
756 
757 	i = et_regs->seq[SEQ_ID_CLOCKING_MODE] & ~0x20;
758 	WSeq(ba, SEQ_ID_CLOCKING_MODE, i);
759 
760 	s = splx(s);
761 }
762