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