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