xref: /netbsd-src/sys/arch/atari/dev/grfabs_et.c (revision ce099b40997c43048fb78bd578195f81d2456523)
1 /*	$NetBSD: grfabs_et.c,v 1.27 2007/03/06 14:40:25 tsutsui 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.27 2007/03/06 14:40:25 tsutsui 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 	void			*regkva;
158 	void 			*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 	volatile u_char *ba;
254 
255 	if (!atari_realconfig)
256 		return;
257 
258 	ba = et_priv.regkva;
259 
260 	if (RGfx(ba, GCT_ID_MISC) & 1) {
261 #if 0 /* XXX: Can't use printf here.... */
262 		printf("et_save_view: Don't know how to save"
263 			" a graphics mode\n");
264 #endif
265 		return;
266 	}
267 	if (v->save_area == NULL)
268 		v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_NOWAIT);
269 
270 	/*
271 	 * Calculate the size of the copy
272 	 */
273 	font_height = RCrt(ba, CRT_ID_MAX_ROW_ADDRESS) & 0x1f;
274 	sv_size = bm->bytes_per_row * (bm->rows / (font_height + 1));
275 	sv_size = min(SAVEBUF_SIZE, sv_size);
276 
277 	/*
278 	 * Save all we need to know....
279 	 */
280 	sa  = (save_area_t *)v->save_area;
281 	et_hwsave(&sa->sv_regs);
282 	sa->fb_size = sv_size;
283 	src = (u_short *)bm->plane;
284 	dst = sa->sv_fb;
285 	while (sv_size--)
286 		*dst++ = *src++;
287 	bm->plane = (u_char *)sa->sv_fb;
288 }
289 
290 void
291 et_free_view(v)
292 view_t *v;
293 {
294 	if(v) {
295 		et_remove_view(v);
296 		if (v->colormap != &gra_con_cmap)
297 			free(v->colormap, M_DEVBUF);
298 		if (v->save_area != NULL)
299 			free(v->save_area, M_DEVBUF);
300 		if (v != &gra_con_view) {
301 			free(v->bitmap, M_DEVBUF);
302 			free(v, M_DEVBUF);
303 		}
304 	}
305 }
306 
307 static int
308 et_use_colormap(v, cm)
309 view_t		*v;
310 colormap_t	*cm;
311 {
312 	return (0); /* XXX: Nothing here for now... */
313 }
314 
315 static view_t *
316 et_alloc_view(mode, dim, depth)
317 dmode_t	*mode;
318 dimen_t	*dim;
319 u_char   depth;
320 {
321 	view_t		*v;
322 	bmap_t		*bm;
323 	box_t		box;
324 	save_area_t	*sa;
325 
326 	if (!atari_realconfig) {
327 		v  = &gra_con_view;
328 		bm = &con_bm;
329 	}
330 	else {
331 		v  = malloc(sizeof(*v), M_DEVBUF, M_WAITOK);
332 		bm = malloc(sizeof(*bm), M_DEVBUF, M_WAITOK);
333 	}
334 	v->bitmap = bm;
335 
336 	/*
337 	 * Initialize the bitmap
338 	 */
339 	bm->plane         = et_priv.memkva;
340 	bm->vga_address   = (void *)kvtop(et_priv.memkva);
341 	bm->vga_base      = VGA_BASE;
342 	bm->hw_address    = (void *)(PCI_MEM_PHYS | et_priv.linbase);
343 	bm->lin_base      = et_priv.linbase;
344 	bm->regs          = et_priv.regkva;
345 	bm->hw_regs       = (void *)kvtop(et_priv.regkva);
346 	bm->reg_size      = REG_MAPPABLE;
347 	bm->phys_mappable = FRAME_MAPPABLE;
348 	bm->vga_mappable  = VGA_MAPPABLE;
349 
350 	bm->bytes_per_row = (mode->size.width * depth) / NBBY;
351 	bm->rows          = mode->size.height;
352 	bm->depth         = depth;
353 
354 	/*
355 	 * Allocate a save_area.
356 	 * Note: If atari_realconfig is false, no save area is (can be)
357 	 * allocated. This means that the plane is the video memory,
358 	 * which is what's wanted in this case.
359 	 */
360 	if (atari_realconfig) {
361 		v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_WAITOK);
362 		sa           = (save_area_t*)v->save_area;
363 		sa->fb_size  = 0;
364 		bm->plane    = (u_char *)sa->sv_fb;
365 		et_loadmode(mode->data, &sa->sv_regs);
366 	}
367 	else v->save_area = NULL;
368 
369 	v->colormap = alloc_colormap(mode);
370 	if (v->colormap) {
371 		INIT_BOX(&box,0,0,mode->size.width,mode->size.height);
372 		init_view(v, bm, mode, &box);
373 		return (v);
374 	}
375 	if (v != &gra_con_view) {
376 		free(v, M_DEVBUF);
377 		free(bm, M_DEVBUF);
378 	}
379 	return (NULL);
380 }
381 
382 static void
383 init_view(v, bm, mode, dbox)
384 view_t	*v;
385 bmap_t	*bm;
386 dmode_t	*mode;
387 box_t	*dbox;
388 {
389 	v->bitmap    = bm;
390 	v->mode      = mode;
391 	v->flags     = 0;
392 	bcopy(dbox, &v->display, sizeof(box_t));
393 }
394 
395 /* XXX: No more than a stub... */
396 static colormap_t *
397 alloc_colormap(dm)
398 dmode_t		*dm;
399 {
400 	colormap_t	*cm;
401 	int		i;
402 
403 	cm = &gra_con_cmap;
404 	cm->entry = gra_con_colors;
405 
406 	cm->first = 0;
407 	cm->size  = 2;
408 
409 	for (i = 0; i < 2; i++)
410 		cm->entry[i] = gra_def_color16[i % 16];
411 	return (cm);
412 }
413 
414 /*
415  * Go look for a VGA card on the PCI-bus. This search is a
416  * stripped down version of the PCI-probe. It only looks on
417  * bus0 for et4000/et6000 cards. The first card found is used.
418  */
419 int
420 et_probe_card()
421 {
422 	pci_chipset_tag_t	pc = NULL; /* XXX */
423 	pcitag_t		tag;
424 	int			device, found, id, maxndevs;
425 
426 	found    = 0;
427 	tag      = 0;
428 	id       = 0;
429 	maxndevs = pci_bus_maxdevs(pc, 0);
430 
431 	for (device = 0; !found && (device < maxndevs); device++) {
432 
433 		tag = pci_make_tag(pc, 0, device, 0);
434 		id  = pci_conf_read(pc, tag, PCI_ID_REG);
435 		if (id == 0 || id == 0xffffffff)
436 			continue;
437 		switch (PCI_PRODUCT(id)) {
438 			case PCI_PRODUCT_TSENG_ET6000:
439 			case PCI_PRODUCT_TSENG_ET4000_W32P_A:
440 			case PCI_PRODUCT_TSENG_ET4000_W32P_B:
441 			case PCI_PRODUCT_TSENG_ET4000_W32P_C:
442 			case PCI_PRODUCT_TSENG_ET4000_W32P_D:
443 				found = 1;
444 				break;
445 			default:
446 				break;
447 		}
448 	}
449 	if (!found)
450 		return (0);
451 
452 	if (PCI_PRODUCT(id) ==  PCI_PRODUCT_TSENG_ET6000)
453 		et_priv.board_type = BT_ET6000;
454 	else {
455 #ifdef ET4000_HAS_2MB_MEM
456 		volatile u_char *ba;
457 #endif
458 
459 		et_priv.board_type = BT_ET4000;
460 
461 #ifdef ET4000_HAS_2MB_MEM
462 		/* set KEY to access the tseng private registers */
463 		ba = (volatile void *)pci_io_addr;
464 		vgaw(ba, GREG_HERCULESCOMPAT, 0x03);
465 		vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
466 
467 		/* enable memory interleave */
468 		WCrt(ba, CRT_ID_RASCAS_CONFIG, 0xa0);
469 		WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x89);
470 #endif
471 	}
472 
473 	et_priv.pci_tag = tag;
474 
475 	/*
476 	 * The things below are setup in atari_init.c
477 	 */
478 	et_priv.regkva  = (void *)pci_io_addr;
479 	et_priv.memkva  = (void *)pci_mem_addr;
480 	et_priv.linbase = PCI_LINMEMBASE; /* XXX pci_conf_read??? */
481 	et_priv.memsz   = PCI_VGA_SIZE;
482 	et_priv.regsz   = PCI_IO_SIZE;
483 
484 	if (!atari_realconfig) {
485 		et_loadmode(&hw_modes[0], NULL);
486 		return (1);
487 	}
488 
489 	return (1);
490 }
491 
492 static void
493 et_loadmode(mode, regs)
494 struct grfvideo_mode	*mode;
495 et_sv_reg_t		*regs;
496 {
497 	unsigned short	HDE, VDE;
498 	int	    	lace, dblscan;
499 	int     	uplim, lowlim;
500 	int		i;
501 	unsigned char	clock, tmp;
502 	volatile u_char	*ba;
503 	et_sv_reg_t	loc_regs;
504 
505 	if (regs == NULL)
506 		regs = &loc_regs;
507 
508 	ba  = et_priv.regkva;
509 	HDE = mode->disp_width / 8 - 1;
510 	VDE = mode->disp_height - 1;
511 
512 	/* figure out whether lace or dblscan is needed */
513 
514 	uplim   = mode->disp_height + (mode->disp_height / 4);
515 	lowlim  = mode->disp_height - (mode->disp_height / 4);
516 	lace    = (((mode->vtotal * 2) > lowlim)
517 		   && ((mode->vtotal * 2) < uplim)) ? 1 : 0;
518 	dblscan = (((mode->vtotal / 2) > lowlim)
519 		   && ((mode->vtotal / 2) < uplim)) ? 1 : 0;
520 
521 	/* adjustments */
522 	if (lace)
523 		VDE /= 2;
524 
525 	regs->misc_output = 0x23; /* Page 0, Color mode */
526 	regs->seg_sel     = 0x00;
527 	regs->state_ctl   = 0x00;
528 
529 	regs->seq[SEQ_ID_RESET]           = 0x03; /* reset off		*/
530 	regs->seq[SEQ_ID_CLOCKING_MODE]   = 0x21; /* Turn off screen	*/
531 	regs->seq[SEQ_ID_MAP_MASK]        = 0xff; /* CPU writes all planes*/
532 	regs->seq[SEQ_ID_CHAR_MAP_SELECT] = 0x00; /* Char. generator 0	*/
533 	regs->seq[SEQ_ID_MEMORY_MODE]     = 0x0e; /* Seq. Memory mode	*/
534 
535 	/*
536 	 * Set the clock...
537 	 */
538 	for(clock = ET_NUMCLOCKS-1; clock > 0; clock--) {
539 		if (et_clockfreqs[clock] <= mode->pixel_clock)
540 			break;
541 	}
542 	regs->misc_output |= (clock & 3) << 2;
543 	regs->aux_mode     = 0xb4 | ((clock & 8) << 3);
544 	regs->compat_6845  = (clock & 4) ? 0x0a : 0x08;
545 
546 	/*
547 	 * The display parameters...
548 	 */
549 	regs->crt[CRT_ID_HOR_TOTAL]        =  mode->htotal;
550 	regs->crt[CRT_ID_HOR_DISP_ENA_END] = ((HDE >= mode->hblank_start)
551 						? mode->hblank_stop - 1
552 						: HDE);
553 	regs->crt[CRT_ID_START_HOR_BLANK]  = mode->hblank_start;
554 	regs->crt[CRT_ID_END_HOR_BLANK]    = (mode->hblank_stop & 0x1f) | 0x80;
555 	regs->crt[CRT_ID_START_HOR_RETR]   = mode->hsync_start;
556 	regs->crt[CRT_ID_END_HOR_RETR]     = (mode->hsync_stop & 0x1f)
557 						| ((mode->hblank_stop & 0x20)
558 							? 0x80 : 0x00);
559 	regs->crt[CRT_ID_VER_TOTAL]        = mode->vtotal;
560 	regs->crt[CRT_ID_START_VER_RETR]   = mode->vsync_start;
561 	regs->crt[CRT_ID_END_VER_RETR]     = (mode->vsync_stop & 0x0f) | 0x30;
562 	regs->crt[CRT_ID_VER_DISP_ENA_END] = VDE;
563 	regs->crt[CRT_ID_START_VER_BLANK]  = mode->vblank_start;
564 	regs->crt[CRT_ID_END_VER_BLANK]    = mode->vblank_stop;
565 	regs->crt[CRT_ID_MODE_CONTROL]     = 0xab;
566 	regs->crt[CRT_ID_START_ADDR_HIGH]  = 0x00;
567 	regs->crt[CRT_ID_START_ADDR_LOW]   = 0x00;
568 	regs->crt[CRT_ID_LINE_COMPARE]     = 0xff;
569 	regs->crt[CRT_ID_UNDERLINE_LOC]    = 0x00;
570 	regs->crt[CRT_ID_PRESET_ROW_SCAN]  = 0x00;
571 	regs->crt[CRT_ID_OFFSET]           = mode->disp_width/16;
572 	regs->crt[CRT_ID_MAX_ROW_ADDRESS]  =
573 		0x40 |
574 		(dblscan ? 0x80 : 0x00) |
575 		((mode->vblank_start & 0x200) ? 0x20 : 0x00);
576 	regs->crt[CRT_ID_OVERFLOW] =
577 		0x10 |
578 		((mode->vtotal       & 0x100) ? 0x01 : 0x00) |
579 		((VDE                & 0x100) ? 0x02 : 0x00) |
580 		((mode->vsync_start  & 0x100) ? 0x04 : 0x00) |
581 		((mode->vblank_start & 0x100) ? 0x08 : 0x00) |
582 		((mode->vtotal       & 0x200) ? 0x20 : 0x00) |
583 		((VDE                & 0x200) ? 0x40 : 0x00) |
584 		((mode->vsync_start  & 0x200) ? 0x80 : 0x00);
585 	regs->overfl_high =
586 		0x10 |
587 		((mode->vblank_start & 0x400) ? 0x01 : 0x00) |
588 		((mode->vtotal       & 0x400) ? 0x02 : 0x00) |
589 		((VDE                & 0x400) ? 0x04 : 0x00) |
590 		((mode->vsync_start  & 0x400) ? 0x08 : 0x00) |
591 		(lace ? 0x80 : 0x00);
592 	regs->hor_overfl =
593 		((mode->htotal       & 0x100) ? 0x01 : 0x00) |
594 		((mode->hblank_start & 0x100) ? 0x04 : 0x00) |
595 		((mode->hsync_start  & 0x100) ? 0x10 : 0x00);
596 
597 	regs->grf[GCT_ID_SET_RESET]        = 0x00;
598 	regs->grf[GCT_ID_ENABLE_SET_RESET] = 0x00;
599 	regs->grf[GCT_ID_COLOR_COMPARE]    = 0x00;
600 	regs->grf[GCT_ID_DATA_ROTATE]      = 0x00;
601 	regs->grf[GCT_ID_READ_MAP_SELECT]  = 0x00;
602 	regs->grf[GCT_ID_GRAPHICS_MODE]    = mode->depth == 1 ? 0x00: 0x40;
603 	regs->grf[GCT_ID_MISC]             = 0x01;
604 	regs->grf[GCT_ID_COLOR_XCARE]      = 0x0f;
605 	regs->grf[GCT_ID_BITMASK]          = 0xff;
606 
607 	for (i = 0; i < 0x10; i++)
608 		regs->attr[i] = i;
609 	regs->attr[ACT_ID_ATTR_MODE_CNTL]  = 0x01;
610 	regs->attr[ACT_ID_OVERSCAN_COLOR]  = 0x00;
611 	regs->attr[ACT_ID_COLOR_PLANE_ENA] = 0x0f;
612 	regs->attr[ACT_ID_HOR_PEL_PANNING] = 0x00;
613 	regs->attr[ACT_ID_COLOR_SELECT]    = 0x00;
614 	regs->attr[ACT_ID_MISCELLANEOUS]   = 0x00;
615 
616 	/*
617 	 * XXX: This works for depth == 4. I need some better docs
618 	 * to fix the other modes....
619 	 */
620 	/*
621 	 * What we need would be probe functions for RAMDAC/clock chip
622 	 */
623 	vgar(ba, VDAC_ADDRESS);		/* clear old state */
624 	vgar(ba, VDAC_MASK);
625 	vgar(ba, VDAC_MASK);
626 	vgar(ba, VDAC_MASK);
627 	vgar(ba, VDAC_MASK);
628 
629 	vgaw(ba, VDAC_MASK, 0);		/* set to palette */
630 	vgar(ba, VDAC_ADDRESS);		/* clear state */
631 
632 	vgaw(ba, VDAC_MASK, 0xff);
633 	/*
634 	 * End of depth stuff
635 	 */
636 
637 	/*
638 	 * Compute Hsync & Vsync polarity
639 	 * Note: This seems to be some kind of a black art :-(
640 	 */
641 	tmp = regs->misc_output & 0x3f;
642 #if 1 /* This is according to my BW monitor & Xfree... */
643 	if (VDE < 400)
644 		tmp |= 0x40;	/* -hsync +vsync */
645 	else if (VDE < 480)
646 		tmp |= 0xc0;	/* -hsync -vsync */
647 #else /* This is according to my color monitor.... */
648 	if (VDE < 400)
649 		tmp |= 0x00;	/* +hsync +vsync */
650 	else if (VDE < 480)
651 		tmp |= 0x80;	/* +hsync -vsync */
652 #endif
653 	/* I'm unable to try the rest.... */
654 	regs->misc_output = tmp;
655 
656 	if(regs == &loc_regs)
657 		et_hwrest(regs);
658 }
659 
660 void
661 et_hwsave(et_regs)
662 et_sv_reg_t	*et_regs;
663 {
664 	volatile u_char *ba;
665 	int		i, s;
666 
667 	ba = et_priv.regkva;
668 
669 	s = splhigh();
670 
671 	/*
672 	 * General VGA registers
673 	 */
674 	et_regs->misc_output = vgar(ba, GREG_MISC_OUTPUT_R);
675 	for(i = 0; i < 25; i++)
676 		et_regs->crt[i]  = RCrt(ba, i);
677 	for(i = 0; i < 21; i++)
678 		et_regs->attr[i] = RAttr(ba, i | 0x20);
679 	for(i = 0; i < 9; i++)
680 		et_regs->grf[i]  = RGfx(ba, i);
681 	for(i = 0; i < 5; i++)
682 		et_regs->seq[i]  = RSeq(ba, i);
683 
684 	/*
685 	 * ET4000 extensions
686 	 */
687 	et_regs->ext_start   = RCrt(ba, CTR_ID_EXT_START);
688 	et_regs->compat_6845 = RCrt(ba, CRT_ID_6845_COMPAT);
689 	et_regs->overfl_high = RCrt(ba, CRT_ID_OVERFLOW_HIGH);
690 	et_regs->hor_overfl  = RCrt(ba, CRT_ID_HOR_OVERFLOW);
691 	et_regs->state_ctl   = RSeq(ba, SEQ_ID_STATE_CONTROL);
692 	et_regs->aux_mode    = RSeq(ba, SEQ_ID_AUXILIARY_MODE);
693 	et_regs->seg_sel     = vgar(ba, GREG_SEGMENTSELECT);
694 
695 	splx(s);
696 }
697 
698 void
699 et_hwrest(et_regs)
700 et_sv_reg_t	*et_regs;
701 {
702 	volatile u_char *ba;
703 	int		i, s;
704 
705 	ba = et_priv.regkva;
706 
707 	s = splhigh();
708 
709 	vgaw(ba, GREG_SEGMENTSELECT, 0);
710 	vgaw(ba, GREG_MISC_OUTPUT_W, et_regs->misc_output);
711 
712 	/*
713 	 * General VGA registers
714 	 */
715 	WSeq(ba, SEQ_ID_RESET, 0x01);
716 	for(i = 1; i < 5; i++)
717 		WSeq(ba, i, et_regs->seq[i]);
718 	WSeq(ba, SEQ_ID_RESET, 0x03);
719 
720 	/*
721 	 * Make sure we're allowed to write all crt-registers
722 	 */
723 	WCrt(ba, CRT_ID_END_VER_RETR,
724 		et_regs->crt[CRT_ID_END_VER_RETR] & 0x7f);
725 	for(i = 0; i < 25; i++)
726 		WCrt(ba, i, et_regs->crt[i]);
727 	for(i = 0; i < 9; i++)
728 		WGfx(ba, i, et_regs->grf[i]);
729 	for(i = 0; i < 21; i++)
730 		WAttr(ba, i | 0x20, et_regs->attr[i]);
731 
732 	/*
733 	 * ET4000 extensions
734 	 */
735 	WSeq(ba, SEQ_ID_STATE_CONTROL, et_regs->state_ctl);
736 	WSeq(ba, SEQ_ID_AUXILIARY_MODE, et_regs->aux_mode);
737 	WCrt(ba, CTR_ID_EXT_START, et_regs->ext_start);
738 	WCrt(ba, CRT_ID_6845_COMPAT, et_regs->compat_6845);
739 	WCrt(ba, CRT_ID_OVERFLOW_HIGH, et_regs->overfl_high);
740 	WCrt(ba, CRT_ID_HOR_OVERFLOW, et_regs->hor_overfl);
741 	vgaw(ba, GREG_SEGMENTSELECT, et_regs->seg_sel);
742 
743 	i = et_regs->seq[SEQ_ID_CLOCKING_MODE] & ~0x20;
744 	WSeq(ba, SEQ_ID_CLOCKING_MODE, i);
745 
746 	splx(s);
747 }
748