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