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