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