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