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