xref: /netbsd-src/sys/arch/atari/dev/grfabs_et.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: grfabs_et.c,v 1.23 2004/02/13 11:36:11 wiz 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.23 2004/02/13 11:36:11 wiz 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 
468 		/* release KEY */
469 		vgaw(ba, GREG_DISPMODECONTROL, 0x00);
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  = (volatile caddr_t)pci_io_addr;
479 	et_priv.memkva  = (volatile caddr_t)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