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