Home | History | Annotate | Line # | Download | only in vme
et4000.c revision 1.10
      1 /*	$NetBSD: et4000.c,v 1.10 2002/10/23 09:10:55 jdolecek Exp $	*/
      2 /*-
      3  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      4  * All rights reserved.
      5  *
      6  * This code is derived from software contributed to The NetBSD Foundation
      7  * by Julian Coleman.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *        This product includes software developed by the NetBSD
     20  *        Foundation, Inc. and its contributors.
     21  * 4. Neither the name of The NetBSD Foundation nor the names of its
     22  *    contributors may be used to endorse or promote products derived
     23  *    from this software without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     26  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 /*
     39  * Thanks to:
     40  *	Leo Weppelman
     41  *	'Maximum Entropy'
     42  *	Thomas Gerner
     43  *	Juergen Orscheidt
     44  * for their help and for code that I could refer to when writing this driver.
     45  *
     46  * Defining DEBUG_ET4000 will cause the driver to *always* attach.  Use for
     47  * debugging register settings.
     48  */
     49 
     50 /*
     51 #define DEBUG_ET4000
     52 */
     53 
     54 #include <sys/param.h>
     55 #include <sys/ioctl.h>
     56 #include <sys/queue.h>
     57 #include <sys/malloc.h>
     58 #include <sys/device.h>
     59 #include <sys/systm.h>
     60 #include <sys/conf.h>
     61 #include <sys/event.h>
     62 #include <atari/vme/vmevar.h>
     63 
     64 #include <machine/iomap.h>
     65 #include <machine/video.h>
     66 #include <machine/mfp.h>
     67 #include <machine/cpu.h>
     68 #include <atari/atari/device.h>
     69 #include <atari/dev/grfioctl.h>
     70 #include <atari/dev/grf_etreg.h>
     71 
     72 /*
     73  * Allow a 8Kb io-region and a 1MB frame buffer to be mapped. This
     74  * is more or less required by the XFree server.  The X server also
     75  * requires that the frame buffer be mapped above 0x3fffff.
     76  */
     77 #define REG_MAPPABLE	(8 * 1024)		/* 0x2000 */
     78 #define FRAME_MAPPABLE	(1 * 1024 * 1024)	/* 0x100000 */
     79 #define FRAME_BASE	(4 * 1024 * 1024)	/* 0x400000 */
     80 #define VGA_MAPPABLE	(128 * 1024)		/* 0x20000 */
     81 #define VGA_BASE	0xa0000
     82 
     83 static int	et_vme_match __P((struct device *, struct cfdata *, void *));
     84 static void	et_vme_attach __P((struct device *, struct device *, void *));
     85 static int	et_probe_addresses __P((struct vme_attach_args *));
     86 static void	et_start __P((bus_space_tag_t *, bus_space_handle_t *, int *,
     87 		    u_char *));
     88 static void	et_stop __P((bus_space_tag_t *, bus_space_handle_t *, int *,
     89 		    u_char *));
     90 static int	et_detect __P((bus_space_tag_t *, bus_space_tag_t *,
     91 		    bus_space_handle_t *, bus_space_handle_t *, u_int));
     92 
     93 int		eton __P((dev_t));
     94 int		etoff __P((dev_t));
     95 
     96 /* Register and screen memory addresses for ET4000 based VME cards */
     97 static struct et_addresses {
     98 	u_long io_addr;
     99 	u_long io_size;
    100 	u_long mem_addr;
    101 	u_long mem_size;
    102 } etstd[] = {
    103 	{ 0xfebf0000, REG_MAPPABLE, 0xfec00000, FRAME_MAPPABLE }, /* Crazy Dots VME & II */
    104 	{ 0xfed00000, REG_MAPPABLE, 0xfec00000, FRAME_MAPPABLE }, /* Spektrum I & HC */
    105 	{ 0xfed80000, REG_MAPPABLE, 0xfec00000, FRAME_MAPPABLE }  /* Spektrum TC */
    106 };
    107 
    108 #define NETSTD (sizeof(etstd) / sizeof(etstd[0]))
    109 
    110 struct grfabs_et_priv {
    111 	volatile caddr_t	regkva;
    112 	volatile caddr_t	memkva;
    113 	int			regsz;
    114 	int			memsz;
    115 } et_priv;
    116 
    117 struct et_softc {
    118 	struct device sc_dev;
    119 	bus_space_tag_t sc_iot;
    120 	bus_space_tag_t sc_memt;
    121 	bus_space_handle_t sc_ioh;
    122 	bus_space_handle_t sc_memh;
    123 	int sc_flags;
    124 	int sc_iobase;
    125 	int sc_maddr;
    126 	int sc_iosize;
    127 	int sc_msize;
    128 };
    129 
    130 #define ET_SC_FLAGS_INUSE 1
    131 
    132 CFATTACH_DECL(et, sizeof(struct et_softc),
    133     et_vme_match, et_vme_attach, NULL, NULL);
    134 
    135 extern struct cfdriver et_cd;
    136 
    137 dev_type_open(etopen);
    138 dev_type_close(etclose);
    139 dev_type_read(etread);
    140 dev_type_write(etwrite);
    141 dev_type_ioctl(etioctl);
    142 dev_type_mmap(etmmap);
    143 
    144 const struct cdevsw et_cdevsw = {
    145 	etopen, etclose, etread, etwrite, etioctl,
    146 	nostop, notty, nopoll, etmmap, nokqfilter,
    147 };
    148 
    149 /*
    150  * Look for a ET4000 (Crazy Dots) card on the VME bus.  We might
    151  * match Spektrum cards too (untested).
    152  */
    153 int
    154 et_vme_match(pdp, cfp, auxp)
    155 	struct device	*pdp;
    156 	struct cfdata	*cfp;
    157 	void		*auxp;
    158 {
    159 	struct vme_attach_args *va = auxp;
    160 
    161 	return(et_probe_addresses(va));
    162 }
    163 
    164 static int
    165 et_probe_addresses(va)
    166 	struct vme_attach_args *va;
    167 {
    168 	int i, found = 0;
    169 	bus_space_tag_t iot;
    170 	bus_space_tag_t memt;
    171 	bus_space_handle_t ioh;
    172 	bus_space_handle_t memh;
    173 
    174 	iot = va->va_iot;
    175 	memt = va->va_memt;
    176 
    177 /* Loop around our possible addresses looking for a match */
    178 	for (i = 0; i < NETSTD; i++) {
    179 		struct et_addresses *et_ap = &etstd[i];
    180 		struct vme_attach_args vat = *va;
    181 
    182 		if (vat.va_irq != VMECF_IRQ_DEFAULT) {
    183 			printf("et probe: config error: no irq support\n");
    184 			return(0);
    185 		}
    186 		if (vat.va_iobase == VMECF_IOPORT_DEFAULT)
    187 			vat.va_iobase = et_ap->io_addr;
    188 		if (vat.va_maddr == VMECF_MEM_DEFAULT)
    189 			vat.va_maddr = et_ap->mem_addr;
    190 		if (vat.va_iosize == VMECF_IOSIZE_DEFAULT)
    191 			vat.va_iosize = et_ap->io_size;
    192 		if (vat.va_msize == VMECF_MEMSIZ_DEFAULT)
    193 			vat.va_msize = et_ap->mem_size;
    194 		if (bus_space_map(iot, vat.va_iobase, vat.va_iosize, 0,
    195 				  &ioh)) {
    196 			printf("et probe: cannot map io area\n");
    197 			return(0);
    198 		}
    199 		if (bus_space_map(memt, vat.va_maddr, vat.va_msize,
    200 			  	  BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_CACHEABLE,
    201 			  	  &memh)) {
    202 			bus_space_unmap(iot, ioh, vat.va_iosize);
    203 			printf("et probe: cannot map memory area\n");
    204 			return(0);
    205 		}
    206 		found = et_detect(&iot, &memt, &ioh, &memh, vat.va_msize);
    207 		bus_space_unmap(iot, ioh, vat.va_iosize);
    208 		bus_space_unmap(memt, memh, vat.va_msize);
    209 		if (found) {
    210 			*va = vat;
    211 			return(1);
    212 		}
    213 	}
    214 	return(0);
    215 }
    216 
    217 static void
    218 et_start(iot, ioh, vgabase, saved)
    219 	bus_space_tag_t *iot;
    220 	bus_space_handle_t *ioh;
    221 	int *vgabase;
    222 	u_char *saved;
    223 {
    224 	/* Enable VGA */
    225 	bus_space_write_1(*iot, *ioh, GREG_VIDEOSYSENABLE, 0x01);
    226 	/* Check whether colour (base = 3d0) or mono (base = 3b0) mode */
    227 	*vgabase = (bus_space_read_1(*iot, *ioh, GREG_MISC_OUTPUT_R) & 0x01)
    228 	    ? 0x3d0 : 0x3b0;
    229 	/* Enable 'Tseng Extensions' - writes to CRTC and ATC[16] */
    230 	bus_space_write_1(*iot, *ioh, GREG_HERCULESCOMPAT, 0x03);
    231 	bus_space_write_1(*iot, *ioh, *vgabase + 0x08, 0xa0);
    232 	/* Set up 16 bit I/O, memory, Tseng addressing and linear mapping */
    233 	bus_space_write_1(*iot, *ioh, *vgabase + 0x04, 0x36);
    234 	bus_space_write_1(*iot, *ioh, *vgabase + 0x05, 0xf0);
    235 	/* Enable writes to CRTC[0..7] */
    236 	bus_space_write_1(*iot, *ioh, *vgabase + 0x04, 0x11);
    237 	*saved = bus_space_read_1(*iot, *ioh, *vgabase + 0x05);
    238 	bus_space_write_1(*iot, *ioh, *vgabase + 0x05, *saved & 0x7f);
    239 	/* Map all memory for video modes */
    240 	bus_space_write_1(*iot, *ioh, 0x3ce, 0x06);
    241 	bus_space_write_1(*iot, *ioh, 0x3cf, 0x01);
    242 }
    243 
    244 static void
    245 et_stop(iot, ioh, vgabase, saved)
    246 	bus_space_tag_t *iot;
    247 	bus_space_handle_t *ioh;
    248 	int *vgabase;
    249 	u_char *saved;
    250 {
    251 	/* Restore writes to CRTC[0..7] */
    252 	bus_space_write_1(*iot, *ioh, *vgabase + 0x04, 0x11);
    253 	*saved = bus_space_read_1(*iot, *ioh, *vgabase + 0x05);
    254 	bus_space_write_1(*iot, *ioh, *vgabase + 0x05, *saved | 0x80);
    255 	/* Disable 'Tseng Extensions' */
    256 	bus_space_write_1(*iot, *ioh, *vgabase + 0x08, 0x00);
    257 	bus_space_write_1(*iot, *ioh, GREG_DISPMODECONTROL, 0x29);
    258 	bus_space_write_1(*iot, *ioh, GREG_HERCULESCOMPAT, 0x01);
    259 }
    260 
    261 static int
    262 et_detect(iot, memt, ioh, memh, memsize)
    263 	bus_space_tag_t *iot, *memt;
    264 	bus_space_handle_t *ioh, *memh;
    265 	u_int memsize;
    266 {
    267 	u_char orig, new, saved;
    268 	int vgabase;
    269 
    270 	/* Test accessibility of registers and memory */
    271 	if(!bus_space_peek_1(*iot, *ioh, GREG_STATUS1_R))
    272 		return(0);
    273 	if(!bus_space_peek_1(*memt, *memh, 0))
    274 		return(0);
    275 
    276 	et_start(iot, ioh, &vgabase, &saved);
    277 
    278 	/* Is the card a Tseng card?  Check read/write of ATC[16] */
    279 	(void)bus_space_read_1(*iot, *ioh, vgabase + 0x0a);
    280 	bus_space_write_1(*iot, *ioh, ACT_ADDRESS, 0x16 | 0x20);
    281 	orig = bus_space_read_1(*iot, *ioh, ACT_ADDRESS_R);
    282 	bus_space_write_1(*iot, *ioh, ACT_ADDRESS_W, (orig ^ 0x10));
    283 	bus_space_write_1(*iot, *ioh, ACT_ADDRESS, 0x16 | 0x20);
    284 	new = bus_space_read_1(*iot, *ioh, ACT_ADDRESS_R);
    285 	bus_space_write_1(*iot, *ioh, ACT_ADDRESS, orig);
    286 	if (new != (orig ^ 0x10)) {
    287 #ifdef DEBUG_ET4000
    288 		printf("et4000: ATC[16] failed (%x != %x)\n",
    289 		    new, (orig ^ 0x10));
    290 #else
    291 		et_stop(iot, ioh, &vgabase, &saved);
    292 		return(0);
    293 #endif
    294 	}
    295 	/* Is the card and ET4000?  Check read/write of CRTC[33] */
    296 	bus_space_write_1(*iot, *ioh, vgabase + 0x04, 0x33);
    297 	orig = bus_space_read_1(*iot, *ioh, vgabase + 0x05);
    298 	bus_space_write_1(*iot, *ioh, vgabase + 0x05, (orig ^ 0x0f));
    299 	new = bus_space_read_1(*iot, *ioh, vgabase + 0x05);
    300 	bus_space_write_1(*iot, *ioh, vgabase + 0x05, orig);
    301 	if (new != (orig ^ 0x0f)) {
    302 #ifdef DEBUG_ET4000
    303 		printf("et4000: CRTC[33] failed (%x != %x)\n",
    304 		    new, (orig ^ 0x0f));
    305 #else
    306 		et_stop(iot, ioh, &vgabase, &saved);
    307 		return(0);
    308 #endif
    309 	}
    310 
    311 	/* Set up video memory so we can read & write it */
    312 	bus_space_write_1(*iot, *ioh, 0x3c4, 0x04);
    313 	bus_space_write_1(*iot, *ioh, 0x3c5, 0x06);
    314 	bus_space_write_1(*iot, *ioh, 0x3c4, 0x07);
    315 	bus_space_write_1(*iot, *ioh, 0x3c5, 0xa8);
    316 	bus_space_write_1(*iot, *ioh, 0x3ce, 0x01);
    317 	bus_space_write_1(*iot, *ioh, 0x3cf, 0x00);
    318 	bus_space_write_1(*iot, *ioh, 0x3ce, 0x03);
    319 	bus_space_write_1(*iot, *ioh, 0x3cf, 0x00);
    320 	bus_space_write_1(*iot, *ioh, 0x3ce, 0x05);
    321 	bus_space_write_1(*iot, *ioh, 0x3cf, 0x40);
    322 
    323 #define TEST_PATTERN 0xa5a5a5a5
    324 
    325 	bus_space_write_4(*memt, *memh, 0x0, TEST_PATTERN);
    326 	if (bus_space_read_4(*memt, *memh, 0x0) != TEST_PATTERN)
    327 	{
    328 #ifdef DEBUG_ET4000
    329 		printf("et4000: Video base write/read failed\n");
    330 #else
    331 		et_stop(iot, ioh, &vgabase, &saved);
    332 		return(0);
    333 #endif
    334 	}
    335 	bus_space_write_4(*memt, *memh, memsize - 4, TEST_PATTERN);
    336 	if (bus_space_read_4(*memt, *memh, memsize - 4) != TEST_PATTERN)
    337 	{
    338 #ifdef DEBUG_ET4000
    339 		printf("et4000: Video top write/read failed\n");
    340 #else
    341 		et_stop(iot, ioh, &vgabase, &saved);
    342 		return(0);
    343 #endif
    344 	}
    345 
    346 	et_stop(iot, ioh, &vgabase, &saved);
    347 	return(1);
    348 }
    349 
    350 static void
    351 et_vme_attach(parent, self, aux)
    352 	struct device *parent, *self;
    353 	void *aux;
    354 {
    355 	struct et_softc *sc = (struct et_softc *)self;
    356 	struct vme_attach_args *va = aux;
    357 	bus_space_handle_t ioh;
    358 	bus_space_handle_t memh;
    359 
    360 	printf("\n");
    361 
    362 	if (bus_space_map(va->va_iot, va->va_iobase, va->va_iosize, 0, &ioh))
    363 		panic("et attach: cannot map io area");
    364 	if (bus_space_map(va->va_memt, va->va_maddr, va->va_msize, 0, &memh))
    365 		panic("et attach: cannot map mem area");
    366 
    367 	sc->sc_iot = va->va_iot;
    368 	sc->sc_ioh = ioh;
    369 	sc->sc_memt = va->va_memt;
    370 	sc->sc_memh = memh;
    371 	sc->sc_flags = 0;
    372 	sc->sc_iobase = va->va_iobase;
    373 	sc->sc_maddr = va->va_maddr;
    374 	sc->sc_iosize = va->va_iosize;
    375 	sc->sc_msize = va->va_msize;
    376 
    377 	et_priv.regkva = (volatile caddr_t)ioh;
    378 	et_priv.memkva = (volatile caddr_t)memh;
    379 	et_priv.regsz = va->va_iosize;
    380 	et_priv.memsz = va->va_msize;
    381 }
    382 
    383 int
    384 etopen(dev, flags, devtype, p)
    385 	dev_t dev;
    386 	int flags, devtype;
    387 	struct proc *p;
    388 {
    389 	struct et_softc *sc;
    390 
    391 	if (minor(dev) >= et_cd.cd_ndevs)
    392 		return(ENXIO);
    393 	sc = et_cd.cd_devs[minor(dev)];
    394 	if (sc->sc_flags & ET_SC_FLAGS_INUSE)
    395 		return(EBUSY);
    396 	sc->sc_flags |= ET_SC_FLAGS_INUSE;
    397 	return(0);
    398 }
    399 
    400 int
    401 etclose(dev, flags, devtype, p)
    402 	dev_t dev;
    403 	int flags, devtype;
    404 	struct proc *p;
    405 {
    406 	struct et_softc *sc;
    407 
    408 	/*
    409 	 * XXX: Should we reset to a default mode?
    410 	 */
    411 	sc = et_cd.cd_devs[minor(dev)];
    412 	sc->sc_flags &= ~ET_SC_FLAGS_INUSE;
    413 	return(0);
    414 }
    415 
    416 int
    417 etread(dev, uio, flags)
    418 	dev_t dev;
    419 	struct uio *uio;
    420 	int flags;
    421 {
    422 	return(EINVAL);
    423 }
    424 
    425 int
    426 etwrite(dev, uio, flags)
    427 	dev_t dev;
    428 	struct uio *uio;
    429 	int flags;
    430 {
    431 	return(EINVAL);
    432 }
    433 
    434 int
    435 etioctl(dev, cmd, data, flags, p)
    436 	dev_t dev;
    437 	u_long cmd;
    438 	caddr_t data;
    439 	int flags;
    440 	struct proc *p;
    441 {
    442 	struct grfinfo g_display;
    443 	struct et_softc *sc;
    444 
    445 	sc = et_cd.cd_devs[minor(dev)];
    446 	switch (cmd) {
    447 	case GRFIOCON:
    448 		return(0);
    449 		break;
    450 	case GRFIOCOFF:
    451 		return(0);
    452 		break;
    453 	case GRFIOCGINFO:
    454 		g_display.gd_fbaddr = (caddr_t) (sc->sc_maddr);
    455 		g_display.gd_fbsize = sc->sc_msize;
    456 		g_display.gd_linbase = FRAME_BASE;
    457 		g_display.gd_regaddr = (caddr_t) (sc->sc_iobase);
    458 		g_display.gd_regsize = sc->sc_iosize;
    459 		g_display.gd_vgaaddr = (caddr_t) (sc->sc_maddr);
    460 		g_display.gd_vgasize = VGA_MAPPABLE;
    461 		g_display.gd_vgabase = VGA_BASE;
    462 		g_display.gd_colors = 16;
    463 		g_display.gd_planes = 4;
    464 		g_display.gd_fbwidth = 640;	/* XXX: should be 'unknown' */
    465 		g_display.gd_fbheight = 400;	/* XXX: should be 'unknown' */
    466 		g_display.gd_fbx = 0;
    467 		g_display.gd_fby = 0;
    468 		g_display.gd_dwidth = 0;
    469 		g_display.gd_dheight = 0;
    470 		g_display.gd_dx = 0;
    471 		g_display.gd_dy = 0;
    472 		g_display.gd_bank_size = 0;
    473 		bcopy((caddr_t)&g_display, data, sizeof(struct grfinfo));
    474 		break;
    475 	case GRFIOCMAP:
    476 		return(EINVAL);
    477 		break;
    478 	case GRFIOCUNMAP:
    479 		return(EINVAL);
    480 		break;
    481 	default:
    482 		return(EINVAL);
    483 		break;
    484 	}
    485 	return(0);
    486 }
    487 
    488 paddr_t
    489 etmmap(dev, offset, prot)
    490 	dev_t dev;
    491 	off_t offset;
    492 	int prot;
    493 {
    494 	struct et_softc *sc;
    495 
    496 	sc = et_cd.cd_devs[minor(dev)];
    497 
    498 	/*
    499 	 * control registers
    500 	 * mapped from offset 0x0 to REG_MAPPABLE
    501 	 */
    502 	if (offset >= 0 && offset <= sc->sc_iosize)
    503 		return(m68k_btop(sc->sc_iobase + offset));
    504 
    505 	/*
    506 	 * VGA memory
    507 	 * mapped from offset 0xa0000 to 0xc0000
    508 	 */
    509 	if (offset >= VGA_BASE && offset < (VGA_MAPPABLE + VGA_BASE))
    510 		return(m68k_btop(sc->sc_maddr + offset - VGA_BASE));
    511 
    512 	/*
    513 	 * frame buffer
    514 	 * mapped from offset 0x400000 to 0x4fffff
    515 	 */
    516 	if (offset >= FRAME_BASE && offset < sc->sc_msize + FRAME_BASE)
    517 		return(m68k_btop(sc->sc_maddr + offset - FRAME_BASE));
    518 
    519 	return(-1);
    520 }
    521 
    522 int
    523 eton(dev)
    524 	dev_t dev;
    525 {
    526 	struct et_softc *sc;
    527 
    528 	if (minor(dev) >= et_cd.cd_ndevs)
    529 		return(ENXIO);
    530 	sc = et_cd.cd_devs[minor(dev)];
    531 	if (!sc)
    532 		return(ENXIO);
    533 	return(0);
    534 }
    535 
    536 int
    537 etoff(dev)
    538 	dev_t dev;
    539 {
    540 	return(0);
    541 }
    542 
    543