xref: /netbsd-src/sys/arch/atari/dev/grfabs_et.c (revision 93f9db1b75d415b78f73ed629beeb86235153473)
1 /*	$NetBSD: grfabs_et.c,v 1.9 1998/05/11 20:43:43 thomas 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_NOWAIT);
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 	/*
570 	 * What we need would be probe functions for RAMDAC/clock chip
571 	 */
572 	vgar(ba, VDAC_ADDRESS);		/* clear old state */
573 	vgar(ba, VDAC_MASK);
574 	vgar(ba, VDAC_MASK);
575 	vgar(ba, VDAC_MASK);
576 	vgar(ba, VDAC_MASK);
577 
578 	vgaw(ba, VDAC_MASK, 0);		/* set to palette */
579 	vgar(ba, VDAC_ADDRESS);		/* clear state */
580 
581 	vgaw(ba, VDAC_MASK, 0xff);
582 	/*
583 	 * End of depth stuff
584 	 */
585 
586 	/*
587 	 * Compute Hsync & Vsync polarity
588 	 * Note: This seems to be some kind of a black art :-(
589 	 */
590 	tmp = regs->misc_output & 0x3f;
591 #if 1 /* This is according to my BW monitor & Xfree... */
592 	if (VDE < 400)
593 		tmp |= 0x40;	/* -hsync +vsync */
594 	else if (VDE < 480)
595 		tmp |= 0xc0;	/* -hsync -vsync */
596 #else /* This is according to my color monitor.... */
597 	if (VDE < 400)
598 		tmp |= 0x00;	/* +hsync +vsync */
599 	else if (VDE < 480)
600 		tmp |= 0x80;	/* +hsync -vsync */
601 #endif
602 	/* I'm unable to try the rest.... */
603 	regs->misc_output = tmp;
604 
605 	if(regs == &loc_regs)
606 		et_hwrest(regs);
607 }
608 
609 static void
610 et_boardinit()
611 {
612 	volatile u_char *ba;
613 	int		i, j;
614 
615 	ba = et_priv.regkva;
616 
617 	vgaw(ba, GREG_HERCULESCOMPAT,     0x03);
618 	vgaw(ba, GREG_DISPMODECONTROL,    0xa0);
619 	vgaw(ba, GREG_MISC_OUTPUT_W,      0x23);
620 
621 	WSeq(ba, SEQ_ID_RESET,            0x03);
622 	WSeq(ba, SEQ_ID_CLOCKING_MODE,    0x21);	/* 8 dot, Display off */
623 	WSeq(ba, SEQ_ID_MAP_MASK,         0x0f);
624 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT,  0x00);
625 	WSeq(ba, SEQ_ID_MEMORY_MODE,      0x0e);
626 	WSeq(ba, SEQ_ID_AUXILIARY_MODE,   0xf4);
627 
628 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN,  0x00);
629 	WCrt(ba, CRT_ID_CURSOR_START,     0x00);
630 	WCrt(ba, CRT_ID_CURSOR_END,       0x08);
631 	WCrt(ba, CRT_ID_START_ADDR_HIGH,  0x00);
632 	WCrt(ba, CRT_ID_START_ADDR_LOW,   0x00);
633 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH,  0x00);
634 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW,   0x00);
635 
636 	WCrt(ba, CRT_ID_UNDERLINE_LOC,    0x07);
637 	WCrt(ba, CRT_ID_MODE_CONTROL,     0xa3);
638 	WCrt(ba, CRT_ID_LINE_COMPARE,     0xff);
639 	/*
640 	 * ET4000 special
641 	 */
642 	WCrt(ba, CRT_ID_RASCAS_CONFIG,    0x28);
643 	WCrt(ba, CTR_ID_EXT_START,        0x00);
644 	WCrt(ba, CRT_ID_6845_COMPAT,      0x08);
645 	WCrt(ba, CRT_ID_VIDEO_CONFIG1,    0x73);
646 	WCrt(ba, CRT_ID_VIDEO_CONFIG2,    0x09);
647 
648 	WCrt(ba, CRT_ID_HOR_OVERFLOW,     0x00);
649 
650 	WGfx(ba, GCT_ID_SET_RESET,        0x00);
651 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
652 	WGfx(ba, GCT_ID_COLOR_COMPARE,    0x00);
653 	WGfx(ba, GCT_ID_DATA_ROTATE,      0x00);
654 	WGfx(ba, GCT_ID_READ_MAP_SELECT,  0x00);
655 	WGfx(ba, GCT_ID_GRAPHICS_MODE,    0x00);
656 	WGfx(ba, GCT_ID_MISC,             0x01);
657 	WGfx(ba, GCT_ID_COLOR_XCARE,      0x0f);
658 	WGfx(ba, GCT_ID_BITMASK,          0xff);
659 
660 	vgaw(ba, GREG_SEGMENTSELECT,      0x00);
661 
662 	for (i = 0; i < 0x10; i++)
663 		WAttr(ba, i, i);
664 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL,  0x01);
665 	WAttr(ba, ACT_ID_OVERSCAN_COLOR,  0x00);
666 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
667 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
668 	WAttr(ba, ACT_ID_COLOR_SELECT,    0x00);
669 	WAttr(ba, ACT_ID_MISCELLANEOUS,   0x00);
670 
671 	vgaw(ba, VDAC_MASK, 0xff);
672 
673 #if 0 /* XXX: We like to do this: */
674 	delay(200000);
675 #else /* But because we run before the delay is initialized: */
676 	for(i = 0; i < 4000; i++)
677 		for(j =  0; j < 400; j++);
678 #endif
679 
680 	/*
681 	 * colors initially set to greyscale
682 	 */
683 	vgaw(ba, VDAC_ADDRESS_W, 0);
684 	for (i = 255; i >= 0; i--) {
685 		vgaw(ba, VDAC_DATA, i);
686 		vgaw(ba, VDAC_DATA, i);
687 		vgaw(ba, VDAC_DATA, i);
688 	}
689 }
690 
691 void
692 et_hwsave(et_regs)
693 et_sv_reg_t	*et_regs;
694 {
695 	volatile u_char *ba;
696 	int		i, s;
697 
698 	ba = et_priv.regkva;
699 
700 	s = splhigh();
701 
702 	/*
703 	 * General VGA registers
704 	 */
705 	et_regs->misc_output = vgar(ba, GREG_MISC_OUTPUT_R);
706 	for(i = 0; i < 25; i++)
707 		et_regs->crt[i]  = RCrt(ba, i);
708 	for(i = 0; i < 21; i++)
709 		et_regs->attr[i] = RAttr(ba, i | 0x20);
710 	for(i = 0; i < 9; i++)
711 		et_regs->grf[i]  = RGfx(ba, i);
712 	for(i = 0; i < 5; i++)
713 		et_regs->seq[i]  = RSeq(ba, i);
714 
715 	/*
716 	 * ET4000 extensions
717 	 */
718 	et_regs->ext_start   = RCrt(ba, CTR_ID_EXT_START);
719 	et_regs->compat_6845 = RCrt(ba, CRT_ID_6845_COMPAT);
720 	et_regs->overfl_high = RCrt(ba, CRT_ID_OVERFLOW_HIGH);
721 	et_regs->hor_overfl  = RCrt(ba, CRT_ID_HOR_OVERFLOW);
722 	et_regs->state_ctl   = RSeq(ba, SEQ_ID_STATE_CONTROL);
723 	et_regs->aux_mode    = RSeq(ba, SEQ_ID_AUXILIARY_MODE);
724 	et_regs->seg_sel     = vgar(ba, GREG_SEGMENTSELECT);
725 
726 	s = splx(s);
727 }
728 
729 void
730 et_hwrest(et_regs)
731 et_sv_reg_t	*et_regs;
732 {
733 	volatile u_char *ba;
734 	int		i, s;
735 
736 	ba = et_priv.regkva;
737 
738 	s = splhigh();
739 
740 	vgaw(ba, GREG_SEGMENTSELECT, 0);
741 	vgaw(ba, GREG_MISC_OUTPUT_W, et_regs->misc_output);
742 
743 	/*
744 	 * General VGA registers
745 	 */
746 	for(i = 0; i < 5; i++)
747 		WSeq(ba, i, et_regs->seq[i]);
748 
749 	/*
750 	 * Make sure we're allowed to write all crt-registers
751 	 */
752 	WCrt(ba, CRT_ID_END_VER_RETR,
753 		et_regs->crt[CRT_ID_END_VER_RETR] & 0x7f);
754 	for(i = 0; i < 25; i++)
755 		WCrt(ba, i, et_regs->crt[i]);
756 	for(i = 0; i < 9; i++)
757 		WGfx(ba, i, et_regs->grf[i]);
758 	for(i = 0; i < 21; i++)
759 		WAttr(ba, i | 0x20, et_regs->attr[i]);
760 
761 	/*
762 	 * ET4000 extensions
763 	 */
764 	WSeq(ba, SEQ_ID_STATE_CONTROL, et_regs->state_ctl);
765 	WSeq(ba, SEQ_ID_AUXILIARY_MODE, et_regs->aux_mode);
766 	WCrt(ba, CTR_ID_EXT_START, et_regs->ext_start);
767 	WCrt(ba, CRT_ID_6845_COMPAT, et_regs->compat_6845);
768 	WCrt(ba, CRT_ID_OVERFLOW_HIGH, et_regs->overfl_high);
769 	WCrt(ba, CRT_ID_HOR_OVERFLOW, et_regs->hor_overfl);
770 	vgaw(ba, GREG_SEGMENTSELECT, et_regs->seg_sel);
771 
772 	i = et_regs->seq[SEQ_ID_CLOCKING_MODE] & ~0x20;
773 	WSeq(ba, SEQ_ID_CLOCKING_MODE, i);
774 
775 	s = splx(s);
776 }
777