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