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