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