diff options
48 files changed, 11389 insertions, 3340 deletions
diff --git a/sys/arch/vax/if/if_de.c b/sys/arch/vax/if/if_de.c index f9ab288aef9..3a3b16720a2 100644 --- a/sys/arch/vax/if/if_de.c +++ b/sys/arch/vax/if/if_de.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_de.c,v 1.10 1997/09/10 08:28:39 maja Exp $ */ +/* $OpenBSD: if_de.c,v 1.11 2000/04/27 03:14:42 bjc Exp $ */ /* $NetBSD: if_de.c,v 1.27 1997/04/19 15:02:29 ragge Exp $ */ /* @@ -61,8 +61,7 @@ #include <machine/sid.h> #include <net/if.h> -#include <net/netisr.h> -#include <net/route.h> +#include <net/if_dl.h> #ifdef INET #include <netinet/in.h> @@ -112,8 +111,7 @@ struct de_softc { struct device ds_dev; /* Configuration common part */ struct arpcom ds_ac; /* Ethernet common part */ struct dedevice *ds_vaddr; /* Virtual address of this interface */ -#define ds_if ds_ac.ac_if /* network-visible interface */ -#define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ +#define ds_if ds_ac.ac_if /* network-visible interface */ int ds_flags; #define DSF_RUNNING 2 /* board is enabled */ #define DSF_SETADDR 4 /* physical address is changed */ @@ -177,6 +175,7 @@ deattach(parent, self, aux) struct dedevice *addr; char *c; int csr1; + u_int8_t myaddr[ETHER_ADDR_LEN]; addr = (struct dedevice *)ua->ua_addr; ds->ds_vaddr = addr; @@ -219,10 +218,9 @@ deattach(parent, self, aux) (void)dewait(ds, "read addr "); ubarelse((void *)ds->ds_dev.dv_parent, &ds->ds_ubaddr); - bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, - sizeof (ds->ds_addr)); + bcopy((caddr_t)&ds->ds_pcbb.pcbb2, myaddr, sizeof (myaddr)); printf("%s: hardware address %s\n", ds->ds_dev.dv_xname, - ether_sprintf(ds->ds_addr)); + ether_sprintf(myaddr)); ifp->if_ioctl = deioctl; ifp->if_start = destart; ds->ds_deuba.iff_flags = UBA_CANTWAIT; @@ -275,7 +273,7 @@ deinit(ds) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubaminit(&ds->ds_deuba, (void *)ds->ds_dev.dv_parent, - sizeof (struct ether_header), (int)btoc(ETHERMTU), + sizeof (struct ether_header), (int)vax_btoc(ETHERMTU), ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { printf("%s: can't initialize\n", ds->ds_dev.dv_xname); ds->ds_if.if_flags &= ~IFF_UP; @@ -347,7 +345,7 @@ deinit(ds) destart(&ds->ds_if); /* queue output packets */ ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */ if (ds->ds_flags & DSF_SETADDR) - de_setaddr(ds->ds_addr, ds); + de_setaddr(ds->ds_ac.ac_enaddr, ds); addr->pclow = CMD_START | PCSR0_INTE; splx(s); } @@ -608,7 +606,8 @@ deioctl(ifp, cmd, data) register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) - ina->x_host = *(union ns_host *)(ds->ds_addr); + ina->x_host = + *(union ns_host *)ds->ds_ac.ac_enaddr; else de_setaddr(ina->x_host.c_host, ds); break; @@ -655,7 +654,7 @@ de_setaddr(physaddr, ds) addr->pclow = PCSR0_INTE|CMD_GETCMD; if (dewait(ds, "address change") == 0) { ds->ds_flags |= DSF_SETADDR; - bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6); + bcopy((caddr_t) physaddr, ds->ds_ac.ac_enaddr, 6); } } @@ -669,7 +668,7 @@ dewait(ds, fn) char *fn; { volatile struct dedevice *addr = ds->ds_vaddr; - register csr0; + register int csr0; while ((addr->pcsr0 & PCSR0_INTR) == 0) ; @@ -684,9 +683,9 @@ dewait(ds, fn) } int -dematch(parent, match, aux) +dematch(parent, cf, aux) struct device *parent; - void *match, *aux; + void *cf, *aux; { struct uba_attach_args *ua = aux; volatile struct dedevice *addr = (struct dedevice *)ua->ua_addr; diff --git a/sys/arch/vax/if/if_le.c b/sys/arch/vax/if/if_le.c index 3b9528685d1..f370c74eb64 100644 --- a/sys/arch/vax/if/if_le.c +++ b/sys/arch/vax/if/if_le.c @@ -1,10 +1,44 @@ -/* $OpenBSD: if_le.c,v 1.4 1998/09/16 22:41:19 jason Exp $ */ -/* $NetBSD: if_le.c,v 1.8 1997/04/21 22:04:23 ragge Exp $ */ +/* $OpenBSD: if_le.c,v 1.5 2000/04/27 03:14:43 bjc Exp $ */ +/* $NetBSD: if_le.c,v 1.14 1999/08/14 18:40:23 ragge Exp $ */ -/* #define LE_CHIP_IS_POKEY /* does VS2000 need this ??? */ +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ /*- - * Copyright (c) 1995 Charles M. Hannum. All rights reserved. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -50,177 +84,146 @@ #include <sys/device.h> #include <sys/reboot.h> +#include <vm/vm.h> +#include <vm/vm_kern.h> + #include <net/if.h> +#include <net/if_media.h> #if INET #include <netinet/in.h> -#include <netinet/if_ether.h> #endif +#include <netinet/if_ether.h> -#include <net/if_media.h> - -/* - * This would be nice, but it's not yet there... - * - * #include <machine/autoconf.h> - */ - -#include <machine/pte.h> #include <machine/cpu.h> -#include <machine/mtpr.h> -#include <machine/uvax.h> -#include <machine/ka410.h> -#include <machine/vsbus.h> +#include <machine/nexus.h> #include <machine/rpb.h> +#include <machine/scb.h> #include <dev/ic/am7990reg.h> -#define LE_NEED_BUF_CONTIG #include <dev/ic/am7990var.h> -#include <dev/tc/if_levar.h> - -#define xdebug(x) - -#ifdef LE_CHIP_IS_POKEY -/* - * access LANCE registers and double-check their contents - */ -#define wbflush() /* do nothing */ -void lewritereg(); -#define LERDWR(cntl, src, dst) { (dst) = (src); wbflush(); } -#define LEWREG(src, dst) lewritereg(&(dst), (src)) -#endif - -#define LE_IOSIZE 64*1024 /* 64K of real-mem are reserved and already */ -extern void *le_iomem; /* mapped into virt-mem by cpu_steal_pages */ -extern u_long le_ioaddr; /* le_iomem is virt, le_ioaddr is phys */ - -#define LE_SOFTC(unit) le_cd.cd_devs[unit] -#define LE_DELAY(x) DELAY(x) +#define ETHER_MIN_LEN 64 /* minimum frame length, including CRC */ +#define LEVEC 0xd4 /* Interrupt vector on 3300/3400 */ -int lematch __P((struct device *, void *, void *)); -void leattach __P((struct device *, struct device *, void *)); - -int leintr __P((void *sc)); - -struct cfattach le_ca = { - sizeof(struct le_softc), lematch, leattach +struct le_softc { + struct am7990_softc sc_am7990; /* Must be first */ + volatile u_short *sc_rap; + volatile u_short *sc_rdp; }; -hide void lewrcsr __P ((struct am7990_softc *, u_int16_t, u_int16_t)); -hide u_int16_t lerdcsr __P ((struct am7990_softc *, u_int16_t)); +int le_ibus_match __P((struct device *, void *, void *)); +void le_ibus_attach __P((struct device *, struct device *, void *)); +void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t)); +u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t)); +void lance_copytobuf_gap2 __P((struct am7990_softc *, void *, int, int)); +void lance_copyfrombuf_gap2 __P((struct am7990_softc *, void *, int, int)); +void lance_zerobuf_gap2 __P((struct am7990_softc *, int, int)); +void leintr __P((void *)); + +struct cfattach le_ibus_ca = { + sizeof(struct le_softc), le_ibus_match, le_ibus_attach +}; -hide void -lewrcsr(sc, port, val) - struct am7990_softc *sc; +void +lewrcsr(ls, port, val) + struct am7990_softc *ls; u_int16_t port, val; { - struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; - -#ifdef LE_CHIP_IS_POKEY - LEWREG(port, ler1->ler1_rap); - LERDWR(port, val, ler1->ler1_rdp); -#else - ler1->ler1_rap = port; - ler1->ler1_rdp = val; -#endif + struct le_softc *sc = (void *)ls; + + *sc->sc_rap = port; + *sc->sc_rdp = val; } -hide u_int16_t -lerdcsr(sc, port) - struct am7990_softc *sc; +u_int16_t +lerdcsr(ls, port) + struct am7990_softc *ls; u_int16_t port; { - struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; - u_int16_t val; - -#ifdef LE_CHIP_IS_POKEY - LEWREG(port, ler1->ler1_rap); - LERDWR(0, ler1->ler1_rdp, val); -#else - ler1->ler1_rap = port; - val = ler1->ler1_rdp; -#endif - return (val); -} + struct le_softc *sc = (void *)ls; -integrate void -lehwinit(sc) - struct am7990_softc *sc; -{ + *sc->sc_rap = port; + return *sc->sc_rdp; } int -lematch(parent, match, aux) +le_ibus_match(parent, cf, aux) struct device *parent; - void *match, *aux; + void *cf; + void *aux; { - struct cfdata *cf = match; - struct confargs *ca = aux; - - /* - * There could/should be more checks, but for now... - */ - if (strcmp(ca->ca_name, "le") && - strcmp(ca->ca_name, "am7990") && - strcmp(ca->ca_name, "AM7990")) - return (0); + struct bp_conf *bp = aux; - return (1); + if (strcmp("lance", bp->type)) + return 0; + return 1; } -/* - * - */ void -leattach(parent, self, aux) +le_ibus_attach(parent, self, aux) struct device *parent, *self; void *aux; { - register struct le_softc *sc = (void *)self; - struct confargs *ca = aux; - u_char *cp; /* pointer to MAC address */ - int i; + struct le_softc *sc = (void *)self; + int *lance_addr; + int i, vec, br; - sc->sc_r1 = (void*)uvax_phys2virt(ca->ca_ioaddr); + sc->sc_rdp = (short *)vax_map_physmem(0x20084400, 1); + sc->sc_rap = sc->sc_rdp + 2; - sc->sc_am7990.sc_conf3 = 0; - sc->sc_am7990.sc_mem = le_iomem; - sc->sc_am7990.sc_addr = le_ioaddr; - sc->sc_am7990.sc_memsize = LE_IOSIZE; - sc->sc_am7990.sc_wrcsr = lewrcsr; + /* + * Set interrupt vector, by forcing an interrupt. + */ + scb_vecref(0, 0); /* Clear vector ref */ + *sc->sc_rap = LE_CSR0; + *sc->sc_rdp = LE_C0_STOP; + DELAY(100); + *sc->sc_rdp = LE_C0_INIT|LE_C0_INEA; + DELAY(100000); + i = scb_vecref(&vec, &br); + if (i == 0 || vec == 0) + return; + scb_vecalloc(vec, (void *)am7990_intr, sc, SCB_ISTACK); + + printf(": vec %o ipl %x\n%s", vec, br, self->dv_xname); + /* + * MD functions. + */ sc->sc_am7990.sc_rdcsr = lerdcsr; - sc->sc_am7990.sc_hwinit = lehwinit; + sc->sc_am7990.sc_wrcsr = lewrcsr; sc->sc_am7990.sc_nocarrier = NULL; - xdebug(("leattach: mem=%x, addr=%x, size=%x (%d)\n", - sc->sc_am7990.sc_mem, sc->sc_am7990.sc_addr, - sc->sc_am7990.sc_memsize, sc->sc_am7990.sc_memsize)); + sc->sc_am7990.sc_mem = + (void *)uvm_km_valloc(kernel_map, (128 * 1024)); + if (sc->sc_am7990.sc_mem == 0) + return; + + ioaccess((vaddr_t)sc->sc_am7990.sc_mem, 0x20120000, + (128 * 1024) >> VAX_PGSHIFT); - sc->sc_am7990.sc_copytodesc = am7990_copytobuf_contig; - sc->sc_am7990.sc_copyfromdesc = am7990_copyfrombuf_contig; - sc->sc_am7990.sc_copytobuf = am7990_copytobuf_contig; - sc->sc_am7990.sc_copyfrombuf = am7990_copyfrombuf_contig; - sc->sc_am7990.sc_zerobuf = am7990_zerobuf_contig; + + sc->sc_am7990.sc_addr = 0; + sc->sc_am7990.sc_memsize = (64 * 1024); + + sc->sc_am7990.sc_copytodesc = lance_copytobuf_gap2; + sc->sc_am7990.sc_copyfromdesc = lance_copyfrombuf_gap2; + sc->sc_am7990.sc_copytobuf = lance_copytobuf_gap2; + sc->sc_am7990.sc_copyfrombuf = lance_copyfrombuf_gap2; + sc->sc_am7990.sc_zerobuf = lance_zerobuf_gap2; /* * Get the ethernet address out of rom */ - for (i = 0; i < sizeof(sc->sc_am7990.sc_arpcom.ac_enaddr); i++) { - int *eaddr = (void*)uvax_phys2virt(ca->ca_enaddr); - sc->sc_am7990.sc_arpcom.ac_enaddr[i] = (u_char)eaddr[i]; - } + lance_addr = (int *)vax_map_physmem(0x20084200, 1); + for (i = 0; i < 6; i++) + sc->sc_am7990.sc_arpcom.ac_enaddr[i] = (u_char)lance_addr[i]; + vax_unmap_physmem((vaddr_t)lance_addr, 1); - bcopy(self->dv_xname, sc->sc_am7990.sc_arpcom.ac_if.if_xname, IFNAMSIZ); + bcopy(self->dv_xname, sc->sc_am7990.sc_arpcom.ac_if.if_xname, + IFNAMSIZ); am7990_config(&sc->sc_am7990); -#ifdef LEDEBUG - sc->sc_am7990.sc_debug = LEDEBUG; -#endif - - vsbus_intr_register(ca, am7990_intr, &sc->sc_am7990); - vsbus_intr_enable(ca); - /* * Register this device as boot device if we booted from it. * This will fail if there are more than one le in a machine, @@ -230,28 +233,98 @@ leattach(parent, self, aux) booted_from = self; } -#ifdef LE_CHIP_IS_POKEY /* - * Write a lance register port, reading it back to ensure success. This seems - * to be necessary during initialization, since the chip appears to be a bit - * pokey sometimes. + * gap2: two bytes of data followed by two bytes of pad. + * + * Buffers must be 4-byte aligned. The code doesn't worry about + * doing an extra byte. */ + void -lewritereg(regptr, val) - register volatile u_short *regptr; - register u_short val; +lance_copytobuf_gap2(sc, fromv, boff, len) + struct am7990_softc *sc; + void *fromv; + int boff; + register int len; { - register int i = 0; - - while (*regptr != val) { - *regptr = val; - wbflush(); - if (++i > 10000) { - printf("le: Reg did not settle (to x%x): x%x\n", val, - *regptr); - return; - } - DELAY(100); + volatile caddr_t buf = sc->sc_mem; + register caddr_t from = fromv; + register volatile u_int16_t *bptr; + + if (boff & 0x1) { + /* handle unaligned first byte */ + bptr = ((volatile u_int16_t *)buf) + (boff - 1); + *bptr = (*from++ << 8) | (*bptr & 0xff); + bptr += 2; + len--; + } else + bptr = ((volatile u_int16_t *)buf) + boff; + while (len > 1) { + *bptr = (from[1] << 8) | (from[0] & 0xff); + bptr += 2; + from += 2; + len -= 2; } + if (len == 1) + *bptr = (u_int16_t)*from; +} + +void +lance_copyfrombuf_gap2(sc, tov, boff, len) + struct am7990_softc *sc; + void *tov; + int boff, len; +{ + volatile caddr_t buf = sc->sc_mem; + register caddr_t to = tov; + register volatile u_int16_t *bptr; + register u_int16_t tmp; + + if (boff & 0x1) { + /* handle unaligned first byte */ + bptr = ((volatile u_int16_t *)buf) + (boff - 1); + *to++ = (*bptr >> 8) & 0xff; + bptr += 2; + len--; + } else + bptr = ((volatile u_int16_t *)buf) + boff; + while (len > 1) { + tmp = *bptr; + *to++ = tmp & 0xff; + *to++ = (tmp >> 8) & 0xff; + bptr += 2; + len -= 2; + } + if (len == 1) + *to = *bptr & 0xff; +} + +void +lance_zerobuf_gap2(sc, boff, len) + struct am7990_softc *sc; + int boff, len; +{ + volatile caddr_t buf = sc->sc_mem; + register volatile u_int16_t *bptr; + + if ((unsigned)boff & 0x1) { + bptr = ((volatile u_int16_t *)buf) + (boff - 1); + *bptr &= 0xff; + bptr += 2; + len--; + } else + bptr = ((volatile u_int16_t *)buf) + boff; + while (len > 0) { + *bptr = 0; + bptr += 2; + len -= 2; + } +} + +void +leintr(arg) + void *arg; +{ + int unit = (int)arg; + am7990_intr(le_cd.cd_devs[unit]); } -#endif diff --git a/sys/arch/vax/if/if_qe.c b/sys/arch/vax/if/if_qe.c index b114420e4d1..36e90edf0b6 100644 --- a/sys/arch/vax/if/if_qe.c +++ b/sys/arch/vax/if/if_qe.c @@ -1,12 +1,7 @@ -/* $OpenBSD: if_qe.c,v 1.10 1999/05/13 15:44:50 jason Exp $ */ -/* $NetBSD: if_qe.c,v 1.22 1997/05/02 17:11:24 ragge Exp $ */ - +/* $OpenBSD: if_qe.c,v 1.11 2000/04/27 03:14:43 bjc Exp $ */ +/* $NetBSD: if_qe.c,v 1.39 2000/01/24 02:40:29 matt Exp $ */ /* - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Digital Equipment Corp. + * Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -18,348 +13,194 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)if_qe.c 7.20 (Berkeley) 3/28/91 - */ - -/* from @(#)if_qe.c 1.15 (ULTRIX) 4/16/86 */ - -/**************************************************************** - * * - * Licensed from Digital Equipment Corporation * - * Copyright (c) * - * Digital Equipment Corporation * - * Maynard, Massachusetts * - * 1985, 1986 * - * All rights reserved. * - * * - * The Information in this software is subject to change * - * without notice and should not be construed as a commitment * - * by Digital Equipment Corporation. Digital makes no * - * representations about the suitability of this software for * - * any purpose. It is supplied "As Is" without expressed or * - * implied warranty. * - * * - * If the Regents of the University of California or its * - * licensees modify the software in a manner creating * - * derivative copyright rights, appropriate copyright * - * legends may be placed on the derivative work in addition * - * to that set forth above. * - * * - ****************************************************************/ -/* --------------------------------------------------------------------- - * Modification History - * - * 15-Apr-86 -- afd - * Rename "unused_multi" to "qunused_multi" for extending Generic - * kernel to MicroVAXen. - * - * 18-mar-86 -- jaw br/cvec changed to NOT use registers. - * - * 12 March 86 -- Jeff Chase - * Modified to handle the new MCLGET macro - * Changed if_qe_data.c to use more receive buffers - * Added a flag to poke with adb to log qe_restarts on console - * - * 19 Oct 85 -- rjl - * Changed the watch dog timer from 30 seconds to 3. VMS is using - * less than 1 second in their's. Also turned the printf into an - * mprintf. - * - * 09/16/85 -- Larry Cohen - * Add 43bsd alpha tape changes for subnet routing - * - * 1 Aug 85 -- rjl - * Panic on a non-existent memory interrupt and the case where a packet - * was chained. The first should never happen because non-existant - * memory interrupts cause a bus reset. The second should never happen - * because we hang 2k input buffers on the device. - * - * 1 Aug 85 -- rich - * Fixed the broadcast loopback code to handle Clusters without - * wedging the system. - * - * 27 Feb. 85 -- ejf - * Return default hardware address on ioctl request. - * - * 12 Feb. 85 -- ejf - * Added internal extended loopback capability. - * - * 27 Dec. 84 -- rjl - * Fixed bug that caused every other transmit descriptor to be used - * instead of every descriptor. - * - * 21 Dec. 84 -- rjl - * Added watchdog timer to mask hardware bug that causes device lockup. + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission * - * 18 Dec. 84 -- rjl - * Reworked driver to use q-bus mapping routines. MicroVAX-I now does - * copying instead of m-buf shuffleing. - * A number of deficencies in the hardware/firmware were compensated - * for. See comments in qestart and qerint. - * - * 14 Nov. 84 -- jf - * Added usage counts for multicast addresses. - * Updated general protocol support to allow access to the Ethernet - * header. - * - * 04 Oct. 84 -- jf - * Added support for new ioctls to add and delete multicast addresses - * and set the physical address. - * Add support for general protocols. - * - * 14 Aug. 84 -- rjl - * Integrated Shannon changes. (allow arp above 1024 and ? ) - * - * 13 Feb. 84 -- rjl - * - * Initial version of driver. derived from IL driver. - * - * --------------------------------------------------------------------- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Digital Q-BUS to NI Adapter - * supports DEQNA and DELQA in DEQNA-mode. + * Driver for DEQNA/DELQA ethernet cards. + * Things that is still to do: + * Have a timeout check for hang transmit logic. + * Handle ubaresets. Does not work at all right now. + * Fix ALLMULTI reception. But someone must tell me how... + * Collect statistics. */ #include "bpfilter.h" #include <sys/param.h> -#include <sys/systm.h> #include <sys/mbuf.h> -#include <sys/buf.h> -#include <sys/protosw.h> #include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/syslog.h> #include <sys/device.h> -#include <sys/time.h> -#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/sockio.h> #include <net/if.h> -#include <net/netisr.h> -#include <net/route.h> - -#ifdef INET +#include <net/if_dl.h> #include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> #include <netinet/if_ether.h> -#endif - -#ifdef NS -#include <netns/ns.h> -#include <netns/ns_if.h> -#endif - -#ifdef ISO -#include <netiso/iso.h> -#include <netiso/iso_var.h> -extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[]; -#endif - -#if defined(CCITT) && defined(LLC) -#include <sys/socketvar.h> -#include <netccitt/x25.h> -#include <netccitt/pk.h> -#include <netccitt/pk_var.h> -#include <netccitt/pk_extern.h> -#endif #if NBPFILTER > 0 #include <net/bpf.h> #include <net/bpfdesc.h> #endif - -#include <machine/pte.h> -#include <machine/cpu.h> -#include <vax/if/if_qereg.h> -#include <vax/if/if_uba.h> -#include <vax/uba/ubareg.h> -#include <vax/uba/ubavar.h> +#include <machine/bus.h> -#define NRCV 15 /* Receive descriptors */ -#define NXMT 5 /* Transmit descriptors */ -#define NTOT (NXMT + NRCV) +#include <arch/vax/qbus/ubavar.h> +#include <arch/vax/qbus/if_qereg.h> -#define QETIMEOUT 2 /* transmit timeout, must be > 1 */ -#define QESLOWTIMEOUT 40 /* timeout when no xmits in progress */ - -#define MINDATA 60 +#define RXDESCS 30 /* # of receive descriptors */ +#define TXDESCS 60 /* # transmit descs */ +#define ETHER_MINLEN 64 /* min frame + crc */ /* - * Ethernet software status per interface. - * - * Each interface is referenced by a network interface structure, - * qe_if, which the routing code uses to locate the interface. - * This structure contains the output queue for the interface, its address, ... + * Structure containing the elements that must be in DMA-safe memory. */ -struct qe_softc { - struct device qe_dev; /* Configuration common part */ - struct arpcom qe_ac; /* Ethernet common part */ -#define qe_if qe_ac.ac_if /* network-visible interface */ -#define qe_addr qe_ac.ac_enaddr /* hardware Ethernet address */ - struct ifubinfo qe_uba; /* Q-bus resources */ - struct ifrw qe_ifr[NRCV]; /* for receive buffers; */ - struct ifxmt qe_ifw[NXMT]; /* for xmit buffers; */ - struct qedevice *qe_vaddr; - int qe_flags; /* software state */ -#define QEF_RUNNING 0x01 -#define QEF_SETADDR 0x02 -#define QEF_FASTTIMEO 0x04 - int setupaddr; /* mapping info for setup pkts */ - int ipl; /* interrupt priority */ - struct qe_ring *rringaddr; /* mapping info for rings */ - struct qe_ring *tringaddr; /* "" */ - struct qe_ring rring[NRCV+1]; /* Receive ring descriptors */ - struct qe_ring tring[NXMT+1]; /* Xmit ring descriptors */ - u_char setup_pkt[16][8]; /* Setup packet */ - int rindex; /* Receive index */ - int tindex; /* Transmit index */ - int otindex; /* Old transmit index */ - int qe_intvec; /* Interrupt vector */ - struct qedevice *addr; /* device addr */ - int setupqueued; /* setup packet queued */ - int setuplength; /* length if setup packet */ - int nxmit; /* Transmits in progress */ - int qe_restarts; /* timeouts */ +struct qe_cdata { + struct qe_ring qc_recv[RXDESCS+1]; /* Receive descriptors */ + struct qe_ring qc_xmit[TXDESCS+1]; /* Transmit descriptors */ + u_int8_t qc_setup[128]; /* Setup packet layout */ }; -int qematch __P((struct device *, void *, void *)); -void qeattach __P((struct device *, struct device *, void *)); -void qereset __P((int)); -void qeinit __P((struct qe_softc *)); -void qestart __P((struct ifnet *)); -void qeintr __P((int)); -void qetint __P((int)); -void qerint __P((int)); -int qeioctl __P((struct ifnet *, u_long, caddr_t)); -void qe_setaddr __P((u_char *, struct qe_softc *)); -void qeinitdesc __P((struct qe_ring *, caddr_t, int)); -void qesetup __P((struct qe_softc *)); -void qeread __P((struct qe_softc *, struct ifrw *, int)); -void qetimeout __P((struct ifnet *)); -void qerestart __P((struct qe_softc *)); - -struct cfdriver qe_cd = { - NULL, "qe", DV_IFNET +struct qe_softc { + struct device sc_dev; /* Configuration common part */ + struct arpcom sc_ac; /* Ethernet common part */ +#define sc_if sc_ac.ac_if /* network-visible interface */ + bus_space_tag_t sc_iot; + bus_addr_t sc_ioh; + bus_dma_tag_t sc_dmat; + struct qe_cdata *sc_qedata; /* Descriptor struct */ + struct qe_cdata *sc_pqedata; /* Unibus address of above */ + bus_dmamap_t sc_cmap; /* Map for control structures */ + struct mbuf* sc_txmbuf[TXDESCS]; + struct mbuf* sc_rxmbuf[RXDESCS]; + bus_dmamap_t sc_xmtmap[TXDESCS]; + bus_dmamap_t sc_rcvmap[RXDESCS]; + int sc_intvec; /* Interrupt vector */ + int sc_nexttx; + int sc_inq; + int sc_lastack; + int sc_nextrx; + int sc_setup; /* Setup packet in queue */ }; +static int qematch __P((struct device *, struct cfdata *, void *)); +static void qeattach __P((struct device *, struct device *, void *)); +static void qeinit __P((struct qe_softc *)); +static void qestart __P((struct ifnet *)); +static void qeintr __P((void *)); +static int qeioctl __P((struct ifnet *, u_long, caddr_t)); +static int qe_add_rxbuf __P((struct qe_softc *, int)); +static void qe_setup __P((struct qe_softc *)); +static void qetimeout __P((struct ifnet *)); + struct cfattach qe_ca = { - sizeof(struct qe_softc), qematch, qeattach + sizeof(struct qe_softc), (cfmatch_t)qematch, qeattach }; -#define QEUNIT(x) minor(x) -/* - * The deqna shouldn't receive more than ETHERMTU + sizeof(struct ether_header) - * but will actually take in up to 2048 bytes. To guard against the receiver - * chaining buffers (which we aren't prepared to handle) we allocate 2kb - * size buffers. - */ -#define MAXPACKETSIZE 2048 /* Should really be ETHERMTU */ +#define QE_WCSR(csr, val) \ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val) +#define QE_RCSR(csr) \ + bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr) + +#define LOWORD(x) ((int)(x) & 0xffff) +#define HIWORD(x) (((int)(x) >> 16) & 0x3f) /* - * Probe the QNA to see if it's there + * Check for present DEQNA. Done by sending a fake setup packet + * and wait for interrupt. */ int -qematch(parent, match, aux) +qematch(parent, cf, aux) struct device *parent; - void *match, *aux; + struct cfdata *cf; + void *aux; { - struct qe_softc *sc = match; + bus_dmamap_t cmap; + struct qe_softc ssc; + struct qe_softc *sc = &ssc; struct uba_attach_args *ua = aux; struct uba_softc *ubasc = (struct uba_softc *)parent; + +#define PROBESIZE (sizeof(struct qe_ring) * 4 + 128) + struct qe_ring ring[15]; /* For diag purposes only */ struct qe_ring *rp; - struct qe_ring *prp; /* physical rp */ - volatile struct qedevice *addr = (struct qedevice *)ua->ua_addr; - int i; + int error; - /* - * The QNA interrupts on i/o operations. To do an I/O operation - * we have to setup the interface by transmitting a setup packet. - */ + bzero(sc, sizeof(struct qe_softc)); + bzero(ring, PROBESIZE); + sc->sc_iot = ua->ua_iot; + sc->sc_ioh = ua->ua_ioh; + sc->sc_dmat = ua->ua_dmat; - addr->qe_csr = QE_RESET; - addr->qe_csr &= ~QE_RESET; - addr->qe_vector = (ubasc->uh_lastiv -= 4); + ubasc->uh_lastiv -= 4; + QE_WCSR(QE_CSR_CSR, QE_RESET); + QE_WCSR(QE_CSR_VECTOR, ubasc->uh_lastiv); /* - * Map the communications area and the setup packet. + * Map the ring area. Actually this is done only to be able to + * send and receive a internal packet; some junk is loopbacked + * so that the DEQNA has a reason to interrupt. */ - sc->setupaddr = - uballoc(ubasc, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0); - sc->rringaddr = (struct qe_ring *) uballoc(ubasc, (caddr_t)sc->rring, - sizeof(struct qe_ring) * (NTOT+2), 0); - prp = (struct qe_ring *)UBAI_ADDR((int)sc->rringaddr); + if ((error = bus_dmamap_create(sc->sc_dmat, PROBESIZE, 1, PROBESIZE, 0, + BUS_DMA_NOWAIT, &cmap))) { + printf("qematch: bus_dmamap_create failed = %d\n", error); + return 0; + } + if ((error = bus_dmamap_load(sc->sc_dmat, cmap, ring, PROBESIZE, 0, + BUS_DMA_NOWAIT))) { + printf("qematch: bus_dmamap_load failed = %d\n", error); + bus_dmamap_destroy(sc->sc_dmat, cmap); + return 0; + } /* - * The QNA will loop the setup packet back to the receive ring - * for verification, therefore we initialize the first - * receive & transmit ring descriptors and link the setup packet - * to them. + * Init a simple "fake" receive and transmit descriptor that + * points to some unused area. Send a fake setup packet. */ - qeinitdesc(sc->tring, (caddr_t)UBAI_ADDR(sc->setupaddr), - sizeof(sc->setup_pkt)); - qeinitdesc(sc->rring, (caddr_t)UBAI_ADDR(sc->setupaddr), - sizeof(sc->setup_pkt)); - - rp = (struct qe_ring *)sc->tring; - rp->qe_setup = 1; - rp->qe_eomsg = 1; - rp->qe_flag = rp->qe_status1 = QE_NOTYET; - rp->qe_valid = 1; + rp = (void *)cmap->dm_segs[0].ds_addr; + ring[0].qe_flag = ring[0].qe_status1 = QE_NOTYET; + ring[0].qe_addr_lo = LOWORD(&rp[4]); + ring[0].qe_addr_hi = HIWORD(&rp[4]) | QE_VALID | QE_EOMSG | QE_SETUP; + ring[0].qe_buf_len = 128; - rp = (struct qe_ring *)sc->rring; - rp->qe_flag = rp->qe_status1 = QE_NOTYET; - rp->qe_valid = 1; + ring[2].qe_flag = ring[2].qe_status1 = QE_NOTYET; + ring[2].qe_addr_lo = LOWORD(&rp[4]); + ring[2].qe_addr_hi = HIWORD(&rp[4]) | QE_VALID; + ring[2].qe_buf_len = 128; - /* - * Get the addr off of the interface and place it into the setup - * packet. This code looks strange due to the fact that the address - * is placed in the setup packet in col. major order. - */ - for (i = 0; i < 6; i++) - sc->setup_pkt[i][1] = addr->qe_sta_addr[i]; + QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET); + DELAY(1000); - qesetup(sc); /* * Start the interface and wait for the packet. */ - addr->qe_csr = QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT; - addr->qe_rcvlist_lo = (short)((int)prp); - addr->qe_rcvlist_hi = (short)((int)prp >> 16); - prp += NRCV+1; - addr->qe_xmtlist_lo = (short)((int)prp); - addr->qe_xmtlist_hi = (short)((int)prp >> 16); + QE_WCSR(QE_CSR_CSR, QE_INT_ENABLE|QE_XMIT_INT|QE_RCV_INT); + QE_WCSR(QE_CSR_RCLL, LOWORD(&rp[2])); + QE_WCSR(QE_CSR_RCLH, HIWORD(&rp[2])); + QE_WCSR(QE_CSR_XMTL, LOWORD(rp)); + QE_WCSR(QE_CSR_XMTH, HIWORD(rp)); DELAY(10000); + /* * All done with the bus resources. */ - ubarelse(ubasc, &sc->setupaddr); - ubarelse(ubasc, (int *)&sc->rringaddr); - sc->ipl = 0x15; - ua->ua_ivec = qeintr; + bus_dmamap_unload(sc->sc_dmat, cmap); + bus_dmamap_destroy(sc->sc_dmat, cmap); return 1; } @@ -374,63 +215,186 @@ qeattach(parent, self, aux) void *aux; { struct uba_attach_args *ua = aux; + struct uba_softc *ubasc = (struct uba_softc *)parent; struct qe_softc *sc = (struct qe_softc *)self; - struct ifnet *ifp = (struct ifnet *)&sc->qe_if; - struct qedevice *addr =(struct qedevice *)ua->ua_addr; - int i; + struct ifnet *ifp = (struct ifnet *)&sc->sc_if; + struct qe_ring *rp; + u_int8_t enaddr[ETHER_ADDR_LEN]; + bus_dma_segment_t seg; + int i, rseg, error; + + sc->sc_iot = ua->ua_iot; + sc->sc_ioh = ua->ua_ioh; + sc->sc_dmat = ua->ua_dmat; + + /* + * Allocate DMA safe memory for descriptors and setup memory. + */ + if ((error = bus_dmamem_alloc(sc->sc_dmat, + sizeof(struct qe_cdata), NBPG, 0, &seg, 1, &rseg, + BUS_DMA_NOWAIT)) != 0) { + printf(": unable to allocate control data, error = %d\n", + error); + goto fail_0; + } + + if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, + sizeof(struct qe_cdata), (caddr_t *)&sc->sc_qedata, + BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { + printf(": unable to map control data, error = %d\n", error); + goto fail_1; + } + + if ((error = bus_dmamap_create(sc->sc_dmat, + sizeof(struct qe_cdata), 1, + sizeof(struct qe_cdata), 0, BUS_DMA_NOWAIT, + &sc->sc_cmap)) != 0) { + printf(": unable to create control data DMA map, error = %d\n", + error); + goto fail_2; + } + + if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap, + sc->sc_qedata, sizeof(struct qe_cdata), NULL, + BUS_DMA_NOWAIT)) != 0) { + printf(": unable to load control data DMA map, error = %d\n", + error); + goto fail_3; + } - printf("\n"); - sc->qe_vaddr = addr; - bcopy(sc->qe_dev.dv_xname, ifp->if_xname, IFNAMSIZ); - ifp->if_softc = sc; /* - * The Deqna is cable of transmitting broadcasts, but - * doesn't listen to its own. + * Zero the newly allocated memory. */ - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | - IFF_MULTICAST; + bzero(sc->sc_qedata, sizeof(struct qe_cdata)); + /* + * Create the transmit descriptor DMA maps. We take advantage + * of the fact that the Qbus address space is big, and therefore + * allocate map registers for all transmit descriptors also, + * so that we can avoid this each time we send a packet. + */ + for (i = 0; i < TXDESCS; i++) { + if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, + 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, + &sc->sc_xmtmap[i]))) { + printf(": unable to create tx DMA map %d, error = %d\n", + i, error); + goto fail_4; + } + } /* - * Read the address from the prom and save it. + * Create receive buffer DMA maps. */ - for (i = 0; i < 6; i++) - sc->setup_pkt[i][1] = sc->qe_addr[i] = - addr->qe_sta_addr[i] & 0xff; - addr->qe_vector |= 1; - printf("qe%d: %s, hardware address %s\n", sc->qe_dev.dv_unit, - addr->qe_vector&01 ? "delqa":"deqna", - ether_sprintf(sc->qe_addr)); - addr->qe_vector &= ~1; + for (i = 0; i < RXDESCS; i++) { + if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, + MCLBYTES, 0, BUS_DMA_NOWAIT, + &sc->sc_rcvmap[i]))) { + printf(": unable to create rx DMA map %d, error = %d\n", + i, error); + goto fail_5; + } + } + /* + * Pre-allocate the receive buffers. + */ + for (i = 0; i < RXDESCS; i++) { + if ((error = qe_add_rxbuf(sc, i)) != 0) { + printf(": unable to allocate or map rx buffer %d\n," + " error = %d\n", i, error); + goto fail_6; + } + } + + /* + * Create ring loops of the buffer chains. + * This is only done once. + */ + sc->sc_pqedata = (struct qe_cdata *)sc->sc_cmap->dm_segs[0].ds_addr; + + rp = sc->sc_qedata->qc_recv; + rp[RXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_recv[0]); + rp[RXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_recv[0]) | + QE_VALID | QE_CHAIN; + rp[RXDESCS].qe_flag = rp[RXDESCS].qe_status1 = QE_NOTYET; + + rp = sc->sc_qedata->qc_xmit; + rp[TXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_xmit[0]); + rp[TXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_xmit[0]) | + QE_VALID | QE_CHAIN; + rp[TXDESCS].qe_flag = rp[TXDESCS].qe_status1 = QE_NOTYET; /* - * Save the vector for initialization at reset time. + * Get the vector that were set at match time, and remember it. */ - sc->qe_intvec = addr->qe_vector; + sc->sc_intvec = ubasc->uh_lastiv; + QE_WCSR(QE_CSR_CSR, QE_RESET); + DELAY(1000); + QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET); + /* + * Read out ethernet address and tell which type this card is. + */ + for (i = 0; i < 6; i++) + enaddr[i] = QE_RCSR(i * 2) & 0xff; + + QE_WCSR(QE_CSR_VECTOR, sc->sc_intvec | 1); + printf("\n%s: %s, hardware address %s\n", sc->sc_dev.dv_xname, + QE_RCSR(QE_CSR_VECTOR) & 1 ? "delqa":"deqna", + ether_sprintf(enaddr)); + + QE_WCSR(QE_CSR_VECTOR, QE_RCSR(QE_CSR_VECTOR) & ~1); /* ??? */ + + uba_intr_establish(ua->ua_icookie, ua->ua_cvec, qeintr, sc); + + strcpy(ifp->if_xname, sc->sc_dev.dv_xname); + ifp->if_softc = sc; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = qestart; ifp->if_ioctl = qeioctl; ifp->if_watchdog = qetimeout; - sc->qe_uba.iff_flags = UBA_CANTWAIT; + + /* + * Attach the interface. + */ if_attach(ifp); ether_ifattach(ifp); #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); #endif -} - -/* - * Reset of interface after UNIBUS reset. - */ -void -qereset(unit) - int unit; -{ - struct qe_softc *sc = qe_cd.cd_devs[unit]; + return; - printf(" %s", sc->qe_dev.dv_xname); - sc->qe_if.if_flags &= ~IFF_RUNNING; - qeinit(sc); + /* + * Free any resources we've allocated during the failed attach + * attempt. Do this in reverse order and fall through. + */ + fail_6: + for (i = 0; i < RXDESCS; i++) { + if (sc->sc_rxmbuf[i] != NULL) { + bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]); + m_freem(sc->sc_rxmbuf[i]); + } + } + fail_5: + for (i = 0; i < RXDESCS; i++) { + if (sc->sc_xmtmap[i] != NULL) + bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]); + } + fail_4: + for (i = 0; i < TXDESCS; i++) { + if (sc->sc_rcvmap[i] != NULL) + bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]); + } + bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap); + fail_3: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap); + fail_2: + bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_qedata, + sizeof(struct qe_cdata)); + fail_1: + bus_dmamem_free(sc->sc_dmat, &seg, rseg); + fail_0: + return; } /* @@ -440,347 +404,260 @@ void qeinit(sc) struct qe_softc *sc; { - struct qedevice *addr = sc->qe_vaddr; - struct uba_softc *ubasc = (void *)sc->qe_dev.dv_parent; - struct ifnet *ifp = (struct ifnet *)&sc->qe_if; + struct ifnet *ifp = (struct ifnet *)&sc->sc_if; + struct qe_cdata *qc = sc->sc_qedata; int i; - int s; - /* address not known */ - if (ifp->if_addrlist.tqh_first == (struct ifaddr *)0) - return; - if (sc->qe_flags & QEF_RUNNING) - return; - if ((ifp->if_flags & IFF_RUNNING) == 0) { - /* - * map the communications area onto the device - */ - i = uballoc(ubasc, (caddr_t)sc->rring, - sizeof(struct qe_ring) * (NTOT+2), 0); - if (i == 0) - goto fail; - sc->rringaddr = (struct qe_ring *)UBAI_ADDR(i); - sc->tringaddr = sc->rringaddr + NRCV + 1; - i = uballoc(ubasc, (caddr_t)sc->setup_pkt, - sizeof(sc->setup_pkt), 0); - if (i == 0) - goto fail; - sc->setupaddr = UBAI_ADDR(i); - /* - * init buffers and maps - */ - if (if_ubaminit(&sc->qe_uba, (void *)sc->qe_dev.dv_parent, - sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE), - sc->qe_ifr, NRCV, sc->qe_ifw, NXMT) == 0) { - fail: - printf("%s: can't allocate uba resources\n", - sc->qe_dev.dv_xname); - sc->qe_if.if_flags &= ~IFF_UP; - return; - } - } /* - * Init the buffer descriptors and indexes for each of the lists and - * loop them back to form a ring. + * Reset the interface. */ - for (i = 0; i < NRCV; i++) { - qeinitdesc( &sc->rring[i], - (caddr_t)UBAI_ADDR(sc->qe_ifr[i].ifrw_info), MAXPACKETSIZE); - sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; - sc->rring[i].qe_valid = 1; + QE_WCSR(QE_CSR_CSR, QE_RESET); + DELAY(1000); + QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET); + QE_WCSR(QE_CSR_VECTOR, sc->sc_intvec); + + sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = 0; + /* + * Release and init transmit descriptors. + */ + for (i = 0; i < TXDESCS; i++) { + if (sc->sc_txmbuf[i]) { + bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]); + m_freem(sc->sc_txmbuf[i]); + sc->sc_txmbuf[i] = 0; + } + qc->qc_xmit[i].qe_addr_hi = 0; /* Clear valid bit */ + qc->qc_xmit[i].qe_status1 = qc->qc_xmit[i].qe_flag = QE_NOTYET; } - qeinitdesc(&sc->rring[i], (caddr_t)NULL, 0); - sc->rring[i].qe_addr_lo = (short)((int)sc->rringaddr); - sc->rring[i].qe_addr_hi = (short)((int)sc->rringaddr >> 16); - sc->rring[i].qe_chain = 1; - sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; - sc->rring[i].qe_valid = 1; - for( i = 0 ; i <= NXMT ; i++ ) - qeinitdesc(&sc->tring[i], (caddr_t)NULL, 0); - i--; + /* + * Init receive descriptors. + */ + for (i = 0; i < RXDESCS; i++) + qc->qc_recv[i].qe_status1 = qc->qc_recv[i].qe_flag = QE_NOTYET; + sc->sc_nextrx = 0; - sc->tring[i].qe_addr_lo = (short)((int)sc->tringaddr); - sc->tring[i].qe_addr_hi = (short)((int)sc->tringaddr >> 16); - sc->tring[i].qe_chain = 1; - sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET; - sc->tring[i].qe_valid = 1; + /* + * Write the descriptor addresses to the device. + * Receiving packets will be enabled in the interrupt routine. + */ + QE_WCSR(QE_CSR_CSR, QE_INT_ENABLE|QE_XMIT_INT|QE_RCV_INT); + QE_WCSR(QE_CSR_RCLL, LOWORD(sc->sc_pqedata->qc_recv)); + QE_WCSR(QE_CSR_RCLH, HIWORD(sc->sc_pqedata->qc_recv)); - sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; /* - * Take the interface out of reset, program the vector, - * enable interrupts, and tell the world we are up. + * Send a setup frame. + * This will start the transmit machinery as well. */ - s = splnet(); - addr->qe_vector = sc->qe_intvec; - sc->addr = addr; - addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | - QE_RCV_INT | QE_ILOOP; - addr->qe_rcvlist_lo = (short)((int)sc->rringaddr); - addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16); - ifp->if_flags |= IFF_UP | IFF_RUNNING; - sc->qe_flags |= QEF_RUNNING; - qesetup( sc ); - qestart( ifp ); - sc->qe_if.if_timer = QESLOWTIMEOUT; /* Start watchdog */ - splx( s ); + qe_setup(sc); + } /* * Start output on interface. - * */ void qestart(ifp) struct ifnet *ifp; { - register struct qe_softc *sc = ifp->if_softc; - volatile struct qedevice *addr = sc->qe_vaddr; - register struct qe_ring *rp; - register index; - struct mbuf *m; - int buf_addr, len, s; + struct qe_softc *sc = ifp->if_softc; + struct qe_cdata *qc = sc->sc_qedata; + paddr_t buffer; + struct mbuf *m, *m0; + int idx, len, s, i, totlen, error; + short orword; + if ((QE_RCSR(QE_CSR_CSR) & QE_RCV_ENABLE) == 0) + return; - s = splnet(); - /* - * The deqna doesn't look at anything but the valid bit - * to determine if it should transmit this packet. If you have - * a ring and fill it the device will loop indefinately on the - * packet and continue to flood the net with packets until you - * break the ring. For this reason we never queue more than n-1 - * packets in the transmit ring. - * - * The microcoders should have obeyed their own defination of the - * flag and status words, but instead we have to compensate. - */ - for( index = sc->tindex; - sc->tring[index].qe_valid == 0 && sc->nxmit < (NXMT-1) ; - sc->tindex = index = ++index % NXMT){ - rp = &sc->tring[index]; - if( sc->setupqueued ) { - buf_addr = sc->setupaddr; - len = sc->setuplength; - rp->qe_setup = 1; - sc->setupqueued = 0; - } else { - IF_DEQUEUE(&sc->qe_if.if_snd, m); - if (m == 0) { - splx(s); - return; - } -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m); -#endif - buf_addr = sc->qe_ifw[index].ifw_info; - len = if_ubaput(&sc->qe_uba, &sc->qe_ifw[index], m); + s = splimp(); + while (sc->sc_inq < (TXDESCS - 1)) { + + if (sc->sc_setup) { + qe_setup(sc); + continue; } - if( len < MINDATA ) - len = MINDATA; + idx = sc->sc_nexttx; + IF_DEQUEUE(&sc->sc_if.if_snd, m); + if (m == 0) + goto out; /* - * Does buffer end on odd byte ? + * Count number of mbufs in chain. + * Always do DMA directly from mbufs, therefore the transmit + * ring is really big. */ - if( len & 1 ) { - len++; - rp->qe_odd_end = 1; + for (m0 = m, i = 0; m0; m0 = m0->m_next) + if (m0->m_len) + i++; + if (i >= TXDESCS) + panic("qestart"); + + if ((i + sc->sc_inq) >= (TXDESCS - 1)) { + IF_PREPEND(&sc->sc_if.if_snd, m); + ifp->if_flags |= IFF_OACTIVE; + goto out; } - rp->qe_buf_len = -(len/2); - buf_addr = UBAI_ADDR(buf_addr); - rp->qe_flag = rp->qe_status1 = QE_NOTYET; - rp->qe_addr_lo = (short)buf_addr; - rp->qe_addr_hi = (short)(buf_addr >> 16); - rp->qe_eomsg = 1; - rp->qe_flag = rp->qe_status1 = QE_NOTYET; - rp->qe_valid = 1; - if (sc->nxmit++ == 0) { - sc->qe_flags |= QEF_FASTTIMEO; - sc->qe_if.if_timer = QETIMEOUT; + +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m); +#endif + /* + * m now points to a mbuf chain that can be loaded. + * Loop around and set it. + */ + totlen = 0; + for (m0 = m; m0; m0 = m0->m_next) { + error = bus_dmamap_load(sc->sc_dmat, sc->sc_xmtmap[idx], + mtod(m0, void *), m0->m_len, 0, 0); + buffer = sc->sc_xmtmap[idx]->dm_segs[0].ds_addr; + len = m0->m_len; + if (len == 0) + continue; + + totlen += len; + /* Word alignment calc */ + orword = 0; + if (totlen == m->m_pkthdr.len) { + if (totlen < ETHER_MINLEN) + len += (ETHER_MINLEN - totlen); + orword |= QE_EOMSG; + sc->sc_txmbuf[idx] = m; + } + if ((buffer & 1) || (len & 1)) + len += 2; + if (buffer & 1) + orword |= QE_ODDBEGIN; + if ((buffer + len) & 1) + orword |= QE_ODDEND; + qc->qc_xmit[idx].qe_buf_len = -(len/2); + qc->qc_xmit[idx].qe_addr_lo = LOWORD(buffer); + qc->qc_xmit[idx].qe_addr_hi = HIWORD(buffer); + qc->qc_xmit[idx].qe_flag = + qc->qc_xmit[idx].qe_status1 = QE_NOTYET; + qc->qc_xmit[idx].qe_addr_hi |= (QE_VALID | orword); + if (++idx == TXDESCS) + idx = 0; + sc->sc_inq++; } +#ifdef DIAGNOSTIC + if (totlen != m->m_pkthdr.len) + panic("qestart: len fault"); +#endif /* - * See if the xmit list is invalid. + * Kick off the transmit logic, if it is stopped. */ - if( addr->qe_csr & QE_XL_INVALID ) { - buf_addr = (int)(sc->tringaddr+index); - addr->qe_xmtlist_lo = (short)buf_addr; - addr->qe_xmtlist_hi = (short)(buf_addr >> 16); + if (QE_RCSR(QE_CSR_CSR) & QE_XL_INVALID) { + QE_WCSR(QE_CSR_XMTL, + LOWORD(&sc->sc_pqedata->qc_xmit[sc->sc_nexttx])); + QE_WCSR(QE_CSR_XMTH, + HIWORD(&sc->sc_pqedata->qc_xmit[sc->sc_nexttx])); } + sc->sc_nexttx = idx; } + if (sc->sc_inq == (TXDESCS - 1)) + ifp->if_flags |= IFF_OACTIVE; + +out: if (sc->sc_inq) + ifp->if_timer = 5; /* If transmit logic dies */ splx(s); - return; } -/* - * Ethernet interface interrupt processor - */ -void -qeintr(unit) - int unit; +static void +qeintr(arg) + void *arg; { - register struct qe_softc *sc; - volatile struct qedevice *addr; - int buf_addr, csr; - - sc = qe_cd.cd_devs[unit]; - addr = sc->qe_vaddr; - splx(sc->ipl); - if (!(sc->qe_flags & QEF_FASTTIMEO)) - sc->qe_if.if_timer = QESLOWTIMEOUT; /* Restart timer clock */ - csr = addr->qe_csr; - addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | - QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; - if (csr & QE_RCV_INT) - qerint(unit); - if (csr & QE_XMIT_INT) - qetint(unit ); - if (csr & QE_NEX_MEM_INT) - printf("qe%d: Nonexistent memory interrupt\n", unit); - - if (addr->qe_csr & QE_RL_INVALID && sc->rring[sc->rindex].qe_status1 == - QE_NOTYET) { - buf_addr = (int)&sc->rringaddr[sc->rindex]; - addr->qe_rcvlist_lo = (short)buf_addr; - addr->qe_rcvlist_hi = (short)(buf_addr >> 16); - } -} + struct qe_softc *sc = arg; + struct qe_cdata *qc = sc->sc_qedata; + struct ifnet *ifp = &sc->sc_if; + struct ether_header *eh; + struct mbuf *m; + int csr, status1, status2, len; -/* - * Ethernet interface transmit interrupt. - */ -void -qetint(unit) - int unit; -{ - register struct qe_softc *sc = qe_cd.cd_devs[unit]; - register struct qe_ring *rp; - register struct ifxmt *ifxp; - int status1, setupflag; - short len; + csr = QE_RCSR(QE_CSR_CSR); + QE_WCSR(QE_CSR_CSR, QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | + QE_RCV_INT | QE_ILOOP); - while (sc->otindex != sc->tindex && sc->tring[sc->otindex].qe_status1 - != QE_NOTYET && sc->nxmit > 0) { - /* - * Save the status words from the descriptor so that it can - * be released. - */ - rp = &sc->tring[sc->otindex]; - status1 = rp->qe_status1; - setupflag = rp->qe_setup; - len = (-rp->qe_buf_len) * 2; - if( rp->qe_odd_end ) - len++; - /* - * Init the buffer descriptor - */ - bzero((caddr_t)rp, sizeof(struct qe_ring)); - if( --sc->nxmit == 0 ) { - sc->qe_flags &= ~QEF_FASTTIMEO; - sc->qe_if.if_timer = QESLOWTIMEOUT; - } - if( !setupflag ) { + if (csr & QE_RCV_INT) + while (qc->qc_recv[sc->sc_nextrx].qe_status1 != QE_NOTYET) { + status1 = qc->qc_recv[sc->sc_nextrx].qe_status1; + status2 = qc->qc_recv[sc->sc_nextrx].qe_status2; + m = sc->sc_rxmbuf[sc->sc_nextrx]; + len = ((status1 & QE_RBL_HI) | + (status2 & QE_RBL_LO)) + 60; + qe_add_rxbuf(sc, sc->sc_nextrx); + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = m->m_len = len; + if (++sc->sc_nextrx == RXDESCS) + sc->sc_nextrx = 0; + eh = mtod(m, struct ether_header *); +#if NBPFILTER > 0 + if (ifp->if_bpf) { + bpf_mtap(ifp->if_bpf, m); + if ((ifp->if_flags & IFF_PROMISC) != 0 && + bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost, + ETHER_ADDR_LEN) != 0 && + ((eh->ether_dhost[0] & 1) == 0)) { + m_freem(m); + continue; + } + } +#endif /* - * Do some statistics. + * ALLMULTI means PROMISC in this driver. */ - sc->qe_if.if_opackets++; - sc->qe_if.if_collisions += ( status1 & QE_CCNT ) >> 4; - if (status1 & QE_ERROR) - sc->qe_if.if_oerrors++; - ifxp = &sc->qe_ifw[sc->otindex]; - if (ifxp->ifw_xtofree) { - m_freem(ifxp->ifw_xtofree); - ifxp->ifw_xtofree = 0; + if ((ifp->if_flags & IFF_ALLMULTI) && + ((eh->ether_dhost[0] & 1) == 0) && + bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost, + ETHER_ADDR_LEN)) { + m_freem(m); + continue; } + ether_input(ifp, eh, m); } - sc->otindex = ++sc->otindex % NXMT; - } - qestart(&sc->qe_if); -} - -/* - * Ethernet interface receiver interrupt. - * If can't determine length from type, then have to drop packet. - * Othewise decapsulate packet based on type and pass to type specific - * higher-level input routine. - */ -void -qerint(unit) - int unit; -{ - register struct qe_softc *sc = qe_cd.cd_devs[unit]; - register struct qe_ring *rp; - register int nrcv = 0; - int len, status1, status2; - int bufaddr; + if (csr & QE_XMIT_INT) { + while (qc->qc_xmit[sc->sc_lastack].qe_status1 != QE_NOTYET) { + int idx = sc->sc_lastack; + + sc->sc_inq--; + if (++sc->sc_lastack == TXDESCS) + sc->sc_lastack = 0; + + /* XXX collect statistics */ + qc->qc_xmit[idx].qe_addr_hi &= ~QE_VALID; + qc->qc_xmit[idx].qe_status1 = + qc->qc_xmit[idx].qe_flag = QE_NOTYET; + + if (qc->qc_xmit[idx].qe_addr_hi & QE_SETUP) + continue; + bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]); + if (sc->sc_txmbuf[idx]) { + m_freem(sc->sc_txmbuf[idx]); + sc->sc_txmbuf[idx] = 0; + } + } + ifp->if_timer = 0; + ifp->if_flags &= ~IFF_OACTIVE; + qestart(ifp); /* Put in more in queue */ + } /* - * Traverse the receive ring looking for packets to pass back. - * The search is complete when we find a descriptor not in use. - * - * As in the transmit case the deqna doesn't honor it's own protocols - * so there exists the possibility that the device can beat us around - * the ring. The proper way to guard against this is to insure that - * there is always at least one invalid descriptor. We chose instead - * to make the ring large enough to minimize the problem. With a ring - * size of 4 we haven't been able to see the problem. To be safe we - * doubled that to 8. - * + * How can the receive list get invalid??? + * Verified that it happens anyway. */ - while (sc->rring[sc->rindex].qe_status1 == QE_NOTYET && nrcv < NRCV) { - /* - * We got an interrupt but did not find an input packet - * where we expected one to be, probably because the ring - * was overrun. - * We search forward to find a valid packet and start - * processing from there. If no valid packet is found it - * means we processed all the packets during a previous - * interrupt and that the QE_RCV_INT bit was set while - * we were processing one of these earlier packets. In - * this case we can safely ignore the interrupt (by dropping - * through the code below). - */ - sc->rindex = (sc->rindex + 1) % NRCV; - nrcv++; - } - if (nrcv && nrcv < NRCV) - log(LOG_ERR, "qe%d: ring overrun, resync'd by skipping %d\n", - unit, nrcv); - - for (; sc->rring[sc->rindex].qe_status1 != QE_NOTYET; - sc->rindex = ++sc->rindex % NRCV) { - rp = &sc->rring[sc->rindex]; - status1 = rp->qe_status1; - status2 = rp->qe_status2; - bzero((caddr_t)rp, sizeof(struct qe_ring)); - if( (status1 & QE_MASK) == QE_MASK ) - panic("qe: chained packet"); - len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)) + 60; - sc->qe_if.if_ipackets++; - - if (status1 & QE_ERROR) { - if ((status1 & QE_RUNT) == 0) - sc->qe_if.if_ierrors++; - } else { - /* - * We don't process setup packets. - */ - if (!(status1 & QE_ESETUP)) - qeread(sc, &sc->qe_ifr[sc->rindex], - len - sizeof(struct ether_header)); - } - /* - * Return the buffer to the ring - */ - bufaddr = (int)UBAI_ADDR(sc->qe_ifr[sc->rindex].ifrw_info); - rp->qe_buf_len = -((MAXPACKETSIZE)/2); - rp->qe_addr_lo = (short)bufaddr; - rp->qe_addr_hi = (short)((int)bufaddr >> 16); - rp->qe_flag = rp->qe_status1 = QE_NOTYET; - rp->qe_valid = 1; + if ((qc->qc_recv[sc->sc_nextrx].qe_status1 == QE_NOTYET) && + (QE_RCSR(QE_CSR_CSR) & QE_RL_INVALID)) { + QE_WCSR(QE_CSR_RCLL, + LOWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx])); + QE_WCSR(QE_CSR_RCLH, + HIWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx])); } } @@ -794,47 +671,48 @@ qeioctl(ifp, cmd, data) caddr_t data; { struct qe_softc *sc = ifp->if_softc; - struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; + struct ifaddr *ifa = (struct ifaddr *)data; int s = splnet(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; - qeinit(sc); switch(ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: - arp_ifinit(&sc->qe_ac, ifa); - break; -#endif -#ifdef NS - case AF_NS: - { - register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); - - if (ns_nullhost(*ina)) - ina->x_host = *(union ns_host *)(sc->qe_addr); - else - qe_setaddr(ina->x_host.c_host, sc); + qeinit(sc); + arp_ifinit(&sc->sc_ac, ifa); break; - } #endif } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && - sc->qe_flags & QEF_RUNNING) { - sc->qe_vaddr->qe_csr = QE_RESET; - sc->qe_flags &= ~QEF_RUNNING; - } else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == - IFF_RUNNING && (sc->qe_flags & QEF_RUNNING) == 0) - qerestart(sc); - else + (ifp->if_flags & IFF_RUNNING) != 0) { + /* + * If interface is marked down and it is running, + * stop it. (by disabling receive mechanism). + */ + QE_WCSR(QE_CSR_CSR, + QE_RCSR(QE_CSR_CSR) & ~QE_RCV_ENABLE); + ifp->if_flags &= ~IFF_RUNNING; + } else if ((ifp->if_flags & IFF_UP) != 0 && + (ifp->if_flags & IFF_RUNNING) == 0) { + /* + * If interface it marked up and it is stopped, then + * start it. + */ qeinit(sc); - + } else if ((ifp->if_flags & IFF_UP) != 0) { + /* + * Send a new setup packet to match any new changes. + * (Like IFF_PROMISC etc) + */ + qe_setup(sc); + } break; case SIOCADDMULTI: @@ -843,15 +721,15 @@ qeioctl(ifp, cmd, data) * Update our multicast list. */ error = (cmd == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->qe_ac): - ether_delmulti(ifr, &sc->qe_ac); + ether_addmulti(ifr, &sc->sc_ac): + ether_delmulti(ifr, &sc->sc_ac); if (error == ENETRESET) { /* * Multicast list has changed; set the hardware filter * accordingly. */ - qeinit(sc); + qe_setup(sc); error = 0; } break; @@ -865,226 +743,154 @@ qeioctl(ifp, cmd, data) } /* - * set ethernet address for unit + * Add a receive buffer to the indicated descriptor. */ -void -qe_setaddr(physaddr, sc) - u_char *physaddr; +int +qe_add_rxbuf(sc, i) struct qe_softc *sc; + int i; { - register int i; + struct mbuf *m; + struct qe_ring *rp; + vaddr_t addr; + int error; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) + return (ENOBUFS); + + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + return (ENOBUFS); + } - for (i = 0; i < 6; i++) - sc->setup_pkt[i][1] = sc->qe_addr[i] = physaddr[i]; - sc->qe_flags |= QEF_SETADDR; - if (sc->qe_if.if_flags & IFF_RUNNING) - qesetup(sc); - qeinit(sc); -} + if (sc->sc_rxmbuf[i] != NULL) + bus_dmamap_unload(sc->sc_dmat, sc->sc_rcvmap[i]); + error = bus_dmamap_load(sc->sc_dmat, sc->sc_rcvmap[i], + m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT); + if (error) + panic("%s: can't load rx DMA map %d, error = %d\n", + sc->sc_dev.dv_xname, i, error); + sc->sc_rxmbuf[i] = m; -/* - * Initialize a ring descriptor with mbuf allocation side effects - */ -void -qeinitdesc(rp, addr, len) - register struct qe_ring *rp; - caddr_t addr; /* mapped address */ - int len; -{ - /* - * clear the entire descriptor - */ - bzero((caddr_t)rp, sizeof(struct qe_ring)); + bus_dmamap_sync(sc->sc_dmat, sc->sc_rcvmap[i], 0, + sc->sc_rcvmap[i]->dm_mapsize, BUS_DMASYNC_PREREAD); - if (len) { - rp->qe_buf_len = -(len/2); - rp->qe_addr_lo = (short)((int)addr); - rp->qe_addr_hi = (short)((int)addr >> 16); - } -} -/* - * Build a setup packet - the physical address will already be present - * in first column. - */ -void -qesetup(sc) - struct qe_softc *sc; -{ - register i, j; - - /* - * Copy the target address to the rest of the entries in this row. - */ - for (j = 0; j < 6; j++) - for (i = 2; i < 8; i++) - sc->setup_pkt[j][i] = sc->setup_pkt[j][1]; - /* - * Duplicate the first half. - */ - bcopy((caddr_t)sc->setup_pkt[0], (caddr_t)sc->setup_pkt[8], 64); /* - * Fill in the broadcast (and ISO multicast) address(es). + * We know that the mbuf cluster is page aligned. Also, be sure + * that the IP header will be longword aligned. */ - for (i = 0; i < 6; i++) { - sc->setup_pkt[i][2] = 0xff; -#ifdef ISO - /* - * XXX layer violation, should use SIOCADDMULTI. - * Will definitely break with IPmulticast. - */ + m->m_data += 2; + addr = sc->sc_rcvmap[i]->dm_segs[0].ds_addr + 2; + rp = &sc->sc_qedata->qc_recv[i]; + rp->qe_flag = rp->qe_status1 = QE_NOTYET; + rp->qe_addr_lo = LOWORD(addr); + rp->qe_addr_hi = HIWORD(addr) | QE_VALID; + rp->qe_buf_len = -(m->m_ext.ext_size - 2)/2; - sc->setup_pkt[i][3] = all_es_snpa[i]; - sc->setup_pkt[i][4] = all_is_snpa[i]; - sc->setup_pkt[i][5] = all_l1is_snpa[i]; - sc->setup_pkt[i][6] = all_l2is_snpa[i]; -#endif - } - if (sc->qe_if.if_flags & IFF_PROMISC) { - sc->setuplength = QE_PROMISC; - /* XXX no IFF_ALLMULTI support in 4.4bsd */ - } else if (sc->qe_if.if_flags & IFF_ALLMULTI) { - sc->setuplength = QE_ALLMULTI; - } else { - register k; - struct ether_multi *enm; - struct ether_multistep step; - /* - * Step through our list of multicast addresses, putting them - * in the third through fourteenth address slots of the setup - * packet. (See the DEQNA manual to understand the peculiar - * layout of the bytes within the setup packet.) If we have - * too many multicast addresses, or if we have to listen to - * a range of multicast addresses, turn on reception of all - * multicasts. - */ - sc->setuplength = QE_SOMEMULTI; - i = 2; - k = 0; - ETHER_FIRST_MULTI(step, &sc->qe_ac, enm); - while (enm != NULL) { - if ((++i > 7 && k != 0) || - bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { - sc->setuplength = QE_ALLMULTI; - break; - } - if (i > 7) { - i = 1; - k = 8; - } - for (j = 0; j < 6; j++) - sc->setup_pkt[j+k][i] = enm->enm_addrlo[j]; - ETHER_NEXT_MULTI(step, enm); - } - } - sc->setupqueued++; + return (0); } /* - * Pass a packet to the higher levels. - * We deal with the trailer protocol here. + * Create a setup packet and put in queue for sending. */ void -qeread(sc, ifrw, len) - register struct qe_softc *sc; - struct ifrw *ifrw; - int len; +qe_setup(sc) + struct qe_softc *sc; { - struct ifnet *ifp = (struct ifnet *)&sc->qe_if; - struct ether_header *eh; - struct mbuf *m; - + struct ether_multi *enm; + struct ether_multistep step; + struct qe_cdata *qc = sc->sc_qedata; + struct ifnet *ifp = &sc->sc_if; + u_int8_t *enaddr = sc->sc_ac.ac_enaddr; + int i, j, k, idx, s; + + s = splimp(); + if (sc->sc_inq == (TXDESCS - 1)) { + sc->sc_setup = 1; + splx(s); + return; + } + sc->sc_setup = 0; /* - * Deal with trailer protocol: if type is INET trailer - * get true type from first 16-bit word past data. - * Remember that type was trailer by setting off. + * Init the setup packet with valid info. */ - - eh = (struct ether_header *)ifrw->ifrw_addr; - if (len == 0) - return; + memset(qc->qc_setup, 0xff, sizeof(qc->qc_setup)); /* Broadcast */ + for (i = 0; i < ETHER_ADDR_LEN; i++) + qc->qc_setup[i * 8 + 1] = enaddr[i]; /* Own address */ /* - * Pull packet off interface. Off is nonzero if packet - * has trailing header; qeget will then force this header - * information to be at the front, but we still have to drop - * the type and length which are at the front of any trailer data. + * Multicast handling. The DEQNA can handle up to 12 direct + * ethernet addresses. */ - m = if_ubaget(&sc->qe_uba, ifrw, len, &sc->qe_if); -#ifdef notdef -if (m) { -*(((u_long *)m->m_data)+0), -*(((u_long *)m->m_data)+1), -*(((u_long *)m->m_data)+2), -*(((u_long *)m->m_data)+3) -; } -#endif + j = 3; k = 0; + ifp->if_flags &= ~IFF_ALLMULTI; + ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); + while (enm != NULL) { + if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) { + ifp->if_flags |= IFF_ALLMULTI; + break; + } + for (i = 0; i < ETHER_ADDR_LEN; i++) + qc->qc_setup[i * 8 + j + k] = enm->enm_addrlo[i]; + j++; + if (j == 8) { + j = 1; k += 64; + } + if (k > 64) { + ifp->if_flags |= IFF_ALLMULTI; + break; + } + ETHER_NEXT_MULTI(step, enm); + } + idx = sc->sc_nexttx; + qc->qc_xmit[idx].qe_buf_len = -64; -#if NBPFILTER > 0 /* - * Check for a BPF filter; if so, hand it up. - * Note that we have to stick an extra mbuf up front, because - * bpf_mtap expects to have the ether header at the front. - * It doesn't matter that this results in an ill-formatted mbuf chain, - * since BPF just looks at the data. (It doesn't try to free the mbuf, - * tho' it will make a copy for tcpdump.) + * How is the DEQNA turned in ALLMULTI mode??? + * Until someone tells me, fall back to PROMISC when more than + * 12 ethernet addresses. */ - if (sc->qe_if.if_bpf) { - struct mbuf m0; - m0.m_len = sizeof (struct ether_header); - m0.m_data = (caddr_t)eh; - m0.m_next = m; - - /* Pass it up */ - bpf_mtap(sc->qe_if.if_bpf, &m0); + if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) + qc->qc_xmit[idx].qe_buf_len = -65; + + qc->qc_xmit[idx].qe_addr_lo = LOWORD(sc->sc_pqedata->qc_setup); + qc->qc_xmit[idx].qe_addr_hi = + HIWORD(sc->sc_pqedata->qc_setup) | QE_SETUP | QE_EOMSG; + qc->qc_xmit[idx].qe_status1 = qc->qc_xmit[idx].qe_flag = QE_NOTYET; + qc->qc_xmit[idx].qe_addr_hi |= QE_VALID; + + if (QE_RCSR(QE_CSR_CSR) & QE_XL_INVALID) { + QE_WCSR(QE_CSR_XMTL, + LOWORD(&sc->sc_pqedata->qc_xmit[idx])); + QE_WCSR(QE_CSR_XMTH, + HIWORD(&sc->sc_pqedata->qc_xmit[idx])); } -#endif /* NBPFILTER > 0 */ - if (m) - ether_input((struct ifnet *)&sc->qe_if, eh, m); + sc->sc_inq++; + if (++sc->sc_nexttx == TXDESCS) + sc->sc_nexttx = 0; + splx(s); } /* - * Watchdog timeout routine. There is a condition in the hardware that - * causes the board to lock up under heavy load. This routine detects - * the hang up and restarts the device. + * Check for dead transmit logic. Not uncommon. */ void qetimeout(ifp) struct ifnet *ifp; { - register struct qe_softc *sc = ifp->if_softc; + struct qe_softc *sc = ifp->if_softc; -#ifdef notdef - log(LOG_ERR, "%s: transmit timeout, restarted %d\n", - sc->sc_dev.dv_xname, sc->qe_restarts++); -#endif - qerestart(sc); -} -/* - * Restart for board lockup problem. - */ -void -qerestart(sc) - struct qe_softc *sc; -{ - register struct ifnet *ifp = (struct ifnet *)&sc->qe_if; - register struct qedevice *addr = sc->addr; - register struct qe_ring *rp; - register i; - - addr->qe_csr = QE_RESET; - addr->qe_csr &= ~QE_RESET; - qesetup(sc); - for (i = 0, rp = sc->tring; i < NXMT; rp++, i++) { - rp->qe_flag = rp->qe_status1 = QE_NOTYET; - rp->qe_valid = 0; - } - sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; - addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | - QE_RCV_INT | QE_ILOOP; - addr->qe_rcvlist_lo = (short)((int)sc->rringaddr); - addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16); - sc->qe_flags |= QEF_RUNNING; - qestart(ifp); + if (sc->sc_inq == 0) + return; + + printf("%s: xmit logic died, resetting...\n", sc->sc_dev.dv_xname); + /* + * Do a reset of interface, to get it going again. + * Will it work by just restart the transmit logic? + */ + qeinit(sc); } diff --git a/sys/arch/vax/if/if_qereg.h b/sys/arch/vax/if/if_qereg.h index bac037498c8..71e7429fdbb 100644 --- a/sys/arch/vax/if/if_qereg.h +++ b/sys/arch/vax/if/if_qereg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: if_qereg.h,v 1.3 1997/09/10 08:28:42 maja Exp $ */ -/* $NetBSD: if_qereg.h,v 1.2 1997/05/15 20:10:23 ragge Exp $ */ +/* $OpenBSD: if_qereg.h,v 1.4 2000/04/27 03:14:43 bjc Exp $ */ +/* $NetBSD: if_qereg.h,v 1.5 1999/06/20 00:04:47 ragge Exp $ */ /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. @@ -58,8 +58,8 @@ * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * - * diriviative copyright rights, appropriate copyright * - * legends may be placed on the drivative work in addition * + * derivative copyright rights, appropriate copyright * + * legends may be placed on the derivative work in addition * * to that set forth above. * * * ****************************************************************/ @@ -76,6 +76,7 @@ /* * Digital Q-BUS to NI Adapter */ +#ifdef notdef struct qedevice { u_short qe_sta_addr[2]; /* Station address (actually 6 */ u_short qe_rcvlist_lo; /* Receive list lo address */ @@ -85,6 +86,19 @@ struct qedevice { u_short qe_vector; /* Interrupt vector */ u_short qe_csr; /* Command and Status Register */ }; +#endif + +/* + * Register offsets in register space. + */ +#define QE_CSR_ADDR1 0 +#define QE_CSR_ADDR2 2 +#define QE_CSR_RCLL 4 +#define QE_CSR_RCLH 6 +#define QE_CSR_XMTL 8 +#define QE_CSR_XMTH 10 +#define QE_CSR_VECTOR 12 +#define QE_CSR_CSR 14 /* * Command and status bits (csr) @@ -117,19 +131,22 @@ struct qedevice { */ struct qe_ring { u_short qe_flag; /* Buffer utilization flags */ - u_short qe_addr_hi:6, /* Hi order bits of buffer addr */ - qe_odd_begin:1, /* Odd byte begin and end (xmit)*/ - qe_odd_end:1, - qe_fill1:4, - qe_setup:1, /* Setup packet */ - qe_eomsg:1, /* End of message flag */ - qe_chain:1, /* Chain address instead of buf */ - qe_valid:1; /* Address field is valid */ + u_short qe_addr_hi; u_short qe_addr_lo; /* Low order bits of address */ short qe_buf_len; /* Negative buffer length */ u_short qe_status1; /* Status word one */ u_short qe_status2; /* Status word two */ }; + +/* + * High word address control bits. + */ +#define QE_VALID 0x8000 +#define QE_CHAIN 0x4000 +#define QE_EOMSG 0x2000 +#define QE_SETUP 0x1000 +#define QE_ODDEND 0x0080 +#define QE_ODDBEGIN 0x0040 /* * Status word definations (receive) @@ -175,6 +192,6 @@ struct qe_ring { /* * Values for the length of the setup packet that control reception filter. */ -#define QE_SOMEMULTI 128 /* Receive up to 12 multicasts */ -#define QE_ALLMULTI 129 /* Receive all multicasts */ -#define QE_PROMISC 130 /* Receive all packets */ +#define QE_SETUPLEN 128 /* Size of setup packet */ +#define QE_ALLMULTI 1 /* Receive all multicasts */ +#define QE_PROMISC 2 /* Receive all packets */ diff --git a/sys/arch/vax/if/if_uba.c b/sys/arch/vax/if/if_uba.c index f0dd19c6051..34175ed4c18 100644 --- a/sys/arch/vax/if/if_uba.c +++ b/sys/arch/vax/if/if_uba.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_uba.c,v 1.5 1997/05/29 00:04:33 niklas Exp $ */ -/* $NetBSD: if_uba.c,v 1.12 1996/08/20 14:07:46 ragge Exp $ */ +/* $OpenBSD: if_uba.c,v 1.6 2000/04/27 03:14:43 bjc Exp $ */ +/* $NetBSD: if_uba.c,v 1.15 1999/01/01 21:43:18 ragge Exp $ */ /* * Copyright (c) 1982, 1986, 1988 Regents of the University of California. @@ -91,7 +91,7 @@ if_ubaminit(ifu, uh, hlen, nmr, ifr, nr, ifw, nw) off = MCLBYTES - hlen; else off = 0; - nclbytes = roundup(nmr * NBPG, MCLBYTES); + nclbytes = roundup(nmr * VAX_NBPG, MCLBYTES); if (hlen) nclbytes += MCLBYTES; if (ifr[0].ifrw_addr) @@ -159,7 +159,7 @@ if_ubaalloc(ifu, ifrw, nmr) register int info; info = - uballoc(ifu->iff_softc, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen, + uballoc(ifu->iff_softc, ifrw->ifrw_addr, nmr*VAX_NBPG + ifu->iff_hlen, ifu->iff_flags); if (info == 0) return (0); @@ -238,16 +238,16 @@ if_ubaget(ifu, ifr, totlen, ifp) pp = mtod(m, char *); cpte = (struct pte *)kvtopte(cp); ppte = (struct pte *)kvtopte(pp); - x = btop(cp - ifr->ifrw_addr); + x = vax_btop(cp - ifr->ifrw_addr); ip = (int *)&ifr->ifrw_mr[x]; - for (i = 0; i < MCLBYTES/NBPG; i++) { + for (i = 0; i < MCLBYTES/VAX_NBPG; i++) { struct pte t; t = *ppte; *ppte++ = *cpte; *cpte = t; *ip++ = cpte++->pg_pfn|ifr->ifrw_proto; mtpr(cp,PR_TBIS); - cp += NBPG; + cp += VAX_NBPG; mtpr((caddr_t)pp,PR_TBIS); - pp += NBPG; + pp += VAX_NBPG; } goto nocopy; } @@ -290,7 +290,7 @@ rcv_xmtbuf(ifw) { register struct mbuf *m; struct mbuf **mprev; - register i; + register int i; char *cp; while ((i = ffs((long)ifw->ifw_xswapd)) != 0) { @@ -319,7 +319,7 @@ static void restor_xmtbuf(ifw) register struct ifxmt *ifw; { - register i; + register int i; for (i = 0; i < ifw->ifw_nmr; i++) ifw->ifw_wmap[i] = ifw->ifw_mr[i]; @@ -353,11 +353,11 @@ if_ubaput(ifu, ifw, m) int *ip; pte = (struct pte *)kvtopte(dp); - x = btop(cp - ifw->ifw_addr); + x = vax_btop(cp - ifw->ifw_addr); ip = (int *)&ifw->ifw_mr[x]; - for (i = 0; i < MCLBYTES/NBPG; i++) + for (i = 0; i < MCLBYTES/VAX_NBPG; i++) *ip++ = ifw->ifw_proto | pte++->pg_pfn; - xswapd |= 1 << (x>>(MCLSHIFT-PGSHIFT)); + xswapd |= 1 << (x>>(MCLSHIFT-VAX_PGSHIFT)); mp = m->m_next; m->m_next = ifw->ifw_xtofree; ifw->ifw_xtofree = m; @@ -385,8 +385,8 @@ if_ubaput(ifu, ifw, m) if (i >= x) break; ifw->ifw_xswapd &= ~(1<<i); - i *= MCLBYTES/NBPG; - for (t = 0; t < MCLBYTES/NBPG; t++) { + i *= MCLBYTES/VAX_NBPG; + for (t = 0; t < MCLBYTES/VAX_NBPG; t++) { ifw->ifw_mr[i] = ifw->ifw_wmap[i]; i++; } diff --git a/sys/arch/vax/if/if_ze.c b/sys/arch/vax/if/if_ze.c new file mode 100644 index 00000000000..66dbe4134a5 --- /dev/null +++ b/sys/arch/vax/if/if_ze.c @@ -0,0 +1,128 @@ +/* $OpenBSD: if_ze.c,v 1.1 2000/04/27 03:14:43 bjc Exp $ */ +/* $NetBSD: if_ze.c,v 1.3 2000/01/24 02:54:03 matt Exp $ */ +/* + * Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <sys/sockio.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <netinet/in.h> +#include <netinet/if_ether.h> + +#if NBPFILTER > 0 +#include <net/bpf.h> +#include <net/bpfdesc.h> +#endif + +#include <machine/bus.h> +#include <machine/nexus.h> +#include <machine/cpu.h> +#include <machine/scb.h> + +#include <arch/vax/if/sgecreg.h> +#include <arch/vax/if/sgecvar.h> + +/* + * Adresses. + */ +#define SGECADDR 0x20008000 +#define NISA_ROM 0x20084000 +#define SGECVEC 0x108 + +static int zematch __P((struct device *, struct cfdata *, void *)); +static void zeattach __P((struct device *, struct device *, void *)); + +struct cfattach ze_ibus_ca = { + sizeof(struct ze_softc), (cfmatch_t)zematch, zeattach +}; + +struct cfdriver ze_cd = { + NULL, "ze", DV_IFNET +}; + +/* + * Check for present SGEC. + */ +int +zematch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct bp_conf *bp = aux; + + /* + * Should some more intelligent checking be done??? + */ + if (strcmp(bp->type, "sgec") == 0) + return 1; + return 0; +} + +/* + * Interface exists: make available by filling in network interface + * record. System will initialize the interface when it is ready + * to accept packets. + */ +void +zeattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + extern struct vax_bus_dma_tag vax_bus_dma_tag; + struct ze_softc *sc = (struct ze_softc *)self; + int *ea, i; + + /* + * Map in SGEC registers. + */ + sc->sc_ioh = vax_map_physmem(SGECADDR, 1); + sc->sc_iot = 0; /* :-) */ + sc->sc_dmat = &vax_bus_dma_tag; + + sc->sc_intvec = SGECVEC; + + /* + * Map in, read and release ethernet rom address. + */ + ea = (int *)vax_map_physmem(NISA_ROM, 1); + for (i = 0; i < ETHER_ADDR_LEN; i++) + sc->sc_ac.ac_enaddr[i] = (ea[i] >> 8) & 0377; + vax_unmap_physmem((vaddr_t)ea, 1); + + scb_vecalloc(SGECVEC, (void (*)(void *)) sgec_intr, sc, SCB_ISTACK); + + sgec_attach(sc); +} diff --git a/sys/arch/vax/if/if_zereg.h b/sys/arch/vax/if/if_zereg.h new file mode 100644 index 00000000000..99b1a2bdbaa --- /dev/null +++ b/sys/arch/vax/if/if_zereg.h @@ -0,0 +1,222 @@ +/* $OpenBSD: if_zereg.h,v 1.1 2000/04/27 03:14:43 bjc Exp $ */ +/* $NetBSD: if_zereg.h,v 1.1 1998/07/01 10:52:10 ragge Exp $ */ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Digital Equipment Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + + +/* Driver for SGEC (second generation Ethernet controller) chip, type DC-541, + found on the KA670 (and prob ably other) CPU. + + 17 May 1998...Jay Maynard, jmaynard@phoenix.net +*/ + +/* SGEC CSRs */ +struct zedevice { + u_long ze_nicsr0; /* vector address, IPL, sync mode */ + u_long ze_nicsr1; /* TX poll demand */ + u_long ze_nicsr2; /* RX poll demand */ + struct ze_rdes *ze_nicsr3; /* RX descriptor list address */ + struct ze_tdes *ze_nicsr4; /* TX descriptor list address */ + u_long ze_nicsr5; /* SGEC status */ + u_long ze_nicsr6; /* SGEC command/mode */ + u_long ze_nicsr7; /* system page table base address */ + u_long ze_nivcsr8; /* reserved virtual CSR */ + u_long ze_nivcsr9; /* watchdog timers (virtual) */ + u_long ze_nivcsr10; /* revision, missed frame count (v) */ + u_long ze_nivcsr11; /* boot message verification (low) (v) */ + u_long ze_nivcsr12; /* boot message verification (high) (v) */ + u_long ze_nivcsr13; /* boot message processor (v) */ + u_long ze_nivcsr14; /* diagnostic breakpoint (v) */ + u_long ze_nicsr15; /* monitor command */ +}; + +/* SGEC bit definitions */ +/* NICSR0: */ +#define ZE_NICSR0_IPL 0xc0000000 /* interrupt priority level: */ +#define ZE_NICSR0_IPL14 0x00000000 /* 0x14 */ +#define ZE_NICSR0_IPL15 0x40000000 /* 0x15 */ +#define ZE_NICSR0_IPL16 0x80000000 /* 0x16 */ +#define ZE_NICSR0_IPL17 0xc0000000 /* 0x17 */ +#define ZE_NICSR0_SA 0x20000000 /* sync(1)/async mode */ +#define ZE_NICSR0_MBO 0x1fff0003 /* must be set to one on write */ +#define ZE_NICSR0_IV_MASK 0x0000fffc /* bits for the interrupt vector */ + +/* NICSR1: */ +#define ZE_NICSR1_TXPD 0xffffffff /* transmit polling demand */ + +/* NICSR2: */ +#define ZE_NICSR2_RXPD 0xffffffff /* receive polling demand */ + +/* NICSR3 and NICSR4 are pure addresses */ +/* NICSR5: */ +#define ZE_NICSR5_ID 0x80000000 /* init done */ +#define ZE_NICSR5_SF 0x40000000 /* self-test failed */ +#define ZE_NICSR5_SS 0x3c000000 /* self-test status field */ +#define ZE_NICSR5_TS 0x03000000 /* transmission state: */ +#define ZE_NICSR5_TS_STOP 0x00000000 /* stopped */ +#define ZE_NICSR5_TS_RUN 0x01000000 /* running */ +#define ZE_NICSR5_TS_SUSP 0x02000000 /* suspended */ +#define ZE_NICSR5_RS 0x00c00000 /* reception state: */ +#define ZE_NICSR5_RS_STOP 0x00000000 /* stopped */ +#define ZE_NICSR5_RS_RUN 0x00400000 /* running */ +#define ZE_NICSR5_RS_SUSP 0x00800000 /* suspended */ +#define ZE_NICSR5_OM 0x00060000 /* operating mode: */ +#define ZE_NICSR5_OM_NORM 0x00000000 /* normal */ +#define ZE_NICSR5_OM_ILBK 0x00020000 /* internal loopback */ +#define ZE_NICSR5_OM_ELBK 0x00040000 /* external loopback */ +#define ZE_NICSR5_OM_DIAG 0x00060000 /* reserved for diags */ +#define ZE_NICSR5_DN 0x00010000 /* virtual CSR access done */ +#define ZE_NICSR5_MBO 0x0038ff00 /* must be one */ +#define ZE_NICSR5_BO 0x00000080 /* boot message received */ +#define ZE_NICSR5_TW 0x00000040 /* transmit watchdog timeout */ +#define ZE_NICSR5_RW 0x00000020 /* receive watchdog timeout */ +#define ZE_NICSR5_ME 0x00000010 /* memory error */ +#define ZE_NICSR5_RU 0x00000008 /* receive buffer unavailable */ +#define ZE_NICSR5_RI 0x00000004 /* receiver interrupt */ +#define ZE_NICSR5_TI 0x00000002 /* transmitter interrupt */ +#define ZE_NICSR5_IS 0x00000001 /* interrupt summary */ +/* whew! */ + +/* NICSR6: */ +#define ZE_NICSR6_RE 0x80000000 /* reset */ +#define ZE_NICSR6_IE 0x40000000 /* interrupt enable */ +#define ZE_NICSR6_MBO 0x01e7f000 /* must be one */ +#define ZE_NICSR6_BL 0x1e000000 /* burst limit mask */ +#define ZE_NICSR6_BL_8 0x10000000 /* 8 longwords */ +#define ZE_NICSR6_BL_4 0x08000000 /* 4 longwords */ +#define ZE_NICSR6_BL_2 0x04000000 /* 2 longwords */ +#define ZE_NICSR6_BL_1 0x02000000 /* 1 longword */ +#define ZE_NICSR6_BE 0x00100000 /* boot message enable */ +#define ZE_NICSR6_SE 0x00080000 /* single cycle enable */ +#define ZE_NICSR6_ST 0x00000800 /* start(1)/stop(0) transmission */ +#define ZE_NICSR6_SR 0x00000400 /* start(1)/stop(0) reception */ +#define ZE_NICSR6_OM 0x00000300 /* operating mode: */ +#define ZE_NICSR6_OM_NORM 0x00000000 /* normal */ +#define ZE_NICSR6_OM_ILBK 0x00000100 /* internal loopback */ +#define ZE_NICSR6_OM_ELBK 0x00000200 /* external loopback */ +#define ZE_NICSR6_OM_DIAG 0x00000300 /* reserved for diags */ +#define ZE_NICSR6_DC 0x00000080 /* disable data chaining */ +#define ZE_NICSR6_FC 0x00000040 /* force collision mode */ +#define ZE_NICSR6_PB 0x00000008 /* pass bad frames */ +#define ZE_NICSR6_AF 0x00000006 /* address filtering mode: */ +#define ZE_NICSR6_AF_NORM 0x00000000 /* normal filtering */ +#define ZE_NICSR6_AF_PROM 0x00000002 /* promiscuous mode */ +#define ZE_NICSR6_AF_ALLM 0x00000004 /* all multicasts */ + +/* NICSR7 is an address, NICSR8 is reserved */ +/* NICSR9: */ +#define ZE_VNICSR9_RT 0xffff0000 /* receiver timeout, *1.6 us */ +#define ZE_VNICSR9_TT 0x0000ffff /* transmitter timeout */ + +/* NICSR10: */ +#define ZE_VNICSR10_RN 0x001f0000 /* SGEC version */ +#define ZE_VNICSR10_MFC 0x0000ffff /* missed frame counter */ + +/* if you want to know what's in NICSRs 11-15, define them yourself! */ + +/* Descriptors: */ +/* Receive descriptor */ +struct ze_rdes { + u_short ze_rdes0; /* descriptor word 0 flags */ + u_short ze_framelen; /* received frame length */ + u_char ze_rsvd1[3]; /* unused bytes */ + u_char ze_rdes1; /* descriptor word 1 flags */ + short ze_pageoffset; /* offset of buffer in page */ + short ze_bufsize; /* length of data buffer */ + u_char *ze_bufaddr; /* address of data buffer */ +}; + +/* Receive descriptor bits */ +#define ZE_FRAMELEN_OW 0x8000 /* SGEC owns this descriptor */ +#define ZE_RDES0_ES 0x8000 /* an error has occurred */ +#define ZE_RDES0_LE 0x4000 /* length error */ +#define ZE_RDES0_DT 0x3000 /* data type: */ +#define ZE_RDES0_DT_NORM 0x0000 /* normal frame */ +#define ZE_RDES0_DT_ILBK 0x1000 /* internally looped back frame */ +#define ZE_RDES0_DT_ELBK 0x2000 /* externally looped back frame */ +#define ZE_RDES0_RF 0x0800 /* runt frame */ +#define ZE_RDES0_BO 0x0400 /* buffer overflow */ +#define ZE_RDES0_FS 0x0200 /* first segment */ +#define ZE_RDES0_LS 0x0100 /* last segment */ +#define ZE_RDES0_TL 0x0080 /* frame too long */ +#define ZE_RDES0_CS 0x0040 /* collision seen */ +#define ZE_RDES0_FT 0x0020 /* Ethernet frame type */ +#define ZE_RDES0_TN 0x0008 /* address translation not valid */ +#define ZE_RDES0_DB 0x0004 /* dribbling bits seen */ +#define ZE_RDES0_CE 0x0002 /* CRC error */ +#define ZE_RDES0_OF 0x0001 /* internal FIFO overflow */ +#define ZE_RDES1_CA 0x80 /* chain address */ +#define ZE_RDES1_VA 0x40 /* virtual address */ +#define ZE_RDES1_VT 0x20 /* virtual(1)/phys PTE address */ + +/* Transmit descriptor */ +struct ze_tdes { + u_short ze_tdes0; /* descriptor word 0 flags */ + u_short ze_tdr; /* TDR count of cable fault */ + u_char ze_rsvd1[2]; /* unused bytes */ + u_short ze_tdes1; /* descriptor word 1 flags */ + short ze_pageoffset; /* offset of buffer in page */ + short ze_bufsize; /* length of data buffer */ + u_char *ze_bufaddr; /* address of data buffer */ +}; + +/* Receive descriptor bits */ +#define ZE_TDR_OW 0x8000 /* SGEC owns this descriptor */ +#define ZE_TDES0_ES 0x8000 /* an error has occurred */ +#define ZE_TDES0_TO 0x4000 /* transmit watchdog timeout */ +#define ZE_TDES0_LE 0x1000 /* length error */ +#define ZE_TDES0_LO 0x0800 /* loss of carrier */ +#define ZE_TDES0_NC 0x0400 /* no carrier */ +#define ZE_TDES0_LC 0x0200 /* late collision */ +#define ZE_TDES0_EC 0x0100 /* excessive collisions */ +#define ZE_TDES0_HF 0x0080 /* heartbeat fail */ +#define ZE_TDES0_CC 0x0078 /* collision count mask */ +#define ZE_TDES0_TN 0x0004 /* address translation invalid */ +#define ZE_TDES0_UF 0x0002 /* underflow */ +#define ZE_TDES0_DE 0x0001 /* transmission deferred */ +#define ZE_TDES1_CA 0x8000 /* chain address */ +#define ZE_TDES1_VA 0x4000 /* virtual address */ +#define ZE_TDES1_DT 0x3000 /* data type: */ +#define ZE_TDES1_DT_NORM 0x0000 /* normal transmit frame */ +#define ZE_TDES1_DT_SETUP 0x2000 /* setup frame */ +#define ZE_TDES1_DT_DIAG 0x3000 /* diagnostic frame */ +#define ZE_TDES1_AC 0x0800 /* CRC disable */ +#define ZE_TDES1_FS 0x0400 /* first segment */ +#define ZE_TDES1_LS 0x0200 /* last segment */ +#define ZE_TDES1_IC 0x0100 /* interrupt on completion */ +#define ZE_TDES1_VT 0x0080 /* virtual(1)/phys PTE address */ + diff --git a/sys/arch/vax/if/sgec.c b/sys/arch/vax/if/sgec.c new file mode 100644 index 00000000000..254e742d82e --- /dev/null +++ b/sys/arch/vax/if/sgec.c @@ -0,0 +1,752 @@ +/* $OpenBSD: sgec.c,v 1.1 2000/04/27 03:14:44 bjc Exp $ */ +/* $NetBSD: sgec.c,v 1.1 1999/08/08 11:41:29 ragge Exp $ */ +/* + * Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Driver for the SGEC (Second Generation Ethernet Controller), sitting + * on for example the VAX 4000/300 (KA670). + * + * The SGEC looks like a mixture of the DEQNA and the TULIP. Fun toy. + * + * Even though the chip is capable to use virtual addresses (read the + * System Page Table directly) this driver doesn't do so, and there + * is no benefit in doing it either in NetBSD of today. + * + * Things that is still to do: + * Collect statistics. + * Use imperfect filtering when many multicast addresses. + */ + +#include "bpfilter.h" + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <sys/sockio.h> + +#include <net/if.h> +#include <net/if_dl.h> + +#include <netinet/in.h> +#include <netinet/if_ether.h> + +#if NBPFILTER > 0 +#include <net/bpf.h> +#include <net/bpfdesc.h> +#endif + +#include <machine/bus.h> + +#include <vax/if/sgecreg.h> +#include <vax/if/sgecvar.h> + +static void zeinit __P((struct ze_softc *)); +static void zestart __P((struct ifnet *)); +static int zeioctl __P((struct ifnet *, u_long, caddr_t)); +static int ze_add_rxbuf __P((struct ze_softc *, int)); +static void ze_setup __P((struct ze_softc *)); +static void zetimeout __P((struct ifnet *)); +static int zereset __P((struct ze_softc *)); + +#define ZE_WCSR(csr, val) \ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, csr, val) +#define ZE_RCSR(csr) \ + bus_space_read_4(sc->sc_iot, sc->sc_ioh, csr) + +/* + * Interface exists: make available by filling in network interface + * record. System will initialize the interface when it is ready + * to accept packets. + */ +void +sgec_attach(sc) + struct ze_softc *sc; +{ + struct ifnet *ifp = (struct ifnet *)&sc->sc_if; + struct ze_tdes *tp; + struct ze_rdes *rp; + bus_dma_segment_t seg; + int i, rseg, error; + + /* + * Allocate DMA safe memory for descriptors and setup memory. + */ + if ((error = bus_dmamem_alloc(sc->sc_dmat, + sizeof(struct ze_cdata), NBPG, 0, &seg, 1, &rseg, + BUS_DMA_NOWAIT)) != 0) { + printf(": unable to allocate control data, error = %d\n", + error); + goto fail_0; + } + + if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, + sizeof(struct ze_cdata), (caddr_t *)&sc->sc_zedata, + BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { + printf(": unable to map control data, error = %d\n", error); + goto fail_1; + } + + if ((error = bus_dmamap_create(sc->sc_dmat, + sizeof(struct ze_cdata), 1, + sizeof(struct ze_cdata), 0, BUS_DMA_NOWAIT, + &sc->sc_cmap)) != 0) { + printf(": unable to create control data DMA map, error = %d\n", + error); + goto fail_2; + } + + if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap, + sc->sc_zedata, sizeof(struct ze_cdata), NULL, + BUS_DMA_NOWAIT)) != 0) { + printf(": unable to load control data DMA map, error = %d\n", + error); + goto fail_3; + } + + /* + * Zero the newly allocated memory. + */ + bzero(sc->sc_zedata, sizeof(struct ze_cdata)); + /* + * Create the transmit descriptor DMA maps. + */ + for (i = 0; i < TXDESCS; i++) { + if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, + 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, + &sc->sc_xmtmap[i]))) { + printf(": unable to create tx DMA map %d, error = %d\n", + i, error); + goto fail_4; + } + } + + /* + * Create receive buffer DMA maps. + */ + for (i = 0; i < RXDESCS; i++) { + if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, + MCLBYTES, 0, BUS_DMA_NOWAIT, + &sc->sc_rcvmap[i]))) { + printf(": unable to create rx DMA map %d, error = %d\n", + i, error); + goto fail_5; + } + } + /* + * Pre-allocate the receive buffers. + */ + for (i = 0; i < RXDESCS; i++) { + if ((error = ze_add_rxbuf(sc, i)) != 0) { + printf(": unable to allocate or map rx buffer %d\n," + " error = %d\n", i, error); + goto fail_6; + } + } + + /* + * Create ring loops of the buffer chains. + * This is only done once. + */ + sc->sc_pzedata = (struct ze_cdata *)sc->sc_cmap->dm_segs[0].ds_addr; + + rp = sc->sc_zedata->zc_recv; + rp[RXDESCS].ze_framelen = ZE_FRAMELEN_OW; + rp[RXDESCS].ze_rdes1 = ZE_RDES1_CA; + rp[RXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_recv; + + tp = sc->sc_zedata->zc_xmit; + tp[TXDESCS].ze_tdr = ZE_TDR_OW; + tp[TXDESCS].ze_tdes1 = ZE_TDES1_CA; + tp[TXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_xmit; + + if (zereset(sc)) + return; + + strcpy(ifp->if_xname, sc->sc_dev.dv_xname); + ifp->if_softc = sc; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_start = zestart; + ifp->if_ioctl = zeioctl; + ifp->if_watchdog = zetimeout; + + /* + * Attach the interface. + */ + if_attach(ifp); + ether_ifattach(ifp); + +#if NBPFILTER > 0 + bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); +#endif + printf("\n%s: hardware address %s\n", sc->sc_dev.dv_xname, + ether_sprintf(sc->sc_ac.ac_enaddr)); + return; + + /* + * Free any resources we've allocated during the failed attach + * attempt. Do this in reverse order and fall through. + */ + fail_6: + for (i = 0; i < RXDESCS; i++) { + if (sc->sc_rxmbuf[i] != NULL) { + bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]); + m_freem(sc->sc_rxmbuf[i]); + } + } + fail_5: + for (i = 0; i < RXDESCS; i++) { + if (sc->sc_xmtmap[i] != NULL) + bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]); + } + fail_4: + for (i = 0; i < TXDESCS; i++) { + if (sc->sc_rcvmap[i] != NULL) + bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]); + } + bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap); + fail_3: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap); + fail_2: + bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_zedata, + sizeof(struct ze_cdata)); + fail_1: + bus_dmamem_free(sc->sc_dmat, &seg, rseg); + fail_0: + return; +} + +/* + * Initialization of interface. + */ +void +zeinit(sc) + struct ze_softc *sc; +{ + struct ifnet *ifp = (struct ifnet *)&sc->sc_if; + struct ze_cdata *zc = sc->sc_zedata; + int i; + + /* + * Reset the interface. + */ + if (zereset(sc)) + return; + + sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = 0; + /* + * Release and init transmit descriptors. + */ + for (i = 0; i < TXDESCS; i++) { + if (sc->sc_txmbuf[i]) { + bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]); + m_freem(sc->sc_txmbuf[i]); + sc->sc_txmbuf[i] = 0; + } + zc->zc_xmit[i].ze_tdr = 0; /* Clear valid bit */ + } + + + /* + * Init receive descriptors. + */ + for (i = 0; i < RXDESCS; i++) + zc->zc_recv[i].ze_framelen = ZE_FRAMELEN_OW; + sc->sc_nextrx = 0; + + ZE_WCSR(ZE_CSR6, ZE_NICSR6_IE|ZE_NICSR6_BL_8|ZE_NICSR6_ST| + ZE_NICSR6_SR|ZE_NICSR6_DC); + + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + + /* + * Send a setup frame. + * This will start the transmit machinery as well. + */ + ze_setup(sc); + +} + +/* + * Start output on interface. + */ +void +zestart(ifp) + struct ifnet *ifp; +{ + struct ze_softc *sc = ifp->if_softc; + struct ze_cdata *zc = sc->sc_zedata; + paddr_t buffer; + struct mbuf *m, *m0; + int idx, len, s, i, totlen, error; + short orword; + + s = splimp(); + while (sc->sc_inq < (TXDESCS - 1)) { + + if (sc->sc_setup) { + ze_setup(sc); + continue; + } + idx = sc->sc_nexttx; + IF_DEQUEUE(&sc->sc_if.if_snd, m); + if (m == 0) + goto out; + /* + * Count number of mbufs in chain. + * Always do DMA directly from mbufs, therefore the transmit + * ring is really big. + */ + for (m0 = m, i = 0; m0; m0 = m0->m_next) + if (m0->m_len) + i++; + if (i >= TXDESCS) + panic("zestart"); /* XXX */ + + if ((i + sc->sc_inq) >= (TXDESCS - 1)) { + IF_PREPEND(&sc->sc_if.if_snd, m); + ifp->if_flags |= IFF_OACTIVE; + goto out; + } + +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m); +#endif + /* + * m now points to a mbuf chain that can be loaded. + * Loop around and set it. + */ + totlen = 0; + for (m0 = m; m0; m0 = m0->m_next) { + error = bus_dmamap_load(sc->sc_dmat, sc->sc_xmtmap[idx], + mtod(m0, void *), m0->m_len, 0, 0); + buffer = sc->sc_xmtmap[idx]->dm_segs[0].ds_addr; + len = m0->m_len; + if (len == 0) + continue; + + totlen += len; + /* Word alignment calc */ + orword = 0; + if (totlen == len) + orword = ZE_TDES1_FS; + if (totlen == m->m_pkthdr.len) { + if (totlen < ETHER_ADDR_LEN) + len += (ETHER_ADDR_LEN - totlen); + orword |= ZE_TDES1_LS; + sc->sc_txmbuf[idx] = m; + } + zc->zc_xmit[idx].ze_bufsize = len; + zc->zc_xmit[idx].ze_bufaddr = (char *)buffer; + zc->zc_xmit[idx].ze_tdes1 = orword | ZE_TDES1_IC; + zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW; + + if (++idx == TXDESCS) + idx = 0; + sc->sc_inq++; + } +#ifdef DIAGNOSTIC + if (totlen != m->m_pkthdr.len) + panic("zestart: len fault"); +#endif + + /* + * Kick off the transmit logic, if it is stopped. + */ + if ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) != ZE_NICSR5_TS_RUN) + ZE_WCSR(ZE_CSR1, -1); + sc->sc_nexttx = idx; + } + if (sc->sc_inq == (TXDESCS - 1)) + ifp->if_flags |= IFF_OACTIVE; + +out: if (sc->sc_inq) + ifp->if_timer = 5; /* If transmit logic dies */ + splx(s); +} + +int +sgec_intr(sc) + struct ze_softc *sc; +{ + struct ze_cdata *zc = sc->sc_zedata; + struct ifnet *ifp = &sc->sc_if; + struct ether_header *eh; + struct mbuf *m; + int csr, len; + + csr = ZE_RCSR(ZE_CSR5); + if ((csr & ZE_NICSR5_IS) == 0) /* Wasn't we */ + return 0; + ZE_WCSR(ZE_CSR5, csr); + + if (csr & ZE_NICSR5_RI) + while ((zc->zc_recv[sc->sc_nextrx].ze_framelen & + ZE_FRAMELEN_OW) == 0) { + + m = sc->sc_rxmbuf[sc->sc_nextrx]; + len = zc->zc_recv[sc->sc_nextrx].ze_framelen; + ze_add_rxbuf(sc, sc->sc_nextrx); + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = m->m_len = len; + if (++sc->sc_nextrx == RXDESCS) + sc->sc_nextrx = 0; + eh = mtod(m, struct ether_header *); +#if NBPFILTER > 0 + if (ifp->if_bpf) { + bpf_mtap(ifp->if_bpf, m); + if ((ifp->if_flags & IFF_PROMISC) != 0 && + bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost, + ETHER_ADDR_LEN) != 0 && + ((eh->ether_dhost[0] & 1) == 0)) { + m_freem(m); + continue; + } + } +#endif + /* + * ALLMULTI means PROMISC in this driver. + */ + if ((ifp->if_flags & IFF_ALLMULTI) && + ((eh->ether_dhost[0] & 1) == 0) && + bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost, + ETHER_ADDR_LEN)) { + m_freem(m); + continue; + } + + /* m_adj() the ethernet header out of the way and pass up */ + m_adj(m, sizeof(struct ether_header)); + ether_input(ifp, eh, m); + } + + if (csr & ZE_NICSR5_TI) { + while ((zc->zc_xmit[sc->sc_lastack].ze_tdr & ZE_TDR_OW) == 0) { + int idx = sc->sc_lastack; + + if (sc->sc_lastack == sc->sc_nexttx) + break; + sc->sc_inq--; + if (++sc->sc_lastack == TXDESCS) + sc->sc_lastack = 0; + + /* XXX collect statistics */ + if ((zc->zc_xmit[idx].ze_tdes1 & ZE_TDES1_DT) == + ZE_TDES1_DT_SETUP) + continue; + bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]); + if (sc->sc_txmbuf[idx]) { + m_freem(sc->sc_txmbuf[idx]); + sc->sc_txmbuf[idx] = 0; + } + } + ifp->if_timer = 0; + ifp->if_flags &= ~IFF_OACTIVE; + zestart(ifp); /* Put in more in queue */ + } + return 1; +} + +/* + * Process an ioctl request. + */ +int +zeioctl(ifp, cmd, data) + register struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ + struct ze_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *)data; + struct ifaddr *ifa = (struct ifaddr *)data; + int s = splnet(), error = 0; + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + switch(ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + zeinit(sc); + arp_ifinit(&sc->sc_ac, ifa); + break; +#endif + } + break; + + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && + (ifp->if_flags & IFF_RUNNING) != 0) { + /* + * If interface is marked down and it is running, + * stop it. (by disabling receive mechanism). + */ + ZE_WCSR(ZE_CSR6, ZE_RCSR(ZE_CSR6) & + ~(ZE_NICSR6_ST|ZE_NICSR6_SR)); + ifp->if_flags &= ~IFF_RUNNING; + } else if ((ifp->if_flags & IFF_UP) != 0 && + (ifp->if_flags & IFF_RUNNING) == 0) { + /* + * If interface it marked up and it is stopped, then + * start it. + */ + zeinit(sc); + } else if ((ifp->if_flags & IFF_UP) != 0) { + /* + * Send a new setup packet to match any new changes. + * (Like IFF_PROMISC etc) + */ + ze_setup(sc); + } + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + /* + * Update our multicast list. + */ + error = (cmd == SIOCADDMULTI) ? + ether_addmulti(ifr, &sc->sc_ac): + ether_delmulti(ifr, &sc->sc_ac); + + if (error == ENETRESET) { + /* + * Multicast list has changed; set the hardware filter + * accordingly. + */ + ze_setup(sc); + error = 0; + } + break; + + default: + error = EINVAL; + + } + splx(s); + return (error); +} + +/* + * Add a receive buffer to the indicated descriptor. + */ +int +ze_add_rxbuf(sc, i) + struct ze_softc *sc; + int i; +{ + struct mbuf *m; + struct ze_rdes *rp; + int error; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) + return (ENOBUFS); + + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + return (ENOBUFS); + } + + if (sc->sc_rxmbuf[i] != NULL) + bus_dmamap_unload(sc->sc_dmat, sc->sc_rcvmap[i]); + + error = bus_dmamap_load(sc->sc_dmat, sc->sc_rcvmap[i], + m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT); + if (error) + panic("%s: can't load rx DMA map %d, error = %d\n", + sc->sc_dev.dv_xname, i, error); + sc->sc_rxmbuf[i] = m; + + bus_dmamap_sync(sc->sc_dmat, sc->sc_rcvmap[i], 0, + sc->sc_rcvmap[i]->dm_mapsize, BUS_DMASYNC_PREREAD); + + /* + * We know that the mbuf cluster is page aligned. Also, be sure + * that the IP header will be longword aligned. + */ + m->m_data += 2; + rp = &sc->sc_zedata->zc_recv[i]; + rp->ze_bufsize = (m->m_ext.ext_size - 2); + rp->ze_bufaddr = (char *)sc->sc_rcvmap[i]->dm_segs[0].ds_addr + 2; + rp->ze_framelen = ZE_FRAMELEN_OW; + + return (0); +} + +/* + * Create a setup packet and put in queue for sending. + */ +void +ze_setup(sc) + struct ze_softc *sc; +{ + struct ether_multi *enm; + struct ether_multistep step; + struct ze_cdata *zc = sc->sc_zedata; + struct ifnet *ifp = &sc->sc_if; + u_int8_t *enaddr = sc->sc_ac.ac_enaddr; + int j, idx, s, reg; + + s = splimp(); + if (sc->sc_inq == (TXDESCS - 1)) { + sc->sc_setup = 1; + splx(s); + return; + } + sc->sc_setup = 0; + /* + * Init the setup packet with valid info. + */ + memset(zc->zc_setup, 0xff, sizeof(zc->zc_setup)); /* Broadcast */ + bcopy(enaddr, zc->zc_setup, ETHER_ADDR_LEN); + + /* + * Multicast handling. The SGEC can handle up to 16 direct + * ethernet addresses. + */ + j = 16; + ifp->if_flags &= ~IFF_ALLMULTI; + ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); + while (enm != NULL) { + if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) { + ifp->if_flags |= IFF_ALLMULTI; + break; + } + bcopy(enm->enm_addrlo, &zc->zc_setup[j], ETHER_ADDR_LEN); + j += 8; + ETHER_NEXT_MULTI(step, enm); + if ((enm != NULL)&& (j == 128)) { + ifp->if_flags |= IFF_ALLMULTI; + break; + } + } + + /* + * Fiddle with the receive logic. + */ + reg = ZE_RCSR(ZE_CSR6); + DELAY(10); + ZE_WCSR(ZE_CSR6, reg & ~ZE_NICSR6_SR); /* Stop rx */ + reg &= ~ZE_NICSR6_AF; + if (ifp->if_flags & IFF_PROMISC) + reg |= ZE_NICSR6_AF_PROM; + else if (ifp->if_flags & IFF_ALLMULTI) + reg |= ZE_NICSR6_AF_ALLM; + DELAY(10); + ZE_WCSR(ZE_CSR6, reg); + /* + * Only send a setup packet if needed. + */ + if ((ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) == 0) { + idx = sc->sc_nexttx; + zc->zc_xmit[idx].ze_tdes1 = ZE_TDES1_DT_SETUP; + zc->zc_xmit[idx].ze_bufsize = 128; + zc->zc_xmit[idx].ze_bufaddr = sc->sc_pzedata->zc_setup; + zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW; + + if ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) != ZE_NICSR5_TS_RUN) + ZE_WCSR(ZE_CSR1, -1); + + sc->sc_inq++; + if (++sc->sc_nexttx == TXDESCS) + sc->sc_nexttx = 0; + } + splx(s); +} + +/* + * Check for dead transmit logic. + */ +void +zetimeout(ifp) + struct ifnet *ifp; +{ + struct ze_softc *sc = ifp->if_softc; + + if (sc->sc_inq == 0) + return; + + printf("%s: xmit logic died, resetting...\n", sc->sc_dev.dv_xname); + /* + * Do a reset of interface, to get it going again. + * Will it work by just restart the transmit logic? + */ + zeinit(sc); +} + +/* + * Reset chip: + * Set/reset the reset flag. + * Write interrupt vector. + * Write ring buffer addresses. + * Write SBR. + */ +int +zereset(sc) + struct ze_softc *sc; +{ + int reg, i, s; + + ZE_WCSR(ZE_CSR6, ZE_NICSR6_RE); + DELAY(50000); + if (ZE_RCSR(ZE_CSR6) & ZE_NICSR5_SF) { + printf("%s: selftest failed\n", sc->sc_dev.dv_xname); + return 1; + } + + /* + * Get the vector that were set at match time, and remember it. + * WHICH VECTOR TO USE? Take one unused. XXX + * Funny way to set vector described in the programmers manual. + */ + reg = ZE_NICSR0_IPL14 | sc->sc_intvec | 0x1fff0003; /* SYNC/ASYNC??? */ + i = 10; + s = splimp(); + do { + if (i-- == 0) { + printf("Failing SGEC CSR0 init\n"); + splx(s); + return 1; + } + ZE_WCSR(ZE_CSR0, reg); + } while (ZE_RCSR(ZE_CSR0) != reg); + splx(s); + + ZE_WCSR(ZE_CSR3, (vaddr_t)sc->sc_pzedata->zc_recv); + ZE_WCSR(ZE_CSR4, (vaddr_t)sc->sc_pzedata->zc_xmit); + return 0; +} diff --git a/sys/arch/vax/if/sgecreg.h b/sys/arch/vax/if/sgecreg.h new file mode 100644 index 00000000000..c3a2090e314 --- /dev/null +++ b/sys/arch/vax/if/sgecreg.h @@ -0,0 +1,242 @@ +/* $OpenBSD: sgecreg.h,v 1.1 2000/04/27 03:14:44 bjc Exp $ */ +/* $NetBSD: sgecreg.h,v 1.1 1999/08/08 11:41:29 ragge Exp $ */ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Digital Equipment Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + + +/* Driver for SGEC (second generation Ethernet controller) chip, type DC-541, + found on the KA670 (and prob ably other) CPU. + + 17 May 1998...Jay Maynard, jmaynard@phoenix.net +*/ + +/* SGEC CSRs */ +struct zedevice { + u_long ze_nicsr0; /* vector address, IPL, sync mode */ + u_long ze_nicsr1; /* TX poll demand */ + u_long ze_nicsr2; /* RX poll demand */ + struct ze_rdes *ze_nicsr3; /* RX descriptor list address */ + struct ze_tdes *ze_nicsr4; /* TX descriptor list address */ + u_long ze_nicsr5; /* SGEC status */ + u_long ze_nicsr6; /* SGEC command/mode */ + u_long ze_nicsr7; /* system page table base address */ + u_long ze_nivcsr8; /* reserved virtual CSR */ + u_long ze_nivcsr9; /* watchdog timers (virtual) */ + u_long ze_nivcsr10; /* revision, missed frame count (v) */ + u_long ze_nivcsr11; /* boot message verification (low) (v) */ + u_long ze_nivcsr12; /* boot message verification (high) (v) */ + u_long ze_nivcsr13; /* boot message processor (v) */ + u_long ze_nivcsr14; /* diagnostic breakpoint (v) */ + u_long ze_nicsr15; /* monitor command */ +}; + +/* + * Register offsets. + */ +#define ZE_CSR0 0 +#define ZE_CSR1 4 +#define ZE_CSR2 8 +#define ZE_CSR3 12 +#define ZE_CSR4 16 +#define ZE_CSR5 20 +#define ZE_CSR6 24 +#define ZE_CSR7 28 +#define ZE_CSR8 32 +#define ZE_CSR9 36 +#define ZE_CSR10 40 +#define ZE_CSR11 44 +#define ZE_CSR12 48 +#define ZE_CSR13 52 +#define ZE_CSR14 56 +#define ZE_CSR15 60 + +/* SGEC bit definitions */ +/* NICSR0: */ +#define ZE_NICSR0_IPL 0xc0000000 /* interrupt priority level: */ +#define ZE_NICSR0_IPL14 0x00000000 /* 0x14 */ +#define ZE_NICSR0_IPL15 0x40000000 /* 0x15 */ +#define ZE_NICSR0_IPL16 0x80000000 /* 0x16 */ +#define ZE_NICSR0_IPL17 0xc0000000 /* 0x17 */ +#define ZE_NICSR0_SA 0x20000000 /* sync(1)/async mode */ +#define ZE_NICSR0_MBO 0x1fff0003 /* must be set to one on write */ +#define ZE_NICSR0_IV_MASK 0x0000fffc /* bits for the interrupt vector */ + +/* NICSR1: */ +#define ZE_NICSR1_TXPD 0xffffffff /* transmit polling demand */ + +/* NICSR2: */ +#define ZE_NICSR2_RXPD 0xffffffff /* receive polling demand */ + +/* NICSR3 and NICSR4 are pure addresses */ +/* NICSR5: */ +#define ZE_NICSR5_ID 0x80000000 /* init done */ +#define ZE_NICSR5_SF 0x40000000 /* self-test failed */ +#define ZE_NICSR5_SS 0x3c000000 /* self-test status field */ +#define ZE_NICSR5_TS 0x03000000 /* transmission state: */ +#define ZE_NICSR5_TS_STOP 0x00000000 /* stopped */ +#define ZE_NICSR5_TS_RUN 0x01000000 /* running */ +#define ZE_NICSR5_TS_SUSP 0x02000000 /* suspended */ +#define ZE_NICSR5_RS 0x00c00000 /* reception state: */ +#define ZE_NICSR5_RS_STOP 0x00000000 /* stopped */ +#define ZE_NICSR5_RS_RUN 0x00400000 /* running */ +#define ZE_NICSR5_RS_SUSP 0x00800000 /* suspended */ +#define ZE_NICSR5_OM 0x00060000 /* operating mode: */ +#define ZE_NICSR5_OM_NORM 0x00000000 /* normal */ +#define ZE_NICSR5_OM_ILBK 0x00020000 /* internal loopback */ +#define ZE_NICSR5_OM_ELBK 0x00040000 /* external loopback */ +#define ZE_NICSR5_OM_DIAG 0x00060000 /* reserved for diags */ +#define ZE_NICSR5_DN 0x00010000 /* virtual CSR access done */ +#define ZE_NICSR5_MBO 0x0038ff00 /* must be one */ +#define ZE_NICSR5_BO 0x00000080 /* boot message received */ +#define ZE_NICSR5_TW 0x00000040 /* transmit watchdog timeout */ +#define ZE_NICSR5_RW 0x00000020 /* receive watchdog timeout */ +#define ZE_NICSR5_ME 0x00000010 /* memory error */ +#define ZE_NICSR5_RU 0x00000008 /* receive buffer unavailable */ +#define ZE_NICSR5_RI 0x00000004 /* receiver interrupt */ +#define ZE_NICSR5_TI 0x00000002 /* transmitter interrupt */ +#define ZE_NICSR5_IS 0x00000001 /* interrupt summary */ +/* whew! */ + +/* NICSR6: */ +#define ZE_NICSR6_RE 0x80000000 /* reset */ +#define ZE_NICSR6_IE 0x40000000 /* interrupt enable */ +#define ZE_NICSR6_MBO 0x01e7f000 /* must be one */ +#define ZE_NICSR6_BL 0x1e000000 /* burst limit mask */ +#define ZE_NICSR6_BL_8 0x10000000 /* 8 longwords */ +#define ZE_NICSR6_BL_4 0x08000000 /* 4 longwords */ +#define ZE_NICSR6_BL_2 0x04000000 /* 2 longwords */ +#define ZE_NICSR6_BL_1 0x02000000 /* 1 longword */ +#define ZE_NICSR6_BE 0x00100000 /* boot message enable */ +#define ZE_NICSR6_SE 0x00080000 /* single cycle enable */ +#define ZE_NICSR6_ST 0x00000800 /* start(1)/stop(0) transmission */ +#define ZE_NICSR6_SR 0x00000400 /* start(1)/stop(0) reception */ +#define ZE_NICSR6_OM 0x00000300 /* operating mode: */ +#define ZE_NICSR6_OM_NORM 0x00000000 /* normal */ +#define ZE_NICSR6_OM_ILBK 0x00000100 /* internal loopback */ +#define ZE_NICSR6_OM_ELBK 0x00000200 /* external loopback */ +#define ZE_NICSR6_OM_DIAG 0x00000300 /* reserved for diags */ +#define ZE_NICSR6_DC 0x00000080 /* disable data chaining */ +#define ZE_NICSR6_FC 0x00000040 /* force collision mode */ +#define ZE_NICSR6_PB 0x00000008 /* pass bad frames */ +#define ZE_NICSR6_AF 0x00000006 /* address filtering mode: */ +#define ZE_NICSR6_AF_NORM 0x00000000 /* normal filtering */ +#define ZE_NICSR6_AF_PROM 0x00000002 /* promiscuous mode */ +#define ZE_NICSR6_AF_ALLM 0x00000004 /* all multicasts */ + +/* NICSR7 is an address, NICSR8 is reserved */ +/* NICSR9: */ +#define ZE_VNICSR9_RT 0xffff0000 /* receiver timeout, *1.6 us */ +#define ZE_VNICSR9_TT 0x0000ffff /* transmitter timeout */ + +/* NICSR10: */ +#define ZE_VNICSR10_RN 0x001f0000 /* SGEC version */ +#define ZE_VNICSR10_MFC 0x0000ffff /* missed frame counter */ + +/* if you want to know what's in NICSRs 11-15, define them yourself! */ + +/* Descriptors: */ +/* Receive descriptor */ +struct ze_rdes { + u_short ze_rdes0; /* descriptor word 0 flags */ + u_short ze_framelen; /* received frame length */ + u_char ze_rsvd1[3]; /* unused bytes */ + u_char ze_rdes1; /* descriptor word 1 flags */ + short ze_pageoffset; /* offset of buffer in page */ + short ze_bufsize; /* length of data buffer */ + u_char *ze_bufaddr; /* address of data buffer */ +}; + +/* Receive descriptor bits */ +#define ZE_FRAMELEN_OW 0x8000 /* SGEC owns this descriptor */ +#define ZE_RDES0_ES 0x8000 /* an error has occurred */ +#define ZE_RDES0_LE 0x4000 /* length error */ +#define ZE_RDES0_DT 0x3000 /* data type: */ +#define ZE_RDES0_DT_NORM 0x0000 /* normal frame */ +#define ZE_RDES0_DT_ILBK 0x1000 /* internally looped back frame */ +#define ZE_RDES0_DT_ELBK 0x2000 /* externally looped back frame */ +#define ZE_RDES0_RF 0x0800 /* runt frame */ +#define ZE_RDES0_BO 0x0400 /* buffer overflow */ +#define ZE_RDES0_FS 0x0200 /* first segment */ +#define ZE_RDES0_LS 0x0100 /* last segment */ +#define ZE_RDES0_TL 0x0080 /* frame too long */ +#define ZE_RDES0_CS 0x0040 /* collision seen */ +#define ZE_RDES0_FT 0x0020 /* Ethernet frame type */ +#define ZE_RDES0_TN 0x0008 /* address translation not valid */ +#define ZE_RDES0_DB 0x0004 /* dribbling bits seen */ +#define ZE_RDES0_CE 0x0002 /* CRC error */ +#define ZE_RDES0_OF 0x0001 /* internal FIFO overflow */ +#define ZE_RDES1_CA 0x80 /* chain address */ +#define ZE_RDES1_VA 0x40 /* virtual address */ +#define ZE_RDES1_VT 0x20 /* virtual(1)/phys PTE address */ + +/* Transmit descriptor */ +struct ze_tdes { + u_short ze_tdes0; /* descriptor word 0 flags */ + u_short ze_tdr; /* TDR count of cable fault */ + u_char ze_rsvd1[2]; /* unused bytes */ + u_short ze_tdes1; /* descriptor word 1 flags */ + short ze_pageoffset; /* offset of buffer in page */ + short ze_bufsize; /* length of data buffer */ + u_char *ze_bufaddr; /* address of data buffer */ +}; + +/* Receive descriptor bits */ +#define ZE_TDR_OW 0x8000 /* SGEC owns this descriptor */ +#define ZE_TDES0_ES 0x8000 /* an error has occurred */ +#define ZE_TDES0_TO 0x4000 /* transmit watchdog timeout */ +#define ZE_TDES0_LE 0x1000 /* length error */ +#define ZE_TDES0_LO 0x0800 /* loss of carrier */ +#define ZE_TDES0_NC 0x0400 /* no carrier */ +#define ZE_TDES0_LC 0x0200 /* late collision */ +#define ZE_TDES0_EC 0x0100 /* excessive collisions */ +#define ZE_TDES0_HF 0x0080 /* heartbeat fail */ +#define ZE_TDES0_CC 0x0078 /* collision count mask */ +#define ZE_TDES0_TN 0x0004 /* address translation invalid */ +#define ZE_TDES0_UF 0x0002 /* underflow */ +#define ZE_TDES0_DE 0x0001 /* transmission deferred */ +#define ZE_TDES1_CA 0x8000 /* chain address */ +#define ZE_TDES1_VA 0x4000 /* virtual address */ +#define ZE_TDES1_DT 0x3000 /* data type: */ +#define ZE_TDES1_DT_NORM 0x0000 /* normal transmit frame */ +#define ZE_TDES1_DT_SETUP 0x2000 /* setup frame */ +#define ZE_TDES1_DT_DIAG 0x3000 /* diagnostic frame */ +#define ZE_TDES1_AC 0x0800 /* CRC disable */ +#define ZE_TDES1_FS 0x0400 /* first segment */ +#define ZE_TDES1_LS 0x0200 /* last segment */ +#define ZE_TDES1_IC 0x0100 /* interrupt on completion */ +#define ZE_TDES1_VT 0x0080 /* virtual(1)/phys PTE address */ + diff --git a/sys/arch/vax/if/sgecvar.h b/sys/arch/vax/if/sgecvar.h new file mode 100644 index 00000000000..7cf93770817 --- /dev/null +++ b/sys/arch/vax/if/sgecvar.h @@ -0,0 +1,68 @@ +/* $OpenBSD: sgecvar.h,v 1.1 2000/04/27 03:14:44 bjc Exp $ */ +/* $NetBSD: sgecvar.h,v 1.1 1999/08/08 11:41:30 ragge Exp $ */ +/* + * Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define RXDESCS 30 /* # of receive descriptors */ +#define TXDESCS 60 /* # transmit descs */ + +/* + * Descriptors must be an even number; optimisation thing. + */ +struct ze_cdata { + struct ze_rdes zc_recv[RXDESCS+2]; /* Receive descriptors */ + struct ze_tdes zc_xmit[TXDESCS+2]; /* Transmit descriptors */ + u_int8_t zc_setup[128]; /* Setup packet layout */ +}; + +struct ze_softc { + struct device sc_dev; /* Configuration common part */ + struct arpcom sc_ac; /* Ethernet common part */ +#define sc_if sc_ac.ac_if /* network-visible interface */ + bus_space_tag_t sc_iot; + bus_addr_t sc_ioh; + bus_dma_tag_t sc_dmat; + struct ze_cdata *sc_zedata; /* Descriptor struct */ + struct ze_cdata *sc_pzedata; /* Physical address of above */ + bus_dmamap_t sc_cmap; /* Map for control structures */ + struct mbuf* sc_txmbuf[TXDESCS]; + struct mbuf* sc_rxmbuf[RXDESCS]; + bus_dmamap_t sc_xmtmap[TXDESCS]; + bus_dmamap_t sc_rcvmap[RXDESCS]; + int sc_intvec; /* Interrupt vector */ + int sc_nexttx; + int sc_inq; + int sc_lastack; + int sc_nextrx; + int sc_setup; /* Setup packet in queue */ +}; + +void sgec_attach __P((struct ze_softc *)); +int sgec_intr __P((struct ze_softc *)); diff --git a/sys/arch/vax/mba/hp.c b/sys/arch/vax/mba/hp.c index 633d6a04aa5..962b2c689ee 100644 --- a/sys/arch/vax/mba/hp.c +++ b/sys/arch/vax/mba/hp.c @@ -1,5 +1,5 @@ -/* $OpenBSD: hp.c,v 1.9 1998/10/03 21:18:59 millert Exp $ */ -/* $NetBSD: hp.c,v 1.15 1997/06/24 01:09:37 thorpej Exp $ */ +/* $OpenBSD: hp.c,v 1.10 2000/04/27 03:14:44 bjc Exp $ */ +/* $NetBSD: hp.c,v 1.22 2000/02/12 16:09:33 ragge Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -74,7 +74,7 @@ struct hp_softc { int sc_physnr; /* Physical disk number */ }; -int hpmatch __P((struct device *, void *, void *)); +int hpmatch __P((struct device *, struct cfdata *, void *)); void hpattach __P((struct device *, struct device *, void *)); void hpstrategy __P((struct buf *)); void hpstart __P((struct mba_device *)); @@ -88,26 +88,25 @@ int hpread __P((dev_t, struct uio *)); int hpwrite __P((dev_t, struct uio *)); int hpsize __P((dev_t)); -struct cfdriver hp_cd = { - NULL, "hp", DV_DISK -}; - struct cfattach hp_ca = { sizeof(struct hp_softc), hpmatch, hpattach }; +extern struct cfdriver hp_cd; + /* * Check if this is a disk drive; done by checking type from mbaattach. */ int -hpmatch(parent, match, aux) +hpmatch(parent, cf, aux) struct device *parent; - void *match, *aux; + struct cfdata *cf; + void *aux; { - struct cfdata *cf = match; struct mba_attach_args *ma = aux; - if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ma->unit) + if (cf->cf_loc[MBACF_DRIVE] != MBACF_DRIVE_DEFAULT && + cf->cf_loc[MBACF_DRIVE] != ma->unit) return 0; if (ma->devtyp != MB_RP) @@ -134,6 +133,7 @@ hpattach(parent, self, aux) /* * Init the common struct for both the adapter and its slaves. */ + BUFQ_INIT(&sc->sc_md.md_q); sc->sc_md.md_softc = (void *)sc; /* Pointer to this softc */ sc->sc_md.md_mba = (void *)parent; /* Pointer to parent softc */ sc->sc_md.md_start = hpstart; /* Disk start routine */ @@ -163,7 +163,7 @@ hpattach(parent, self, aux) * Read in label. */ if ((msg = readdisklabel(makedev(0, self->dv_unit * 8), hpstrategy, - dl, NULL, 0)) != NULL) + dl, NULL)) != NULL) printf(": %s", msg); printf(": %s, size = %d sectors\n", dl->d_typename, dl->d_secperunit); /* @@ -181,18 +181,25 @@ hpstrategy(bp) { struct hp_softc *sc; struct buf *gp; - int unit, s; + int unit, s, err; + struct disklabel *lp; unit = DISKUNIT(bp->b_dev); sc = hp_cd.cd_devs[unit]; + lp = sc->sc_disk.dk_label; - if (bounds_check_with_label(bp, sc->sc_disk.dk_label, - sc->sc_disk.dk_cpulabel, sc->sc_wlabel) <= 0) + err = bounds_check_with_label(bp, lp, sc->sc_wlabel); + if (err < 0) goto done; + + bp->b_rawblkno = + bp->b_blkno + lp->d_partitions[DISKPART(bp->b_dev)].p_offset; + bp->b_cylinder = bp->b_rawblkno / lp->d_secpercyl; + s = splbio(); - gp = sc->sc_md.md_q.b_actf; - disksort(&sc->sc_md.md_q, bp); + gp = BUFQ_FIRST(&sc->sc_md.md_q); + disksort_cylinder(&sc->sc_md.md_q, bp); if (gp == 0) mbaqueue(&sc->sc_md); @@ -215,9 +222,8 @@ hpstart(md) struct mba_regs *mr = md->md_mba->sc_mbareg; volatile struct hp_regs *hr; struct disklabel *lp = sc->sc_disk.dk_label; - struct buf *bp = md->md_q.b_actf; + struct buf *bp = BUFQ_FIRST(&md->md_q); unsigned bn, cn, sn, tn; - int part = DISKPART(bp->b_dev); /* * Collect statistics. @@ -227,7 +233,7 @@ hpstart(md) hr = (void *)&mr->mba_md[DISKUNIT(bp->b_dev)]; - bn = bp->b_blkno + lp->d_partitions[part].p_offset; + bn = bp->b_rawblkno; if (bn) { cn = bn / lp->d_secpercyl; sn = bn % lp->d_secpercyl; @@ -368,7 +374,7 @@ hpfinish(md, mbasr, attn) int mbasr, *attn; { struct hp_softc *sc = md->md_softc; - struct buf *bp = md->md_q.b_actf; + struct buf *bp = BUFQ_FIRST(&md->md_q); volatile struct mba_regs *mr = md->md_mba->sc_mbareg; volatile struct hp_regs *hr = (void *)&mr->mba_md[DISKUNIT(bp->b_dev)]; int er1, er2; @@ -407,8 +413,8 @@ hper2: printf("massbuss error :%s %x\n", sc->sc_dev.dv_xname, mbasr); - md->md_q.b_actf->b_resid = 0; - disk_unbusy(&sc->sc_disk, md->md_q.b_actf->b_bcount); + BUFQ_FIRST(&md->md_q)->b_resid = 0; + disk_unbusy(&sc->sc_disk, BUFQ_FIRST(&md->md_q)->b_bcount); return XFER_FINISH; } @@ -445,7 +451,8 @@ hpsize(dev) return -1; sc = hp_cd.cd_devs[unit]; - size = sc->sc_disk.dk_label->d_partitions[DISKPART(dev)].p_size; + size = sc->sc_disk.dk_label->d_partitions[DISKPART(dev)].p_size * + (sc->sc_disk.dk_label->d_secsize / DEV_BSIZE); return size; } @@ -475,29 +482,3 @@ hpwrite(dev, uio) { return (physio(hpstrategy, NULL, dev, B_WRITE, minphys, uio)); } - -/* - * Convert physical adapternr and unit to the unit number used by kernel. - */ -int -hp_getdev(mbanr, unit, uname) - int mbanr, unit; - char **uname; -{ - struct mba_softc *ms; - struct hp_softc *sc; - int i; - - for (i = 0; i < hp_cd.cd_ndevs; i++) { - if (hp_cd.cd_devs[i] == 0) - continue; - - sc = hp_cd.cd_devs[i]; - ms = (void *)sc->sc_dev.dv_parent; - if (ms->sc_physnr == mbanr && sc->sc_physnr == unit) { - *uname = sc->sc_dev.dv_xname; - return i; - } - } - return -1; -} diff --git a/sys/arch/vax/mba/mba.c b/sys/arch/vax/mba/mba.c index 88e269579e9..d11ce0caaa5 100644 --- a/sys/arch/vax/mba/mba.c +++ b/sys/arch/vax/mba/mba.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mba.c,v 1.5 1997/05/29 00:04:59 niklas Exp $ */ -/* $NetBSD: mba.c,v 1.10 1996/10/13 03:35:00 christos Exp $ */ +/* $OpenBSD: mba.c,v 1.6 2000/04/27 03:14:45 bjc Exp $ */ +/* $NetBSD: mba.c,v 1.18 2000/01/24 02:40:36 matt Exp $ */ /* * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -54,6 +54,7 @@ #include <machine/pte.h> #include <machine/pcb.h> #include <machine/sid.h> +#include <machine/cpu.h> #include <vax/mba/mbareg.h> #include <vax/mba/mbavar.h> @@ -70,18 +71,14 @@ struct mbaunit mbaunit[] = { {0, 0, 0} }; -int mbamatch __P((struct device *, void *, void *)); +int mbamatch __P((struct device *, struct cfdata *, void *)); void mbaattach __P((struct device *, struct device *, void *)); -void mbaintr __P((int)); +void mbaintr __P((void *)); int mbaprint __P((void *, const char *)); void mbaqueue __P((struct mba_device *)); void mbastart __P((struct mba_softc *)); void mbamapregs __P((struct mba_softc *)); -struct cfdriver mba_cd = { - NULL, "mba", DV_DULL -}; - struct cfattach mba_cmi_ca = { sizeof(struct mba_softc), mbamatch, mbaattach }; @@ -90,16 +87,18 @@ struct cfattach mba_sbi_ca = { sizeof(struct mba_softc), mbamatch, mbaattach }; +extern struct cfdriver mba_cd; + /* * Look if this is a massbuss adapter. */ int -mbamatch(parent, match, aux) +mbamatch(parent, cf, aux) struct device *parent; - void *match, *aux; + struct cfdata *cf; + void *aux; { struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; - struct cfdata *cf = match; if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 )) return 0; @@ -123,22 +122,21 @@ mbaattach(parent, self, aux) struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; volatile struct mba_regs *mbar = (struct mba_regs *)sa->nexaddr; struct mba_attach_args ma; - extern struct ivec_dsp idsptch; int i, j; printf("\n"); /* * Set up interrupt vectors for this MBA. */ - bcopy(&idsptch, &sc->sc_dsp, sizeof(struct ivec_dsp)); + sc->sc_dsp = idsptch; + sc->sc_dsp.pushlarg = sc; + sc->sc_dsp.hoppaddr = mbaintr; scb->scb_nexvec[0][sa->nexnum] = scb->scb_nexvec[1][sa->nexnum] = scb->scb_nexvec[2][sa->nexnum] = scb->scb_nexvec[3][sa->nexnum] = &sc->sc_dsp; - sc->sc_dsp.pushlarg = sc->sc_dev.dv_unit; - sc->sc_dsp.hoppaddr = mbaintr; sc->sc_physnr = sa->nexnum - 8; /* MBA's have TR between 8 - 11... */ -#ifdef VAX750 +#if VAX750 if (vax_cputype == VAX_750) sc->sc_physnr += 4; /* ...but not on 11/750 */ #endif @@ -171,9 +169,9 @@ mbaattach(parent, self, aux) */ void mbaintr(mba) - int mba; + void *mba; { - struct mba_softc *sc = mba_cd.cd_devs[mba]; + struct mba_softc *sc = mba; volatile struct mba_regs *mr = sc->sc_mbareg; struct mba_device *md; struct buf *bp; @@ -189,7 +187,7 @@ mbaintr(mba) return; /* During autoconfig */ md = sc->sc_first; - bp = md->md_q.b_actf; + bp = BUFQ_FIRST(&md->md_q); /* * A data-transfer interrupt. Current operation is finished, * call that device's finish routine to see what to do next. @@ -206,13 +204,13 @@ mbaintr(mba) * If more to transfer, start the adapter again * by calling mbastart(). */ - md->md_q.b_actf = bp->b_actf; + BUFQ_REMOVE(&md->md_q, bp); sc->sc_first = md->md_back; md->md_back = 0; if (sc->sc_first == 0) sc->sc_last = (void *)&sc->sc_first; - if (md->md_q.b_actf) { + if (BUFQ_FIRST(&md->md_q) != NULL) { sc->sc_last->md_back = md; sc->sc_last = md; } @@ -287,12 +285,13 @@ mbastart(sc) { struct mba_device *md = sc->sc_first; volatile struct mba_regs *mr = sc->sc_mbareg; - struct buf *bp = md->md_q.b_actf; + struct buf *bp = BUFQ_FIRST(&md->md_q); - disk_reallymapin(md->md_q.b_actf, sc->sc_mbareg->mba_map, 0, PG_V); + disk_reallymapin(BUFQ_FIRST(&md->md_q), sc->sc_mbareg->mba_map, + 0, PG_V); sc->sc_state = SC_ACTIVE; - mr->mba_var = ((u_int)bp->b_un.b_addr & PGOFSET); + mr->mba_var = ((u_int)bp->b_un.b_addr & VAX_PGOFSET); mr->mba_bc = (~bp->b_bcount) + 1; (*md->md_start)(md); /* machine-dependent start */ } diff --git a/sys/arch/vax/mba/mbavar.h b/sys/arch/vax/mba/mbavar.h index e2960d67880..cc1c59a5706 100644 --- a/sys/arch/vax/mba/mbavar.h +++ b/sys/arch/vax/mba/mbavar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: mbavar.h,v 1.3 1997/05/29 00:05:00 niklas Exp $ */ -/* $NetBSD: mbavar.h,v 1.4 1996/04/08 18:39:01 ragge Exp $ */ +/* $OpenBSD: mbavar.h,v 1.4 2000/04/27 03:14:45 bjc Exp $ */ +/* $NetBSD: mbavar.h,v 1.5 2000/01/21 23:39:56 thorpej Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden * All rights reserved. @@ -98,7 +98,7 @@ struct mba_device { enum xfer_action (*md_finish) __P((struct mba_device *, int, int *)); void *md_softc; /* Backpointer to this units softc. */ struct mba_softc *md_mba; - struct buf md_q; /* Buffer head for transfers */ + struct buf_queue md_q; /* queue of I/O requests */ }; struct mba_softc { diff --git a/sys/arch/vax/mscp/files.mscp b/sys/arch/vax/mscp/files.mscp index fcf48862246..0791bca132a 100644 --- a/sys/arch/vax/mscp/files.mscp +++ b/sys/arch/vax/mscp/files.mscp @@ -1,19 +1,22 @@ -# $OpenBSD: files.mscp,v 1.2 1997/05/29 00:05:01 niklas Exp $ -# $NetBSD: files.mscp,v 1.1 1996/07/01 20:41:30 ragge Exp $ +# $OpenBSD: files.mscp,v 1.3 2000/04/27 03:14:45 bjc Exp $ +# $NetBSD: files.mscp,v 1.7 1999/06/06 19:16:18 ragge Exp $ # # File and device description for MSCP devices. # define mscp {} -file arch/vax/mscp/mscp.c -file arch/vax/mscp/mscp_subr.c +file arch/vax/mscp/mscp.c mscp +file arch/vax/mscp/mscp_subr.c mscp device mscpbus {drive = -1} attach mscpbus at mscp +device rx: disk +attach rx at mscpbus + device ra: disk attach ra at mscpbus -file arch/vax/mscp/mscp_disk.c ra needs-flag +file arch/vax/mscp/mscp_disk.c ra | rx needs-flag device mt: tape attach mt at mscpbus diff --git a/sys/arch/vax/mscp/mscp.c b/sys/arch/vax/mscp/mscp.c index 4d1821b29c6..09b46db5145 100644 --- a/sys/arch/vax/mscp/mscp.c +++ b/sys/arch/vax/mscp/mscp.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mscp.c,v 1.3 1997/09/12 09:25:47 maja Exp $ */ -/* $NetBSD: mscp.c,v 1.6 1997/07/04 11:58:20 ragge Exp $ */ +/* $OpenBSD: mscp.c,v 1.4 2000/04/27 03:14:45 bjc Exp $ */ +/* $NetBSD: mscp.c,v 1.11 1999/06/06 19:16:18 ragge Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. @@ -48,16 +48,16 @@ #include <sys/buf.h> #include <sys/malloc.h> #include <sys/device.h> +#include <sys/proc.h> +#include <sys/systm.h> -#include <vax/mscp/mscp.h> -#include <vax/mscp/mscpvar.h> +#include <machine/bus.h> -#define PCMD PSWP /* priority for command packet waits */ +#include <arch/vax/mscp/mscp.h> +#include <arch/vax/mscp/mscpreg.h> +#include <arch/vax/mscp/mscpvar.h> -/* - * During transfers, mapping info is saved in the buffer's b_resid. - */ -#define b_info b_resid +#define PCMD PSWP /* priority for command packet waits */ /* * Get a command packet. Second argument is true iff we are @@ -69,10 +69,10 @@ mscp_getcp(mi, canwait) register struct mscp_softc *mi; int canwait; { -#define mri (&mi->mi_cmd) +#define mri (&mi->mi_cmd) register struct mscp *mp; register int i; - int s = splbio(); + int s = splimp(); again: /* @@ -115,8 +115,8 @@ again: mp->mscp_seq.seq_bytecount = 0; mp->mscp_seq.seq_buffer = 0; mp->mscp_seq.seq_mapbase = 0; -/*???*/ mp->mscp_sccc.sccc_errlgfl = 0; -/*???*/ mp->mscp_sccc.sccc_copyspd = 0; +/*???*/ mp->mscp_sccc.sccc_errlgfl = 0; +/*???*/ mp->mscp_sccc.sccc_copyspd = 0; return (mp); #undef mri } @@ -135,10 +135,11 @@ mscp_dorsp(mi) struct device *drive; struct mscp_device *me = mi->mi_me; struct mscp_ctlr *mc = mi->mi_mc; - register struct buf *bp; - register struct mscp *mp; - register int nextrsp; - int st, error, info; + struct buf *bp; + struct mscp *mp; + struct mscp_xi *mxi; + int nextrsp; + int st, error; extern int cold; extern struct mscp slavereply; @@ -239,7 +240,7 @@ loop: case M_OP_ONLINE | M_OP_END: /* - * Finished an ON LINE request. Call the driver to + * Finished an ON LINE request. Call the driver to * find out whether it succeeded. If so, mark it on * line. */ @@ -291,6 +292,7 @@ loop: case M_OP_POS | M_OP_END: case M_OP_WRITM | M_OP_END: + case M_OP_AVAILABLE | M_OP_END: /* * A non-data transfer operation completed. */ @@ -300,33 +302,36 @@ loop: case M_OP_READ | M_OP_END: case M_OP_WRITE | M_OP_END: /* - * A transfer finished. Get the buffer, and release its - * map registers via ubadone(). If the command finished + * A transfer finished. Get the buffer, and release its + * map registers via ubadone(). If the command finished * with an off line or available status, the drive went * off line (the idiot controller does not tell us until * it comes back *on* line, or until we try to use it). */ rwend: #ifdef DIAGNOSTIC - if (mp->mscp_cmdref == 0) { + if (mp->mscp_cmdref >= NCMD) { /* * No buffer means there is a bug somewhere! */ - printf("%s: io done, but no buffer?\n", + printf("%s: io done, but bad xfer number?\n", drive->dv_xname); mscp_hexdump(mp); break; } #endif - bp = (struct buf *) mp->mscp_cmdref; if (mp->mscp_cmdref == -1) { (*me->me_cmddone)(drive, mp); break; } + mxi = &mi->mi_xi[mp->mscp_cmdref]; + if (mxi->mxi_inuse == 0) + panic("mxi not inuse"); + bp = mxi->mxi_bp; /* * Mark any error-due-to-bad-LBN (via `goto rwend'). - * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE + * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. */ if (error) { @@ -340,11 +345,6 @@ rwend: } /* - * Unlink the transfer from the wait queue. - */ - _remque(&bp->b_actf); - - /* * If the transfer has something to do with bad * block forwarding, let the driver handle the * rest. @@ -379,12 +379,14 @@ rwend: * done. If the I/O wait queue is now empty, release * the shared BDP, if any. */ - info = bp->b_info; /* we are about to clobber it */ bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount; + bus_dmamap_unload(mi->mi_dmat, mxi->mxi_dmam); - (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent, info); + (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent); (*me->me_iodone)(drive, bp); out: + mxi->mxi_inuse = 0; + mi->mi_mxiuse |= (1 << mp->mscp_cmdref); break; case M_OP_REPLACE | M_OP_END: @@ -414,18 +416,13 @@ unknown: /* * If the drive needs to be put back in the controller queue, - * do that now. (`bp' below ought to be `dp', but they are all + * do that now. (`bp' below ought to be `dp', but they are all * struct buf *.) Note that b_active was cleared in the driver; * we presume that there is something to be done, hence reassert it. */ #ifdef notyet /* XXX */ if (ui->ui_flags & UNIT_REQUEUE) { - bp = &md->md_utab[ui->ui_unit]; - if (bp->b_active) panic("mscp_dorsp requeue"); - MSCP_APPEND(bp, mi->mi_XXXtab, b_hash.le_next); -/* Was: MSCP_APPEND(bp, mi->mi_XXXtab, b_forw); */ - bp->b_active = 1; - ui->ui_flags &= ~UNIT_REQUEUE; + ... } #endif done: @@ -447,67 +444,6 @@ void mscp_requeue(mi) struct mscp_softc *mi; { - register struct mscp_device *me = mi->mi_me; - register struct buf *bp, *dp; - register int unit; - struct buf *nextbp; - -panic("mscp_requeue"); - /* - * Clear the controller chain. Mark everything un-busy; we - * will soon fix any that are in fact busy. - */ -#ifdef notyet /* XXX */ - mi->mi_XXXtab->b_actf = NULL; - mi->mi_XXXtab->b_active = 0; - for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { - ui = md->md_dinfo[unit]; - if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) - continue; /* not ours */ - dp->b_hash.le_next = NULL; - dp->b_active = 0; - } - /* - * Scan the wait queue, linking buffers onto drive queues. - * Note that these must be put at the front of the drive queue, - * lest we reorder I/O operations. - */ - for (bp = *mi->mi_XXXwtab.b_actb; bp != &mi->mi_XXXwtab; bp = nextbp) { - nextbp = *bp->b_actb; - dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift]; - bp->b_actf = dp->b_actf; - if (dp->b_actf == NULL) - dp->b_actb = (void *)bp; - dp->b_actf = bp; - } - mi->mi_XXXwtab.b_actf = *mi->mi_XXXwtab.b_actb = &mi->mi_XXXwtab; - - /* - * Scan for drives waiting for on line or status responses, - * and for drives with pending transfers. Put these on the - * controller queue, and mark the controller busy. - */ - for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { - ui = md->md_dinfo[unit]; - if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) - continue; - ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE); - if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL) - continue; - ui->ui_flags &= ~UNIT_REQUEUE; - MSCP_APPEND(dp, mi->mi_XXXtab, b_hash.le_next); - - dp->b_active = 1; - mi->mi_XXXtab->b_active = 1; - } - -#endif -#ifdef AVOID_EMULEX_BUG - /* - * ... and clear the index-to-buffer table. - */ - for (unit = 0; unit < AEB_MAX_BP; unit++) - mi->mi_bp[unit] = 0; -#endif + panic("mscp_requeue"); } diff --git a/sys/arch/vax/mscp/mscp.h b/sys/arch/vax/mscp/mscp.h index ffae864af27..1c74b6f7388 100644 --- a/sys/arch/vax/mscp/mscp.h +++ b/sys/arch/vax/mscp/mscp.h @@ -1,5 +1,5 @@ -/* $OpenBSD: mscp.h,v 1.3 1997/09/12 09:25:51 maja Exp $ */ -/* $NetBSD: mscp.h,v 1.3 1997/07/04 11:58:21 ragge Exp $ */ +/* $OpenBSD: mscp.h,v 1.4 2000/04/27 03:14:46 bjc Exp $ */ +/* $NetBSD: mscp.h,v 1.6 1999/05/29 19:11:16 ragge Exp $ */ /* * Copyright (c) 1988 Regents of the University of California. @@ -48,178 +48,178 @@ /* * Control message opcodes */ -#define M_OP_ABORT 0x01 /* Abort command */ -#define M_OP_GETCMDST 0x02 /* Get command status command */ -#define M_OP_GETUNITST 0x03 /* Get unit status command */ -#define M_OP_SETCTLRC 0x04 /* Set controller characteristics command */ -#define M_OP_SEREX 0x07 /* Serious exception end message */ -#define M_OP_AVAILABLE 0x08 /* Available command */ -#define M_OP_ONLINE 0x09 /* Online command */ -#define M_OP_SETUNITC 0x0a /* Set unit characteristics command */ -#define M_OP_DTACCPATH 0x0b /* Determine access paths command */ -#define M_OP_ACCESS 0x10 /* Access command */ -#define M_OP_COMPCD 0x11 /* Compare controller data command */ -#define M_OP_ERASE 0x12 /* Erase command */ -#define M_OP_FLUSH 0x13 /* Flush command */ -#define M_OP_REPLACE 0x14 /* Replace command */ -#define M_OP_COMPHD 0x20 /* Compare host data command */ -#define M_OP_READ 0x21 /* Read command */ -#define M_OP_WRITE 0x22 /* Write command */ -#define M_OP_WRITM 0x24 /* Write mark command */ -#define M_OP_POS 0x25 /* Positioning command */ -#define M_OP_AVAILATTN 0x40 /* Available attention message */ -#define M_OP_DUPUNIT 0x41 /* Duplicate unit number attention message */ -#define M_OP_ACCPATH 0x42 /* Access path attention message */ -#define M_OP_END 0x80 /* End message flag */ +#define M_OP_ABORT 0x01 /* Abort command */ +#define M_OP_GETCMDST 0x02 /* Get command status command */ +#define M_OP_GETUNITST 0x03 /* Get unit status command */ +#define M_OP_SETCTLRC 0x04 /* Set controller characteristics command */ +#define M_OP_SEREX 0x07 /* Serious exception end message */ +#define M_OP_AVAILABLE 0x08 /* Available command */ +#define M_OP_ONLINE 0x09 /* Online command */ +#define M_OP_SETUNITC 0x0a /* Set unit characteristics command */ +#define M_OP_DTACCPATH 0x0b /* Determine access paths command */ +#define M_OP_ACCESS 0x10 /* Access command */ +#define M_OP_COMPCD 0x11 /* Compare controller data command */ +#define M_OP_ERASE 0x12 /* Erase command */ +#define M_OP_FLUSH 0x13 /* Flush command */ +#define M_OP_REPLACE 0x14 /* Replace command */ +#define M_OP_COMPHD 0x20 /* Compare host data command */ +#define M_OP_READ 0x21 /* Read command */ +#define M_OP_WRITE 0x22 /* Write command */ +#define M_OP_WRITM 0x24 /* Write mark command */ +#define M_OP_POS 0x25 /* Positioning command */ +#define M_OP_AVAILATTN 0x40 /* Available attention message */ +#define M_OP_DUPUNIT 0x41 /* Duplicate unit number attention message */ +#define M_OP_ACCPATH 0x42 /* Access path attention message */ +#define M_OP_END 0x80 /* End message flag */ /* * Generic command modifiers */ -#define M_MD_EXPRS 0x8000 /* Express request */ -#define M_MD_COMP 0x4000 /* Compare */ -#define M_MD_CLSEX 0x2000 /* Clear serious exception */ -#define M_MD_ERROR 0x1000 /* Force error */ -#define M_MD_SCCHH 0x0800 /* Suppress caching (high speed) */ -#define M_MD_SCCHL 0x0400 /* Suppress caching (low speed) */ -#define M_MD_SECOR 0x0200 /* Suppress error correction */ -#define M_MD_SEREC 0x0100 /* Suppress error recovery */ -#define M_MD_SSHDW 0x0080 /* Suppress shadowing */ -#define M_MD_WBKNV 0x0040 /* Write back (non-volatile) */ -#define M_MD_WBKVL 0x0020 /* Write back (volatile) */ -#define M_MD_WRSEQ 0x0010 /* Write shadow set one unit at a time */ +#define M_MD_EXPRS 0x8000 /* Express request */ +#define M_MD_COMP 0x4000 /* Compare */ +#define M_MD_CLSEX 0x2000 /* Clear serious exception */ +#define M_MD_ERROR 0x1000 /* Force error */ +#define M_MD_SCCHH 0x0800 /* Suppress caching (high speed) */ +#define M_MD_SCCHL 0x0400 /* Suppress caching (low speed) */ +#define M_MD_SECOR 0x0200 /* Suppress error correction */ +#define M_MD_SEREC 0x0100 /* Suppress error recovery */ +#define M_MD_SSHDW 0x0080 /* Suppress shadowing */ +#define M_MD_WBKNV 0x0040 /* Write back (non-volatile) */ +#define M_MD_WBKVL 0x0020 /* Write back (volatile) */ +#define M_MD_WRSEQ 0x0010 /* Write shadow set one unit at a time */ /* * tape command modifiers */ -#define M_MD_IMMEDIATE 0x0040 /* Immediate completion */ -#define M_MD_UNLOAD 0x0010 /* Unload tape */ -#define M_MD_REVERSE 0x0008 /* Reverse action */ -#define M_MD_OBJCOUNT 0x0004 /* Object count */ -#define M_MD_REWIND 0x0002 /* Rewind */ +#define M_MD_IMMEDIATE 0x0040 /* Immediate completion */ +#define M_MD_UNLOAD 0x0010 /* Unload tape */ +#define M_MD_REVERSE 0x0008 /* Reverse action */ +#define M_MD_OBJCOUNT 0x0004 /* Object count */ +#define M_MD_REWIND 0x0002 /* Rewind */ /* * AVAILABLE command modifiers */ -#define M_AVM_ALLCD 0x0002 /* All class drivers */ -#define M_AVM_SPINDOWN 0x0001 /* Spin down */ +#define M_AVM_ALLCD 0x0002 /* All class drivers */ +#define M_AVM_SPINDOWN 0x0001 /* Spin down */ /* * FLUSH command modifiers */ -#define M_FLM_FLUSHENU 0x0001 /* Flush entire unit */ -#define M_FLM_VOLATILE 0x0002 /* Volatile only */ +#define M_FLM_FLUSHENU 0x0001 /* Flush entire unit */ +#define M_FLM_VOLATILE 0x0002 /* Volatile only */ /* * GET UNIT STATUS command modifiers */ -#define M_GUM_NEXTUNIT 0x0001 /* Next unit */ +#define M_GUM_NEXTUNIT 0x0001 /* Next unit */ /* * ONLINE command modifiers */ -#define M_OLM_RIP 0x0001 /* Allow self destruction */ -#define M_OLM_IGNMF 0x0002 /* Ignore media format error */ +#define M_OLM_RIP 0x0001 /* Allow self destruction */ +#define M_OLM_IGNMF 0x0002 /* Ignore media format error */ /* * ONLINE and SET UNIT CHARACTERISTICS command modifiers */ -#define M_OSM_ALTERHI 0x0020 /* Alter host identifier */ -#define M_OSM_SHADOWSP 0x0010 /* Shadow unit specified */ -#define M_OSM_CLEARWBL 0x0008 /* Clear write-back data lost */ -#define M_OSM_SETWRPROT 0x0004 /* Set write protect */ +#define M_OSM_ALTERHI 0x0020 /* Alter host identifier */ +#define M_OSM_SHADOWSP 0x0010 /* Shadow unit specified */ +#define M_OSM_CLEARWBL 0x0008 /* Clear write-back data lost */ +#define M_OSM_SETWRPROT 0x0004 /* Set write protect */ /* * REPLACE command modifiers */ -#define M_RPM_PRIMARY 0x0001 /* Primary replacement block */ +#define M_RPM_PRIMARY 0x0001 /* Primary replacement block */ /* * End message flags */ -#define M_EF_BBLKR 0x80 /* Bad block reported */ -#define M_EF_BBLKU 0x40 /* Bad block unreported */ -#define M_EF_ERLOG 0x20 /* Error log generated */ -#define M_EF_SEREX 0x10 /* Serious exception */ -#define M_EF_EOT 0x08 /* at end-of-tape */ -#define M_EF_POSLOST 0x04 /* position lost */ +#define M_EF_BBLKR 0x80 /* Bad block reported */ +#define M_EF_BBLKU 0x40 /* Bad block unreported */ +#define M_EF_ERLOG 0x20 /* Error log generated */ +#define M_EF_SEREX 0x10 /* Serious exception */ +#define M_EF_EOT 0x08 /* at end-of-tape */ +#define M_EF_POSLOST 0x04 /* position lost */ /* * Controller flags */ -#define M_CF_ATTN 0x80 /* Enable attention messages */ -#define M_CF_MISC 0x40 /* Enable miscellaneous error log messages */ -#define M_CF_OTHER 0x20 /* Enable other host's error log messages */ -#define M_CF_THIS 0x10 /* Enable this host's error log messages */ -#define M_CF_MLTHS 0x04 /* Multi-host */ -#define M_CF_SHADW 0x02 /* Shadowing */ -#define M_CF_576 0x01 /* 576 byte sectors */ +#define M_CF_ATTN 0x80 /* Enable attention messages */ +#define M_CF_MISC 0x40 /* Enable miscellaneous error log messages */ +#define M_CF_OTHER 0x20 /* Enable other host's error log messages */ +#define M_CF_THIS 0x10 /* Enable this host's error log messages */ +#define M_CF_MLTHS 0x04 /* Multi-host */ +#define M_CF_SHADW 0x02 /* Shadowing */ +#define M_CF_576 0x01 /* 576 byte sectors */ /* * Unit flags */ -#define M_UF_REPLC 0x8000 /* Controller initiated bad block replacement */ -#define M_UF_INACT 0x4000 /* Inactive shadow set unit */ -#define M_UF_WRTPH 0x2000 /* Write protect (hardware) */ -#define M_UF_WRTPS 0x1000 /* Write protect (software or volume) */ -#define M_UF_SCCHH 0x8000 /* Suppress caching (high speed) */ -#define M_UF_SCCHL 0x4000 /* Suppress caching (low speed) */ -#define M_UF_RMVBL 0x0080 /* Removable media */ -#define M_UF_WBKNV 0x0040 /* Write back (non-volatile) */ -#define M_UF_576 0x0004 /* 576 byte sectors */ -#define M_UF_CMPWR 0x0002 /* Compare writes */ -#define M_UF_CMPRD 0x0001 /* Compare reads */ +#define M_UF_REPLC 0x8000 /* Controller initiated bad block replacement */ +#define M_UF_INACT 0x4000 /* Inactive shadow set unit */ +#define M_UF_WRTPH 0x2000 /* Write protect (hardware) */ +#define M_UF_WRTPS 0x1000 /* Write protect (software or volume) */ +#define M_UF_SCCHH 0x8000 /* Suppress caching (high speed) */ +#define M_UF_SCCHL 0x4000 /* Suppress caching (low speed) */ +#define M_UF_RMVBL 0x0080 /* Removable media */ +#define M_UF_WBKNV 0x0040 /* Write back (non-volatile) */ +#define M_UF_576 0x0004 /* 576 byte sectors */ +#define M_UF_CMPWR 0x0002 /* Compare writes */ +#define M_UF_CMPRD 0x0001 /* Compare reads */ /* * Error Log message format codes */ -#define M_FM_CTLRERR 0x00 /* Controller error */ -#define M_FM_BUSADDR 0x01 /* Host memory access error */ -#define M_FM_DISKTRN 0x02 /* Disk transfer error */ -#define M_FM_SDI 0x03 /* SDI error */ -#define M_FM_SMLDSK 0x04 /* Small disk error */ -#define M_FM_TAPETRN 0x05 /* Tape transfer error */ -#define M_FM_STIERR 0x06 /* STI communication or command failure */ -#define M_FM_STIDEL 0x07 /* STI drive error log */ -#define M_FM_STIFEL 0x08 /* STI formatter error log */ +#define M_FM_CTLRERR 0x00 /* Controller error */ +#define M_FM_BUSADDR 0x01 /* Host memory access error */ +#define M_FM_DISKTRN 0x02 /* Disk transfer error */ +#define M_FM_SDI 0x03 /* SDI error */ +#define M_FM_SMLDSK 0x04 /* Small disk error */ +#define M_FM_TAPETRN 0x05 /* Tape transfer error */ +#define M_FM_STIERR 0x06 /* STI communication or command failure */ +#define M_FM_STIDEL 0x07 /* STI drive error log */ +#define M_FM_STIFEL 0x08 /* STI formatter error log */ /* * Error Log message flags */ -#define M_LF_SUCC 0x80 /* Operation successful */ -#define M_LF_CONT 0x40 /* Operation continuing */ -#define M_LF_SQNRS 0x01 /* Sequence number reset */ +#define M_LF_SUCC 0x80 /* Operation successful */ +#define M_LF_CONT 0x40 /* Operation continuing */ +#define M_LF_SQNRS 0x01 /* Sequence number reset */ /* * Status codes */ -#define M_ST_MASK 0x1f /* Status code mask */ -#define M_ST_SUCCESS 0x00 /* Success */ -#define M_ST_INVALCMD 0x01 /* Invalid command */ -#define M_ST_ABORTED 0x02 /* Command aborted */ -#define M_ST_OFFLINE 0x03 /* Unit offline */ -#define M_ST_AVAILABLE 0x04 /* Unit available */ -#define M_ST_MFMTERR 0x05 /* Media format error */ -#define M_ST_WRPROT 0x06 /* Write protected */ -#define M_ST_COMPERR 0x07 /* Compare error */ -#define M_ST_DATAERR 0x08 /* Data error */ -#define M_ST_HOSTBUFERR 0x09 /* Host buffer access error */ -#define M_ST_CTLRERR 0x0a /* Controller error */ -#define M_ST_DRIVEERR 0x0b /* Drive error */ -#define M_ST_FORMATTERR 0x0c /* Formatter error */ -#define M_ST_BOT 0x0d /* Beginning-of-tape */ -#define M_ST_TAPEMARK 0x0e /* Tape mark encountered */ -#define M_ST_RDTRUNC 0x10 /* Record data truncated */ -#define M_ST_DIAG 0x1f /* Message from an internal diagnostic */ +#define M_ST_MASK 0x1f /* Status code mask */ +#define M_ST_SUCCESS 0x00 /* Success */ +#define M_ST_INVALCMD 0x01 /* Invalid command */ +#define M_ST_ABORTED 0x02 /* Command aborted */ +#define M_ST_OFFLINE 0x03 /* Unit offline */ +#define M_ST_AVAILABLE 0x04 /* Unit available */ +#define M_ST_MFMTERR 0x05 /* Media format error */ +#define M_ST_WRPROT 0x06 /* Write protected */ +#define M_ST_COMPERR 0x07 /* Compare error */ +#define M_ST_DATAERR 0x08 /* Data error */ +#define M_ST_HOSTBUFERR 0x09 /* Host buffer access error */ +#define M_ST_CTLRERR 0x0a /* Controller error */ +#define M_ST_DRIVEERR 0x0b /* Drive error */ +#define M_ST_FORMATTERR 0x0c /* Formatter error */ +#define M_ST_BOT 0x0d /* Beginning-of-tape */ +#define M_ST_TAPEMARK 0x0e /* Tape mark encountered */ +#define M_ST_RDTRUNC 0x10 /* Record data truncated */ +#define M_ST_DIAG 0x1f /* Message from an internal diagnostic */ /* * Subcodes of M_ST_OFFLINE */ -#define M_OFFLINE_UNKNOWN (0 << 5) /* unknown or on other ctlr */ -#define M_OFFLINE_UNMOUNTED (1 << 5) /* unmounted or RUN/STOP at STOP */ -#define M_OFFLINE_INOPERATIVE (2 << 5) /* inoperative? */ -#define M_OFFLINE_DUPLICATE (4 << 5) /* duplicate unit number */ -#define M_OFFLINE_INDIAGNOSTIC (8 << 5) /* disabled by FS or diagnostic */ +#define M_OFFLINE_UNKNOWN (0 << 5) /* unknown or on other ctlr */ +#define M_OFFLINE_UNMOUNTED (1 << 5) /* unmounted or RUN/STOP at STOP */ +#define M_OFFLINE_INOPERATIVE (2 << 5) /* inoperative? */ +#define M_OFFLINE_DUPLICATE (4 << 5) /* duplicate unit number */ +#define M_OFFLINE_INDIAGNOSTIC (8 << 5) /* disabled by FS or diagnostic */ /* * An MSCP packet begins with a header giving the length of @@ -237,13 +237,13 @@ */ struct mscpv_seq { long seq_bytecount; /* byte count */ -#define seq_rbn seq_bytecount /* aka RBN (replace) */ -#define seq_outref seq_bytecount /* aka outref (abort/get cmd status) */ +#define seq_rbn seq_bytecount /* aka RBN (replace) */ +#define seq_outref seq_bytecount /* aka outref (abort/get cmd status) */ long seq_buffer; /* buffer descriptor */ long seq_mapbase; /* page map (first PTE) phys address */ - long seq_xxx1; /* ? */ /* unused */ + long seq_xxx1; /* ? */ /* unused */ long seq_lbn; /* logical block number */ - long seq_xxx2; /* ? */ /* unused */ + long seq_xxx2; /* ? */ /* unused */ long *seq_addr; /* pointer to cmd descriptor */ long seq_software[4]; /* reserved to software; unused */ }; @@ -252,10 +252,10 @@ struct mscpv_seq { * Set Controller Characteristics command variant */ struct mscpv_sccc { - u_short sccc_version; /* MSCP version number */ - u_short sccc_ctlrflags; /* controller flags */ - u_short sccc_hosttimo; /* host timeout */ - u_short sccc_usefrac; /* use fraction */ + u_short sccc_version; /* MSCP version number */ + u_short sccc_ctlrflags; /* controller flags */ + u_short sccc_hosttimo; /* host timeout */ + u_short sccc_usefrac; /* use fraction */ long sccc_time; /* time and date */ long sccc_time1; /* it's a quad field */ long sccc_errlgfl; /* ? */ @@ -267,10 +267,10 @@ struct mscpv_sccc { * Set Controller Characteristics end variant */ struct mscpv_scce { - u_short scce_version; /* MSCP version number */ - u_short scce_ctlrflags; /* controller flags */ - u_short scce_ctlrtimo; /* controller timeout */ - u_short scce_ctlrcmdl; /* ??? */ + u_short scce_version; /* MSCP version number */ + u_short scce_ctlrflags; /* controller flags */ + u_short scce_ctlrtimo; /* controller timeout */ + u_short scce_ctlrcmdl; /* ??? */ quad_t scce_ctlrid; /* controller ID */ long scce_xxx[3]; /* ? */ long scce_volser; /* volume serial number */ @@ -291,7 +291,7 @@ struct mscpv_onlc { */ struct mscpv_onle { long onle_xxx1[3]; /* ? */ -/*???*/ short onle_xxx2; /* ? */ +/*???*/ short onle_xxx2; /* ? */ u_char onle_drivetype; /* drive type index (same in guse) */ char onle_xxx3; /* ? */ long onle_mediaid; /* media type id (same in guse) */ @@ -304,8 +304,8 @@ struct mscpv_onle { * Get Unit Status end variant (and Avail Attn?) */ struct mscpv_guse { - u_short guse_multunit; /* multi-unit code */ - u_short guse_unitflags; /* unit flags */ + u_short guse_multunit; /* multi-unit code */ + u_short guse_unitflags; /* unit flags */ long guse_hostid; /* host id */ long guse_unitid0; /*???*/ short guse_unitid1; /*???*/ @@ -314,11 +314,11 @@ struct mscpv_guse { long guse_mediaid; /* media type id (encoded) */ short guse_shadowunit; /* shadow unit */ short guse_shadowstat; /* shadow status */ - u_short guse_nspt; /* sectors per track */ - u_short guse_group; /* track group size */ - u_short guse_ngpc; /* groups per cylinder */ - u_short guse_xxx; /* reserved */ - u_short guse_rctsize; /* RCT size (sectors) */ + u_short guse_nspt; /* sectors per track */ + u_short guse_group; /* track group size */ + u_short guse_ngpc; /* groups per cylinder */ + u_short guse_xxx; /* reserved */ + u_short guse_rctsize; /* RCT size (sectors) */ u_char guse_nrpt; /* RBNs per track */ u_char guse_nrct; /* number of RCTs */ }; @@ -328,23 +328,23 @@ struct mscpv_guse { * type in the top 10 bits, and the drive type in the remaining 22. * The 10 bits, and 15 of the 22, are in groups of 5, with the value * 0 representing space and values 1..26 representing A..Z. The low - * 7 bits represent a number in 0..127. Hence an RA81 on a UDA50 - * is <D><U><R><A>< >81, or 0x25641051. This encoding scheme is known + * 7 bits represent a number in 0..127. Hence an RA81 on a UDA50 + * is <D><U><R><A>< >81, or 0x25641051. This encoding scheme is known * in part in uda.c. * * The casts below are just to make pcc generate better code. */ -#define MSCP_MEDIA_PORT(id) (((long)(id) >> 22) & 0x3ff) /* port */ -#define MSCP_MEDIA_DRIVE(id) ((long)(id) & 0x003fffff) /* drive */ -#define MSCP_MID_ECH(n, id) (((long)(id) >> ((n) * 5 + 7)) & 0x1f) -#define MSCP_MID_CHAR(n, id) \ +#define MSCP_MEDIA_PORT(id) (((long)(id) >> 22) & 0x3ff) /* port */ +#define MSCP_MEDIA_DRIVE(id) ((long)(id) & 0x003fffff) /* drive */ +#define MSCP_MID_ECH(n, id) (((int)(id) >> ((n) * 5 + 7)) & 0x1f) +#define MSCP_MID_CHAR(n, id) \ (MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ') -#define MSCP_MID_NUM(id) ((id) & 0x7f) +#define MSCP_MID_NUM(id) ((id) & 0x7f) /* for, e.g., RA81 */ -#define MSCP_MKDRIVE2(a, b, n) \ +#define MSCP_MKDRIVE2(a, b, n) \ (((a) - '@') << 17 | ((b) - '@') << 12 | (n)) /* for, e.g., RRD50 */ -#define MSCP_MKDRIVE3(a, b, c, n) \ +#define MSCP_MKDRIVE3(a, b, c, n) \ (((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n)) /* @@ -354,22 +354,22 @@ struct mscpv_erd { quad_t erd_ctlrid; /* controller ID */ u_char erd_ctlrsoftware; /* controller software version */ u_char erd_ctlrhardware; /* controller hardware version */ - u_short erd_multiunit; /* multi-unit code (?) */ + u_short erd_multiunit; /* multi-unit code (?) */ union { u_long un_busaddr; /* bus address, if mem access err */ quad_t un_unitid; /* unit id, otherwise */ } erd_un1; -#define erd_busaddr erd_un1.un_busaddr -#define erd_unitid erd_un1.un_unitid +#define erd_busaddr erd_un1.un_busaddr +#define erd_unitid erd_un1.un_unitid u_char erd_unitsoftware; /* unit software version */ u_char erd_unithardware; /* unit hardware version */ union { u_char un_b[2]; /* level, retry (if disk xfer err) */ - u_short un_s; /* cylinder (if small disk error) */ + u_short un_s; /* cylinder (if small disk error) */ } erd_un2; -#define erd_level erd_un2.un_b[0] -#define erd_retry erd_un2.un_b[1] -#define erd_sdecyl erd_un2.un_s +#define erd_level erd_un2.un_b[0] +#define erd_retry erd_un2.un_b[1] +#define erd_sdecyl erd_un2.un_s long erd_volser; /* volume serial number */ u_long erd_hdr; /* `header' (block number) */ u_char erd_sdistat[12]; /* SDI status information (?) */ @@ -378,23 +378,23 @@ struct mscpv_erd { /* * I am making brash assumptions about the first four bytes of all * MSCP packets. These appear to be true for both UDA50s and TMSCP - * devices (TU81, TA81, TK50). DEC claim that these four bytes are + * devices (TU81, TA81, TK50). DEC claim that these four bytes are * not part of MSCP itself, yet at least the length is necessary * for, e.g., error checking. */ struct mscp { - u_short mscp_msglen; /* length in bytes */ + u_short mscp_msglen; /* length in bytes */ u_char mscp_msgtc; /* type (high 4 bits) and credits */ u_char mscp_vcid; /* virtual circuit ID */ long mscp_cmdref; /* command reference number */ - u_short mscp_unit; /* unit number */ - u_short mscp_seqnum; /* sequence number */ + u_short mscp_unit; /* unit number */ + u_short mscp_seqnum; /* sequence number */ u_char mscp_opcode; /* opcode */ -#define mscp_format mscp_opcode /* aka format (datagrams) */ +#define mscp_format mscp_opcode /* aka format (datagrams) */ u_char mscp_flags; /* flags */ - u_short mscp_modifier; /* modifier (commands) */ -#define mscp_status mscp_modifier /* aka status (ends) */ -#define mscp_event mscp_modifier /* aka event (datagrams) */ + u_short mscp_modifier; /* modifier (commands) */ +#define mscp_status mscp_modifier /* aka status (ends) */ +#define mscp_event mscp_modifier /* aka event (datagrams) */ union { struct mscpv_seq un_seq; /* generic sequential msg */ struct mscpv_sccc un_sccc; /* SCC command */ @@ -404,14 +404,14 @@ struct mscp { struct mscpv_guse un_guse; /* get unit status */ struct mscpv_erd un_erd; /* error datagram */ } mscp_un; -/*???*/ long mscp_xxx; /* pad to 64 bytes */ +/*???*/ long mscp_xxx; /* pad to 64 bytes */ }; /* * Define message length according to the DEC specifications by dropping * the four byte header. */ -#define MSCP_MSGLEN (sizeof (struct mscp) - 4) +#define MSCP_MSGLEN (sizeof (struct mscp) - 4) /* * Shorthand @@ -420,53 +420,53 @@ struct mscp { /* * Generic packet */ -#define mscp_seq mscp_un.un_seq +#define mscp_seq mscp_un.un_seq /* * Set Controller Characteristics packet */ -#define mscp_sccc mscp_un.un_sccc +#define mscp_sccc mscp_un.un_sccc /* * Set Controller Characteristics end packet */ -#define mscp_scce mscp_un.un_scce +#define mscp_scce mscp_un.un_scce /* * Online / Set Unit Characteristics command packet */ -#define mscp_onlc mscp_un.un_onlc +#define mscp_onlc mscp_un.un_onlc /* * Online end packet */ -#define mscp_onle mscp_un.un_onle +#define mscp_onle mscp_un.un_onle /* * Get Unit Status end packet */ -#define mscp_guse mscp_un.un_guse +#define mscp_guse mscp_un.un_guse /* * MSCP Error Log packet */ -#define mscp_erd mscp_un.un_erd +#define mscp_erd mscp_un.un_erd /* * MSCP seq_addr field actually belongs to overall packet. */ -#define mscp_addr mscp_seq.seq_addr +#define mscp_addr mscp_seq.seq_addr /* * Macros to break up mscp_msgtc, and types. */ -#define MSCP_MSGTYPE(m) ((m) & 0xf0) -#define MSCP_CREDITS(m) ((m) & 0x0f) +#define MSCP_MSGTYPE(m) ((m) & 0xf0) +#define MSCP_CREDITS(m) ((m) & 0x0f) -#define MSCPT_SEQ 0x00 /* sequential message */ -#define MSCPT_DATAGRAM 0x10 /* error datagram */ -#define MSCPT_CREDITS 0x20 /* credit notification */ -#define MSCPT_MAINTENANCE 0xf0 /* who knows */ +#define MSCPT_SEQ 0x00 /* sequential message */ +#define MSCPT_DATAGRAM 0x10 /* error datagram */ +#define MSCPT_CREDITS 0x20 /* credit notification */ +#define MSCPT_MAINTENANCE 0xf0 /* who knows */ /* @@ -474,7 +474,7 @@ struct mscp { */ /* - * MSCP controllers have `command rings' and `response rings'. A + * MSCP controllers have `command rings' and `response rings'. A * command ring is a pool of MSCP packets that the host uses to give * commands to the controller; a response ring is a pool of MSCP * packets that the controller uses to give back responses. Entries @@ -490,5 +490,5 @@ struct mscp { * The pool is `described' by a set of pointers to the packets, along * with the two flags below. */ -#define MSCP_OWN 0x80000000 /* controller owns this packet */ -#define MSCP_INT 0x40000000 /* controller should interrupt */ +#define MSCP_OWN 0x80000000 /* controller owns this packet */ +#define MSCP_INT 0x40000000 /* controller should interrupt */ diff --git a/sys/arch/vax/mscp/mscp_disk.c b/sys/arch/vax/mscp/mscp_disk.c index 24450c28d67..6c61963e064 100644 --- a/sys/arch/vax/mscp/mscp_disk.c +++ b/sys/arch/vax/mscp/mscp_disk.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mscp_disk.c,v 1.6 1998/10/03 21:18:59 millert Exp $ */ -/* $NetBSD: mscp_disk.c,v 1.13 1997/06/24 01:12:40 thorpej Exp $ */ +/* $OpenBSD: mscp_disk.c,v 1.7 2000/04/27 03:14:46 bjc Exp $ */ +/* $NetBSD: mscp_disk.c,v 1.21 1999/06/06 19:16:18 ragge Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * Copyright (c) 1988 Regents of the University of California. @@ -41,12 +41,12 @@ /* * RA disk device driver + * RX MSCP floppy disk device driver */ /* * TODO * write bad block forwarding code - * split the file into a separate floppy file */ #include <sys/param.h> @@ -57,17 +57,32 @@ #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/fcntl.h> +#include <sys/reboot.h> #include <sys/proc.h> #include <sys/systm.h> -#include <sys/reboot.h> +#include <ufs/ufs/dinode.h> +#include <ufs/ffs/fs.h> + +#include <machine/bus.h> #include <machine/cpu.h> #include <machine/rpb.h> -#include <ufs/ffs/fs.h> /* For some disklabel stuff */ +#include <arch/vax/mscp/mscp.h> +#include <arch/vax/mscp/mscpreg.h> +#include <arch/vax/mscp/mscpvar.h> + +#include "ra.h" + +struct cfdriver ra_cd = { + NULL, "ra", DV_DISK +}; + +struct cfdriver rx_cd = { + NULL, "rx", DV_DISK +}; -#include <vax/mscp/mscp.h> -#include <vax/mscp/mscpvar.h> +#define RAMAJOR 9 /* RA major device number XXX */ /* * Drive status, per drive @@ -80,23 +95,21 @@ struct ra_softc { int ra_hwunit; /* Hardware unit number */ int ra_havelabel; /* true if we have a label */ int ra_wlabel; /* label sector is currently writable */ - int ra_isafloppy; /* unit is a floppy disk */ }; -int ramatch __P((struct device *, void *, void *)); +#define rx_softc ra_softc + +void rxattach __P((struct device *, struct device *, void *)); +int rx_putonline __P((struct rx_softc *)); +void rrmakelabel __P((struct disklabel *, long)); + +#if NRA + +int ramatch __P((struct device *, struct cfdata *, void *)); void raattach __P((struct device *, struct device *, void *)); -void radgram __P((struct device *, struct mscp *, struct mscp_softc *)); -void raiodone __P((struct device *, struct buf *)); -int raonline __P((struct device *, struct mscp *)); -int ragotstatus __P((struct device *, struct mscp *)); -void rareplace __P((struct device *, struct mscp *)); -int raioerror __P((struct device *, struct mscp *, struct buf *)); -void rafillin __P((struct buf *, struct mscp *)); -void rabb __P((struct device *, struct mscp *, struct buf *)); int raopen __P((dev_t, int, int, struct proc *)); int raclose __P((dev_t, int, int, struct proc *)); void rastrategy __P((struct buf *)); -void rastrat1 __P((struct buf *)); int raread __P((dev_t, struct uio *)); int rawrite __P((dev_t, struct uio *)); int raioctl __P((dev_t, int, caddr_t, int, struct proc *)); @@ -104,59 +117,32 @@ int radump __P((dev_t, daddr_t, caddr_t, size_t)); int rasize __P((dev_t)); int ra_putonline __P((struct ra_softc *)); - -struct mscp_device ra_device = { - radgram, - raiodone, - raonline, - ragotstatus, - rareplace, - raioerror, - rabb, - rafillin, -}; - -/* - * Device to unit number and partition and back - */ -#define UNITSHIFT 3 -#define UNITMASK 7 -#define raunit(dev) (minor(dev) >> UNITSHIFT) -#define rapart(dev) (minor(dev) & UNITMASK) -#define raminor(u, p) (((u) << UNITSHIFT) | (p)) - -struct cfdriver ra_cd = { - NULL, "ra", DV_DISK -}; - struct cfattach ra_ca = { - sizeof(struct ra_softc), ramatch, raattach + sizeof(struct ra_softc), (cfmatch_t)ramatch, raattach }; /* - * Software state, per drive - */ -#define RA_OFFLINE 0 -#define RA_WANTOPEN 1 -#define RA_ONLINE 3 - -/* * More driver definitions, for generic MSCP code. */ -extern int cold; int -ramatch(parent, match, aux) +ramatch(parent, cf, aux) struct device *parent; - void *match, *aux; + struct cfdata *cf; + void *aux; { - struct cfdata *cf = match; struct drive_attach_args *da = aux; struct mscp *mp = da->da_mp; if ((da->da_typ & MSCPBUS_DISK) == 0) return 0; if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit) + return 0; + /* + * Check if this disk is a floppy; then don't configure it. + * Seems to be a safe way to test it per Chris Torek. + */ + if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@') return 0; return 1; } @@ -172,28 +158,9 @@ raattach(parent, self, aux) void *aux; { struct ra_softc *ra = (void *)self; - struct drive_attach_args *da = aux; - struct mscp *mp = da->da_mp; struct mscp_softc *mi = (void *)parent; - struct disklabel *dl; - - ra->ra_mediaid = mp->mscp_guse.guse_mediaid; - ra->ra_state = RA_OFFLINE; - ra->ra_havelabel = 0; - ra->ra_hwunit = mp->mscp_unit; - mi->mi_dp[mp->mscp_unit] = self; - - ra->ra_disk.dk_name = ra->ra_dev.dv_xname; - disk_attach((struct disk *)&ra->ra_disk); - /* Fill in what we know. The actual size is gotten later */ - dl = ra->ra_disk.dk_label; - - dl->d_secsize = DEV_BSIZE; - dl->d_nsectors = mp->mscp_guse.guse_nspt; - dl->d_ntracks = mp->mscp_guse.guse_ngpc; - dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; - disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid); + rxattach(parent, self, aux); /* * Find out if we booted from this disk. */ @@ -211,45 +178,29 @@ int ra_putonline(ra) struct ra_softc *ra; { - struct mscp *mp; - struct mscp_softc *mi = (struct mscp_softc *)ra->ra_dev.dv_parent; struct disklabel *dl; - volatile int i; char *msg; - dl = ra->ra_disk.dk_label; - - ra->ra_state = RA_WANTOPEN; - mp = mscp_getcp(mi, MSCP_WAIT); - mp->mscp_opcode = M_OP_ONLINE; - mp->mscp_unit = ra->ra_hwunit; - mp->mscp_cmdref = (long)&ra->ra_state; - *mp->mscp_addr |= MSCP_OWN | MSCP_INT; - - /* Poll away */ - i = *mi->mi_ip; - if (tsleep(&ra->ra_state, PRIBIO, "raonline", 100*100)) { - ra->ra_state = RA_OFFLINE; + if (rx_putonline(ra) != MSCP_DONE) return MSCP_FAILED; - } - if (ra->ra_state == RA_OFFLINE) - return MSCP_FAILED; - if (ra->ra_isafloppy) - return MSCP_DONE; + dl = ra->ra_disk.dk_label; + ra->ra_state = DK_RDLABEL; printf("%s", ra->ra_dev.dv_xname); - if ((msg = readdisklabel(raminor(ra->ra_dev.dv_unit, 0), - rastrategy, dl, NULL, 0)) != NULL) + if ((msg = readdisklabel(MAKEDISKDEV(RAMAJOR, ra->ra_dev.dv_unit, + RAW_PART), rastrategy, dl, NULL, 0)) != NULL) printf(": %s", msg); - else + else { ra->ra_havelabel = 1; - ra->ra_state = RA_ONLINE; + ra->ra_state = DK_OPEN; + } printf(": size %d sectors\n", dl->d_secperunit); return MSCP_DONE; } + /* * Open a drive. */ @@ -262,11 +213,10 @@ raopen(dev, flag, fmt, p) { register struct ra_softc *ra; int part, unit, mask; - /* * Make sure this is a reasonable open request. */ - unit = raunit(dev); + unit = DISKUNIT(dev); if (unit >= ra_cd.cd_ndevs) return ENXIO; ra = ra_cd.cd_devs[unit]; @@ -277,24 +227,23 @@ raopen(dev, flag, fmt, p) * If this is the first open; we must first try to put * the disk online (and read the label). */ - if (ra->ra_state == RA_OFFLINE) + if (ra->ra_state == DK_CLOSED) if (ra_putonline(ra) == MSCP_FAILED) - return EIO; + return ENXIO; /* If the disk has no label; allow writing everywhere */ if (ra->ra_havelabel == 0) ra->ra_wlabel = 1; - part = rapart(dev); - if (ra->ra_isafloppy == 0) - if (part >= ra->ra_disk.dk_label->d_npartitions) - return ENXIO; + part = DISKPART(dev); + if (part >= ra->ra_disk.dk_label->d_npartitions) + return ENXIO; /* * Wait for the state to settle */ #if notyet - while (ra->ra_state != RA_ONLINE) + while (ra->ra_state != DK_OPEN) if ((error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH, devopn, 0))) { splx(s); @@ -323,9 +272,9 @@ raclose(dev, flags, fmt, p) int flags, fmt; struct proc *p; { - register int unit = raunit(dev); + register int unit = DISKUNIT(dev); register struct ra_softc *ra = ra_cd.cd_devs[unit]; - int mask = (1 << rapart(dev)); + int mask = (1 << DISKPART(dev)); switch (fmt) { case S_IFCHR: @@ -344,7 +293,7 @@ raclose(dev, flags, fmt, p) */ #if notyet if (ra->ra_openpart == 0) { - s = splbio(); + s = splimp(); while (udautab[unit].b_actf) sleep((caddr_t)&udautab[unit], PZERO - 1); splx(s); @@ -357,10 +306,6 @@ raclose(dev, flags, fmt, p) /* * Queue a transfer request, and if possible, hand it to the controller. - * - * This routine is broken into two so that the internal version - * udastrat1() can be called by the (nonexistent, as yet) bad block - * revectoring routine. */ void rastrategy(bp) @@ -368,11 +313,10 @@ rastrategy(bp) { register int unit; register struct ra_softc *ra; - int p; /* * Make sure this is a reasonable drive to use. */ - unit = raunit(bp->b_dev); + unit = DISKUNIT(bp->b_dev); if (unit > ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) { bp->b_error = ENXIO; bp->b_flags |= B_ERROR; @@ -381,25 +325,26 @@ rastrategy(bp) /* * If drive is open `raw' or reading label, let it at it. */ - if (ra->ra_state < RA_ONLINE) { + if (ra->ra_state == DK_RDLABEL) { mscp_strategy(bp, ra->ra_dev.dv_parent); return; } - p = rapart(bp->b_dev); + + /* If disk is not online, try to put it online */ + if (ra->ra_state == DK_CLOSED) + if (ra_putonline(ra) == MSCP_FAILED) { + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + goto done; + } /* * Determine the size of the transfer, and make sure it is * within the boundaries of the partition. */ - if (ra->ra_isafloppy) { - if (bp->b_blkno >= ra->ra_disk.dk_label->d_secperunit) { - bp->b_resid = bp->b_bcount; - goto done; - } - } else - if (bounds_check_with_label(bp, ra->ra_disk.dk_label, - ra->ra_disk.dk_cpulabel, ra->ra_wlabel) <= 0) - goto done; + if (bounds_check_with_label(bp, ra->ra_disk.dk_label, + ra->ra_disk.dk_cpulabel, ra->ra_wlabel) <= 0) + goto done; /* Make some statistics... /bqt */ ra->ra_disk.dk_xfer++; @@ -413,242 +358,401 @@ done: int raread(dev, uio) - dev_t dev; - struct uio *uio; + dev_t dev; + struct uio *uio; { - return (physio(rastrategy, NULL, dev, B_READ, minphys, uio)); + return (physio(rastrategy, NULL, dev, B_READ, minphys, uio)); } int rawrite(dev, uio) - dev_t dev; - struct uio *uio; + dev_t dev; + struct uio *uio; { - return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio)); + return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio)); } -void -raiodone(usc, bp) - struct device *usc; - struct buf *bp; +/* + * I/O controls. + */ +int +raioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; { + register int unit = DISKUNIT(dev); + register struct disklabel *lp, *tp; + register struct ra_softc *ra = ra_cd.cd_devs[unit]; + int error = 0; - biodone(bp); + lp = ra->ra_disk.dk_label; + + switch (cmd) { + + case DIOCGDINFO: + bcopy(lp, data, sizeof (struct disklabel)); + break; + + case DIOCGPART: + ((struct partinfo *)data)->disklab = lp; + ((struct partinfo *)data)->part = + &lp->d_partitions[DISKPART(dev)]; + break; + + case DIOCWDINFO: + case DIOCSDINFO: + if ((flag & FWRITE) == 0) + error = EBADF; + else { + error = setdisklabel(lp, (struct disklabel *)data,0,0); + if ((error == 0) && (cmd == DIOCWDINFO)) { + ra->ra_wlabel = 1; + error = writedisklabel(dev, rastrategy, lp,0); + ra->ra_wlabel = 0; + } + } + break; + + case DIOCWLABEL: + if ((flag & FWRITE) == 0) + error = EBADF; + else + ra->ra_wlabel = 1; + break; + +#ifdef __NetBSD__ + case DIOCGDEFLABEL: + tp = (struct disklabel *)data; + bzero(data, sizeof(struct disklabel)); + tp->d_secsize = lp->d_secsize; + tp->d_nsectors = lp->d_nsectors; + tp->d_ntracks = lp->d_ntracks; + tp->d_ncylinders = lp->d_ncylinders; + tp->d_secpercyl = lp->d_secpercyl; + tp->d_secperunit = lp->d_secperunit; + tp->d_type = DTYPE_MSCP; + tp->d_rpm = 3600; + rrmakelabel(tp, ra->ra_mediaid); + break; +#endif + + default: + error = ENOTTY; + break; + } + return (error); +} + + +int +radump(dev, blkno, va, size) + dev_t dev; + daddr_t blkno; + caddr_t va; + size_t size; +{ + return ENXIO; } /* - * Fill in disk addresses in a mscp packet waiting for transfer. + * Return the size of a partition, if known, or -1 if not. */ -void -rafillin(bp, mp) - struct buf *bp; - struct mscp *mp; +int +rasize(dev) + dev_t dev; { - int unit = raunit(bp->b_dev); - int part = rapart(bp->b_dev); - struct ra_softc *ra = ra_cd.cd_devs[unit]; - struct disklabel *lp = ra->ra_disk.dk_label; - - - /* XXX more checks needed */ - mp->mscp_unit = ra->ra_hwunit; - mp->mscp_seq.seq_lbn = bp->b_blkno + lp->d_partitions[part].p_offset; - mp->mscp_seq.seq_bytecount = bp->b_bcount; + register int unit = DISKUNIT(dev); + struct ra_softc *ra; + + if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0) + return -1; + + ra = ra_cd.cd_devs[unit]; + + if (ra->ra_state == DK_CLOSED) + if (ra_putonline(ra) == MSCP_FAILED) + return -1; + + return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size * + (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE); } +int +ra_getdev(adaptor, controller, unit, uname) + int adaptor, controller, unit; + char **uname; +{ + struct mscp_softc *mi; + struct ra_softc *ra; + int i; + + for (i = 0; i < ra_cd.cd_ndevs; i++) { + if ((ra = ra_cd.cd_devs[i]) == 0) + continue; + + mi = (void *)ra->ra_dev.dv_parent; + if (mi->mi_ctlrnr == controller && mi->mi_adapnr == adaptor && + ra->ra_hwunit == unit) { + *uname = ra->ra_dev.dv_xname; + return i; + } + } + return -1; +} + +#endif /* NRA */ + +#if NRX + +int rxmatch __P((struct device *, struct cfdata *, void *)); +int rxopen __P((dev_t, int, int, struct proc *)); +int rxclose __P((dev_t, int, int, struct proc *)); +void rxstrategy __P((struct buf *)); +int rxread __P((dev_t, struct uio *)); +int rxwrite __P((dev_t, struct uio *)); +int rxioctl __P((dev_t, int, caddr_t, int, struct proc *)); +int rxdump __P((dev_t, daddr_t, caddr_t, size_t)); +int rxsize __P((dev_t)); + +struct cfattach rx_ca = { + sizeof(struct rx_softc), (cfmatch_t)rxmatch, rxattach +}; + /* - * Handle an error datagram. - * This can come from an unconfigured drive as well. + * More driver definitions, for generic MSCP code. */ -void -radgram(usc, mp, mi) - struct device *usc; - struct mscp *mp; - struct mscp_softc *mi; + +int +rxmatch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; { - if (mscp_decodeerror(usc == NULL?"unconf ra" : usc->dv_xname, mp, mi)) - return; + struct drive_attach_args *da = aux; + struct mscp *mp = da->da_mp; + + if ((da->da_typ & MSCPBUS_DISK) == 0) + return 0; + if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit) + return 0; /* - * SDI status information bytes 10 and 11 are the microprocessor - * error code and front panel code respectively. These vary per - * drive type and are printed purely for field service information. + * Check if this disk is a floppy; then configure it. + * Seems to be a safe way to test it per Chris Torek. */ - if (mp->mscp_format == M_FM_SDI) - printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n", - mp->mscp_erd.erd_sdistat[10], - mp->mscp_erd.erd_sdistat[11]); + if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@') + return 1; + return 0; } +#endif /* NRX */ + /* - * A drive came on line. Check its type and size. Return DONE if - * we think the drive is truly on line. In any case, awaken anyone - * sleeping on the drive on-line-ness. + * The attach routine only checks and prints drive type. + * Bringing the disk online is done when the disk is accessed + * the first time. */ -int -raonline(usc, mp) - struct device *usc; - struct mscp *mp; +void +rxattach(parent, self, aux) + struct device *parent, *self; + void *aux; { - register struct ra_softc *ra = (void *)usc; - struct disklabel *dl; - int p = 0, d, n; - - wakeup((caddr_t)&ra->ra_state); - if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { - printf("%s: attempt to bring on line failed: ", - ra->ra_dev.dv_xname); - mscp_printevent(mp); - ra->ra_state = RA_OFFLINE; - return (MSCP_FAILED); - } + struct rx_softc *rx = (void *)self; + struct drive_attach_args *da = aux; + struct mscp *mp = da->da_mp; + struct mscp_softc *mi = (void *)parent; + struct disklabel *dl; - /* - * Fill in the rest of disk size. - */ - ra->ra_state = RA_WANTOPEN; - dl = ra->ra_disk.dk_label; - dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize; + rx->ra_mediaid = mp->mscp_guse.guse_mediaid; + rx->ra_state = DK_CLOSED; + rx->ra_hwunit = mp->mscp_unit; + mi->mi_dp[mp->mscp_unit] = self; - if (dl->d_secpercyl != 0) - dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl; - else - ra->ra_isafloppy = 1; - dl->d_type = DTYPE_MSCP; - dl->d_rpm = 3600; - dl->d_bbsize = BBSIZE; - dl->d_sbsize = SBSIZE; + rx->ra_disk.dk_name = rx->ra_dev.dv_xname; + disk_attach((struct disk *)&rx->ra_disk); - /* Create the disk name for disklabel. Phew... */ - d = ra->ra_mediaid; - dl->d_typename[p++] = MSCP_MID_CHAR(2, d); - dl->d_typename[p++] = MSCP_MID_CHAR(1, d); - if (MSCP_MID_ECH(0, d)) - dl->d_typename[p++] = MSCP_MID_CHAR(0, d); - n = MSCP_MID_NUM(d); - if (n > 99) { - dl->d_typename[p++] = '1'; - n -= 100; - } - if (n > 9) { - dl->d_typename[p++] = (n / 10) + '0'; - n %= 10; - } - dl->d_typename[p++] = n + '0'; - dl->d_typename[p] = 0; - dl->d_npartitions = MAXPARTITIONS; - dl->d_partitions[0].p_size = dl->d_partitions[2].p_size = - dl->d_secperunit; - dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0; - dl->d_interleave = dl->d_headswitch = 1; - dl->d_magic = dl->d_magic2 = DISKMAGIC; - dl->d_checksum = dkcksum(dl); + /* Fill in what we know. The actual size is gotten later */ + dl = rx->ra_disk.dk_label; - return (MSCP_DONE); + dl->d_secsize = DEV_BSIZE; + dl->d_nsectors = mp->mscp_guse.guse_nspt; + dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group; + dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; + disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid); +#ifdef DEBUG + printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n", + self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group, + mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize, + mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct); +#endif } -/* - * We got some (configured) unit's status. Return DONE if it succeeded. +/* + * (Try to) put the drive online. This is done the first time the + * drive is opened, or if it har fallen offline. */ int -ragotstatus(usc, mp) - register struct device *usc; - register struct mscp *mp; +rx_putonline(rx) + struct rx_softc *rx; { - if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { - printf("%s: attempt to get status failed: ", usc->dv_xname); - mscp_printevent(mp); - return (MSCP_FAILED); - } - /* record for (future) bad block forwarding and whatever else */ -#ifdef notyet - uda_rasave(ui->ui_unit, mp, 1); -#endif - return (MSCP_DONE); + struct mscp *mp; + struct mscp_softc *mi = (struct mscp_softc *)rx->ra_dev.dv_parent; + volatile int i; + + rx->ra_state = DK_CLOSED; + mp = mscp_getcp(mi, MSCP_WAIT); + mp->mscp_opcode = M_OP_ONLINE; + mp->mscp_unit = rx->ra_hwunit; + mp->mscp_cmdref = 1; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + + /* Poll away */ + i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); + if (tsleep(&rx->ra_dev.dv_unit, PRIBIO, "rxonline", 100*100)) + rx->ra_state = DK_CLOSED; + + if (rx->ra_state == DK_CLOSED) + return MSCP_FAILED; + + return MSCP_DONE; } +#if NRX + /* - * A transfer failed. We get a chance to fix or restart it. - * Need to write the bad block forwaring code first.... + * Open a drive. */ /*ARGSUSED*/ int -raioerror(usc, mp, bp) - register struct device *usc; - register struct mscp *mp; - struct buf *bp; +rxopen(dev, flag, fmt, p) + dev_t dev; + int flag, fmt; + struct proc *p; { -printf("raioerror\n"); -#if 0 - if (mp->mscp_flags & M_EF_BBLKR) { - /* - * A bad block report. Eventually we will - * restart this transfer, but for now, just - * log it and give up. - */ - log(LOG_ERR, "ra%d: bad block report: %d%s\n", - ui->ui_unit, (int)mp->mscp_seq.seq_lbn, - mp->mscp_flags & M_EF_BBLKU ? " + others" : ""); - } else { - /* - * What the heck IS a `serious exception' anyway? - * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION - * FOR THEIR OWN CONTROLLERS. - */ - if (mp->mscp_flags & M_EF_SEREX) - log(LOG_ERR, "ra%d: serious exception reported\n", - ui->ui_unit); - } -#endif - return (MSCP_FAILED); + register struct rx_softc *rx; + int unit; + + /* + * Make sure this is a reasonable open request. + */ + unit = DISKUNIT(dev); + if (unit >= rx_cd.cd_ndevs) + return ENXIO; + rx = rx_cd.cd_devs[unit]; + if (rx == 0) + return ENXIO; + + /* + * If this is the first open; we must first try to put + * the disk online (and read the label). + */ + if (rx->ra_state == DK_CLOSED) + if (rx_putonline(rx) == MSCP_FAILED) + return ENXIO; + + return 0; +} + +/* ARGSUSED */ +int +rxclose(dev, flags, fmt, p) + dev_t dev; + int flags, fmt; + struct proc *p; +{ + return (0); } /* - * A replace operation finished. + * Queue a transfer request, and if possible, hand it to the controller. + * + * This routine is broken into two so that the internal version + * udastrat1() can be called by the (nonexistent, as yet) bad block + * revectoring routine. */ -/*ARGSUSED*/ void -rareplace(usc, mp) - struct device *usc; - struct mscp *mp; +rxstrategy(bp) + register struct buf *bp; { + register int unit; + register struct rx_softc *rx; - panic("udareplace"); + /* + * Make sure this is a reasonable drive to use. + */ + unit = DISKUNIT(bp->b_dev); + if (unit > rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) { + bp->b_error = ENXIO; + bp->b_flags |= B_ERROR; + goto done; + } + + /* If disk is not online, try to put it online */ + if (rx->ra_state == DK_CLOSED) + if (rx_putonline(rx) == MSCP_FAILED) { + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + goto done; + } + + /* + * Determine the size of the transfer, and make sure it is + * within the boundaries of the partition. + */ + if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) { + bp->b_resid = bp->b_bcount; + goto done; + } + + /* Make some statistics... /bqt */ + rx->ra_disk.dk_xfer++; + rx->ra_disk.dk_bytes += bp->b_bcount; + mscp_strategy(bp, rx->ra_dev.dv_parent); + return; + +done: + biodone(bp); } -/* - * A bad block related operation finished. - */ -/*ARGSUSED*/ -void -rabb(usc, mp, bp) - struct device *usc; - struct mscp *mp; - struct buf *bp; +int +rxread(dev, uio) + dev_t dev; + struct uio *uio; { - panic("udabb"); + return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio)); } +int +rxwrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio)); +} /* * I/O controls. */ int -raioctl(dev, cmd, data, flag, p) +rxioctl(dev, cmd, data, flag, p) dev_t dev; int cmd; caddr_t data; int flag; struct proc *p; { - register int unit = raunit(dev); + register int unit = DISKUNIT(dev); register struct disklabel *lp; - register struct ra_softc *ra = ra_cd.cd_devs[unit]; + register struct rx_softc *rx = rx_cd.cd_devs[unit]; int error = 0; - lp = ra->ra_disk.dk_label; + lp = rx->ra_disk.dk_label; switch (cmd) { @@ -659,28 +763,13 @@ raioctl(dev, cmd, data, flag, p) case DIOCGPART: ((struct partinfo *)data)->disklab = lp; ((struct partinfo *)data)->part = - &lp->d_partitions[rapart(dev)]; + &lp->d_partitions[DISKPART(dev)]; break; + case DIOCWDINFO: case DIOCSDINFO: - if ((flag & FWRITE) == 0) - error = EBADF; - else { - error = setdisklabel(lp, (struct disklabel *)data,0,0); - if ((error == 0) && (cmd == DIOCWDINFO)) { - ra->ra_wlabel = 1; - error = writedisklabel(dev, rastrategy, lp,0); - ra->ra_wlabel = 0; - } - } - break; - case DIOCWLABEL: - if ((flag & FWRITE) == 0) - error = EBADF; - else - ra->ra_wlabel = 1; break; default: @@ -690,296 +779,262 @@ raioctl(dev, cmd, data, flag, p) return (error); } -#if 0 -/* - * Do a panic dump. We set up the controller for one command packet - * and one response packet, for which we use `struct uda1'. - */ -struct uda1 { - struct uda1ca uda1_ca; /* communications area */ - struct mscp uda1_rsp; /* response packet */ - struct mscp uda1_cmd; /* command packet */ -} uda1; -#endif +int +rxdump(dev, blkno, va, size) + dev_t dev; + daddr_t blkno; + caddr_t va; + size_t size; +{ -#define DBSIZE 32 /* dump 16K at a time */ + /* Not likely. */ + return ENXIO; +} int -radump(dev, blkno, va, size) - dev_t dev; - daddr_t blkno; - caddr_t va; - size_t size; +rxsize(dev) + dev_t dev; { -#if 0 - struct udadevice *udaddr; - struct uda1 *ud_ubaddr; - char *start; - int num, blk, unit, maxsz, blkoff, reg; - struct partition *pp; - struct uba_regs *uba; - struct uba_device *ui; - struct uda1 *ud; - struct pte *io; - int i; - /* - * Make sure the device is a reasonable place on which to dump. - */ - unit = udaunit(dev); - if (unit >= NRA) - return (ENXIO); -#define phys(cast, addr) ((cast) ((int)addr & 0x7fffffff)) - ui = phys(struct uba_device *, udadinfo[unit]); - if (ui == NULL || ui->ui_alive == 0) - return (ENXIO); + return -1; +} - /* - * Find and initialise the UBA; get the physical address of the - * device registers, and of communications area and command and - * response packet. - */ - uba = phys(struct uba_softc *, ui->ui_hd)->uh_physuba; - ubainit(ui->ui_hd); - udaddr = (struct udadevice *)ui->ui_physaddr; - ud = phys(struct uda1 *, &uda1); - /* - * Map the ca+packets into Unibus I/O space so the UDA50 can get - * at them. Use the registers at the end of the Unibus map (since - * we will use the registers at the beginning to map the memory - * we are dumping). - */ - num = btoc(sizeof(struct uda1)) + 1; - reg = NUBMREG - num; - io = (void *)&uba->uba_map[reg]; - for (i = 0; i < num; i++) - *(int *)io++ = UBAMR_MRV | (btop(ud) + i); - ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9)); +#endif /* NRX */ - /* - * Initialise the controller, with one command and one response - * packet. - */ - udaddr->udaip = 0; - if (udadumpwait(udaddr, UDA_STEP1)) - return (EFAULT); - udaddr->udasa = UDA_ERR; - if (udadumpwait(udaddr, UDA_STEP2)) - return (EFAULT); - udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc; - if (udadumpwait(udaddr, UDA_STEP3)) - return (EFAULT); - udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16; - if (udadumpwait(udaddr, UDA_STEP4)) - return (EFAULT); - ((struct uda_softc *)uda_cd.cd_devs[ui->ui_ctlr])->sc_micro = udaddr->udasa & 0xff; - udaddr->udasa = UDA_GO; +void rrdgram __P((struct device *, struct mscp *, struct mscp_softc *)); +void rriodone __P((struct device *, struct buf *)); +int rronline __P((struct device *, struct mscp *)); +int rrgotstatus __P((struct device *, struct mscp *)); +void rrreplace __P((struct device *, struct mscp *)); +int rrioerror __P((struct device *, struct mscp *, struct buf *)); +void rrfillin __P((struct buf *, struct mscp *)); +void rrbb __P((struct device *, struct mscp *, struct buf *)); - /* - * Set up the command and response descriptor, then set the - * controller characteristics and bring the drive on line. - * Note that all uninitialised locations in uda1_cmd are zero. - */ - ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref; - ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref; - /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */ - /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */ - if (udadumpcmd(M_OP_SETCTLRC, ud, ui)) - return (EFAULT); - ud->uda1_cmd.mscp_unit = ui->ui_slave; - if (udadumpcmd(M_OP_ONLINE, ud, ui)) - return (EFAULT); - - pp = phys(struct partition *, - &udalabel[unit].d_partitions[udapart(dev)]); - maxsz = pp->p_size; - blkoff = pp->p_offset; - /* - * Dump all of physical memory, or as much as will fit in the - * space provided. - */ - start = 0; - printf("Dumpar {r inte implementerade {n :) \n"); - asm("halt"); -/* num = maxfree; */ - if (dumplo + num >= maxsz) - num = maxsz - dumplo; - blkoff += dumplo; +struct mscp_device ra_device = { + rrdgram, + rriodone, + rronline, + rrgotstatus, + rrreplace, + rrioerror, + rrbb, + rrfillin, +}; +/* + * Handle an error datagram. + * This can come from an unconfigured drive as well. + */ +void +rrdgram(usc, mp, mi) + struct device *usc; + struct mscp *mp; + struct mscp_softc *mi; +{ + if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi)) + return; /* - * Write out memory, DBSIZE pages at a time. - * N.B.: this code depends on the fact that the sector - * size == the page size. + * SDI status information bytes 10 and 11 are the microprocessor + * error code and front panel code respectively. These vary per + * drive type and are printed purely for field service information. */ - while (num > 0) { - blk = num > DBSIZE ? DBSIZE : num; - io = (void *)uba->uba_map; - /* - * Map in the pages to write, leaving an invalid entry - * at the end to guard against wild Unibus transfers. - * Then do the write. - */ - for (i = 0; i < blk; i++) - *(int *)io++ = UBAMR_MRV | (btop(start) + i); - *(int *)io = 0; - ud->uda1_cmd.mscp_unit = ui->ui_slave; - ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff; - ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT; - if (udadumpcmd(M_OP_WRITE, ud, ui)) - return (EIO); - start += blk << PGSHIFT; - num -= blk; - } - return (0); /* made it! */ + if (mp->mscp_format == M_FM_SDI) + printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n", + mp->mscp_erd.erd_sdistat[10], + mp->mscp_erd.erd_sdistat[11]); +} + +void +rriodone(usc, bp) + struct device *usc; + struct buf *bp; +{ + + biodone(bp); } /* - * Wait for some of the bits in `bits' to come on. If the error bit - * comes on, or ten seconds pass without response, return true (error). + * A drive came on line. Check its type and size. Return DONE if + * we think the drive is truly on line. In any case, awaken anyone + * sleeping on the drive on-line-ness. */ int -udadumpwait(udaddr, bits) - struct udadevice *udaddr; - register int bits; +rronline(usc, mp) + struct device *usc; + struct mscp *mp; { - register int timo = todr() + 1000; - - while ((udaddr->udasa & bits) == 0) { - if (udaddr->udasa & UDA_ERR) { - char bits[64]; - printf("udasa=%s\ndump ", - bitmask_snprintf(udaddr->udasa, udasr_bits, - bits, sizeof(bits))); - return (1); - } - if (todr() >= timo) { - printf("timeout\ndump "); - return (1); - } + struct rx_softc *rx = (struct rx_softc *)usc; + struct disklabel *dl; + + wakeup((caddr_t)&usc->dv_unit); + if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { + printf("%s: attempt to bring on line failed: ", usc->dv_xname); + mscp_printevent(mp); + return (MSCP_FAILED); } - return (0); + + rx->ra_state = DK_OPEN; + + dl = rx->ra_disk.dk_label; + dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize; + + if (dl->d_secpercyl) { + dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl; + dl->d_type = DTYPE_MSCP; + dl->d_rpm = 3600; + } else { + dl->d_type = DTYPE_FLOPPY; + dl->d_rpm = 300; + } + rrmakelabel(dl, rx->ra_mediaid); + + return (MSCP_DONE); } -/* - * Feed a command to the UDA50, wait for its response, and return - * true iff something went wrong. - */ -int -udadumpcmd(op, ud, ui) - int op; - struct uda1 *ud; - struct uba_device *ui; +void +rrmakelabel(dl, type) + struct disklabel *dl; + long type; { - volatile struct udadevice *udaddr; - volatile int n; -#define mp (&ud->uda1_rsp) - - udaddr = (struct udadevice *)ui->ui_physaddr; - ud->uda1_cmd.mscp_opcode = op; - ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN; - ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN; - ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; - ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT; - if (udaddr->udasa & UDA_ERR) { - char bits[64]; - printf("udasa=%s\ndump ", bitmask_snprintf(udaddr->udasa, - udasr_bits, bits, sizeof(bits))); - return (1); + int n, p = 0; + + dl->d_bbsize = BBSIZE; + dl->d_sbsize = SBSIZE; + + /* Create the disk name for disklabel. Phew... */ + dl->d_typename[p++] = MSCP_MID_CHAR(2, type); + dl->d_typename[p++] = MSCP_MID_CHAR(1, type); + if (MSCP_MID_ECH(0, type)) + dl->d_typename[p++] = MSCP_MID_CHAR(0, type); + n = MSCP_MID_NUM(type); + if (n > 99) { + dl->d_typename[p++] = '1'; + n -= 100; } - n = udaddr->udaip; - n = todr() + 1000; - for (;;) { - if (todr() > n) { - printf("timeout\ndump "); - return (1); - } - if (ud->uda1_ca.ca_cmdint) - ud->uda1_ca.ca_cmdint = 0; - if (ud->uda1_ca.ca_rspint == 0) - continue; - ud->uda1_ca.ca_rspint = 0; - if (mp->mscp_opcode == (op | M_OP_END)) - break; - printf("\n"); - switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { - - case MSCPT_SEQ: - printf("sequential"); - break; - - case MSCPT_DATAGRAM: - mscp_decodeerror("uda", ui->ui_ctlr, mp); - printf("datagram"); - break; - - case MSCPT_CREDITS: - printf("credits"); - break; - - case MSCPT_MAINTENANCE: - printf("maintenance"); - break; - - default: - printf("unknown (type 0x%x)", - MSCP_MSGTYPE(mp->mscp_msgtc)); - break; - } - printf(" ignored\ndump "); - ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; + if (n > 9) { + dl->d_typename[p++] = (n / 10) + '0'; + n %= 10; } + dl->d_typename[p++] = n + '0'; + dl->d_typename[p] = 0; + dl->d_npartitions = MAXPARTITIONS; + dl->d_partitions[0].p_size = dl->d_partitions[2].p_size = + dl->d_secperunit; + dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0; + dl->d_interleave = dl->d_headswitch = 1; + dl->d_magic = dl->d_magic2 = DISKMAGIC; + dl->d_checksum = dkcksum(dl); +} + +/* + * We got some (configured) unit's status. Return DONE if it succeeded. + */ +int +rrgotstatus(usc, mp) + register struct device *usc; + register struct mscp *mp; +{ if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { - printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op, - mp->mscp_opcode, mp->mscp_status); - return (1); + printf("%s: attempt to get status failed: ", usc->dv_xname); + mscp_printevent(mp); + return (MSCP_FAILED); } + /* record for (future) bad block forwarding and whatever else */ +#ifdef notyet + uda_rasave(ui->ui_unit, mp, 1); #endif - return (0); -#undef mp + return (MSCP_DONE); } -/* - * Return the size of a partition, if known, or -1 if not. +/* + * A replace operation finished. */ -int -rasize(dev) - dev_t dev; +/*ARGSUSED*/ +void +rrreplace(usc, mp) + struct device *usc; + struct mscp *mp; { - register int unit = raunit(dev); - struct ra_softc *ra; - if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0) - return -1; + panic("udareplace"); +} - ra = ra_cd.cd_devs[unit]; +/* + * A transfer failed. We get a chance to fix or restart it. + * Need to write the bad block forwaring code first.... + */ +/*ARGSUSED*/ +int +rrioerror(usc, mp, bp) + register struct device *usc; + register struct mscp *mp; + struct buf *bp; +{ + struct ra_softc *ra = (void *)usc; + int code = mp->mscp_event; - if (ra->ra_state == RA_OFFLINE) - if (ra_putonline(ra) == MSCP_FAILED) - return -1; + switch (code & M_ST_MASK) { + /* The unit has fallen offline. Try to figure out why. */ + case M_ST_OFFLINE: + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + ra->ra_state = DK_CLOSED; + if (code & M_OFFLINE_UNMOUNTED) + printf("%s: not mounted/spun down\n", usc->dv_xname); + if (code & M_OFFLINE_DUPLICATE) + printf("%s: duplicate unit number!!!\n", usc->dv_xname); + return MSCP_DONE; - return ra->ra_disk.dk_label->d_partitions[rapart(dev)].p_size; + case M_ST_AVAILABLE: + ra->ra_state = DK_CLOSED; /* Force another online */ + return MSCP_DONE; + + default: + printf("%s:", usc->dv_xname); + break; + } + return (MSCP_FAILED); } -int -ra_getdev(adaptor, controller, unit, uname) - int adaptor, controller, unit; - char **uname; +/* + * Fill in disk addresses in a mscp packet waiting for transfer. + */ +void +rrfillin(bp, mp) + struct buf *bp; + struct mscp *mp; { - struct mscp_softc *mi; - struct ra_softc *ra; - int i; + struct rx_softc *rx = 0; /* Wall */ + struct disklabel *lp; + int unit = DISKUNIT(bp->b_dev); + int part = DISKPART(bp->b_dev); + +#if NRA + if (major(bp->b_dev) == RAMAJOR) + rx = ra_cd.cd_devs[unit]; +#endif +#if NRX + if (major(bp->b_dev) != RAMAJOR) + rx = rx_cd.cd_devs[unit]; +#endif + lp = rx->ra_disk.dk_label; - for (i = 0; i < ra_cd.cd_ndevs; i++) { - if ((ra = ra_cd.cd_devs[i]) == 0) - continue; + mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno; + mp->mscp_unit = rx->ra_hwunit; + mp->mscp_seq.seq_bytecount = bp->b_bcount; +} - mi = (void *)ra->ra_dev.dv_parent; - if (mi->mi_ctlrnr == controller && mi->mi_adapnr == adaptor && - ra->ra_hwunit == unit) { - *uname = ra->ra_dev.dv_xname; - return i; - } - } - return -1; +/* + * A bad block related operation finished. + */ +/*ARGSUSED*/ +void +rrbb(usc, mp, bp) + struct device *usc; + struct mscp *mp; + struct buf *bp; +{ + + panic("udabb"); } diff --git a/sys/arch/vax/mscp/mscp_subr.c b/sys/arch/vax/mscp/mscp_subr.c index 0452ff14b3e..c94d5919563 100644 --- a/sys/arch/vax/mscp/mscp_subr.c +++ b/sys/arch/vax/mscp/mscp_subr.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mscp_subr.c,v 1.2 1997/05/29 00:05:03 niklas Exp $ */ -/* $NetBSD: mscp_subr.c,v 1.6 1997/01/11 11:20:34 ragge Exp $ */ +/* $OpenBSD: mscp_subr.c,v 1.3 2000/04/27 03:14:46 bjc Exp $ */ +/* $NetBSD: mscp_subr.c,v 1.12 1999/06/06 19:16:18 ragge Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * Copyright (c) 1988 Regents of the University of California. @@ -49,32 +49,42 @@ #include <sys/systm.h> #include <sys/proc.h> +#include <machine/bus.h> #include <machine/sid.h> -#include <vax/mscp/mscp.h> -#include <vax/mscp/mscpreg.h> -#include <vax/mscp/mscpvar.h> +#include <arch/vax/mscp/mscp.h> +#include <arch/vax/mscp/mscpreg.h> +#include <arch/vax/mscp/mscpvar.h> #include "ra.h" #include "mt.h" -#define b_forw b_hash.le_next +#define b_forw b_hash.le_next -int mscp_match __P((struct device *, void *, void *)); +#ifndef offsetof +#define offsetof(type, member) ((size_t)(&((type *)0)->member)) +#endif + +int mscp_match __P((struct device *, struct cfdata *, void *)); void mscp_attach __P((struct device *, struct device *, void *)); -void mscp_start __P((struct mscp_softc *)); +void mscp_start __P((struct mscp_softc *)); int mscp_init __P((struct mscp_softc *)); void mscp_initds __P((struct mscp_softc *)); int mscp_waitstep __P((struct mscp_softc *, int, int)); struct cfattach mscpbus_ca = { - sizeof(struct mscp_softc), mscp_match, mscp_attach + sizeof(struct mscp_softc), (cfmatch_t)mscp_match, mscp_attach }; struct cfdriver mscpbus_cd = { NULL, "mscpbus", DV_DULL }; +#define READ_SA (bus_space_read_2(mi->mi_iot, mi->mi_sah, 0)) +#define READ_IP (bus_space_read_2(mi->mi_iot, mi->mi_iph, 0)) +#define WRITE_IP(x) bus_space_write_2(mi->mi_iot, mi->mi_iph, 0, (x)) +#define WRITE_SW(x) bus_space_write_2(mi->mi_iot, mi->mi_swh, 0, (x)) + struct mscp slavereply; /* @@ -91,9 +101,9 @@ mscp_waitstep(mi, mask, result) { int status = 1; - if ((*mi->mi_sa & mask) != result) { + if ((READ_SA & mask) != result) { volatile int count = 0; - while ((*mi->mi_sa & mask) != result) { + while ((READ_SA & mask) != result) { DELAY(10000); count += 1; if (count > DELAYTEN) @@ -108,11 +118,12 @@ mscp_waitstep(mi, mask, result) int mscp_match(parent, match, aux) struct device *parent; - void *match, *aux; + struct cfdata *match; + void *aux; { struct mscp_attach_args *ma = aux; -#if NRA +#if NRA || NRX if (ma->ma_type & MSCPBUS_DISK) return 1; #endif @@ -130,18 +141,20 @@ mscp_attach(parent, self, aux) { struct mscp_attach_args *ma = aux; struct mscp_softc *mi = (void *)self; - volatile struct mscp *mp; + volatile struct mscp *mp; volatile int i; int timeout, next = 0; mi->mi_mc = ma->ma_mc; mi->mi_me = NULL; mi->mi_type = ma->ma_type; - mi->mi_uuda = ma->ma_uuda; mi->mi_uda = ma->ma_uda; - mi->mi_ip = ma->ma_ip; - mi->mi_sa = ma->ma_sa; - mi->mi_sw = ma->ma_sw; + mi->mi_dmat = ma->ma_dmat; + mi->mi_dmam = ma->ma_dmam; + mi->mi_iot = ma->ma_iot; + mi->mi_iph = ma->ma_iph; + mi->mi_sah = ma->ma_sah; + mi->mi_swh = ma->ma_swh; mi->mi_ivec = ma->ma_ivec; mi->mi_adapnr = ma->ma_adapnr; mi->mi_ctlrnr = ma->ma_ctlrnr; @@ -150,20 +163,28 @@ mscp_attach(parent, self, aux) * Go out to init the bus, so that we can give commands * to its devices. */ - mi->mi_cmd.mri_size = NCMD; - mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc; - mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd; - mi->mi_rsp.mri_size = NRSP; - mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc; - mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp; - mi->mi_actf = (void *)&mi->mi_actf; /* Circular wait queue */ - mi->mi_actb = (void *)&mi->mi_actf; + mi->mi_cmd.mri_size = NCMD; + mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc; + mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd; + mi->mi_rsp.mri_size = NRSP; + mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc; + mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp; + SIMPLEQ_INIT(&mi->mi_resq); if (mscp_init(mi)) { printf("%s: can't init, controller hung\n", mi->mi_dev.dv_xname); return; } + for (i = 0; i < NCMD; i++) { + mi->mi_mxiuse |= (1 << i); + if (bus_dmamap_create(mi->mi_dmat, (64*1024), 1, (64*1024), + 0, BUS_DMA_NOWAIT, &mi->mi_xi[i].mxi_dmam)) { + printf("Couldn't alloc dmamap %d\n", i); + return; + } + } + #if NRA if (ma->ma_type & MSCPBUS_DISK) { @@ -193,7 +214,7 @@ findunit: *mp->mscp_addr |= MSCP_OWN | MSCP_INT; slavereply.mscp_opcode = 0; - i = *mi->mi_ip; /* Kick off polling */ + i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); mp = &slavereply; timeout = 1000; while (timeout-- > 0) { @@ -210,65 +231,65 @@ gotit: /* */ switch (mp->mscp_status & M_ST_MASK) { - case M_ST_SUCCESS: /* worked */ - case M_ST_AVAILABLE: /* found another drive */ - break; /* use it */ + case M_ST_SUCCESS: /* worked */ + case M_ST_AVAILABLE: /* found another drive */ + break; /* use it */ case M_ST_OFFLINE: /* * Figure out why it is off line. It may be because - * it is nonexistent, or because it is spun down, or - * for some other reason. - */ - switch (mp->mscp_status & ~M_ST_MASK) { - - case M_OFFLINE_UNKNOWN: - /* - * No such drive, and there are none with - * higher unit numbers either, if we are - * using M_GUM_NEXTUNIT. - */ + * it is nonexistent, or because it is spun down, or + * for some other reason. + */ + switch (mp->mscp_status & ~M_ST_MASK) { + + case M_OFFLINE_UNKNOWN: + /* + * No such drive, and there are none with + * higher unit numbers either, if we are + * using M_GUM_NEXTUNIT. + */ mi->mi_ierr = 3; - return; - - case M_OFFLINE_UNMOUNTED: - /* - * The drive is not spun up. Use it anyway. - * - * N.B.: this seems to be a common occurrance - * after a power failure. The first attempt - * to bring it on line seems to spin it up - * (and thus takes several minutes). Perhaps - * we should note here that the on-line may - * take longer than usual. - */ - break; - - default: - /* - * In service, or something else equally unusable. - */ - printf("%s: unit %d off line: ", mi->mi_dev.dv_xname, - mp->mscp_unit); - mscp_printevent((struct mscp *)mp); + return; + + case M_OFFLINE_UNMOUNTED: + /* + * The drive is not spun up. Use it anyway. + * + * N.B.: this seems to be a common occurrance + * after a power failure. The first attempt + * to bring it on line seems to spin it up + * (and thus takes several minutes). Perhaps + * we should note here that the on-line may + * take longer than usual. + */ + break; + + default: + /* + * In service, or something else equally unusable. + */ + printf("%s: unit %d off line: ", mi->mi_dev.dv_xname, + mp->mscp_unit); + mscp_printevent((struct mscp *)mp); next++; - goto findunit; - } - break; - - default: - printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname); - mscp_printevent((struct mscp *)mp); - return; - } - - /* - * If we get a lower number, we have circulated around all + goto findunit; + } + break; + + default: + printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname); + mscp_printevent((struct mscp *)mp); + return; + } + + /* + * If we get a lower number, we have circulated around all * devices and are finished, otherwise try to find next unit. * We shouldn't ever get this, it's a workaround. - */ - if (mp->mscp_unit < next) - return; + */ + if (mp->mscp_unit < next) + return; next = mp->mscp_unit + 1; goto findunit; @@ -289,29 +310,29 @@ mscp_init(mi) int status, count; unsigned int j = 0; - /* - * While we are thinking about it, reset the next command - * and response indicies. - */ + /* + * While we are thinking about it, reset the next command + * and response indicies. + */ mi->mi_cmd.mri_next = 0; mi->mi_rsp.mri_next = 0; mi->mi_flags |= MSC_IGNOREINTR; if ((mi->mi_type & MSCPBUS_KDB) == 0) - *mi->mi_ip = 0; /* Kick off */ + WRITE_IP(0); /* Kick off */; status = mscp_waitstep(mi, MP_STEP1, MP_STEP1);/* Wait to it wakes up */ if (status == 0) return 1; /* Init failed */ - if (*mi->mi_sa & MP_ERR) { + if (READ_SA & MP_ERR) { (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); return 1; } /* step1 */ - *mi->mi_sw = MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | - MP_IE | (mi->mi_ivec >> 2); + WRITE_SW(MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | + MP_IE | (mi->mi_ivec >> 2)); status = mscp_waitstep(mi, STEP1MASK, STEP1GOOD); if (status == 0) { (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); @@ -319,31 +340,33 @@ mscp_init(mi) } /* step2 */ - *mi->mi_sw = (int)&mi->mi_uuda->mp_ca.ca_rspdsc[0] | - (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0); + WRITE_SW(((mi->mi_dmam->dm_segs[0].ds_addr & 0xffff) + + offsetof(struct mscp_pack, mp_ca.ca_rspdsc[0])) | + (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0)); status = mscp_waitstep(mi, STEP2MASK, STEP2GOOD(mi->mi_ivec >> 2)); - if (status == 0) { - (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); - return 1; - } + if (status == 0) { + (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); + return 1; + } /* step3 */ - *mi->mi_sw = ((int)&mi->mi_uuda->mp_ca.ca_rspdsc[0]) >> 16; + + WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 16)); status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD); - if (status == 0) { - (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); - return 1; - } - i = *mi->mi_sa & 0377; + if (status == 0) { + (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); + return 1; + } + i = READ_SA & 0377; printf(": version %d model %d\n", i & 15, i >> 4); -#define BURST 4 /* XXX */ +#define BURST 4 /* XXX */ if (mi->mi_type & MSCPBUS_UDA) { - *mi->mi_sw = MP_GO | (BURST - 1) << 2; + WRITE_SW(MP_GO | (BURST - 1) << 2); printf("%s: DMA burst size set to %d\n", mi->mi_dev.dv_xname, BURST); } - *mi->mi_sw = MP_GO; + WRITE_SW(MP_GO); mscp_initds(mi); mi->mi_flags &= ~MSC_IGNOREINTR; @@ -363,17 +386,17 @@ mscp_init(mi) mp->mscp_sccc.sccc_errlgfl = 0; mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS; *mp->mscp_addr |= MSCP_OWN | MSCP_INT; - i = *mi->mi_ip; + i = READ_IP; - count = 0; - while (count < DELAYTEN) { - if (((volatile)mi->mi_flags & MSC_READY) != 0) - break; - if ((j = *mi->mi_sa) & MP_ERR) + count = 0; + while (count < DELAYTEN) { + if (((volatile int)mi->mi_flags & MSC_READY) != 0) + break; + if ((j = READ_SA) & MP_ERR) goto out; - DELAY(10000); - count += 1; - } + DELAY(10000); + count += 1; + } if (count == DELAYTEN) { out: printf("%s: couldn't set ctlr characteristics, sa=%x\n", @@ -390,20 +413,21 @@ void mscp_initds(mi) struct mscp_softc *mi; { - struct mscp_pack *uud = mi->mi_uuda; struct mscp_pack *ud = mi->mi_uda; struct mscp *mp; int i; for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) { ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | - (long)&uud->mp_rsp[i].mscp_cmdref; + (mi->mi_dmam->dm_segs[0].ds_addr + + offsetof(struct mscp_pack, mp_rsp[i].mscp_cmdref)); mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i]; mp->mscp_msglen = MSCP_MSGLEN; } for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) { ud->mp_ca.ca_cmddsc[i] = MSCP_INT | - (long)&uud->mp_cmd[i].mscp_cmdref; + (mi->mi_dmam->dm_segs[0].ds_addr + + offsetof(struct mscp_pack, mp_cmd[i].mscp_cmdref)); mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i]; mp->mscp_msglen = MSCP_MSGLEN; if (mi->mi_type & MSCPBUS_TAPE) @@ -411,6 +435,8 @@ mscp_initds(mi) } } +static void mscp_kickaway(struct mscp_softc *); + void mscp_intr(mi) struct mscp_softc *mi; @@ -419,31 +445,23 @@ mscp_intr(mi) if (mi->mi_flags & MSC_IGNOREINTR) return; - /* - * Check for response and command ring transitions. - */ - if (ud->mp_ca.ca_rspint) { - ud->mp_ca.ca_rspint = 0; - mscp_dorsp(mi); - } - if (ud->mp_ca.ca_cmdint) { - ud->mp_ca.ca_cmdint = 0; - MSCP_DOCMD(mi); - } - /* - * If there are any not-yet-handled requeset, try them now. - * XXX - We handles them (erroneous) in last-in first-handled order. - * Must we fix this??? + * Check for response and command ring transitions. */ - while (mi->mi_w) { - struct buf *bp = mi->mi_w; - - mi->mi_w = (void *)bp->b_actb; - mscp_strategy(bp, (struct device *)mi); - if (mi->mi_w == bp) - break; + if (ud->mp_ca.ca_rspint) { + ud->mp_ca.ca_rspint = 0; + mscp_dorsp(mi); + } + if (ud->mp_ca.ca_cmdint) { + ud->mp_ca.ca_cmdint = 0; + MSCP_DOCMD(mi); } + + /* + * If there are any not-yet-handled request, try them now. + */ + if (SIMPLEQ_FIRST(&mi->mi_resq)) + mscp_kickaway(mi); } int @@ -451,12 +469,22 @@ mscp_print(aux, name) void *aux; const char *name; { + struct drive_attach_args *da = aux; + struct mscp *mp = da->da_mp; + int type = mp->mscp_guse.guse_mediaid; + + if (name) { + printf("%c%c", MSCP_MID_CHAR(2, type), MSCP_MID_CHAR(1, type)); + if (MSCP_MID_ECH(0, type)) + printf("%c", MSCP_MID_CHAR(0, type)); + printf("%d at %s drive %d", MSCP_MID_NUM(type), name, + mp->mscp_unit); + } return UNCONF; } /* * common strategy routine for all types of MSCP devices. - * bp is the current buf, dp is the drive queue. */ void mscp_strategy(bp, usc) @@ -464,60 +492,82 @@ mscp_strategy(bp, usc) struct device *usc; { struct mscp_softc *mi = (void *)usc; + int s = splimp(); + +/* SIMPLEQ_INSERT_TAIL(&mi->mi_resq, bp, xxx) */ + bp->b_actf = NULL; + *mi->mi_resq.sqh_last = bp; + mi->mi_resq.sqh_last = &bp->b_actf; + mscp_kickaway(mi); + splx(s); +} + + +void +mscp_kickaway(mi) + struct mscp_softc *mi; +{ + struct buf *bp; struct mscp *mp; - int s = spl6(); + int next; - /* - * Ok; we are ready to try to start a xfer. Get a MSCP packet - * and try to start... - */ - if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) { - if (mi->mi_credits > MSCP_MINCREDITS) - printf("%s: command ring too small\n", - mi->mi_dev.dv_parent->dv_xname); + while ((bp = SIMPLEQ_FIRST(&mi->mi_resq))) { /* - * By some (strange) reason we didn't get a MSCP packet. - * Put it on queue and wait for free packets. + * Ok; we are ready to try to start a xfer. Get a MSCP packet + * and try to start... */ - (void *)bp->b_actb = mi->mi_w; - mi->mi_w = bp; - splx(s); - return; + if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) { + if (mi->mi_credits > MSCP_MINCREDITS) + printf("%s: command ring too small\n", + mi->mi_dev.dv_parent->dv_xname); + /* + * By some (strange) reason we didn't get a MSCP packet. + * Just return and wait for free packets. + */ + return; + } + + if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0) + panic("no mxi buffers"); + mi->mi_mxiuse &= ~(1 << next); + if (mi->mi_xi[next].mxi_inuse) + panic("mxi inuse"); + /* + * Set up the MSCP packet and ask the ctlr to start. + */ + mp->mscp_opcode = + (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; + mp->mscp_cmdref = next; + mi->mi_xi[next].mxi_bp = bp; + mi->mi_xi[next].mxi_mp = mp; + mi->mi_xi[next].mxi_inuse = 1; + bp->b_resid = next; + (*mi->mi_me->me_fillin)(bp, mp); + (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, &mi->mi_xi[next]); + if ((mi->mi_resq.sqh_first = bp->b_actf) == NULL) + mi->mi_resq.sqh_last = &mi->mi_resq.sqh_first; +#if 0 + mi->mi_w = bp->b_actf; +#endif } - - /* - * Set up the MSCP packet and ask the ctlr to start. - */ - mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; - (*mi->mi_me->me_fillin)(bp, mp); - (void *)bp->b_actb = mp; /* b_actb is unused, save mscp packet here */ - (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, bp); - splx(s); } void -mscp_dgo(mi, buffer, info, bp) +mscp_dgo(mi, mxi) struct mscp_softc *mi; - long buffer, info; - struct buf *bp; + struct mscp_xi *mxi; { volatile int i; struct mscp *mp; - /* - * Fill in the MSCP packet and move the buffer to the I/O wait queue. - */ - mp = (void *)bp->b_actb; - - mp->mscp_seq.seq_buffer = buffer; - - _insque(&bp->b_actf, &mi->mi_actf); + /* + * Fill in the MSCP packet and move the buffer to the I/O wait queue. + */ + mp = mxi->mxi_mp; + mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr; - bp->b_resid = info; - mp->mscp_cmdref = (long) bp; *mp->mscp_addr |= MSCP_OWN | MSCP_INT; - - i = *mi->mi_ip; + i = READ_IP; } #ifdef DIAGNOSTIC @@ -686,7 +736,7 @@ static char *drive_msgs[] = { "lost rd/wr ready", /* 4 = Lost R/W Ready Error */ "drive clock dropout", /* 5 = Lost Drive Clock */ "lost recvr ready", /* 6 = Lost Receiver Ready */ - "drive detected error", /* 7 = Drive Error */ + "drive detected error", /* 7 = Drive Error */ "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */ }; @@ -699,7 +749,7 @@ struct code_decode { int cdc_nsubcodes; char **cdc_submsgs; } code_decode[] = { -#define SC(m) sizeof (m) / sizeof (m[0]), m +#define SC(m) sizeof (m) / sizeof (m[0]), m {"success", SC(succ_msgs)}, {"invalid command", SC(icmd_msgs)}, {"command aborted", 0, 0}, diff --git a/sys/arch/vax/mscp/mscp_tape.c b/sys/arch/vax/mscp/mscp_tape.c index 9e3a23dcf2d..49f53e1df12 100644 --- a/sys/arch/vax/mscp/mscp_tape.c +++ b/sys/arch/vax/mscp/mscp_tape.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mscp_tape.c,v 1.3 1997/09/12 09:25:52 maja Exp $ */ -/* $NetBSD: mscp_tape.c,v 1.5 1997/07/04 11:58:22 ragge Exp $ */ +/* $OpenBSD: mscp_tape.c,v 1.4 2000/04/27 03:14:46 bjc Exp $ */ +/* $NetBSD: mscp_tape.c,v 1.14 1999/06/06 19:16:18 ragge Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -14,8 +14,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed at Ludd, University of - * Lule}, Sweden and its contributors. + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * @@ -52,8 +52,12 @@ #include <sys/systm.h> #include <sys/proc.h> -#include <vax/mscp/mscp.h> -#include <vax/mscp/mscpvar.h> +#include <machine/bus.h> +#include <machine/cpu.h> + +#include <arch/vax/mscp/mscp.h> +#include <arch/vax/mscp/mscpreg.h> +#include <arch/vax/mscp/mscpvar.h> /* * Drive status, per drive @@ -68,10 +72,10 @@ struct mt_softc { int mt_ioctlerr; /* Error after last ioctl */ }; -#define MT_OFFLINE 0 -#define MT_ONLINE 1 +#define MT_OFFLINE 0 +#define MT_ONLINE 1 -int mtmatch __P((struct device *, void *, void *)); +int mtmatch __P((struct device *, struct cfdata *, void *)); void mtattach __P((struct device *, struct device *, void *)); void mtdgram __P((struct device *, struct mscp *, struct mscp_softc *)); void mtiodone __P((struct device *, struct buf *)); @@ -88,6 +92,7 @@ int mtioctl __P((dev_t, int, caddr_t, int, struct proc *)); int mtdump __P((dev_t, daddr_t, caddr_t, size_t)); int mtcmd __P((struct mt_softc *, int, int, int)); void mtcmddone __P((struct device *, struct mscp *)); +int mt_putonline __P((struct mt_softc *)); struct mscp_device mt_device = { mtdgram, @@ -102,16 +107,16 @@ struct mscp_device mt_device = { }; /* This is not good, should allow more than 4 tapes/device type */ -#define mtunit(dev) (minor(dev) & T_UNIT) -#define mtnorewind(dev) (dev & T_NOREWIND) -#define mthdensity(dev) (dev & T_1600BPI) +#define mtunit(dev) (minor(dev) & T_UNIT) +#define mtnorewind(dev) (dev & T_NOREWIND) +#define mthdensity(dev) (dev & T_1600BPI) -struct cfdriver mt_cd = { - NULL, "mt", DV_DULL +struct cfattach mt_ca = { + sizeof(struct mt_softc), (cfmatch_t)mtmatch, mtattach }; -struct cfattach mt_ca = { - sizeof(struct mt_softc), mtmatch, mtattach +struct cfdriver mt_cd = { + NULL, "mt", DV_TAPE }; /* @@ -119,11 +124,11 @@ struct cfattach mt_ca = { */ int -mtmatch(parent, match, aux) +mtmatch(parent, cf, aux) struct device *parent; - void *match, *aux; + struct cfdata *cf; + void *aux; { - struct cfdata *cf = match; struct drive_attach_args *da = aux; struct mscp *mp = da->da_mp; @@ -165,7 +170,7 @@ mt_putonline(mt) struct mscp_softc *mi = (struct mscp_softc *)mt->mt_dev.dv_parent; volatile int i; - (volatile)mt->mt_state = MT_OFFLINE; + (volatile int)mt->mt_state = MT_OFFLINE; mp = mscp_getcp(mi, MSCP_WAIT); mp->mscp_opcode = M_OP_ONLINE; mp->mscp_unit = mt->mt_hwunit; @@ -173,11 +178,11 @@ mt_putonline(mt) *mp->mscp_addr |= MSCP_OWN | MSCP_INT; /* Poll away */ - i = *mi->mi_ip; + i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz)) return MSCP_FAILED; - if ((volatile)mt->mt_state != MT_ONLINE) + if ((volatile int)mt->mt_state != MT_ONLINE) return MSCP_FAILED; return MSCP_DONE; @@ -209,8 +214,10 @@ mtopen(dev, flag, fmt, p) return EBUSY; mt->mt_inuse = 1; - if (mt_putonline(mt) == MSCP_FAILED) + if (mt_putonline(mt) == MSCP_FAILED) { + mt->mt_inuse = 0; return EIO; + } return 0; } @@ -269,20 +276,20 @@ bad: int mtread(dev, uio) - dev_t dev; - struct uio *uio; + dev_t dev; + struct uio *uio; { - return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio)); + return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio)); } int mtwrite(dev, uio) - dev_t dev; - struct uio *uio; + dev_t dev; + struct uio *uio; { - return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio)); + return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio)); } void @@ -363,12 +370,12 @@ static char *mt_ioerrs[] = { "unit offline", /* 3 M_ST_OFFLINE */ "unknown", /* 4 M_ST_AVAILABLE */ "unknown", /* 5 M_ST_MFMTERR */ - "unit write protected", /* 6 M_ST_WRPROT */ + "unit write protected", /* 6 M_ST_WRPROT */ "compare error", /* 7 M_ST_COMPERR */ - "data error", /* 8 M_ST_DATAERR */ - "host buffer access error", /* 9 M_ST_HOSTBUFERR */ + "data error", /* 8 M_ST_DATAERR */ + "host buffer access error", /* 9 M_ST_HOSTBUFERR */ "controller error", /* 10 M_ST_CTLRERR */ - "drive error", /* 11 M_ST_DRIVEERR */ + "drive error", /* 11 M_ST_DRIVEERR */ "formatter error", /* 12 M_ST_FORMATTERR */ "BOT encountered", /* 13 M_ST_BOT */ "tape mark encountered",/* 14 M_ST_TAPEMARK */ @@ -401,6 +408,7 @@ mtioerror(usc, mp, bp) else printf("%s: error %d\n", mt->mt_dev.dv_xname, st); bp->b_flags |= B_ERROR; + bp->b_error = EROFS; } return (MSCP_DONE); @@ -421,7 +429,7 @@ mtioctl(dev, cmd, data, flag, p) register struct mt_softc *mt = mt_cd.cd_devs[unit]; struct mtop *mtop; struct mtget *mtget; - int error = 0, i, count; + int error = 0, count; count = mtop->mt_count; @@ -455,8 +463,8 @@ mtioctl(dev, cmd, data, flag, p) int mtdump(dev, blkno, va, size) dev_t dev; - daddr_t blkno; - caddr_t va; + daddr_t blkno; + caddr_t va; size_t size; { return -1; @@ -536,7 +544,7 @@ mtcmd(mt, cmd, count, complete) break; } - i = *mi->mi_ip; + i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0); return mt->mt_ioctlerr; } diff --git a/sys/arch/vax/mscp/mscpreg.h b/sys/arch/vax/mscp/mscpreg.h index 065996ada8d..660ab4638c9 100644 --- a/sys/arch/vax/mscp/mscpreg.h +++ b/sys/arch/vax/mscp/mscpreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: mscpreg.h,v 1.3 1997/09/10 11:54:42 maja Exp $ */ -/* $NetBSD: mscpreg.h,v 1.2 1997/03/15 16:39:20 ragge Exp $ */ +/* $OpenBSD: mscpreg.h,v 1.4 2000/04/27 03:14:46 bjc Exp $ */ +/* $NetBSD: mscpreg.h,v 1.4 1999/05/29 19:12:53 ragge Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * Copyright (c) 1988 Regents of the University of California. @@ -46,11 +46,11 @@ * If you get warnings about your command ring being too small, * try increasing the values by one. */ -#ifndef NRSP -#define NRSPL2 5 -#define NCMDL2 5 -#define NRSP (1 << NRSPL2) -#define NCMD (1 << NCMDL2) +#ifndef NRSP +#define NRSPL2 5 +#define NCMDL2 5 +#define NRSP (1 << NRSPL2) +#define NCMD (1 << NCMDL2) #endif /* @@ -97,30 +97,30 @@ struct mscp_pack { /* * Bits in UDA status register during initialisation */ -#define MP_ERR 0x8000 /* error */ -#define MP_STEP4 0x4000 /* step 4 has started */ -#define MP_STEP3 0x2000 /* step 3 has started */ -#define MP_STEP2 0x1000 /* step 2 has started */ -#define MP_STEP1 0x0800 /* step 1 has started */ -#define MP_NV 0x0400 /* no host settable interrupt vector */ -#define MP_QB 0x0200 /* controller supports Q22 bus */ -#define MP_DI 0x0100 /* controller implements diagnostics */ -#define MP_IE 0x0080 /* interrupt enable */ -#define MP_NCNRMASK 0x003f /* in STEP1, bits 0-2=NCMDL2, 3-5=NRSPL2 */ -#define MP_IVECMASK 0x007f /* in STEP2, bits 0-6 are interruptvec / 4 */ -#define MP_PI 0x0001 /* host requests adapter purge interrupts */ -#define MP_GO 0x0001 /* Go command to ctlr */ +#define MP_ERR 0x8000 /* error */ +#define MP_STEP4 0x4000 /* step 4 has started */ +#define MP_STEP3 0x2000 /* step 3 has started */ +#define MP_STEP2 0x1000 /* step 2 has started */ +#define MP_STEP1 0x0800 /* step 1 has started */ +#define MP_NV 0x0400 /* no host settable interrupt vector */ +#define MP_QB 0x0200 /* controller supports Q22 bus */ +#define MP_DI 0x0100 /* controller implements diagnostics */ +#define MP_IE 0x0080 /* interrupt enable */ +#define MP_NCNRMASK 0x003f /* in STEP1, bits 0-2=NCMDL2, 3-5=NRSPL2 */ +#define MP_IVECMASK 0x007f /* in STEP2, bits 0-6 are interruptvec / 4 */ +#define MP_PI 0x0001 /* host requests adapter purge interrupts */ +#define MP_GO 0x0001 /* Go command to ctlr */ #define ALLSTEPS (MP_ERR | MP_STEP4 | MP_STEP3 | MP_STEP2 | MP_STEP1) #define STEP0MASK (ALLSTEPS | MP_NV) -#define STEP1MASK (ALLSTEPS | MP_IE | MP_NCNRMASK) -#define STEP1GOOD (MP_STEP2 | MP_IE | (NCMDL2 << 3) | NRSPL2) +#define STEP1MASK (ALLSTEPS | MP_IE | MP_NCNRMASK) +#define STEP1GOOD (MP_STEP2 | MP_IE | (NCMDL2 << 3) | NRSPL2) -#define STEP2MASK (ALLSTEPS | MP_IE | MP_IVECMASK) -#define STEP2GOOD(iv) (MP_STEP3 | MP_IE | (iv)) +#define STEP2MASK (ALLSTEPS | MP_IE | MP_IVECMASK) +#define STEP2GOOD(iv) (MP_STEP3 | MP_IE | (iv)) -#define STEP3MASK ALLSTEPS -#define STEP3GOOD MP_STEP4 +#define STEP3MASK ALLSTEPS +#define STEP3GOOD MP_STEP4 diff --git a/sys/arch/vax/mscp/mscpvar.h b/sys/arch/vax/mscp/mscpvar.h index 3a2b6cd24c3..0e0654be62b 100644 --- a/sys/arch/vax/mscp/mscpvar.h +++ b/sys/arch/vax/mscp/mscpvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: mscpvar.h,v 1.2 1997/05/29 00:05:04 niklas Exp $ */ -/* $NetBSD: mscpvar.h,v 1.4 1997/01/11 11:20:36 ragge Exp $ */ +/* $OpenBSD: mscpvar.h,v 1.3 2000/04/27 03:14:46 bjc Exp $ */ +/* $NetBSD: mscpvar.h,v 1.7 1999/06/06 19:16:18 ragge Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * Copyright (c) 1988 Regents of the University of California. @@ -70,11 +70,21 @@ struct mscp_ri { struct mscp *mri_ring; /* base address of packets */ }; +/* + * Transfer info, one per command packet. + */ +struct mscp_xi { + bus_dmamap_t mxi_dmam; /* Allocated DMA map for this entry */ + struct buf * mxi_bp; /* Buffer used in this command */ + struct mscp * mxi_mp; /* Packet used in this command */ + int mxi_inuse; +}; + struct mscp_ctlr { void (*mc_ctlrdone) /* controller operation complete */ - __P((struct device *, int)); - int (*mc_go) /* device-specific start routine */ - __P((struct device *, struct buf *)); + __P((struct device *)); + void (*mc_go) /* device-specific start routine */ + __P((struct device *, struct mscp_xi *)); void (*mc_saerror) /* ctlr error handling */ __P((struct device *, int)); }; @@ -88,7 +98,7 @@ struct mscp_device { __P((struct device *, struct buf *)); int (*me_online) /* drive on line */ __P((struct device *, struct mscp *)); - int (*me_gotstatus) /* got unit status */ + int (*me_gotstatus) /* got unit status */ __P((struct device *, struct mscp *)); void (*me_replace) /* replace done */ __P((struct device *, struct mscp *)); @@ -109,20 +119,22 @@ struct mscp_attach_args { struct mscp_ctlr *ma_mc; /* Pointer to ctlr's mscp_ctlr */ int ma_type; /* disk/tape bus type */ struct mscp_pack *ma_uda; /* comm area virtual */ - struct mscp_pack *ma_uuda; /* comm area on bus */ struct mscp_softc **ma_softc; /* backpointer to bus softc */ - short *ma_ip; /* initialisation and polling */ - short *ma_sa; /* status & address (read part) */ - short *ma_sw; /* status & address (write part) */ + bus_dmamap_t ma_dmam; /* This comm area dma info */ + bus_dma_tag_t ma_dmat; + bus_space_tag_t ma_iot; + bus_space_handle_t ma_iph; /* initialisation and polling */ + bus_space_handle_t ma_sah; /* status & address (read part) */ + bus_space_handle_t ma_swh; /* status & address (write part) */ short ma_ivec; /* Interrupt vector to use */ char ma_ctlrnr; /* Phys ctlr nr */ char ma_adapnr; /* Phys adapter nr */ }; #define MSCPBUS_DISK 001 /* Bus is used for disk mounts */ #define MSCPBUS_TAPE 002 /* Bus is used for tape mounts */ -#define MSCPBUS_UDA 004 /* ctlr is disk on unibus/qbus */ -#define MSCPBUS_KDB 010 /* ctlr is disk on BI */ -#define MSCPBUS_KLE 020 /* ctlr is tape on unibus/qbus */ +#define MSCPBUS_UDA 004 /* ctlr is disk on unibus/qbus */ +#define MSCPBUS_KDB 010 /* ctlr is disk on BI */ +#define MSCPBUS_KLE 020 /* ctlr is tape on unibus/qbus */ /* * Used when going for child devices. @@ -158,11 +170,13 @@ struct mscp_softc { struct device mi_dev; /* Autoconf stuff */ struct mscp_ri mi_cmd; /* MSCP command ring info */ struct mscp_ri mi_rsp; /* MSCP response ring info */ + bus_dma_tag_t mi_dmat; + bus_dmamap_t mi_dmam; + struct mscp_xi mi_xi[NCMD]; + int mi_mxiuse; /* Bitfield of inuse mxi packets */ short mi_credits; /* transfer credits */ char mi_wantcmd; /* waiting for command packet */ char mi_wantcredits; /* waiting for transfer credits */ - struct buf *mi_actf; /* Pointer to buffers in */ - struct buf *mi_actb; /* circular wait queue */ struct mscp_ctlr *mi_mc; /* Pointer to parent's mscp_ctlr */ struct mscp_device *mi_me; /* Pointer to child's mscp_device */ struct device **mi_dp; /* array of backpointers */ @@ -171,21 +185,21 @@ struct mscp_softc { char mi_adapnr; /* Phys adapter nr */ int mi_flags; struct mscp_pack *mi_uda; /* virtual address */ - struct mscp_pack *mi_uuda; /* (device-specific) address */ int mi_type; short mi_ivec; /* Interrupt vector to use */ short mi_ierr; /* Init err counter */ - volatile short *mi_ip; /* initialisation and polling */ - volatile short *mi_sa; /* status & address (read part) */ - volatile short *mi_sw; /* status & address (write part) */ - struct buf *mi_w; /* While waiting for packets */ + bus_space_tag_t mi_iot; + bus_space_handle_t mi_iph; /* initialisation and polling */ + bus_space_handle_t mi_sah; /* status & address (read part) */ + bus_space_handle_t mi_swh; /* status & address (write part) */ + SIMPLEQ_HEAD(, buf) mi_resq; /* While waiting for packets */ }; /* mi_flags */ -#define MSC_STARTPOLL 1 -#define MSC_INSTART 2 -#define MSC_IGNOREINTR 4 -#define MSC_READY 8 +#define MSC_STARTPOLL 1 +#define MSC_INSTART 2 +#define MSC_IGNOREINTR 4 +#define MSC_READY 8 /* * We have run out of credits when mi_credits is <= MSCP_MINCREDITS. @@ -221,24 +235,6 @@ struct mscp_softc { } \ } -/* - * The following macro appends a buffer to a drive queue or a drive to - * a controller queue, given the name of the forward link. Use as - * `APPEND(dp, &um->um_tab, b_forw)' or `APPEND(bp, dp, av_forw)', - * where `bp' is a transfer request, `dp' is a drive queue, and `um_tab' - * is a controller queue. (That is, the forward link for controller - * queues is `b_forw'; for drive queues, it is `av_forw'.) - */ - -#define MSCP_APPEND(bp, queue, link) { \ - (bp)->link = NULL; \ - if ((queue)->link == NULL) \ - (queue)->link = (bp); \ - else \ - *(queue)->b_actb = (bp); \ - (queue)->b_actb = &(bp)->link; \ -} - /* Prototypes */ struct mscp *mscp_getcp __P((struct mscp_softc *, int)); void mscp_printevent __P((struct mscp *)); @@ -251,5 +247,5 @@ void mscp_hexdump __P((struct mscp *)); void mscp_strategy __P((struct buf *, struct device *)); void mscp_printtype __P((int, int)); int mscp_waitstep __P((struct mscp_softc *, int, int)); -void mscp_dgo __P((struct mscp_softc *, long, long, struct buf *)); +void mscp_dgo __P((struct mscp_softc *, struct mscp_xi *)); void mscp_intr __P((struct mscp_softc *)); diff --git a/sys/arch/vax/uba/dhu.c b/sys/arch/vax/qbus/dhu.c index a3c2089a37a..a28a8b77fc3 100644 --- a/sys/arch/vax/uba/dhu.c +++ b/sys/arch/vax/qbus/dhu.c @@ -1,5 +1,5 @@ -/* $OpenBSD: dhu.c,v 1.4 1997/05/29 00:05:05 niklas Exp $ */ -/* $NetBSD: dhu.c,v 1.9 1997/01/11 11:34:41 ragge Exp $ */ +/* $OpenBSD: dhu.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */ +/* $NetBSD: dhu.c,v 1.17 2000/01/24 02:40:28 matt Exp $ */ /* * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. * Copyright (c) 1992, 1993 @@ -51,11 +51,11 @@ #include <sys/syslog.h> #include <sys/device.h> -#include <machine/trap.h> +#include <machine/bus.h> +#include <machine/scb.h> -#include <vax/uba/ubavar.h> - -#include <vax/uba/dhureg.h> +#include <arch/vax/qbus/ubavar.h> +#include <arch/vax/qbus/dhureg.h> /* A DHU-11 has 16 ports while a DHV-11 has only 8. We use 16 by default */ @@ -66,12 +66,14 @@ struct dhu_softc { struct device sc_dev; /* Device struct used by config */ - dhuregs * sc_addr; /* controller reg address */ int sc_type; /* controller type, DHU or DHV */ + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_dma_tag_t sc_dmat; struct { struct tty *dhu_tty; /* what we work on */ + bus_dmamap_t dhu_dmah; int dhu_state; /* to manage TX output status */ - int dhu_txaddr; /* UBA map address to TX buf */ short dhu_cc; /* character count on TX */ short dhu_modem; /* modem bits state */ } sc_dhu[NDHULINE]; @@ -95,6 +97,16 @@ struct dhu_softc { #define DML_DSR TIOCM_DSR #define DML_BRK 0100000 /* no equivalent, we will mask */ +#define DHU_READ_WORD(reg) \ + bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg) +#define DHU_WRITE_WORD(reg, val) \ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val) +#define DHU_READ_BYTE(reg) \ + bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg) +#define DHU_WRITE_BYTE(reg, val) \ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val) + + /* On a stock DHV, channel pairs (0/1, 2/3, etc.) must use */ /* a baud rate from the same group. So limiting to B is likely */ /* best, although clone boards like the ABLE QHV allow all settings. */ @@ -120,10 +132,10 @@ static struct speedtab dhuspeedtab[] = { { -1, -1 } }; -static int dhu_match __P((struct device *, void *, void *)); +static int dhu_match __P((struct device *, struct cfdata *, void *)); static void dhu_attach __P((struct device *, struct device *, void *)); -static void dhurint __P((int)); -static void dhuxint __P((int)); +static void dhurint __P((void *)); +static void dhuxint __P((void *)); static void dhustart __P((struct tty *)); static int dhuparam __P((struct tty *, struct termios *)); static int dhuiflow __P((struct tty *, int)); @@ -136,38 +148,38 @@ static unsigned dhumctl __P((struct dhu_softc *,int, int, int)); void dhustop __P((struct tty *, int)); struct tty * dhutty __P((dev_t)); -struct cfdriver dhu_cd = { - NULL, "dhu", DV_TTY +struct cfattach dhu_ca = { + sizeof(struct dhu_softc), (cfmatch_t)dhu_match, dhu_attach }; -struct cfattach dhu_ca = { - sizeof(struct dhu_softc), dhu_match, dhu_attach +struct cfdriver dhu_cd = { + NULL, "dhu", DV_TTY }; /* Autoconfig handles: setup the controller to interrupt, */ /* then complete the housecleaning for full operation */ static int -dhu_match(parent, match, aux) +dhu_match(parent, cf, aux) struct device *parent; - void *match, *aux; + struct cfdata *cf; + void *aux; { struct uba_attach_args *ua = aux; - register dhuregs *dhuaddr; register int n; - dhuaddr = (dhuregs *) ua->ua_addr; - /* Reset controller to initialize, enable TX/RX interrupts */ /* to catch floating vector info elsewhere when completed */ - dhuaddr->dhu_csr = (DHU_CSR_MASTER_RESET | DHU_CSR_RXIE | DHU_CSR_TXIE); + bus_space_write_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR, + DHU_CSR_MASTER_RESET | DHU_CSR_RXIE | DHU_CSR_TXIE); /* Now wait up to 3 seconds for self-test to complete. */ for (n = 0; n < 300; n++) { DELAY(10000); - if ((dhuaddr->dhu_csr & DHU_CSR_MASTER_RESET) == 0) + if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) & + DHU_CSR_MASTER_RESET) == 0) break; } @@ -179,13 +191,10 @@ dhu_match(parent, match, aux) /* Check whether diagnostic run has signalled a failure. */ - if ((dhuaddr->dhu_csr & DHU_CSR_DIAG_FAIL) != 0) + if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) & + DHU_CSR_DIAG_FAIL) != 0) return 0; - /* Register the RX interrupt handler */ - - ua->ua_ivec = dhurint; - return 1; } @@ -196,18 +205,18 @@ dhu_attach(parent, self, aux) { register struct dhu_softc *sc = (void *)self; register struct uba_attach_args *ua = aux; - register dhuregs *dhuaddr; register unsigned c; - register int n; - - dhuaddr = (dhuregs *) ua->ua_addr; + register int n, i; + sc->sc_iot = ua->ua_iot; + sc->sc_ioh = ua->ua_ioh; + sc->sc_dmat = ua->ua_dmat; /* Process the 8 bytes of diagnostic info put into */ /* the FIFO following the master reset operation. */ printf("\n%s:", self->dv_xname); for (n = 0; n < 8; n++) { - c = dhuaddr->dhu_rbuf; + c = DHU_READ_WORD(DHU_UBA_RBUF); if ((c&DHU_DIAG_CODE) == DHU_DIAG_CODE) { if ((c&0200) == 0000) @@ -218,35 +227,43 @@ dhu_attach(parent, self, aux) ((c>>1)&01), ((c>>2)&07)); } } - printf("\n"); - c = dhuaddr->dhu_stat; /* get flag to distinguish DHU from DHV */ + c = DHU_READ_WORD(DHU_UBA_STAT); - sc->sc_addr = dhuaddr; sc->sc_type = (c & DHU_STAT_DHU)? IS_DHU: IS_DHV; + printf("\n%s: DH%s-11\n", self->dv_xname, (c & DHU_STAT_DHU)?"U":"V"); + + for (i = 0; i < sc->sc_type; i++) { + struct tty *tp; + tp = sc->sc_dhu[i].dhu_tty = ttymalloc(); + sc->sc_dhu[i].dhu_state = STATE_IDLE; + bus_dmamap_create(sc->sc_dmat, tp->t_outq.c_cn, 1, + tp->t_outq.c_cn, 0, BUS_DMA_ALLOCNOW|BUS_DMA_NOWAIT, + &sc->sc_dhu[i].dhu_dmah); + bus_dmamap_load(sc->sc_dmat, sc->sc_dhu[i].dhu_dmah, + tp->t_outq.c_cs, tp->t_outq.c_cn, 0, BUS_DMA_NOWAIT); + + } - /* Now stuff TX interrupt handler in place */ + /* Now establish RX & TX interrupt handlers */ - ubasetvec(self, ua->ua_cvec + 1, dhuxint); - return; + uba_intr_establish(ua->ua_icookie, ua->ua_cvec , dhurint, sc); + uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4, dhuxint, sc); } /* Receiver Interrupt */ static void -dhurint(unit) - int unit; +dhurint(arg) + void *arg; { - struct dhu_softc *sc = dhu_cd.cd_devs[unit]; - register dhuregs *dhuaddr; + struct dhu_softc *sc = arg; register struct tty *tp; register int cc, line; register unsigned c, delta; int overrun = 0; - dhuaddr = sc->sc_addr; - - while ((c = dhuaddr->dhu_rbuf) & DHU_RBUF_DATA_VALID) { + while ((c = DHU_READ_WORD(DHU_UBA_RBUF)) & DHU_RBUF_DATA_VALID) { /* Ignore diagnostic FIFO entries. */ @@ -305,23 +322,19 @@ dhurint(unit) (*linesw[tp->t_line].l_rint)(cc, tp); } - return; } /* Transmitter Interrupt */ static void -dhuxint(unit) - int unit; +dhuxint(arg) + void *arg; { - register struct dhu_softc *sc = dhu_cd.cd_devs[unit]; - register dhuregs *dhuaddr; + register struct dhu_softc *sc = arg; register struct tty *tp; register int line; - dhuaddr = sc->sc_addr; - - line = DHU_LINE(dhuaddr->dhu_csr_hi); + line = DHU_LINE(DHU_READ_BYTE(DHU_UBA_CSR_HI)); tp = sc->sc_dhu[line].dhu_tty; @@ -330,7 +343,8 @@ dhuxint(unit) tp->t_state &= ~TS_FLUSH; else { if (sc->sc_dhu[line].dhu_state == STATE_DMA_STOPPED) - sc->sc_dhu[line].dhu_cc -= dhuaddr->dhu_tbufcnt; + sc->sc_dhu[line].dhu_cc -= + DHU_READ_WORD(DHU_UBA_TBUFCNT); ndflush(&tp->t_outq, sc->sc_dhu[line].dhu_cc); sc->sc_dhu[line].dhu_cc = 0; } @@ -341,8 +355,6 @@ dhuxint(unit) (*linesw[tp->t_line].l_start)(tp); else dhustart(tp); - - return; } int @@ -351,7 +363,6 @@ dhuopen(dev, flag, mode, p) int flag, mode; struct proc *p; { - register dhuregs *dhuaddr; register struct tty *tp; register int unit, line; struct dhu_softc *sc; @@ -368,33 +379,18 @@ dhuopen(dev, flag, mode, p) if (line >= sc->sc_type) return ENXIO; - tp = sc->sc_dhu[line].dhu_tty; - if (tp == NULL) { - - tp = sc->sc_dhu[line].dhu_tty = ttymalloc(); - if (tp == NULL) - return ENXIO; - - sc->sc_dhu[line].dhu_state = STATE_IDLE; - - sc->sc_dhu[line].dhu_txaddr = - uballoc((struct uba_softc *)sc->sc_dev.dv_parent, - tp->t_outq.c_cs, tp->t_outq.c_cn, 0); - - dhuaddr = sc->sc_addr; + s = spltty(); + DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); + sc->sc_dhu[line].dhu_modem = DHU_READ_WORD(DHU_UBA_STAT); + (void) splx(s); - s = spltty(); - dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line); - sc->sc_dhu[line].dhu_modem = dhuaddr->dhu_stat; - (void) splx(s); - } + tp = sc->sc_dhu[line].dhu_tty; tp->t_oproc = dhustart; tp->t_param = dhuparam; tp->t_hwiflow = dhuiflow; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { - tp->t_state |= TS_WOPEN; ttychars(tp); if (tp->t_ispeed == 0) { tp->t_iflag = TTYDEF_IFLAG; @@ -413,7 +409,6 @@ dhuopen(dev, flag, mode, p) s = spltty(); while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && !(tp->t_state & TS_CARR_ON)) { - tp->t_state |= TS_WOPEN; error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); if (error) @@ -451,9 +446,8 @@ dhuclose(dev, flag, mode, p) /* Do a hangup if so required. */ - if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || - !(tp->t_state & TS_ISOPEN)) - (void) dhumctl(sc, line, 0, DMSET); + if ((tp->t_cflag & HUPCL) || !(tp->t_state & TS_ISOPEN)) + (void) dhumctl(sc, line, 0, DMSET); return (ttyclose(tp)); } @@ -567,7 +561,6 @@ dhustop(tp, flag) register struct tty *tp; { register struct dhu_softc *sc; - register dhuregs *dhuaddr; register int line; int s; @@ -582,9 +575,10 @@ dhustop(tp, flag) sc->sc_dhu[line].dhu_state = STATE_DMA_STOPPED; - dhuaddr = sc->sc_addr; - dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line); - dhuaddr->dhu_lnctrl |= DHU_LNCTRL_DMA_ABORT; + DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); + DHU_WRITE_WORD(DHU_UBA_LNCTRL, + DHU_READ_WORD(DHU_UBA_LNCTRL) | + DHU_LNCTRL_DMA_ABORT); } if (!(tp->t_state & TS_TTSTOP)) @@ -598,7 +592,6 @@ dhustart(tp) register struct tty *tp; { register struct dhu_softc *sc; - register dhuregs *dhuaddr; register int line, cc; register int addr; int s; @@ -625,30 +618,32 @@ dhustart(tp) line = DHU_LINE(minor(tp->t_dev)); - dhuaddr = sc->sc_addr; - dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line); + DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); sc->sc_dhu[line].dhu_cc = cc; if (cc == 1) { sc->sc_dhu[line].dhu_state = STATE_TX_ONE_CHAR; - dhuaddr->dhu_txchar = DHU_TXCHAR_DATA_VALID | *tp->t_outq.c_cf; + + DHU_WRITE_WORD(DHU_UBA_TXCHAR, + DHU_TXCHAR_DATA_VALID | *tp->t_outq.c_cf); } else { sc->sc_dhu[line].dhu_state = STATE_DMA_RUNNING; - addr = UBAI_ADDR(sc->sc_dhu[line].dhu_txaddr) + + addr = sc->sc_dhu[line].dhu_dmah->dm_segs[0].ds_addr + (tp->t_outq.c_cf - tp->t_outq.c_cs); - dhuaddr->dhu_tbufcnt = cc; - dhuaddr->dhu_tbufad1 = (addr & 0xFFFF); - dhuaddr->dhu_tbufad2 = ((addr>>16) & 0x3F) | - DHU_TBUFAD2_TX_ENABLE; - - dhuaddr->dhu_lnctrl &= ~DHU_LNCTRL_DMA_ABORT; - dhuaddr->dhu_tbufad2 |= DHU_TBUFAD2_DMA_START; + DHU_WRITE_WORD(DHU_UBA_TBUFCNT, cc); + DHU_WRITE_WORD(DHU_UBA_TBUFAD1, addr & 0xFFFF); + DHU_WRITE_WORD(DHU_UBA_TBUFAD2, ((addr>>16) & 0x3F) | + DHU_TBUFAD2_TX_ENABLE); + DHU_WRITE_WORD(DHU_UBA_LNCTRL, + DHU_READ_WORD(DHU_UBA_LNCTRL) & ~DHU_LNCTRL_DMA_ABORT); + DHU_WRITE_WORD(DHU_UBA_TBUFAD2, + DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_DMA_START); } out: (void) splx(s); @@ -661,7 +656,6 @@ dhuparam(tp, t) register struct termios *t; { struct dhu_softc *sc; - register dhuregs *dhuaddr; register int cflag = t->c_cflag; int ispeed = ttspeedtab(t->c_ispeed, dhuspeedtab); int ospeed = ttspeedtab(t->c_ospeed, dhuspeedtab); @@ -688,8 +682,7 @@ dhuparam(tp, t) } s = spltty(); - dhuaddr = sc->sc_addr; - dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line); + DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); lpr = ((ispeed&017)<<8) | ((ospeed&017)<<12) ; @@ -719,11 +712,12 @@ dhuparam(tp, t) if (cflag & CSTOPB) lpr |= DHU_LPR_2_STOP; - dhuaddr->dhu_lpr = lpr; + DHU_WRITE_WORD(DHU_UBA_LPR, lpr); - dhuaddr->dhu_tbufad2 |= DHU_TBUFAD2_TX_ENABLE; + DHU_WRITE_WORD(DHU_UBA_TBUFAD2, + DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_TX_ENABLE); - lnctrl = dhuaddr->dhu_lnctrl; + lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL); /* Setting LINK.TYPE enables modem signal change interrupts. */ @@ -741,7 +735,7 @@ dhuparam(tp, t) else lnctrl &= ~DHU_LNCTRL_IAUTO; - dhuaddr->dhu_lnctrl = lnctrl; + DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl); (void) splx(s); return (0); @@ -768,7 +762,6 @@ dhumctl(sc, line, bits, how) struct dhu_softc *sc; int line, bits, how; { - register dhuregs *dhuaddr; register unsigned status; register unsigned lnctrl; register unsigned mbits; @@ -776,14 +769,13 @@ dhumctl(sc, line, bits, how) s = spltty(); - dhuaddr = sc->sc_addr; - dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line); + DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); mbits = 0; /* external signals as seen from the port */ - status = dhuaddr->dhu_stat; + status = DHU_READ_WORD(DHU_UBA_STAT); if (status & DHU_STAT_CTS) mbits |= DML_CTS; @@ -799,7 +791,7 @@ dhumctl(sc, line, bits, how) /* internal signals/state delivered to port */ - lnctrl = dhuaddr->dhu_lnctrl; + lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL); if (lnctrl & DHU_LNCTRL_RTS) mbits |= DML_RTS; @@ -844,7 +836,7 @@ dhumctl(sc, line, bits, how) else lnctrl &= ~DHU_LNCTRL_BREAK; - dhuaddr->dhu_lnctrl = lnctrl; + DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl); (void) splx(s); return (mbits); diff --git a/sys/arch/vax/uba/dhureg.h b/sys/arch/vax/qbus/dhureg.h index 9db5650a392..32b4291d87b 100644 --- a/sys/arch/vax/uba/dhureg.h +++ b/sys/arch/vax/qbus/dhureg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: dhureg.h,v 1.2 1997/05/29 00:05:05 niklas Exp $ */ -/* $NetBSD: dhureg.h,v 1.2 1996/03/17 22:51:50 ragge Exp $ */ +/* $OpenBSD: dhureg.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */ +/* $NetBSD: dhureg.h,v 1.4 1999/05/28 20:17:29 ragge Exp $ */ /* * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. * @@ -32,6 +32,7 @@ * SUCH DAMAGE. */ +#ifdef notdef union w_b { u_short word; @@ -59,6 +60,18 @@ struct DHUregs #define dhu_csr_hi u_csr.bytes.byte_hi typedef struct DHUregs dhuregs; +#endif + +#define DHU_UBA_CSR 0 +#define DHU_UBA_CSR_HI 1 +#define DHU_UBA_RBUF 2 +#define DHU_UBA_TXCHAR 2 +#define DHU_UBA_LPR 4 +#define DHU_UBA_STAT 6 +#define DHU_UBA_LNCTRL 8 +#define DHU_UBA_TBUFAD1 10 +#define DHU_UBA_TBUFAD2 12 +#define DHU_UBA_TBUFCNT 14 /* CSR bits */ diff --git a/sys/arch/vax/uba/dl.c b/sys/arch/vax/qbus/dl.c index 80c8be5d5ad..7bd7d71859c 100644 --- a/sys/arch/vax/uba/dl.c +++ b/sys/arch/vax/qbus/dl.c @@ -1,9 +1,45 @@ -/* $OpenBSD: dl.c,v 1.2 1998/05/11 14:59:05 niklas Exp $ */ -/* $NetBSD: dl.c,v 1.1 1997/02/04 19:13:18 ragge Exp $ */ +/* $OpenBSD: dl.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */ +/* $NetBSD: dl.c,v 1.11 2000/01/24 02:40:29 matt Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + /* * Copyright (c) 1997 Ben Harris. All rights reserved. * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. - * Copyright (c) 1995, 1996 Jason R. Thorpe. All rights reserved. * Copyright (c) 1982, 1986, 1990, 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -59,27 +95,23 @@ #include <sys/syslog.h> #include <sys/device.h> -#include <machine/pte.h> -#include <machine/trap.h> - -#include <vax/uba/ubareg.h> -#include <vax/uba/ubavar.h> +#include <machine/bus.h> +#include <machine/scb.h> -#include <vax/uba/dlreg.h> - -#define DL_I2C(i) (i) -#define DL_C2I(c) (c) +#include <arch/vax/qbus/ubavar.h> +#include <arch/vax/qbus/dlreg.h> struct dl_softc { struct device sc_dev; - dlregs* sc_addr; - struct tty* sc_tty; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + struct tty *sc_tty; }; -static int dl_match __P((struct device *, void *, void *)); +static int dl_match __P((struct device *, struct cfdata *, void *)); static void dl_attach __P((struct device *, struct device *, void *)); -static void dlrint __P((int)); -static void dlxint __P((int)); +static void dlrint __P((void *)); +static void dlxint __P((void *)); static void dlstart __P((struct tty *)); static int dlparam __P((struct tty *, struct termios *)); static void dlbrk __P((struct dl_softc *, int)); @@ -91,35 +123,43 @@ struct tty * dltty __P((dev_t)); int dlioctl __P((dev_t, int, caddr_t, int, struct proc *)); void dlstop __P((struct tty *, int)); -struct cfdriver dl_cd = { - NULL, "dl", DV_TTY +struct cfattach dl_ca = { + sizeof(struct dl_softc), (cfmatch_t)dl_match, dl_attach }; -struct cfattach dl_ca = { - sizeof(struct dl_softc), dl_match, dl_attach +struct cfdriver dl_cd = { + NULL, "dl", DV_TTY }; +#define DL_READ_WORD(reg) \ + bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg) +#define DL_WRITE_WORD(reg, val) \ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val) +#define DL_WRITE_BYTE(reg, val) \ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val) + /* Autoconfig handles: setup the controller to interrupt, */ /* then complete the housecleaning for full operation */ static int -dl_match (parent, match, aux) +dl_match (parent, cf, aux) struct device * parent; - void *match, *aux; + struct cfdata *cf; + void *aux; { struct uba_attach_args *ua = aux; - register dlregs *dladdr; - dladdr = (dlregs*) ua->ua_addr; #ifdef DL_DEBUG - printf("Probing for dl at %lo ... ", (long)dladdr); + printf("Probing for dl at %lo ... ", (long)ua->ua_iaddr); #endif - dladdr->dl_xcsr = DL_XCSR_TXIE; - if (dladdr->dl_xcsr != (DL_XCSR_TXIE | DL_XCSR_TX_READY)) { + bus_space_write_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR, DL_XCSR_TXIE); + if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) != + (DL_XCSR_TXIE | DL_XCSR_TX_READY)) { #ifdef DL_DEBUG - printf("failed (step 1; XCSR = %.4b)\n", dladdr->dl_xcsr, - DL_XCSR_BITS); + printf("failed (step 1; XCSR = %.4b)\n", + bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR), + DL_XCSR_BITS); #endif return 0; } @@ -132,7 +172,7 @@ dl_match (parent, match, aux) * anything. */ - dladdr->u_xbuf.bytes.byte_lo = '\0'; + bus_space_write_1(ua->ua_iot, ua->ua_ioh, DL_UBA_XBUFL, '\0'); #if 0 /* This test seems to fail 2/3 of the time :-( */ if (dladdr->dl_xcsr != (DL_XCSR_TXIE)) { #ifdef DL_DEBUG @@ -143,16 +183,16 @@ dl_match (parent, match, aux) } #endif DELAY(100000); /* delay 1/10 s for character to transmit */ - if (dladdr->dl_xcsr != (DL_XCSR_TXIE | DL_XCSR_TX_READY)) { + if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) != + (DL_XCSR_TXIE | DL_XCSR_TX_READY)) { #ifdef DL_DEBUG - printf("failed (step 3; XCSR = %.4b)\n", dladdr->dl_xcsr, - DL_XCSR_BITS); + printf("failed (step 3; XCSR = %.4b)\n", + bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR), + DL_XCSR_BITS); #endif return 0; } - /* Register the TX interrupt handler */ - ua->ua_ivec = dlxint; /* What else do I need to do? */ @@ -165,47 +205,42 @@ dl_attach (parent, self, aux) struct device *parent, *self; void *aux; { - struct uba_softc *uh = (void *)parent; struct dl_softc *sc = (void *)self; register struct uba_attach_args *ua = aux; - register dlregs *dladdr; - dladdr = (dlregs *) ua->ua_addr; - sc->sc_addr = dladdr; + sc->sc_iot = ua->ua_iot; + sc->sc_ioh = ua->ua_ioh; /* Tidy up the device */ - dladdr->dl_rcsr = DL_RCSR_RXIE; - dladdr->dl_xcsr = DL_XCSR_TXIE; + DL_WRITE_WORD(DL_UBA_RCSR, DL_RCSR_RXIE); + DL_WRITE_WORD(DL_UBA_XCSR, DL_XCSR_TXIE); /* Initialize our softc structure. Should be done in open? */ sc->sc_tty = ttymalloc(); tty_attach(sc->sc_tty); - /* Now register the RX interrupt handler */ - ubasetvec(self, ua->ua_cvec-1, dlrint); + /* Now register the TX & RX interrupt handlers */ + uba_intr_establish(ua->ua_icookie, ua->ua_cvec , dlxint, sc); + uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4, dlrint, sc); printf("\n"); - return; } /* Receiver Interrupt Handler */ static void -dlrint(cntlr) - int cntlr; +dlrint(arg) + void *arg; { - struct dl_softc *sc = dl_cd.cd_devs[cntlr]; - volatile dlregs *dladdr; + struct dl_softc *sc = arg; register struct tty *tp; register int cc; register unsigned c; - dladdr = sc->sc_addr; - - if (dladdr->dl_rcsr & DL_RCSR_RX_DONE) { - c = dladdr->dl_rbuf; + if (DL_READ_WORD(DL_UBA_RCSR) & DL_RCSR_RX_DONE) { + c = DL_READ_WORD(DL_UBA_RBUF); cc = c & 0xFF; tp = sc->sc_tty; @@ -236,14 +271,12 @@ dlrint(cntlr) /* Transmitter Interrupt Handler */ static void -dlxint(cntlr) - int cntlr; +dlxint(arg) + void *arg; { - struct dl_softc *sc = dl_cd.cd_devs[cntlr]; - volatile dlregs *dladdr; + struct dl_softc *sc = arg; register struct tty *tp; - dladdr = sc->sc_addr; tp = sc->sc_tty; tp->t_state &= ~(TS_BUSY | TS_FLUSH); if (tp->t_line) @@ -263,9 +296,8 @@ dlopen(dev, flag, mode, p) register struct tty *tp; register int unit; struct dl_softc *sc; - int s, error = 0; - unit = DL_I2C(minor(dev)); + unit = minor(dev); if (unit >= dl_cd.cd_ndevs || dl_cd.cd_devs[unit] == NULL) return ENXIO; @@ -279,7 +311,6 @@ dlopen(dev, flag, mode, p) tp->t_dev = dev; if (!(tp->t_state & TS_ISOPEN)) { - tp->t_state |= TS_WOPEN; ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; @@ -308,7 +339,7 @@ dlclose(dev, flag, mode, p) register struct tty *tp; register int unit; - unit = DL_I2C(minor(dev)); + unit = minor(dev); sc = dl_cd.cd_devs[unit]; tp = sc->sc_tty; @@ -330,7 +361,7 @@ dlread(dev, uio, flag) struct dl_softc *sc; register int unit; - unit = DL_I2C(minor(dev)); + unit = minor(dev); sc = dl_cd.cd_devs[unit]; tp = sc->sc_tty; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); @@ -346,7 +377,7 @@ dlwrite(dev, uio, flag) struct dl_softc *sc; register int unit; - unit = DL_I2C(minor(dev)); + unit = minor(dev); sc = dl_cd.cd_devs[unit]; tp = sc->sc_tty; return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); @@ -365,7 +396,7 @@ dlioctl(dev, cmd, data, flag, p) register int unit; int error; - unit = DL_I2C(minor(dev)); + unit = minor(dev); sc = dl_cd.cd_devs[unit]; tp = sc->sc_tty; @@ -403,7 +434,7 @@ dltty(dev) { register struct dl_softc* sc; - sc = dl_cd.cd_devs[DL_I2C(minor(dev))]; + sc = dl_cd.cd_devs[minor(dev)]; return sc->sc_tty; } @@ -415,7 +446,7 @@ dlstop(tp, flag) register struct dl_softc *sc; int unit, s; - unit = DL_I2C(minor(tp->t_dev)); + unit = minor(tp->t_dev); sc = dl_cd.cd_devs[unit]; s = spltty(); @@ -431,11 +462,10 @@ dlstart(tp) register struct tty *tp; { register struct dl_softc *sc; - register dlregs *dladdr; - register int unit, cc; + register int unit; int s; - unit = DL_I2C(minor(tp->t_dev)); + unit = minor(tp->t_dev); sc = dl_cd.cd_devs[unit]; s = spltty(); @@ -451,11 +481,10 @@ dlstart(tp) if (tp->t_outq.c_cc == 0) goto out; - dladdr = sc->sc_addr; - if (dladdr->dl_xcsr & DL_XCSR_TX_READY) { + if (DL_READ_WORD(DL_UBA_XCSR) & DL_XCSR_TX_READY) { tp->t_state |= TS_BUSY; - dladdr->u_xbuf.bytes.byte_lo = getc(&tp->t_outq); + DL_WRITE_BYTE(DL_UBA_XBUFL, getc(&tp->t_outq)); } out: splx(s); @@ -481,13 +510,14 @@ dlbrk(sc, state) register struct dl_softc *sc; int state; { - register dlregs *dladdr; - int s; - dladdr = sc->sc_addr; - s = spltty(); - if (state) - dladdr->dl_xcsr |= DL_XCSR_TX_BREAK; - else - dladdr->dl_xcsr &= ~DL_XCSR_TX_BREAK; + int s = spltty(); + + if (state) { + DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) | + DL_XCSR_TX_BREAK); + } else { + DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) & + ~DL_XCSR_TX_BREAK); + } splx(s); } diff --git a/sys/arch/vax/uba/dlreg.h b/sys/arch/vax/qbus/dlreg.h index 120b283fb75..42462cb38e2 100644 --- a/sys/arch/vax/uba/dlreg.h +++ b/sys/arch/vax/qbus/dlreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: dlreg.h,v 1.2 1998/05/11 14:59:06 niklas Exp $ */ -/* $NetBSD: dlreg.h,v 1.1 1997/02/04 19:13:19 ragge Exp $ */ +/* $OpenBSD: dlreg.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */ +/* $NetBSD: dlreg.h,v 1.3 1999/05/27 16:02:04 ragge Exp $ */ /* * Copyright (c) 1997 Ben Harris. All rights reserved. * @@ -37,6 +37,7 @@ * Style in imitation of dzreg.h. */ +#ifdef notdef union w_b { u_short word; @@ -56,6 +57,12 @@ struct DLregs }; typedef struct DLregs dlregs; +#endif + +#define DL_UBA_RCSR 0 +#define DL_UBA_RBUF 2 +#define DL_UBA_XCSR 4 +#define DL_UBA_XBUFL 6 /* RCSR bits */ diff --git a/sys/arch/vax/uba/dz.c b/sys/arch/vax/qbus/dz.c index 9792b1521b9..a22b0daeaba 100644 --- a/sys/arch/vax/uba/dz.c +++ b/sys/arch/vax/qbus/dz.c @@ -1,5 +1,5 @@ -/* $OpenBSD: dz.c,v 1.3 1997/05/29 00:05:06 niklas Exp $ */ -/* $NetBSD: dz.c,v 1.4 1996/10/13 03:35:15 christos Exp $ */ +/* $OpenBSD: dz.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */ +/* $NetBSD: dz.c,v 1.19 2000/01/24 02:40:29 matt Exp $ */ /* * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. * Copyright (c) 1992, 1993 @@ -51,13 +51,26 @@ #include <sys/syslog.h> #include <sys/device.h> +#ifdef DDB +#include <dev/cons.h> +#endif + +#include <machine/bus.h> #include <machine/pte.h> #include <machine/trap.h> +#include <machine/cpu.h> -#include <vax/uba/ubareg.h> -#include <vax/uba/ubavar.h> +#include <arch/vax/qbus/dzreg.h> +#include <arch/vax/qbus/dzvar.h> -#include <vax/uba/dzreg.h> +#define DZ_READ_BYTE(adr) \ + bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr) +#define DZ_READ_WORD(adr) \ + bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr) +#define DZ_WRITE_BYTE(adr, val) \ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val) +#define DZ_WRITE_WORD(adr, val) \ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val) /* A DZ-11 has 8 ports while a DZV/DZQ-11 has only 4. We use 8 by default */ @@ -67,19 +80,6 @@ #define DZ_I2C(c) ((c)>>3) /* convert minor to controller # */ #define DZ_PORT(u) ((u)&07) /* extract the port # */ -struct dz_softc { - struct device sc_dev; /* Autoconf blaha */ - dzregs * sc_addr; /* controller reg address */ - int sc_type; /* DZ11 or DZV11? */ - int sc_rxint; /* Receive interrupt count XXX */ - u_char sc_brk; /* Break asserted on some lines */ - struct { - struct tty * dz_tty; /* what we work on */ - caddr_t dz_mem; /* pointers to clist output */ - caddr_t dz_end; /* allowing pdma action */ - } sc_dz[NDZLINE]; -}; - /* Flags used to monitor modem bits, make them understood outside driver */ #define DML_DTR TIOCM_DTR @@ -105,142 +105,65 @@ static struct speedtab dzspeedtab[] = { 4800, DZ_LPR_B4800 }, { 7200, DZ_LPR_B7200 }, { 9600, DZ_LPR_B9600 }, + { 19200, DZ_LPR_B19200 }, { -1, -1 } }; -static int dz_match __P((struct device *, void *, void *)); -static void dz_attach __P((struct device *, struct device *, void *)); -static void dzrint __P((int)); -static void dzxint __P((int)); static void dzstart __P((struct tty *)); static int dzparam __P((struct tty *, struct termios *)); static unsigned dzmctl __P((struct dz_softc *, int, int, int)); static void dzscan __P((void *)); -struct tty * dztty __P((dev_t)); - int dzopen __P((dev_t, int, int, struct proc *)); - int dzclose __P((dev_t, int, int, struct proc *)); - int dzread __P((dev_t, struct uio *, int)); - int dzwrite __P((dev_t, struct uio *, int)); - int dzioctl __P((dev_t, int, caddr_t, int, struct proc *)); - void dzstop __P((struct tty *, int)); struct cfdriver dz_cd = { NULL, "dz", DV_TTY }; -struct cfattach dz_ca = { - sizeof(struct dz_softc), dz_match, dz_attach -}; - +cdev_decl(dz); /* * The DZ series doesn't interrupt on carrier transitions, * so we have to use a timer to watch it. */ -static int dz_timer = 0; /* true if timer started */ +int dz_timer = 0; /* true if timer started */ #define DZ_DZ 8 /* Unibus DZ-11 board linecount */ #define DZ_DZV 4 /* Q-bus DZV-11 or DZQ-11 */ -/* Autoconfig handles: setup the controller to interrupt, */ -/* then complete the housecleaning for full operation */ - -static int -dz_match (parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct uba_attach_args *ua = aux; - register dzregs *dzaddr; - register int n; - - dzaddr = (dzregs *) ua->ua_addr; - - /* Reset controller to initialize, enable TX interrupts */ - /* to catch floating vector info elsewhere when completed */ - - dzaddr->dz_csr = (DZ_CSR_MSE | DZ_CSR_TXIE); - dzaddr->dz_tcr = 1; /* Force a TX interrupt */ - - DELAY(100000); /* delay 1/10 second */ - - dzaddr->dz_csr = DZ_CSR_RESET; - - /* Now wait up to 3 seconds for reset/clear to complete. */ - - for (n = 0; n < 300; n++) { - DELAY(10000); - if ((dzaddr->dz_csr & DZ_CSR_RESET) == 0) - break; - } - - /* If the RESET did not clear after 3 seconds, */ - /* the controller must be broken. */ - - if (n >= 300) - return (0); - - /* Register the TX interrupt handler */ - - ua->ua_ivec = dzxint; - - return (1); -} - -static void -dz_attach (parent, self, aux) - struct device *parent, *self; - void *aux; +void +dzattach(sc) + struct dz_softc *sc; { - struct uba_softc *uh = (void *)parent; - struct dz_softc *sc = (void *)self; - register struct uba_attach_args *ua = aux; - register dzregs *dzaddr; register int n; - dzaddr = (dzregs *) ua->ua_addr; - sc->sc_addr = dzaddr; - -#ifdef QBA - if (uh->uh_type == QBA) - sc->sc_type = DZ_DZV; - else -#endif - sc->sc_type = DZ_DZ; - sc->sc_rxint = sc->sc_brk = 0; - dzaddr->dz_csr = (DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE); - dzaddr->dz_dtr = 0; /* Make sure DTR bits are zero */ - dzaddr->dz_break = 0; /* Status of BREAK bits, all off */ + sc->sc_dr.dr_tcrw = sc->sc_dr.dr_tcr; + DZ_WRITE_WORD(dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE); + DZ_WRITE_BYTE(dr_dtr, 0); + DZ_WRITE_BYTE(dr_break, 0); /* Initialize our softc structure. Should be done in open? */ for (n = 0; n < sc->sc_type; n++) sc->sc_dz[n].dz_tty = ttymalloc(); - /* Now register the RX interrupt handler */ - ubasetvec(self, ua->ua_cvec-1, dzrint); - /* Alas no interrupt on modem bit changes, so we manually scan */ if (dz_timer == 0) { dz_timer = 1; timeout(dzscan, (void *)0, hz); } - printf("\n"); return; } /* Receiver Interrupt */ -static void -dzrint(cntlr) - int cntlr; +void +dzrint(arg) + void *arg; { - struct dz_softc *sc = dz_cd.cd_devs[cntlr]; - volatile dzregs *dzaddr; + struct dz_softc *sc = arg; register struct tty *tp; register int cc, line; register unsigned c; @@ -248,13 +171,15 @@ dzrint(cntlr) sc->sc_rxint++; - dzaddr = sc->sc_addr; - - while ((c = dzaddr->dz_rbuf) & DZ_RBUF_DATA_VALID) { + while ((c = DZ_READ_WORD(dr_rbuf)) & DZ_RBUF_DATA_VALID) { cc = c & 0xFF; line = DZ_PORT(c>>8); tp = sc->sc_dz[line].dz_tty; + /* Must be caught early */ + if (sc->sc_catch && (*sc->sc_catch)(line, cc)) + continue; + if (!(tp->t_state & TS_ISOPEN)) { wakeup((caddr_t)&tp->t_rawq); continue; @@ -265,30 +190,39 @@ dzrint(cntlr) sc->sc_dev.dv_xname, line); overrun = 1; } + /* A BREAK key will appear as a NULL with a framing error */ if (c & DZ_RBUF_FRAMING_ERR) cc |= TTY_FE; if (c & DZ_RBUF_PARITY_ERR) cc |= TTY_PE; +#if defined(DDB) && (defined(VAX410) || defined(VAX43) || defined(VAX46)) + if (tp->t_dev == cn_tab->cn_dev) { + int j = kdbrint(cc); + + if (j == 1) /* Escape received, just return */ + continue; + + if (j == 2) /* Second char wasn't 'D' */ + (*linesw[tp->t_line].l_rint)(27, tp); + } +#endif (*linesw[tp->t_line].l_rint)(cc, tp); } - return; } /* Transmitter Interrupt */ -static void -dzxint(cntlr) - int cntlr; +void +dzxint(arg) + void *arg; { - volatile dzregs *dzaddr; - register struct dz_softc *sc = dz_cd.cd_devs[cntlr]; + register struct dz_softc *sc = arg; register struct tty *tp; - register unsigned csr; - register int line; - - dzaddr = sc->sc_addr; + register struct clist *cl; + register int line, ch, csr; + u_char tcr; /* * Switch to POLLED mode. @@ -302,54 +236,45 @@ dzxint(cntlr) * Each UART is double buffered, so if the scanner * is quick enough and timing works out, we can even * feed the same port twice. + * + * Ragge 980517: + * Do not need to turn off interrupts, already at interrupt level. + * Remove the pdma stuff; no great need of it right now. */ - dzaddr->dz_csr &= ~(DZ_CSR_TXIE); - - while (((csr = dzaddr->dz_csr) & DZ_CSR_TX_READY) != 0) { + while (((csr = DZ_READ_WORD(dr_csr)) & DZ_CSR_TX_READY) != 0) { line = DZ_PORT(csr>>8); - if (sc->sc_dz[line].dz_mem < sc->sc_dz[line].dz_end) { - dzaddr->dz_tbuf = *sc->sc_dz[line].dz_mem++; - continue; - } - - /* - * Turn off this TX port as all pending output - * has been completed - thus freeing the scanner - * on the controller to hopefully find another - * pending TX operation we can service now. - * (avoiding the overhead of another interrupt) - */ - - dzaddr->dz_tcr &= ~(1 << line); - tp = sc->sc_dz[line].dz_tty; - + cl = &tp->t_outq; tp->t_state &= ~TS_BUSY; + /* Just send out a char if we have one */ + /* As long as we can fill the chip buffer, we just loop here */ + if (cl->c_cc) { + tp->t_state |= TS_BUSY; + ch = getc(cl); + DZ_WRITE_BYTE(dr_tbuf, ch); + continue; + } + /* Nothing to send; clear the scan bit */ + /* Clear xmit scanner bit; dzstart may set it again */ + tcr = DZ_READ_WORD(dr_tcrw); + tcr &= 255; + tcr &= ~(1 << line); + DZ_WRITE_BYTE(dr_tcr, tcr); + if (tp->t_state & TS_FLUSH) tp->t_state &= ~TS_FLUSH; - else { - ndflush (&tp->t_outq, (sc->sc_dz[line].dz_mem - - (caddr_t)tp->t_outq.c_cf)); - sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem = - tp->t_outq.c_cf; - } + else + ndflush (&tp->t_outq, cl->c_cc); if (tp->t_line) (*linesw[tp->t_line].l_start)(tp); else dzstart(tp); } - - /* - * Re-enable TX interrupts. - */ - - dzaddr->dz_csr |= (DZ_CSR_TXIE); - return; } int @@ -365,7 +290,6 @@ dzopen(dev, flag, mode, p) unit = DZ_I2C(minor(dev)); line = DZ_PORT(minor(dev)); - if (unit >= dz_cd.cd_ndevs || dz_cd.cd_devs[unit] == NULL) return (ENXIO); @@ -381,7 +305,6 @@ dzopen(dev, flag, mode, p) tp->t_param = dzparam; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { - tp->t_state |= TS_WOPEN; ttychars(tp); if (tp->t_ispeed == 0) { tp->t_iflag = TTYDEF_IFLAG; @@ -400,7 +323,6 @@ dzopen(dev, flag, mode, p) s = spltty(); while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && !(tp->t_state & TS_CARR_ON)) { - tp->t_state |= TS_WOPEN; error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); if (error) @@ -414,7 +336,7 @@ dzopen(dev, flag, mode, p) /*ARGSUSED*/ int -dzclose (dev, flag, mode, p) +dzclose(dev, flag, mode, p) dev_t dev; int flag, mode; struct proc *p; @@ -436,8 +358,7 @@ dzclose (dev, flag, mode, p) (void) dzmctl(sc, line, DML_BRK, DMBIC); /* Do a hangup if so required. */ - if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || - !(tp->t_state & TS_ISOPEN)) + if ((tp->t_cflag & HUPCL) || !(tp->t_state & TS_ISOPEN)) (void) dzmctl(sc, line, 0, DMSET); return (ttyclose(tp)); @@ -475,7 +396,7 @@ dzwrite (dev, uio, flag) int dzioctl (dev, cmd, data, flag, p) dev_t dev; - int cmd; + u_long cmd; caddr_t data; int flag; struct proc *p; @@ -548,36 +469,23 @@ dztty (dev) } /*ARGSUSED*/ -void +int dzstop(tp, flag) register struct tty *tp; { - register struct dz_softc *sc; - int unit, line, s; - - unit = DZ_I2C(minor(tp->t_dev)); - line = DZ_PORT(minor(tp->t_dev)); - sc = dz_cd.cd_devs[unit]; - - s = spltty(); - - if (tp->t_state & TS_BUSY) { - sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem; + if (tp->t_state & TS_BUSY) if (!(tp->t_state & TS_TTSTOP)) tp->t_state |= TS_FLUSH; - } - (void) splx(s); } -static void -dzstart (tp) +void +dzstart(tp) register struct tty *tp; { register struct dz_softc *sc; - register dzregs *dzaddr; - register int unit, line; - register int cc; - int s; + register struct clist *cl; + register int unit, line, s; + char state; unit = DZ_I2C(minor(tp->t_dev)); line = DZ_PORT(minor(tp->t_dev)); @@ -585,31 +493,26 @@ dzstart (tp) s = spltty(); if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) - goto out; - if (tp->t_outq.c_cc <= tp->t_lowat) { + return; + cl = &tp->t_outq; + if (cl->c_cc <= tp->t_lowat) { if (tp->t_state & TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; - wakeup((caddr_t)&tp->t_outq); + wakeup((caddr_t)cl); } selwakeup(&tp->t_wsel); } - if (tp->t_outq.c_cc == 0) - goto out; - cc = ndqb(&tp->t_outq, 0); - if (cc == 0) - goto out; + if (cl->c_cc == 0) + return; tp->t_state |= TS_BUSY; - dzaddr = sc->sc_addr; - - sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem = tp->t_outq.c_cf; - sc->sc_dz[line].dz_end += cc; - dzaddr->dz_tcr |= (1 << line); /* Enable this TX port */ - -out: - (void) splx(s); - return; + state = DZ_READ_WORD(dr_tcrw) & 255; + if ((state & (1 << line)) == 0) { + DZ_WRITE_BYTE(dr_tcr, state | (1 << line)); + } + dzxint(sc); + splx(s); } static int @@ -618,7 +521,6 @@ dzparam(tp, t) register struct termios *t; { struct dz_softc *sc; - register dzregs *dzaddr; register int cflag = t->c_cflag; int unit, line; int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab); @@ -644,7 +546,6 @@ dzparam(tp, t) } s = spltty(); - dzaddr = sc->sc_addr; lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line; @@ -670,7 +571,7 @@ dzparam(tp, t) if (cflag & CSTOPB) lpr |= DZ_LPR_2_STOP; - dzaddr->dz_lpr = lpr; + DZ_WRITE_WORD(dr_lpr, lpr); (void) splx(s); return (0); @@ -681,7 +582,6 @@ dzmctl(sc, line, bits, how) register struct dz_softc *sc; int line, bits, how; { - register dzregs *dzaddr; register unsigned status; register unsigned mbits; register unsigned bit; @@ -689,27 +589,25 @@ dzmctl(sc, line, bits, how) s = spltty(); - dzaddr = sc->sc_addr; - mbits = 0; bit = (1 << line); /* external signals as seen from the port */ - status = dzaddr->dz_dcd; + status = DZ_READ_BYTE(dr_dcd) | sc->sc_dsr; if (status & bit) mbits |= DML_DCD; - status = dzaddr->dz_ring; + status = DZ_READ_BYTE(dr_ring); if (status & bit) mbits |= DML_RI; /* internal signals/state delivered to port */ - status = dzaddr->dz_dtr; + status = DZ_READ_BYTE(dr_dtr); if (status & bit) mbits |= DML_DTR; @@ -736,15 +634,19 @@ dzmctl(sc, line, bits, how) return (mbits); } - if (mbits & DML_DTR) - dzaddr->dz_dtr |= bit; - else - dzaddr->dz_dtr &= ~bit; + if (mbits & DML_DTR) { + DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) | bit); + } else { + DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) & ~bit); + } - if (mbits & DML_BRK) - dzaddr->dz_break = (sc->sc_brk |= bit); - else - dzaddr->dz_break = (sc->sc_brk &= ~bit); + if (mbits & DML_BRK) { + sc->sc_brk |= bit; + DZ_WRITE_BYTE(dr_break, sc->sc_brk); + } else { + sc->sc_brk &= ~bit; + DZ_WRITE_BYTE(dr_break, sc->sc_brk); + } (void) splx(s); return (mbits); @@ -758,7 +660,6 @@ static void dzscan(arg) void *arg; { - register dzregs *dzaddr; register struct dz_softc *sc; register struct tty *tp; register int n, bit, port; @@ -776,18 +677,17 @@ dzscan(arg) for (port = 0; port < sc->sc_type; port++) { - dzaddr = sc->sc_addr; tp = sc->sc_dz[port].dz_tty; bit = (1 << port); - if (dzaddr->dz_dcd & bit) { /* carrier present */ - + if ((DZ_READ_BYTE(dr_dcd) | sc->sc_dsr) & bit) { if (!(tp->t_state & TS_CARR_ON)) - (void)(*linesw[tp->t_line].l_modem) - (tp, 1); + (*linesw[tp->t_line].l_modem) (tp, 1); } else if ((tp->t_state & TS_CARR_ON) && - (*linesw[tp->t_line].l_modem)(tp, 0) == 0) - dzaddr->dz_tcr &= ~bit; + (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { + DZ_WRITE_BYTE(dr_tcr, + (DZ_READ_WORD(dr_tcrw) & 255) & ~bit); + } } /* @@ -799,16 +699,14 @@ dzscan(arg) * if off unless the rate is appropriately low. */ - dzaddr = sc->sc_addr; - - csr = dzaddr->dz_csr; + csr = DZ_READ_WORD(dr_csr); if (sc->sc_rxint > (16*10)) { if ((csr & DZ_CSR_SAE) == 0) - dzaddr->dz_csr = (csr | DZ_CSR_SAE); + DZ_WRITE_WORD(dr_csr, csr | DZ_CSR_SAE); } else if ((csr & DZ_CSR_SAE) != 0) if (sc->sc_rxint < 10) - dzaddr->dz_csr = (csr & ~(DZ_CSR_SAE)); + DZ_WRITE_WORD(dr_csr, csr & ~(DZ_CSR_SAE)); sc->sc_rxint = 0; } diff --git a/sys/arch/vax/qbus/dz_uba.c b/sys/arch/vax/qbus/dz_uba.c new file mode 100644 index 00000000000..d9595840a52 --- /dev/null +++ b/sys/arch/vax/qbus/dz_uba.c @@ -0,0 +1,137 @@ +/* $OpenBSD: dz_uba.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */ +/* $NetBSD: dz_uba.c,v 1.8 2000/01/24 02:40:29 matt Exp $ */ +/* + * Copyright (c) 1998 Ludd, University of Lule}, Sweden. All rights reserved. + * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/map.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/syslog.h> +#include <sys/device.h> + +#include <machine/bus.h> +#include <machine/pte.h> +#include <machine/trap.h> +#include <machine/scb.h> + +#include <arch/vax/qbus/ubavar.h> + +#include <arch/vax/qbus/dzreg.h> +#include <arch/vax/qbus/dzvar.h> + +static int dz_uba_match __P((struct device *, struct cfdata *, void *)); +static void dz_uba_attach __P((struct device *, struct device *, void *)); + +struct cfattach dz_uba_ca = { + sizeof(struct dz_softc), (cfmatch_t)dz_uba_match, dz_uba_attach +}; + +/* Autoconfig handles: setup the controller to interrupt, */ +/* then complete the housecleaning for full operation */ + +static int +dz_uba_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct uba_attach_args *ua = aux; + bus_space_tag_t iot = ua->ua_iot; + bus_space_handle_t ioh = ua->ua_ioh; + register int n; + + iot = iot; /* Silly GCC */ + /* Reset controller to initialize, enable TX interrupts */ + /* to catch floating vector info elsewhere when completed */ + + bus_space_write_2(iot, ioh, DZ_UBA_CSR, DZ_CSR_MSE | DZ_CSR_TXIE); + bus_space_write_1(iot, ioh, DZ_UBA_TCR, 1); + + DELAY(100000); /* delay 1/10 second */ + + bus_space_write_2(iot, ioh, DZ_UBA_CSR, DZ_CSR_RESET); + + /* Now wait up to 3 seconds for reset/clear to complete. */ + + for (n = 0; n < 300; n++) { + DELAY(10000); + if ((bus_space_read_2(iot, ioh, DZ_UBA_CSR)&DZ_CSR_RESET) == 0) + break; + } + + /* If the RESET did not clear after 3 seconds, */ + /* the controller must be broken. */ + + if (n >= 300) + return (0); + + /* Register the TX interrupt handler */ + + + return (1); +} + +static void +dz_uba_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct dz_softc *sc = (void *)self; + register struct uba_attach_args *ua = aux; + + sc->sc_iot = ua->ua_iot; + sc->sc_ioh = ua->ua_ioh; + + sc->sc_dr.dr_csr = DZ_UBA_CSR; + sc->sc_dr.dr_rbuf = DZ_UBA_RBUF; + sc->sc_dr.dr_dtr = DZ_UBA_DTR; + sc->sc_dr.dr_break = DZ_UBA_BREAK; + sc->sc_dr.dr_tbuf = DZ_UBA_TBUF; + sc->sc_dr.dr_tcr = DZ_UBA_TCR; + sc->sc_dr.dr_dcd = DZ_UBA_DCD; + sc->sc_dr.dr_ring = DZ_UBA_RING; + + sc->sc_type = DZ_DZ; + + /* Now register the TX & RX interrupt handlers */ + uba_intr_establish(ua->ua_icookie, ua->ua_cvec, dzxint, sc); + uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4, dzrint, sc); + + dzattach(sc); +} diff --git a/sys/arch/vax/uba/dzreg.h b/sys/arch/vax/qbus/dzreg.h index ee4237a75c8..8f046c50fa0 100644 --- a/sys/arch/vax/uba/dzreg.h +++ b/sys/arch/vax/qbus/dzreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: dzreg.h,v 1.2 1997/05/29 00:05:06 niklas Exp $ */ -/* $NetBSD: dzreg.h,v 1.1 1996/04/08 17:22:21 ragge Exp $ */ +/* $OpenBSD: dzreg.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */ +/* $NetBSD: dzreg.h,v 1.4 1999/05/27 16:03:13 ragge Exp $ */ /* * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. * @@ -8,28 +8,19 @@ * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ union w_b @@ -60,6 +51,43 @@ struct DZregs typedef struct DZregs dzregs; +#if 0 +struct dz_regs { + volatile unsigned short *dr_csr; + volatile unsigned short *dr_rbuf; +#define dr_lpr dr_rbuf + volatile unsigned char *dr_dtr; + volatile unsigned char *dr_break; + volatile unsigned char *dr_tbuf; + volatile unsigned char *dr_tcr; + volatile unsigned short *dr_tcrw; + volatile unsigned char *dr_ring; + volatile unsigned char *dr_dcd; +}; +#else +struct dz_regs { + bus_addr_t dr_csr; + bus_addr_t dr_rbuf; +#define dr_lpr dr_rbuf + bus_addr_t dr_dtr; + bus_addr_t dr_break; + bus_addr_t dr_tbuf; + bus_addr_t dr_tcr; + bus_addr_t dr_tcrw; + bus_addr_t dr_ring; + bus_addr_t dr_dcd; +}; +#define DZ_UBA_CSR 0 +#define DZ_UBA_RBUF 2 +#define DZ_UBA_DTR 5 +#define DZ_UBA_BREAK 7 +#define DZ_UBA_TBUF 6 +#define DZ_UBA_TCR 4 +#define DZ_UBA_DCD 7 +#define DZ_UBA_RING 6 + +#endif + /* CSR bits */ #define DZ_CSR_TX_READY 0100000 /* Transmitter Ready */ @@ -103,7 +131,7 @@ typedef struct DZregs dzregs; #define DZ_LPR_B4800 0xC #define DZ_LPR_B7200 0xD #define DZ_LPR_B9600 0xE -#define DZ_LPR_ILLEGAL 0xF +#define DZ_LPR_B19200 0xF #define DZ_LPR_OPAR 0000200 #define DZ_LPR_PARENB 0000100 diff --git a/sys/arch/vax/uba/udareg.h b/sys/arch/vax/qbus/dzvar.h index 20c0b995b15..ae183c5f901 100644 --- a/sys/arch/vax/uba/udareg.h +++ b/sys/arch/vax/qbus/dzvar.h @@ -1,12 +1,12 @@ -/* $OpenBSD: udareg.h,v 1.3 1997/05/29 00:05:11 niklas Exp $ */ -/* $NetBSD: udareg.h,v 1.3 1996/07/01 21:24:50 ragge Exp $ */ - +/* $OpenBSD: dzvar.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */ +/* $NetBSD: dzvar.h,v 1.6 2000/01/24 02:40:29 matt Exp $ */ /* - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by - * Chris Torek. + * Ralph Campbell and Rick Macklem. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,30 +35,39 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)udareg.h 7.3 (Berkeley) 5/8/91 */ -/* - * UDA50 registers and structures - */ +/* A DZ-11 has 8 ports while a DZV/DZQ-11 has only 4. We use 8 by default */ -/* - * Writing any value to udaip starts initialisation. Reading from it - * when the UDA is running makes the UDA look through the command ring - * to find any new commands. Reading udasa gives status; writing it - * during initialisation sets things up. - */ -struct udadevice { - u_short udaip; /* initialisation and polling */ - u_short udasa; /* status and address */ -}; +#define NDZLINE 8 -/* - * Bits in UDA status register after initialisation - */ -#define UDA_GO 0x0001 /* run */ +#define DZ_DZ 8 +#define DZ_DZV 4 +#define DZ_DC 4 -#define UDASR_BITS \ -"\20\20ERR\17STEP4\16STEP3\15STEP2\14STEP1\13NV\12QB\11DI\10IE\1GO" +#define DZ_C2I(c) ((c)<<3) /* convert controller # to index */ +#define DZ_I2C(c) ((c)>>3) /* convert minor to controller # */ +#define DZ_PORT(u) ((u)&07) /* extract the port # */ + +struct dz_softc { + struct device sc_dev; /* Autoconf blaha */ + struct dz_regs sc_dr; /* reg pointers */ + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + int sc_type; /* DZ11 or DZV11? */ + int sc_rxint; /* Receive interrupt count XXX */ + u_char sc_brk; /* Break asserted on some lines */ + u_char sc_dsr; /* DSR set bits if no mdm ctrl */ + int (*sc_catch) __P((int, int)); /* Fast catch recv */ + struct { + struct tty * dz_tty; /* what we work on */ +#ifdef notyet + caddr_t dz_mem; /* pointers to clist output */ + caddr_t dz_end; /* allowing pdma action */ +#endif + } sc_dz[NDZLINE]; +}; +void dzattach __P((struct dz_softc *)); +void dzrint __P((void *)); +void dzxint __P((void *)); diff --git a/sys/arch/vax/qbus/files.uba b/sys/arch/vax/qbus/files.uba new file mode 100644 index 00000000000..98761e6bf71 --- /dev/null +++ b/sys/arch/vax/qbus/files.uba @@ -0,0 +1,52 @@ +# $OpenBSD: files.uba,v 1.1 2000/04/27 03:14:48 bjc Exp $ +# $NetBSD: files.uba,v 1.6 1999/06/20 18:09:22 ragge Exp $ +# +# Config file and device description for machine-independent +# code for devices Digital Equipment Corp. Unibus and Q22 bus. +# Included by ports that need it. +device uba { csr } + +define qfont + +file arch/vax/qbus/uba.c uba + +# DZ-11 (-compatible) tty device driver. +device dz { }: tty +attach dz at uba with dz_uba +file arch/vax/qbus/dz.c dz needs-flag +file arch/vax/qbus/dz_uba.c dz_uba + +# DL-11 at UBA +device dl: tty +attach dl at uba +file arch/vax/qbus/dl.c dl needs-flag + +# DHU-11 at UBA +device dhu: tty +attach dhu at uba +file arch/vax/qbus/dhu.c dhu needs-flag + +# UDA50/whatever disk/tape MSCP controller +device mtc: mscp +attach mtc at uba +device uda: mscp +attach uda at uba +file arch/vax/qbus/uda.c uda | mtc + +# DEQNA/DELQA Ethernet controller +device qe: ifnet, ether +attach qe at uba +file arch/vax/if/if_qe.c qe + +# DEUNA/DELUA Ethernet controller +device de: ifnet, ether +attach de at uba +file arch/vax/if/if_de.c de + +# QDSS at UBA +device qd: qfont +attach qd at uba +file arch/vax/qbus/qd.c qd needs-count + +# Fontfile for DEC framebuffers, soon to die in favour for MI fontfiles. +file arch/vax/qbus/qfont.c qfont diff --git a/sys/arch/vax/uba/qd.c b/sys/arch/vax/qbus/qd.c index 8e4402a6f35..38eaa483b17 100644 --- a/sys/arch/vax/uba/qd.c +++ b/sys/arch/vax/qbus/qd.c @@ -1,5 +1,5 @@ -/* $OpenBSD: qd.c,v 1.2 1997/05/29 00:05:07 niklas Exp $ */ -/* $NetBSD: qd.c,v 1.4 1996/10/13 03:35:17 christos Exp $ */ +/* $OpenBSD: qd.c,v 1.1 2000/04/27 03:14:48 bjc Exp $ */ +/* $NetBSD: qd.c,v 1.17 2000/01/24 02:40:29 matt Exp $ */ /*- * Copyright (c) 1988 Regents of the University of California. @@ -64,29 +64,33 @@ #include "qd.h" -#if NQD > 0 -#include "../include/pte.h" -#include "../include/mtpr.h" -#include "sys/param.h" -#include "../include/cpu.h" -#include "sys/conf.h" -#include "sys/user.h" -#include "qdioctl.h" -#include "sys/tty.h" -#include "sys/map.h" -#include "sys/buf.h" -#include "sys/vm.h" -#include "sys/clist.h" -#include "sys/file.h" -#include "sys/uio.h" -#include "sys/kernel.h" -#include "sys/exec.h" -#include "sys/proc.h" -#include "ubareg.h" -#include "ubavar.h" -#include "sys/syslog.h" -#include "qduser.h" /* definitions shared with user level client */ -#include "qdreg.h" /* QDSS device register structures */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/tty.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/poll.h> +#include <sys/buf.h> + +#include <vm/vm.h> + +#include <dev/cons.h> + +#include <machine/bus.h> +#include <machine/scb.h> + +#ifdef __vax__ +#include <machine/sid.h> +#include <machine/cpu.h> +#include <machine/pte.h> +#endif + +#include <arch/vax/qbus/ubavar.h> + +#include <arch/vax/qbus/qduser.h> +#include <arch/vax/qbus/qdreg.h> +#include <arch/vax/qbus/qdioctl.h> /* * QDSS driver status flags for tracking operational state @@ -107,6 +111,16 @@ struct qdflags { }; /* + * Softc struct to keep track of all states in this driver. + */ +struct qd_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_dma_tag_t sc_dmat; +}; + +/* * bit definitions for 'inuse' entry */ #define CONS_DEV 0x01 @@ -144,9 +158,9 @@ struct qdflags { * maintained info. */ struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ -struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ -extern char qvmem[][128*NBPG]; -extern struct pte QVmap[][128]; +struct tty *qd_tty[NQD*4]; /* teletype structures for each.. */ +volatile char *qvmem[NQD]; +volatile struct pte *QVmap[NQD]; #define CHUNK (64 * 1024) #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ @@ -154,8 +168,8 @@ extern struct pte QVmap[][128]; * static storage used by multiple functions in this code */ int Qbus_unmap[NQD]; /* Qbus mapper release code */ -struct qdflags qdflags[NQD]; /* QDSS device status flags */ struct qdmap qdmap[NQD]; /* QDSS register map structure */ +struct qdflags qdflags[NQD]; /* QDSS register map structure */ caddr_t qdbase[NQD]; /* base address of each QDSS unit */ struct buf qdbuf[NQD]; /* buf structs used by strategy */ short qdopened[NQD]; /* graphics device is open exclusive use */ @@ -212,39 +226,32 @@ struct color_buf *color_buf[NQD]; /* pointers to color bufs */ struct mouse_report last_rep[NQD]; struct mouse_report current_rep[NQD]; -struct proc *qdrsel[NQD]; /* process waiting for select */ +struct selinfo qdrsel[NQD]; /* process waiting for select */ struct _vs_cursor cursor[NQD]; /* console cursor */ int qdcount = 0; /* count of successfully probed qd's */ int nNQD = NQD; int DMAbuf_size = DMA_BUFSIZ; int QDlast_DMAtype; /* type of the last DMA operation */ -#define QDSSMAJOR 41 /* QDSS major device number */ +/* #define QDSSMAJOR 41 */ /* QDSS major device number. We don't care! */ + /* * macro to get system time. Used to time stamp event queue entries */ #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) -int qdprobe(); -int qdattach(); -int qddint(); /* DMA gate array intrpt service */ -int qdaint(); /* Dragon ADDER intrpt service */ -int qdiint(); - -u_short qdstd[] = { 0 }; - -struct uba_driver qddriver = { - qdprobe, /* device probe entry */ - 0, /* no slave device */ - qdattach, /* device attach entry */ - 0, /* no "fill csr/ba to start" */ - qdstd, /* device addresses */ - "qd", /* device name string */ - qdinfo /* ptr to QDSS's uba_device struct */ -}; +void qd_attach __P((struct device *, struct device *, void *)); +static int qd_match __P((struct device *, struct cfdata *, void *)); + +static void qddint __P((void *)); /* DMA gate array intrpt service */ +static void qdaint __P((void *)); /* Dragon ADDER intrpt service */ +static void qdiint __P((void *)); #define QDPRIOR (PZERO-1) /* must be negative */ #define FALSE 0 +#ifdef TRUE +#undef TRUE +#endif #define TRUE ~FALSE #define BAD -1 #define GOOD 0 @@ -252,7 +259,7 @@ struct uba_driver qddriver = { /* * macro to create a system virtual page number from system virtual adrs */ -#define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) +#define VTOP(x) (((int)x & ~0xC0000000) >> VAX_PGSHIFT) /* * QDSS register address offsets from start of QDSS address space @@ -320,16 +327,22 @@ extern char *q_special[]; /* * virtual console support. */ -extern (*v_putc)(); -#ifdef KADB -extern (*v_getc)(); -extern (*v_poll)(); -#endif extern struct cdevsw *consops; -int qdputc(); -int qdgetc(); -int qdpoll(); -int qdstart(); +cons_decl(qd); +cdev_decl(qd); +void setup_dragon __P((int)); +void init_shared __P((int)); +void clear_qd_screen __P((int)); +void ldfont __P((int)); +void ldcursor __P((int, short *)); +void setup_input __P((int)); +void blitc __P((int, u_char)); +void scroll_up __P((volatile struct adder *)); +void write_ID __P((volatile struct adder *, short, short)); +int wait_status __P((volatile struct adder *, int)); +void led_control __P((int, int, int)); +void qdstart(struct tty *); +void qdearly(void); int qdpolling = 0; /* @@ -354,55 +367,122 @@ struct q_keyboard { #define CFLAG (PARENB|CREAD|CS7|CLOCAL) /* - * Init QDSS as console (before probe routine) + * Kernel virtual addresses where we can map in the QBUS io page and the + * QDSS memory during qdcninit. pmap_bootstrap fills this in. + */ +void *qd_ubaio; + +/* This is the QDSS unit 0 CSR. It is hard-coded in here so that the + * QDSS can be used as the console. The console routines don't get + * any config info. The ROM also autodetects at this address, so + * the console QDSS should be at this address. Furthermore, nothing + * else shuld be at this address instead because that would confuse the + * ROM and this driver. */ +#define QDSSCSR 0x1F00 + +volatile u_short *qdaddr; /* Virtual address for QDSS CSR */ + +/* + * This flag is set to 1 if the console initialization (qdcninit) + * has been performed on qd0. That initialization is required and must + * be done before the device probe routine. + */ +int qd0cninited = 0, qd0iscons = 0; -qdcons_init() +/* + * Do early check if the qdss is console. If not; don't allocate + * any memory for it in bootstrap. + */ +void +qdearly() { - register unit; - caddr_t phys_adr; /* physical QDSS base adrs */ - u_int mapix; /* index into QVmap[] array */ - struct percpu *pcpu; /* pointer to cpusw structure */ - register struct qbus *qb; - u_short *qdaddr; /* address of QDSS IO page CSR */ - u_short *devptr; /* vitual device space */ - extern cnputc(); + extern vaddr_t virtual_avail; + int tmp; + + /* Make sure we're running on a system that can have a QDSS */ + if (vax_boardtype == VAX_BTYP_630) { + /* Now check some undocumented flag */ + if ((*(int *)(0x200B801E) & 0x60) == 0) + /* The KA630 isn't using a QDSS as the console, + * so we won't either */ + return; + } else if (vax_boardtype != VAX_BTYP_650) + return; -#define QDSSCSR 0x1F00 + /* How to check for console on KA650? We assume that if there is a + * QDSS, it is console. + */ +#define QIOPAGE 0x20000000 /* XXX */ +#define UBAIOPAGES 16 + tmp = QIOPAGE + ubdevreg(QDSSCSR); + if (badaddr((caddr_t)tmp, sizeof(short))) + return; - if (v_putc != cnputc) - return 0; + MAPVIRT(qvmem[0], 64 * 1024 * NQD / VAX_NBPG); + MAPVIRT(qd_ubaio, 16); + pmap_map((int)qd_ubaio, QIOPAGE, QIOPAGE + UBAIOPAGES * VAX_NBPG, + VM_PROT_READ|VM_PROT_WRITE); + qdaddr = (u_short *)((u_int)qd_ubaio + ubdevreg(QDSSCSR)); + qd0iscons = 1; +} - unit = 0; +void +qdcnprobe(cndev) + struct consdev *cndev; +{ + int i; - /* - * find the cpusw entry that matches this machine. - */ - for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) - ; - if (pcpu == NULL) - return 0; - if (pcpu->pc_io->io_type != IO_QBUS) - return 0; + cndev->cn_pri = CN_DEAD; + + if (mfpr(PR_MAPEN) == 0) + return; /* Cannot use qd if vm system is OFF */ - /* - * Map device registers - the last 8K of qvmem. - */ - qb = (struct qbus *)pcpu->pc_io->io_details; - ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, - UBAIOPAGES * NBPG); - devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); - qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); - if (badaddr((caddr_t)qdaddr, sizeof(short))) - return 0; + if (!qd0iscons) + return; + + /* Find the console device corresponding to the console QDSS */ + for (i = 0; i < nchrdev; i++) + if (cdevsw[i].d_open == qdopen) { + cndev->cn_dev = makedev(i,0); + cndev->cn_pri = CN_INTERNAL; + return; + } + return; +} + + +/* + * Init QDSS as console (before probe routine) + */ +void +qdcninit(cndev) + struct consdev *cndev; +{ + caddr_t phys_adr; /* physical QDSS base adrs */ + u_int mapix; /* index into QVmap[] array */ + int unit; + + /* qdaddr must point to CSR for this unit! */ + + /* The console QDSS is QDSS unit 0 */ + unit = 0; /* * Map q-bus memory used by qdss. (separate map) */ mapix = QMEMSIZE - (CHUNK * (unit + 1)); - phys_adr = qb->qb_maddr + mapix; - ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); +#define QMEM 0x30000000 + (int)phys_adr = QMEM + mapix; + pmap_map((int)(qvmem[0]), (int)phys_adr, (int)(phys_adr + (CHUNK*NQD)), + VM_PROT_READ|VM_PROT_WRITE); + /* + * Set QVmap to point to page table entries for what we just + * mapped. + */ + QVmap[0] = (struct pte *)kvtopte(qvmem[0]); + /* * tell QDSS which Q memory address base to decode * (shifted right 16 bits - its in 64K units) @@ -428,11 +508,7 @@ qdcons_init() /* * init the QDSS */ - /* - printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", - (char *)qdbase[0], qdmap[0].memcsr); - */ - + *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ cursor[unit].x = 0; @@ -443,16 +519,21 @@ qdcons_init() ldfont(unit); /* load the console font */ ldcursor(unit, cons_cursor); /* load default cursor map */ setup_input(unit); /* init the DUART */ - v_putc = qdputc; /* kernel console output to qdss */ -#ifdef KADB - v_getc = qdgetc; /* kernel console input from qdss */ - v_poll = qdpoll; /* kdb hook to disable char intr */ -#endif - consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ - return 1; -} /* qdcons_init */ + /* Set flag so probe knows */ + qd0cninited = 1; +} /* qdcninit */ + +/* see <sys/device.h> */ +struct cfattach qd_ca = { + sizeof(struct qd_softc), qd_match, qd_attach +}; +#define QD_RCSR(reg) \ + bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg) +#define QD_WCSR(reg, val) \ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val) + /* * Configure QDSS into Q memory and make it intrpt. * @@ -464,12 +545,18 @@ qdcons_init() * registers by UNIX convention. * */ -qdprobe(reg) - caddr_t reg; /* character pointer to the QDSS I/O page register */ +static int +qd_match(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; { - register int br, cvec; + struct qd_softc ssc; + struct qd_softc *sc = &ssc; + struct uba_attach_args *ua = aux; + struct uba_softc *uh = (void *)parent; register int unit; - struct dga *dga; /* pointer to gate array structure */ + volatile struct dga *dga; /* pointer to gate array structure */ int vector; #ifdef notdef int *ptep; /* page table entry pointer */ @@ -477,19 +564,18 @@ qdprobe(reg) u_int mapix; #endif -#ifdef lint - br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; - qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); -#endif - + /* Create a "fake" softc with only a few fields used. */ + sc->sc_iot = ua->ua_iot; + sc->sc_ioh = ua->ua_ioh; + sc->sc_dmat = ua->ua_dmat; /* * calculate board unit number from I/O page register address */ - unit = (int) (((int)reg >> 1) & 0x0007); + unit = (int) (((int)sc->sc_ioh >> 1) & 0x0007); /* * QDSS regs must be mapped to Qbus memory space at a 64kb - * physical boundary. The Qbus memory space is mapped into + * physical boundary. The Qbus memory space is mapped into * the system memory space at config time. After config * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs * of the start of Qbus memory. The Qbus memory page table @@ -534,7 +620,7 @@ qdprobe(reg) */ mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); ptep = (int *) QVmap[0] + mapix; - phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); + phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<VAX_PGSHIFT); *(u_short *)reg = (u_short) ((int)phys_adr >> 16); /* @@ -566,7 +652,35 @@ qdprobe(reg) *(short *)qdmap[unit].memcsr |= SYNC_ON; } #endif /*notdef*/ + } else { + /* We are dealing with qd0 */ + + if (!qd0cninited) { + /* + * qd0 has not been initiallized as the console. + * We need to do some initialization now + * + * XXX + * However, if the QDSS is not the console then + * that stupid undocumented bit (see qdcnprobe) + * is cleared. Then the QDSS refuses to work. + * (What did the ROM do to it!?) + * XXX + */ + return 0; + +#if 0 + qdaddr = (void *)reg; + + /* Lame probe for QDSS. Should be ok for qd0 */ + if (badaddr((caddr_t)qdaddr, sizeof(short))) + return 0; + + qdcninit(NULL); +#endif + } } + /* * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 @@ -577,11 +691,11 @@ qdprobe(reg) * order. */ - vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ + vector = (uh->uh_lastiv -= 4*3); /* take three vectors */ while (vector & 0x0F) { /* if lo nibble != 0.. */ /* ..take another vector */ - vector = (uba_hd[0].uh_lastiv -= 4); + vector = (uh->uh_lastiv -= 4); } /* @@ -602,24 +716,31 @@ qdprobe(reg) DELAY(20000); /* wait for the intrpt */ dga->csr = HALT; /* stop the wheels */ - if (cvec != vector) /* if vector != base vector.. */ - return(0); /* ..return = 'no device' */ - /* * score this as an existing qdss */ qdcount++; - return(sizeof(short)); /* return size of QDSS I/O page reg */ - + return 1; } /* qdprobe */ -qdattach(ui) - struct uba_device *ui; -{ - register unit; /* QDSS module # for this call */ - unit = ui->ui_unit; /* get QDSS number */ +void qd_attach(parent, self, aux) + struct device *parent, *self; + void *aux; + { + register struct uba_attach_args *ua = aux; + register int unit; /* QDSS module # for this call */ + + printf("\n"); + + unit = self->dv_unit; /* get QDSS number */ + + /* Set interrupt vectors for interrupt handlers */ + + uba_intr_establish(ua->ua_icookie, ua->ua_cvec , qddint, self); + uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4, qdaint, self); + uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 8, qdiint, self); /* * init "qdflags[]" for this QDSS @@ -665,15 +786,17 @@ qdattach(ui) } /* qdattach */ + /*ARGSUSED*/ -qdopen(dev, flag) +int +qdopen(dev, flag, mode, p) dev_t dev; - int flag; + int flag, mode; + struct proc *p; { - register struct uba_device *ui; /* ptr to uba structures */ - register struct dga *dga; /* ptr to gate array struct */ + volatile register struct dga *dga; /* ptr to gate array struct */ register struct tty *tp; - struct duart *duart; + volatile struct duart *duart; int unit; int minor_dev; @@ -683,9 +806,8 @@ qdopen(dev, flag) /* * check for illegal conditions */ - ui = qdinfo[unit]; /* get ptr to QDSS device struct */ - if (ui == 0 || ui->ui_alive == 0) - return(ENXIO); /* no such device or address */ + if (unit >= qd_cd.cd_ndevs || qd_cd.cd_devs[unit] == NULL) + return (ENXIO); /* no such device or address */ duart = (struct duart *) qdmap[unit].duart; dga = (struct dga *) qdmap[unit].dga; @@ -705,7 +827,17 @@ qdopen(dev, flag) qdflags[unit].duart_imask |= 0x22; duart->imask = qdflags[unit].duart_imask; } else { - /* + /* Only one console */ + if (minor_dev) return ENXIO; + + /* If not done already, allocate tty structure */ + if (qd_tty[minor_dev] == NULL) + qd_tty[minor_dev] = ttymalloc(); + + if (qd_tty[minor_dev] == NULL) + return ENXIO; + + /* * this is the console */ qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ @@ -715,9 +847,10 @@ qdopen(dev, flag) /* * some setup for tty handling */ - tp = &qd_tty[minor_dev]; - tp->t_addr = ui->ui_addr; + tp = qd_tty[minor_dev]; + /* tp->t_addr = ui->ui_addr; */ tp->t_oproc = qdstart; + tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); tp->t_ispeed = B9600; @@ -727,6 +860,7 @@ qdopen(dev, flag) tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; + ttsetwater(tp); } /* * enable intrpts, open line discipline @@ -740,6 +874,7 @@ qdopen(dev, flag) } /* qdopen */ /*ARGSUSED*/ +int qdclose(dev, flag, mode, p) dev_t dev; int flag, mode; @@ -747,25 +882,30 @@ qdclose(dev, flag, mode, p) { register struct tty *tp; register struct qdmap *qd; - register int *ptep; - struct dga *dga; /* gate array register map pointer */ - struct duart *duart; - struct adder *adder; + volatile register int *ptep; + volatile struct dga *dga; /* gate array register map pointer */ + volatile struct duart *duart; + volatile struct adder *adder; int unit; int minor_dev; u_int mapix; int i; /* SIGNED index */ - + struct uba_softc *uh; + minor_dev = minor(dev); /* get minor device number */ unit = minor_dev >> 2; /* get QDSS number */ qd = &qdmap[unit]; + uh = (struct uba_softc *) + (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent); + + if ((minor_dev & 0x03) == 2) { /* * this is the graphic device... */ if (qdopened[unit] != 1) - return(EBUSY); + return(EBUSY); else qdopened[unit] = 0; /* allow it to be re-opened */ /* @@ -777,21 +917,21 @@ qdclose(dev, flag, mode, p) */ mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); ptep = (int *)(QVmap[0] + mapix); - for (i = 0; i < btop(TMPSIZE); i++, ptep++) + for (i = 0; i < vax_btop(TMPSIZE); i++, ptep++) *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; /* * ADDER */ mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); ptep = (int *)(QVmap[0] + mapix); - for (i = 0; i < btop(REGSIZE); i++, ptep++) + for (i = 0; i < vax_btop(REGSIZE); i++, ptep++) *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; /* * COLOR MAPS */ mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); ptep = (int *)(QVmap[0] + mapix); - for (i = 0; i < btop(CLRSIZE); i++, ptep++) + for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++) *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; } @@ -799,6 +939,12 @@ qdclose(dev, flag, mode, p) * re-protect DMA buffer and free the map registers */ if (qdflags[unit].mapped & MAPDMA) { + panic("Unmapping unmapped buffer"); +#ifdef notyet +/* + * Ragge 990620: + * Can't happen because the buffer can't be mapped. + */ dga = (struct dga *) qdmap[unit].dga; adder = (struct adder *) qdmap[unit].adder; dga->csr &= ~DMA_IE; @@ -815,10 +961,11 @@ qdclose(dev, flag, mode, p) dga->csr &= ~DMA_IE; } ptep = (int *) - ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); - for (i = 0; i < btop(DMAbuf_size); i++, ptep++) + ((VTOP(DMAheader[unit]*4)) + (mfpr(PR_SBR)|0x80000000)); + for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++) *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; - ubarelse(0, &Qbus_unmap[unit]); + ubarelse(uh, &Qbus_unmap[unit]); +#endif } /* @@ -826,7 +973,7 @@ qdclose(dev, flag, mode, p) */ if (qdflags[unit].mapped & MAPEQ) { ptep = (int *) - ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); + ((VTOP(eq_header[unit])*4) + (mfpr(PR_SBR)|0x80000000)); *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; } @@ -835,7 +982,7 @@ qdclose(dev, flag, mode, p) */ if (qdflags[unit].mapped & MAPSCR) { ptep = (int *) ((VTOP(scroll[unit]) * 4) - + (mfpr(SBR) | 0x80000000)); + + (mfpr(PR_SBR) | 0x80000000)); /* * re-protect 512 scroll param area */ @@ -849,7 +996,7 @@ qdclose(dev, flag, mode, p) */ if (qdflags[unit].mapped & MAPCOLOR) { ptep = (int *) ((VTOP(color_buf[unit]) * 4) - + (mfpr(SBR) | 0x80000000)); + + (mfpr(PR_SBR) | 0x80000000)); *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; color_buf[unit]->status = 0; @@ -857,7 +1004,7 @@ qdclose(dev, flag, mode, p) qdflags[unit].adder_ie &= ~VSYNC; adder->interrupt_enable = qdflags[unit].adder_ie; } - mtpr(TBIA, 0); + mtpr(0, PR_TBIA); /* flag everything now unmapped */ qdflags[unit].mapped = 0; qdflags[unit].inuse &= ~GRAPHIC_DEV; @@ -907,7 +1054,7 @@ qdclose(dev, flag, mode, p) /* * this is the console */ - tp = &qd_tty[minor_dev]; + tp = qd_tty[minor_dev]; (*linesw[tp->t_line].l_close)(tp, flag); ttyclose(tp); tp->t_state = 0; @@ -925,21 +1072,23 @@ qdclose(dev, flag, mode, p) } /* qdclose */ -qdioctl(dev, cmd, datap, flags) +int +qdioctl(dev, cmd, datap, flags, p) dev_t dev; - int cmd; - register caddr_t datap; + u_long cmd; + caddr_t datap; int flags; + struct proc *p; { - register int *ptep; /* page table entry pointer */ + volatile register int *ptep; /* page table entry pointer */ register int mapix; /* QVmap[] page table index */ register struct _vs_event *event; register struct tty *tp; - register i; + register int i; struct qdmap *qd; /* pointer to device map struct */ - struct dga *dga; /* Gate Array reg structure pntr */ - struct duart *duart; /* DUART reg structure pointer */ - struct adder *adder; /* ADDER reg structure pointer */ + volatile struct dga *dga; /* Gate Array reg structure pntr */ + volatile struct duart *duart; /* DUART reg structure pointer */ + volatile struct adder *adder; /* ADDER reg structure pointer */ struct prgkbd *cmdbuf; struct prg_cursor *curs; struct _vs_cursor *pos; @@ -948,6 +1097,10 @@ qdioctl(dev, cmd, datap, flags) int error; int s; short *temp; /* a pointer to template RAM */ + struct uba_softc *uh; + + uh = (struct uba_softc *) + (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent); /* * service graphic device ioctl commands @@ -1045,7 +1198,7 @@ qdioctl(dev, cmd, datap, flags) break; case QD_MAPDEVICE: - /* + /* * enable 'user write' to device pages */ qdflags[unit].mapped |= MAPDEV; @@ -1055,37 +1208,47 @@ qdioctl(dev, cmd, datap, flags) */ mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); ptep = (int *)(QVmap[0] + mapix); - for (i = 0; i < btop(TMPSIZE); i++, ptep++) - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; - /* + for (i = 0; i < vax_btop(TMPSIZE); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; + + /* * enable user write to registers */ mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); ptep = (int *)(QVmap[0] + mapix); - for (i = 0; i < btop(REGSIZE); i++, ptep++) - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; + for (i = 0; i < vax_btop(REGSIZE); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; + /* * enable user write to color maps */ mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); ptep = (int *)(QVmap[0] + mapix); - for (i = 0; i < btop(CLRSIZE); i++, ptep++) - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; - /* + for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; + + /* * enable user write to DUART */ mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); ptep = (int *)(QVmap[0] + mapix); - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; /* duart page */ - mtpr(TBIA, 0); /* invalidate translation buffer */ + mtpr(0, PR_TBIA); /* invalidate translation buffer */ /* * stuff qdmap structure in return buffer */ bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); + break; +#ifdef notyet +/* + * Ragge 999620: + * Can't map in the graphic buffer into user space for now. + * The best way to fix this is to convert this driver to wscons. + */ case QD_MAPIOBUF: /* * do setup for DMA by user process @@ -1094,15 +1257,15 @@ qdioctl(dev, cmd, datap, flags) */ qdflags[unit].mapped |= MAPDMA; ptep = (int *) ((VTOP(DMAheader[unit]) * 4) - + (mfpr(SBR) | 0x80000000)); - for (i = 0; i < btop(DMAbuf_size); i++, ptep++) - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; - mtpr(TBIA, 0); /* invalidate translation buffer */ + + (mfpr(PR_SBR) | 0x80000000)); + for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; + mtpr(0, PR_TBIA); /* invalidate translation buffer */ /* * set up QBUS map registers for DMA */ DMAheader[unit]->QBAreg = - uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); + uballoc(uh, (caddr_t)DMAheader[unit], DMAbuf_size, 0); if (DMAheader[unit]->QBAreg == 0) printf("qd%d: qdioctl: QBA setup error\n", unit); Qbus_unmap[unit] = DMAheader[unit]->QBAreg; @@ -1112,6 +1275,7 @@ qdioctl(dev, cmd, datap, flags) */ *(int *)datap = (int) DMAheader[unit]; break; +#endif case QD_MAPSCROLL: /* @@ -1119,12 +1283,12 @@ qdioctl(dev, cmd, datap, flags) */ qdflags[unit].mapped |= MAPSCR; ptep = (int *) ((VTOP(scroll[unit]) * 4) - + (mfpr(SBR) | 0x80000000)); + + (mfpr(PR_SBR) | 0x80000000)); /* * allow user write to scroll area */ - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; - mtpr(TBIA, 0); /* invalidate translation buf */ + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; + mtpr(0, PR_TBIA); /* invalidate translation buf */ scroll[unit]->status = 0; adder = (struct adder *) qdmap[unit].adder; qdflags[unit].adder_ie |= FRAME_SYNC; @@ -1139,12 +1303,12 @@ qdioctl(dev, cmd, datap, flags) if (qdflags[unit].mapped & MAPSCR) { qdflags[unit].mapped &= ~MAPSCR; ptep = (int *) ((VTOP(scroll[unit]) * 4) - + (mfpr(SBR) | 0x80000000)); + + (mfpr(PR_SBR) | 0x80000000)); /* * re-protect 512 scroll param area */ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; - mtpr(TBIA, 0); /* smash CPU's translation buf */ + mtpr(0, PR_TBIA); /* smash CPU's translation buf */ adder = (struct adder *) qdmap[unit].adder; qdflags[unit].adder_ie &= ~FRAME_SYNC; adder->interrupt_enable = qdflags[unit].adder_ie; @@ -1157,13 +1321,13 @@ qdioctl(dev, cmd, datap, flags) */ qdflags[unit].mapped |= MAPCOLOR; ptep = (int *) ((VTOP(color_buf[unit]) * 4) - + (mfpr(SBR) | 0x80000000)); + + (mfpr(PR_SBR) | 0x80000000)); /* * allow user write to color map write buffer */ - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; - mtpr(TBIA, 0); /* clr CPU translation buf */ + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++; + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; + mtpr(0, PR_TBIA); /* clr CPU translation buf */ adder = (struct adder *) qdmap[unit].adder; qdflags[unit].adder_ie |= VSYNC; adder->interrupt_enable = qdflags[unit].adder_ie; @@ -1180,13 +1344,13 @@ qdioctl(dev, cmd, datap, flags) if (qdflags[unit].mapped & MAPCOLOR) { qdflags[unit].mapped &= ~MAPCOLOR; ptep = (int *) ((VTOP(color_buf[unit]) * 4) - + (mfpr(SBR) | 0x80000000)); + + (mfpr(PR_SBR) | 0x80000000)); /* * re-protect color map write buffer */ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; - mtpr(TBIA, 0); + mtpr(0, PR_TBIA); adder = (struct adder *) qdmap[unit].adder; qdflags[unit].adder_ie &= ~VSYNC; adder->interrupt_enable = qdflags[unit].adder_ie; @@ -1199,13 +1363,13 @@ qdioctl(dev, cmd, datap, flags) */ qdflags[unit].mapped |= MAPEQ; ptep = (int *) ((VTOP(eq_header[unit]) * 4) - + (mfpr(SBR) | 0x80000000)); + + (mfpr(PR_SBR) | 0x80000000)); /* * allow user write to 1K event queue */ - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; - *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; - mtpr(TBIA, 0); /* clr CPU translation buf */ + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++; + *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; + mtpr(0, PR_TBIA); /* clr CPU translation buf */ /* * return event queue address */ @@ -1322,13 +1486,14 @@ qdioctl(dev, cmd, datap, flags) * service tty ioctl's */ if (!(minor_dev & 0x02)) { - tp = &qd_tty[minor_dev]; + tp = qd_tty[minor_dev]; error = - (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); + + (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags, p); if (error >= 0) { return(error); } - error = ttioctl(tp, cmd, datap, flags); + error = ttioctl(tp, cmd, datap, flags, p); if (error >= 0) { return(error); } @@ -1340,96 +1505,110 @@ qdioctl(dev, cmd, datap, flags) } /* qdioctl */ -qdselect(dev, rw) + +int +qdpoll(dev, events, p) dev_t dev; - int rw; + int events; + struct proc *p; { - register s; - register unit; + register int s; + register int unit; register struct tty *tp; u_int minor_dev = minor(dev); + int revents = 0; s = spl5(); unit = minor_dev >> 2; - switch (rw) { - case FREAD: - if ((minor_dev & 0x03) == 2) { - /* - * this is a graphics device, so check for events - */ - if(!(ISEMPTY(eq_header[unit]))) { - splx(s); - return(1); - } - qdrsel[unit] = u.u_procp; - qdflags[unit].selmask |= SEL_READ; - splx(s); - return(0); - } else { - /* - * this is a tty device - */ - tp = &qd_tty[minor_dev]; - if (ttnread(tp)) - return(1); - tp->t_rsel = u.u_procp; - splx(s); - return(0); - } + if ((minor_dev & 0x03) == 2) { + /* + * This is a graphics device, so check for events. + */ - case FWRITE: - if ((minor(dev) & 0x03) == 2) { - /* - * this is a graphics device, so check for dma buffers - */ + if (events & (POLLIN | POLLRDNORM)) + if(!(ISEMPTY(eq_header[unit]))) + revents |= events & (POLLIN | POLLRDNORM); + + if (events & (POLLOUT | POLLWRNORM)) if (DMA_ISEMPTY(DMAheader[unit])) - { - splx(s); - return(1); + revents |= events & (POLLOUT | POLLWRNORM); + + if (revents == 0) { + if (events & (POLLIN | POLLRDNORM)) { + selrecord(p, &qdrsel[unit]); + qdflags[unit].selmask |= SEL_READ; } - qdrsel[unit] = u.u_procp; - qdflags[unit].selmask |= SEL_WRITE; - splx(s); - return(0); - } else { - /* - * this is a tty device - */ - tp = &qd_tty[minor_dev]; + + if (events & (POLLOUT | POLLWRNORM)) { + selrecord(p, &qdrsel[unit]); + qdflags[unit].selmask |= SEL_WRITE; + } + } + } else { + /* + * this is a tty device + */ + tp = qd_tty[minor_dev]; + + if (events & (POLLIN | POLLRDNORM)) { + /* This is ttnread. It's static and I don't feel + * like altering platform independant parts of NetBSD + */ + int nread; + /* if (tp->t_lflag & PENDIN) + ttypend(tp); */ + nread = tp->t_canq.c_cc; + if (!(tp->t_lflag & ICANON)) { + nread += tp->t_rawq.c_cc; + if (nread < tp->t_cc[VMIN] && !tp->t_cc[VTIME]) + nread = 0; + } + if (nread > 0) + revents |= events & (POLLIN | POLLRDNORM); + } + + if (events & (POLLOUT | POLLWRNORM)) if (tp->t_outq.c_cc <= tp->t_lowat) - return(1); - tp->t_wsel = u.u_procp; - splx(s); - return(0); + revents |= events & (POLLOUT | POLLWRNORM); + + if (revents == 0) { + if (events & (POLLIN | POLLRDNORM)) + selrecord(p, &tp->t_rsel); + + if (events & (POLLOUT | POLLWRNORM)) + selrecord(p, &tp->t_wsel); } } + splx(s); - return(0); + return (revents); +} /* qdpoll() */ -} /* qdselect() */ -extern qd_strategy(); +void qd_strategy(struct buf *bp); -qdwrite(dev, uio) +/*ARGSUSED*/ +int +qdwrite(dev, uio, flag) dev_t dev; struct uio *uio; { register struct tty *tp; - register minor_dev; - register unit; + register int minor_dev; + register int unit; minor_dev = minor(dev); unit = (minor_dev >> 2) & 0x07; if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { - /* + /* * this is the console... */ - tp = &qd_tty[minor_dev]; - return ((*linesw[tp->t_line].l_write)(tp, uio)); + tp = qd_tty[minor_dev]; + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } else if (qdflags[unit].inuse & GRAPHIC_DEV) { - /* + /* * this is a DMA xfer from user space */ return (physio(qd_strategy, &qdbuf[unit], @@ -1438,25 +1617,27 @@ qdwrite(dev, uio) return (ENXIO); } -qdread(dev, uio) +/*ARGSUSED*/ +int +qdread(dev, uio, flag) dev_t dev; struct uio *uio; { register struct tty *tp; - register minor_dev; - register unit; + register int minor_dev; + register int unit; minor_dev = minor(dev); unit = (minor_dev >> 2) & 0x07; if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { - /* + /* * this is the console */ - tp = &qd_tty[minor_dev]; - return ((*linesw[tp->t_line].l_read)(tp, uio)); + tp = qd_tty[minor_dev]; + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } else if (qdflags[unit].inuse & GRAPHIC_DEV) { - /* + /* * this is a bitmap-to-processor xfer */ return (physio(qd_strategy, &qdbuf[unit], @@ -1471,26 +1652,34 @@ qdread(dev, uio) * ***************************************************************/ +void qd_strategy(bp) register struct buf *bp; { - register struct dga *dga; - register struct adder *adder; - register unit; + volatile register struct dga *dga; + volatile register struct adder *adder; + register int unit; int QBAreg; int s; int cookie; - + struct uba_softc *uh; + unit = (minor(bp->b_dev) >> 2) & 0x07; + uh = (struct uba_softc *) + (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent); + /* * init pointers */ - if ((QBAreg = ubasetup(0, bp, 0)) == 0) { + dga = (struct dga *) qdmap[unit].dga; +panic("qd_strategy"); +#ifdef notyet + if ((QBAreg = ubasetup(uh, bp, 0)) == 0) { printf("qd%d: qd_strategy: QBA setup error\n", unit); goto STRAT_ERR; } - dga = (struct dga *) qdmap[unit].dga; +#endif s = spl5(); qdflags[unit].user_dma = -1; dga->csr |= DMA_IE; @@ -1499,18 +1688,20 @@ qd_strategy(bp) dga->adrs_hi = (short) (cookie >> 16); dga->bytcnt_lo = (short) bp->b_bcount; dga->bytcnt_hi = (short) (bp->b_bcount >> 16); - + while (qdflags[unit].user_dma) { sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); } splx(s); - ubarelse(0, &QBAreg); +#ifdef notyet + ubarelse(uh, &QBAreg); +#endif if (!(dga->csr & DMA_ERR)) { - iodone(bp); + biodone(bp); return; } -STRAT_ERR: +/* STRAT_ERR: */ adder = (struct adder *) qdmap[unit].adder; adder->command = CANCEL; /* cancel adder activity */ dga->csr &= ~DMA_IE; @@ -1527,17 +1718,17 @@ STRAT_ERR: DMA_SETIGNORE(DMAheader[unit]); dga->csr |= DMA_IE; } - iodone(bp); - + biodone(bp); } /* qd_strategy */ + /* * Start output to the console screen */ -qdstart(tp) - register struct tty *tp; +void qdstart(tp) + struct tty *tp; { - register which_unit, unit, c; + register int which_unit, unit, c; int s; unit = minor(tp->t_dev); @@ -1586,30 +1777,31 @@ out: /*ARGSUSED*/ void qdstop(tp, flag) - register struct tty *tp; + struct tty *tp; int flag; { register int s; s = spl5(); /* block intrpts during state modification */ - if (tp->t_state & TS_BUSY) + if (tp->t_state & TS_BUSY) { if ((tp->t_state & TS_TTSTOP) == 0) tp->t_state |= TS_FLUSH; else tp->t_state &= ~TS_BUSY; + } splx(s); } /* * Output a character to the QDSS screen */ - +void blitc(unit, chr) - register unit; - register u_char chr; + int unit; + u_char chr; { - register struct adder *adder; - register struct dga *dga; + volatile register struct adder *adder; + volatile register struct dga *dga; register int i; int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); static short inescape[NQD]; @@ -1804,8 +1996,6 @@ blitc(unit, chr) } /* blitc */ -qdreset() { } - /* * INTERRUPT SERVICE ROUTINES */ @@ -1813,13 +2003,16 @@ qdreset() { } /* * Service "DMA DONE" interrupt condition */ -qddint(qd) - register qd; + +static void +qddint(arg) + void *arg; { + struct device *dv = arg; register struct DMAreq_header *header; register struct DMAreq *request; - register struct dga *dga; - struct adder *adder; + volatile register struct dga *dga; + volatile struct adder *adder; int cookie; /* DMA adrs for QDSS */ (void)spl4(); /* allow interval timer in */ @@ -1827,15 +2020,15 @@ qddint(qd) /* * init pointers */ - header = DMAheader[qd]; /* register for optimization */ - dga = (struct dga *) qdmap[qd].dga; - adder = (struct adder *) qdmap[qd].adder; + header = DMAheader[dv->dv_unit]; /* register for optimization */ + dga = (struct dga *) qdmap[dv->dv_unit].dga; + adder = (struct adder *) qdmap[dv->dv_unit].adder; /* * if this interrupt flagged as bogus for interrupt flushing purposes.. */ if (DMA_ISIGNORE(header)) { - DMA_CLRIGNORE(header); + DMA_CLRIGNORE(header); return; } @@ -1845,18 +2038,18 @@ qddint(qd) if (dga->csr & DMA_ERR) { if (dga->csr & PARITY_ERR) - printf("qd%d: qddint: DMA hardware parity fault.\n", qd); + printf("qd%d: qddint: DMA hardware parity fault.\n", dv->dv_unit); if (dga->csr & BUS_ERR) - printf("qd%d: qddint: DMA hardware bus error.\n", qd); + printf("qd%d: qddint: DMA hardware bus error.\n", dv->dv_unit); } /* * if this was a DMA from user space... */ - if (qdflags[qd].user_dma) { - qdflags[qd].user_dma = 0; - wakeup((caddr_t)&qdflags[qd].user_dma); + if (qdflags[dv->dv_unit].user_dma) { + qdflags[dv->dv_unit].user_dma = 0; + wakeup((caddr_t)&qdflags[dv->dv_unit].user_dma); return; } @@ -1875,10 +2068,10 @@ qddint(qd) header->newest = header->oldest; header->used = 0; - if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { - selwakeup(qdrsel[qd], 0); - qdrsel[qd] = 0; - qdflags[qd].selmask &= ~SEL_WRITE; + if (qdrsel[dv->dv_unit].si_pid && qdflags[dv->dv_unit].selmask & SEL_WRITE) { + selwakeup(&qdrsel[dv->dv_unit]); + qdrsel[dv->dv_unit].si_pid = 0; + qdflags[dv->dv_unit].selmask &= ~SEL_WRITE; } if (dga->bytcnt_lo != 0) { @@ -1894,10 +2087,10 @@ qddint(qd) * wakeup "select" client. */ if (DMA_ISFULL(header)) { - if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { - selwakeup(qdrsel[qd], 0); - qdrsel[qd] = 0; - qdflags[qd].selmask &= ~SEL_WRITE; + if (qdrsel[dv->dv_unit].si_pid && qdflags[dv->dv_unit].selmask & SEL_WRITE) { + selwakeup(&qdrsel[dv->dv_unit]); + qdrsel[dv->dv_unit].si_pid = 0; + qdflags[dv->dv_unit].selmask &= ~SEL_WRITE; } } @@ -1914,13 +2107,11 @@ qddint(qd) * if no more DMA pending, wake up "select" client and exit */ if (DMA_ISEMPTY(header)) { - - if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { - selwakeup(qdrsel[qd], 0); - qdrsel[qd] = 0; - qdflags[qd].selmask &= ~SEL_WRITE; + if (qdrsel[dv->dv_unit].si_pid && qdflags[dv->dv_unit].selmask & SEL_WRITE) { + selwakeup(&qdrsel[dv->dv_unit]); + qdrsel[dv->dv_unit].si_pid = 0; + qdflags[dv->dv_unit].selmask &= ~SEL_WRITE; } - DMA_CLRACTIVE(header); /* flag DMA done */ return; } @@ -1968,7 +2159,7 @@ qddint(qd) } break; default: - printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); + printf("qd%d: qddint: illegal DMAtype parameter.\n", dv->dv_unit); DMA_CLRACTIVE(header); /* flag DMA done */ return; } @@ -2002,20 +2193,22 @@ qddint(qd) /* * ADDER interrupt service routine */ -qdaint(qd) - register qd; +static void +qdaint(arg) + void *arg; { - register struct adder *adder; + struct device *dv = arg; + volatile register struct adder *adder; struct color_buf *cbuf; int i; register struct rgb *rgbp; - register short *red; - register short *green; - register short *blue; + volatile register short *red; + volatile register short *green; + volatile register short *blue; (void)spl4(); /* allow interval timer in */ - adder = (struct adder *) qdmap[qd].adder; + adder = (struct adder *) qdmap[dv->dv_unit].adder; /* * service the vertical blank interrupt (VSYNC bit) by loading @@ -2023,12 +2216,12 @@ qdaint(qd) */ if (adder->status & VSYNC) { adder->status &= ~VSYNC; /* clear the interrupt */ - cbuf = color_buf[qd]; + cbuf = color_buf[dv->dv_unit]; if (cbuf->status & LOAD_COLOR_MAP) { - red = (short *) qdmap[qd].red; - green = (short *) qdmap[qd].green; - blue = (short *) qdmap[qd].blue; + red = (short *) qdmap[dv->dv_unit].red; + green = (short *) qdmap[dv->dv_unit].green; + blue = (short *) qdmap[dv->dv_unit].blue; for (i = cbuf->count, rgbp = cbuf->rgb; --i >= 0; rgbp++) { @@ -2047,7 +2240,7 @@ qdaint(qd) if (adder->status & FRAME_SYNC) { adder->status &= ~FRAME_SYNC; /* clear the interrupt */ - if (scroll[qd]->status & LOAD_REGS) { + if (scroll[dv->dv_unit]->status & LOAD_REGS) { for (i = 1000, adder->status = 0; i > 0 && !(adder->status&ID_SCROLL_READY); --i) @@ -2059,22 +2252,22 @@ qdaint(qd) return; } - adder->ID_scroll_data = scroll[qd]->viper_constant; + adder->ID_scroll_data = scroll[dv->dv_unit]->viper_constant; adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; adder->y_scroll_constant = - scroll[qd]->y_scroll_constant; - adder->y_offset_pending = scroll[qd]->y_offset; + scroll[dv->dv_unit]->y_scroll_constant; + adder->y_offset_pending = scroll[dv->dv_unit]->y_offset; - if (scroll[qd]->status & LOAD_INDEX) { + if (scroll[dv->dv_unit]->status & LOAD_INDEX) { adder->x_index_pending = - scroll[qd]->x_index_pending; + scroll[dv->dv_unit]->x_index_pending; adder->y_index_pending = - scroll[qd]->y_index_pending; + scroll[dv->dv_unit]->y_index_pending; } - scroll[qd]->status = 0x00; + scroll[dv->dv_unit]->status = 0x00; } } } @@ -2086,15 +2279,16 @@ qdaint(qd) * straight line code. */ -qdiint(qd) - register qd; +static void +qdiint(arg) + void *arg; { + struct device *dv = arg; register struct _vs_event *event; register struct qdinput *eqh; - struct dga *dga; - struct duart *duart; + volatile struct dga *dga; + volatile struct duart *duart; struct mouse_report *new_rep; - struct uba_device *ui; struct tty *tp; u_short chr; u_short status; @@ -2105,14 +2299,14 @@ qdiint(qd) (void)spl4(); /* allow interval timer in */ - eqh = eq_header[qd]; /* optimized as a register */ - new_rep = ¤t_rep[qd]; - duart = (struct duart *) qdmap[qd].duart; + eqh = eq_header[dv->dv_unit]; /* optimized as a register */ + new_rep = ¤t_rep[dv->dv_unit]; + duart = (struct duart *) qdmap[dv->dv_unit].duart; /* * if the graphic device is turned on.. */ - if (qdflags[qd].inuse & GRAPHIC_DEV) { + if (qdflags[dv->dv_unit].inuse & GRAPHIC_DEV) { /* * empty DUART */ @@ -2175,7 +2369,7 @@ qdiint(qd) * pick up the mouse input (if any) */ if ((status = duart->statusB) & RCV_RDY && - qdflags[qd].pntr_id == MOUSE_ID) { + qdflags[dv->dv_unit].pntr_id == MOUSE_ID) { if (status & 0x70) { duart->cmdB = 0x40; @@ -2230,17 +2424,17 @@ qdiint(qd) /* * calculate acceleration factor, if needed */ - if (qdflags[qd].curs_acc > ACC_OFF) { + if (qdflags[dv->dv_unit].curs_acc > ACC_OFF) { - if (qdflags[qd].curs_thr <= new_rep->dx) + if (qdflags[dv->dv_unit].curs_thr <= new_rep->dx) new_rep->dx += - (new_rep->dx - qdflags[qd].curs_thr) - * qdflags[qd].curs_acc; + (new_rep->dx - qdflags[dv->dv_unit].curs_thr) + * qdflags[dv->dv_unit].curs_acc; - if (qdflags[qd].curs_thr <= new_rep->dy) + if (qdflags[dv->dv_unit].curs_thr <= new_rep->dy) new_rep->dy += - (new_rep->dy - qdflags[qd].curs_thr) - * qdflags[qd].curs_acc; + (new_rep->dy - qdflags[dv->dv_unit].curs_thr) + * qdflags[dv->dv_unit].curs_acc; } /* @@ -2271,7 +2465,7 @@ qdiint(qd) /* * update cursor screen position */ - dga = (struct dga *) qdmap[qd].dga; + dga = (struct dga *) qdmap[dv->dv_unit].dga; dga->x_cursor = TRANX(eqh->curs_pos.x); dga->y_cursor = TRANY(eqh->curs_pos.y); @@ -2308,7 +2502,7 @@ GET_MBUTTON: * if button state has changed */ a = new_rep->state & 0x07; /*mask nonbutton bits */ - b = last_rep[qd].state & 0x07; + b = last_rep[dv->dv_unit].state & 0x07; if (a ^ b) { @@ -2356,11 +2550,11 @@ GET_MBUTTON: /* refresh last report */ - last_rep[qd] = current_rep[qd]; + last_rep[dv->dv_unit] = current_rep[dv->dv_unit]; } /* get last byte of report */ } else if ((status = duart->statusB)&RCV_RDY && - qdflags[qd].pntr_id == TABLET_ID) { + qdflags[dv->dv_unit].pntr_id == TABLET_ID) { /* * pickup tablet input, if any */ @@ -2422,9 +2616,9 @@ GET_MBUTTON: /* * update cursor position coordinates */ - new_rep->dx /= qdflags[qd].tab_res; + new_rep->dx /= qdflags[dv->dv_unit].tab_res; new_rep->dy = (2200 - new_rep->dy) - / qdflags[qd].tab_res; + / qdflags[dv->dv_unit].tab_res; if (new_rep->dx > 1023) { new_rep->dx = 1023; @@ -2446,7 +2640,7 @@ GET_MBUTTON: /* * update cursor screen position */ - dga = (struct dga *) qdmap[qd].dga; + dga = (struct dga *) qdmap[dv->dv_unit].dga; dga->x_cursor = TRANX(eqh->curs_pos.x); dga->y_cursor = TRANY(eqh->curs_pos.y); @@ -2487,7 +2681,7 @@ GET_TBUTTON: * if button state has changed */ a = new_rep->state & 0x1E; /* mask nonbutton bits */ - b = last_rep[qd].state & 0x1E; + b = last_rep[dv->dv_unit].state & 0x1E; if (a ^ b) { @@ -2536,7 +2730,7 @@ GET_TBUTTON: /* refresh last report */ - last_rep[qd] = current_rep[qd]; + last_rep[dv->dv_unit] = current_rep[dv->dv_unit]; } /* get last byte of report */ } /* pick up tablet input */ @@ -2546,10 +2740,10 @@ GET_TBUTTON: /* * do select wakeup */ - if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { - selwakeup(qdrsel[qd], 0); - qdrsel[qd] = 0; - qdflags[qd].selmask &= ~SEL_READ; + if (qdrsel[dv->dv_unit].si_pid && do_wakeup && qdflags[dv->dv_unit].selmask & SEL_READ) { + selwakeup(&qdrsel[dv->dv_unit]); + qdrsel[dv->dv_unit].si_pid = 0; + qdflags[dv->dv_unit].selmask &= ~SEL_READ; do_wakeup = 0; } } else { @@ -2558,11 +2752,11 @@ GET_TBUTTON: */ if (qdpolling) return; - ui = qdinfo[qd]; - if (ui == 0 || ui->ui_alive == 0) - return; + + if (dv->dv_unit >= qd_cd.cd_ndevs || qd_cd.cd_devs[dv->dv_unit] == NULL) + return; /* no such device or address */ - tp = &qd_tty[qd << 2]; + tp = qd_tty[dv->dv_unit << 2]; /* * Get a character from the keyboard. @@ -2590,10 +2784,10 @@ GET_TBUTTON: case LOCK: q_keyboard.lock ^= 0xffff; /* toggle */ if (q_keyboard.lock) - (void)led_control(qd, LK_LED_ENABLE, + led_control(qd, LK_LED_ENABLE, LK_LED_LOCK); else - (void)led_control(qd, LK_LED_DISABLE, + led_control(qd, LK_LED_DISABLE, LK_LED_LOCK); return; @@ -2646,8 +2840,17 @@ GET_TBUTTON: (*linesw[tp->t_line].l_rint)(*string++, tp); } else { -#ifdef KADB - if (!kdbrintr(chr&0177, tp)) +#ifdef DDB + /* Check for kernel debugger escape here */ + int j; + + j = kdbrint(chr&0177); + + if (j == 1) /* Escape received, just return */ + return; + + if (j == 2) /* Second char wasn't 'D' */ + (*linesw[tp->t_line].l_rint)(27, tp); #endif (*linesw[tp->t_line].l_rint)(chr&0177, tp); } @@ -2671,10 +2874,11 @@ GET_TBUTTON: * bitmap * */ +void clear_qd_screen(unit) int unit; { - register struct adder *adder; + volatile register struct adder *adder; adder = (struct adder *) qdmap[unit].adder; adder->x_limit = 1024; @@ -2703,14 +2907,16 @@ clear_qd_screen(unit) /* * kernel console output to the glass tty */ -qdputc(chr) - register char chr; +void +qdcnputc(dev, chr) + dev_t dev; + int chr; { /* * if system is now physical, forget it (ie: crash DUMP) */ - if ((mfpr(MAPEN) & 1) == 0) + if ((mfpr(PR_MAPEN) & 1) == 0) return; blitc(0, (u_char)(chr & 0xff)); @@ -2722,12 +2928,13 @@ qdputc(chr) /* * load the mouse cursor's template RAM bitmap */ +void ldcursor(unit, bitmap) int unit; - register short *bitmap; + short *bitmap; { - register struct dga *dga; - register short *temp; + volatile register struct dga *dga; + volatile register short *temp; register int i; int curs; @@ -2756,12 +2963,13 @@ ldcursor(unit, bitmap) /* * Put the console font in the QDSS off-screen memory */ +void ldfont(unit) int unit; { - register struct adder *adder; + volatile register struct adder *adder; - register i, j, k, max_chars_line; + register int i, j, k, max_chars_line; register short packed; adder = (struct adder *) qdmap[unit].adder; @@ -2881,19 +3089,30 @@ ldfont(unit) } /* ldfont */ -qdpoll(onoff) + +/* + * Disable or enable polling. This is used when entering or leaving the + * kernel debugger. + */ +void +qdcnpollc(dev, onoff) + dev_t dev; + int onoff; { - qdpolling = onoff; + qdpolling = onoff; } + /* * Get a character from the LK201 (polled) */ -qdgetc() +int +qdcngetc(dev) + dev_t dev; { register short key; register char chr; - register struct duart *duart; + volatile register struct duart *duart; duart = (struct duart *) qdmap[0].duart; @@ -2927,9 +3146,9 @@ LOOP: case LOCK: q_keyboard.lock ^= 0xffff; /* toggle */ if (q_keyboard.lock) - (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); + led_control(0, LK_LED_ENABLE, LK_LED_LOCK); else - (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); + led_control(0, LK_LED_DISABLE, LK_LED_LOCK); goto LOOP; case SHIFT: @@ -2985,11 +3204,12 @@ LOOP: /* * led_control()... twiddle LK-201 LED's */ +void led_control(unit, cmd, led_mask) int unit, cmd, led_mask; { - register i; - register struct duart *duart; + register int i; + volatile register struct duart *duart; duart = (struct duart *)qdmap[unit].duart; @@ -3005,17 +3225,16 @@ led_control(unit, cmd, led_mask) break; } } - if (i == 0) - return(BAD); - return(GOOD); + return; } /* led_control */ /* * scroll_up()... move the screen up one character height */ +void scroll_up(adder) - register struct adder *adder; + volatile struct adder *adder; { /* * setup VIPER operand control registers @@ -3076,10 +3295,11 @@ scroll_up(adder) /* * init shared memory pointers and structures */ +void init_shared(unit) - register unit; + int unit; { - register struct dga *dga; + volatile register struct dga *dga; dga = (struct dga *) qdmap[unit].dga; @@ -3138,21 +3358,22 @@ init_shared(unit) /* * init the ADDER, VIPER, bitmaps, & color map */ +void setup_dragon(unit) int unit; { - register struct adder *adder; - register struct dga *dga; - short *memcsr; - register i; + volatile register struct adder *adder; + volatile register struct dga *dga; + volatile short *memcsr; + register int i; short top; /* clipping/scrolling boundaries */ short bottom; short right; short left; - short *red; /* color map pointers */ - short *green; - short *blue; + volatile short *red; /* color map pointers */ + volatile short *green; + volatile short *blue; /* * init for setup @@ -3392,11 +3613,12 @@ setup_dragon(unit) /* * Init the DUART and set defaults in input */ +void setup_input(unit) int unit; { - register struct duart *duart; /* DUART register structure pointer */ - register i, bits; + volatile register struct duart *duart; /* DUART register structure pointer */ + register int i, bits; char id_byte; duart = (struct duart *) qdmap[unit].duart; @@ -3558,11 +3780,12 @@ OUT: * vertical sync status bit * GOOD otherwise */ +int wait_status(adder, mask) - register struct adder *adder; - register int mask; + volatile struct adder *adder; + int mask; { - register i; + register int i; for (i = 10000, adder->status = 0 ; i > 0 && !(adder->status&mask) ; --i) @@ -3580,12 +3803,13 @@ wait_status(adder, mask) /* * write out onto the ID bus */ +void write_ID(adder, adrs, data) - register struct adder *adder; - register short adrs; - register short data; + volatile struct adder *adder; + short adrs; + short data; { - register i; + register int i; for (i = 100000, adder->status = 0 ; i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) @@ -3609,4 +3833,3 @@ ERR: return ; } /* write_ID */ -#endif diff --git a/sys/arch/vax/qbus/qdioctl.h b/sys/arch/vax/qbus/qdioctl.h new file mode 100644 index 00000000000..3e91b891b01 --- /dev/null +++ b/sys/arch/vax/qbus/qdioctl.h @@ -0,0 +1,118 @@ +/* $OpenBSD: qdioctl.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */ +/* $NetBSD: qdioctl.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)qdioctl.h 7.2 (Berkeley) 1/21/94 + */ + +/* + * derived from: qdioctl.h 1.1 (ULTRIX) 8/22/85 + */ +/* + * QDSS IOCTL definitions + */ + + +/************************************************************************ + * * + * Copyright (c) 1985 by * + * Digital Equipment Corporation, Maynard, MA * + * All rights reserved. * + * * + * This software is furnished under a license and may be used and * + * copied only in accordance with the terms of such license and * + * with the inclusion of the above copyright notice. This * + * software or any other copies thereof may not be provided or * + * otherwise made available to any other person. No title to and * + * ownership of the software is hereby transferred. * + * * + * This software is derived from software received from the * + * University of California, Berkeley, and from Bell * + * Laboratories. Use, duplication, or disclosure is subject to * + * restrictions under license agreements with University of * + * California and with AT&T. * + * * + * The information in this software is subject to change without * + * notice and should not be construed as a commitment by Digital * + * Equipment Corporation. * + * * + * Digital assumes no responsibility for the use or reliability * + * of its software on equipment which is not supplied by Digital. * + * * + ************************************************************************/ +/*************************************************************************** +* revision history: (belongs in sccs) +**************************************************************************** +* +* 22 oct 85 longo fixed QD_PRGTABRES cmd number to be 22 instead of 12 +* 14 oct 85 longo added QD_KERN_LOOP and QD_KERN_UNLOOP +* 02 oct 85 longo added QD_MAPCOLOR and QD_UNMAPCOLOR +* 17 sep 85 longo made QD_MAPIOBUF a read/write command type +* +***************************************************************************/ + + +#ifdef KERNEL +#include "sys/ioctl.h" +#else +#include <sys/ioctl.h> +#endif + + +#define QD_GETEVENT _IOR('g', 1, struct _vs_event) /* get oldest event */ +#define QD_WTCURSOR _IOW('g', 2, short[32]) /* write cursor bitmap */ +#define QD_RDCURSOR _IOR('g', 3, 64) /* read cursor bitmap */ +#define QD_CLRSCRN _IO('g', 4) /* clear the screen */ +#define QD_RDCONFIG _IOR('g', 5, short) /* read QDSS configuration */ +#define QD_PRGMOUSE _IOW('g', 6, char) /* program mouse */ +#define QD_PRGTABLET _IOW('g', 7, char) /* program tablet */ +#define QD_PRGKBD _IOW('g', 8, struct prgkbd) /* program LK201 kbd */ +#define QD_MAPDEVICE _IOR('g', 9, struct qdmap) /* map device to user */ +#define QD_MAPIOBUF _IOWR('g', 10, caddr_t) /* map DMA iobuf to user */ +#define QD_MAPEVENT _IOR('g', 11, caddr_t) /* map event queue to user */ +#define QD_PRGCURSOR _IOW('g', 12, struct prg_cursor) /* program cursor */ +#define QD_RESET _IO('g', 13) /* set device & driver defaults */ +#define QD_POSCURSOR _IOW('g', 14, struct _vs_cursor) /* position cursor */ +#define QD_SET _IO('g', 15) /* set DUART & driver defaults */ +#define QD_MAPSCROLL _IOR('g', 16, caddr_t) /* map scroll param area */ +#define QD_UNMAPSCROLL _IO('g', 17) /* unmap scroll param area */ +#define QD_MAPCOLOR _IOR('g', 18, caddr_t) /* map color map write buf */ +#define QD_UNMAPCOLOR _IO('g', 19) /* unmap color map write buf */ +#define QD_KERN_LOOP _IO('g', 20) /* detour kernel console output */ +#define QD_KERN_UNLOOP _IO('g', 21) /* un-detour kernel console output */ +#define QD_PRGTABRES _IOW('g', 22, short) /* program tablet resolution */ diff --git a/sys/arch/vax/qbus/qdreg.h b/sys/arch/vax/qbus/qdreg.h new file mode 100644 index 00000000000..d6aa7452ceb --- /dev/null +++ b/sys/arch/vax/qbus/qdreg.h @@ -0,0 +1,381 @@ +/* $OpenBSD: qdreg.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */ +/* $NetBSD: qdreg.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)qdreg.h 7.1 (Berkeley) 5/9/91 + */ + +/************************************************************************ + * * + * Copyright (c) 1985, 1986 by * + * Digital Equipment Corporation, Maynard, MA * + * All rights reserved. * + * * + * This software is furnished under a license and may be used and * + * copied only in accordance with the terms of such license and * + * with the inclusion of the above copyright notice. This * + * software or any other copies thereof may not be provided or * + * otherwise made available to any other person. No title to and * + * ownership of the software is hereby transferred. * + * * + * The information in this software is subject to change without * + * notice and should not be construed as a commitment by Digital * + * Equipment Corporation. * + * * + * Digital assumes no responsibility for the use or reliability * + * of its software on equipment which is not supplied by Digital. * + * * + ************************************************************************/ + +/* Dragon ADDER reg map */ +/* ADDER register bit definitions */ +/* Y_SCROLL_CONSTANT */ + +#define SCROLL_ERASE 0x2000 +#define ADDER_SCROLL_DOWN 0x1000 + +/* ADDER status and interrupt enable registers [1], [2], [3] */ + +#define DISABLE 0x0000 +#define PAUSE_COMPLETE 0x0001 +#define FRAME_SYNC 0x0002 +#define INIT_COMPLETE 0x0004 +#define RASTEROP_COMPLETE 0x0008 + +#define ADDRESS_COMPLETE 0x0010 +#define RX_READY 0x0020 +#define TX_READY 0x0040 +#define ID_SCROLL_READY 0x0080 + +#define TOP_CLIP 0x0100 +#define BOTTOM_CLIP 0x0200 +#define LEFT_CLIP 0x0400 +#define RIGHT_CLIP 0x0800 +#define NO_CLIP 0x1000 +#define VSYNC 0x2000 + +/* ADDER command register [8], [10] */ + +#define OCR_zero 0x0000 +#define Z_BLOCK0 0x0000 +#define OCRA 0x0000 +#define OCRB 0x0004 +#define RASTEROP 0x02c0 +#define PBT 0x03c0 +#define BTPZ 0x0bb0 +#define PTBZ 0x07a0 +#define DTE 0x0400 +#define S1E 0x0800 +#define S2E 0x1000 +#define VIPER_Z_LOAD 0x01A0 +#define ID_LOAD 0x0100 +#define CANCEL 0x0000 +#define LF_R1 0x0000 +#define LF_R2 0x0010 +#define LF_R3 0x0020 +#define LF_R4 0x0030 + +/* ADDER rasterop mode register [9] */ + +#define NORMAL 0x0000 +#define LINEAR_PATTERN 0x0002 +#define X_FILL 0x0003 +#define Y_FILL 0x0007 +#define BASELINE 0x0008 +#define HOLE_ENABLE 0x0010 +#define SRC_1_INDEX_ENABLE 0x0020 +#define DST_INDEX_ENABLE 0x0040 +#define DST_WRITE_ENABLE 0x0080 + +/* ADDER source 2 size register */ + +#define NO_TILE 0x0080 + +/* External registers base addresses */ + +#define CS_UPDATE_MASK 0x0060 +#define CS_SCROLL_MASK 0x0040 + +/* VIPER registers */ + +#define RESOLUTION_MODE 0x0080 +#define MEMORY_BUS_WIDTH 0x0081 +#define PLANE_ADDRESS 0x0083 +#define LU_FUNCTION_R1 0x0084 +#define LU_FUNCTION_R2 0x0085 +#define LU_FUNCTION_R3 0x0086 +#define LU_FUNCTION_R4 0x0087 +#define MASK_1 0x0088 +#define MASK_2 0x0089 +#define SOURCE 0x008a +#define SOURCE_Z 0x0000 +#define BACKGROUND_COLOR 0x008e +#define BACKGROUND_COLOR_Z 0x000C +#define FOREGROUND_COLOR 0x008f +#define FOREGROUND_COLOR_Z 0x0004 +#define SRC1_OCR_A 0x0090 +#define SRC2_OCR_A 0x0091 +#define DST_OCR_A 0x0092 +#define SRC1_OCR_B 0x0094 +#define SRC2_OCR_B 0x0095 +#define DST_OCR_B 0x0096 + +/* VIPER scroll registers */ + +#define SCROLL_CONSTANT 0x0082 +#define SCROLL_FILL 0x008b +#define SCROLL_FILL_Z 0x0008 +#define LEFT_SCROLL_MASK 0x008c +#define RIGHT_SCROLL_MASK 0x008d + +/* VIPER register bit definitions */ + +#define EXT_NONE 0x0000 +#define EXT_SOURCE 0x0001 +#define EXT_M1_M2 0x0002 +#define INT_NONE 0x0000 +#define INT_SOURCE 0x0004 +#define INT_M1_M2 0x0008 +#define ID 0x0010 +#define NO_ID 0x0000 +#define WAIT 0x0020 +#define NO_WAIT 0x0000 +#define BAR_SHIFT_DELAY WAIT +#define NO_BAR_SHIFT_DELAY NO_WAIT + + +/* VIPER logical function unit codes */ + +#define LF_ZEROS 0x0000 +#define LF_D_XOR_S 0x0006 +#define LF_SOURCE 0x000A +#define LF_D_OR_S 0x000E +#define LF_ONES 0x000F +#define INV_M1_M2 0x0030 +#define FULL_SRC_RESOLUTION 0X00C0 /* makes second pass like first pass */ + +/* VIPER scroll register [2] */ + +#define SCROLL_DISABLE 0x0040 +#define SCROLL_ENABLE 0x0020 +#define VIPER_LEFT 0x0000 +#define VIPER_RIGHT 0x0010 +#define VIPER_UP 0x0040 +#define VIPER_DOWN 0x0000 + +/* Adder scroll register */ + +#define ADDER_UP 0x0000 +#define ADDER_DOWN 0x1000 + +/* Misc scroll definitions */ + +#define UP 0 +#define DOWN 1 +#define LEFT 2 +#define RIGHT 3 +#define NODIR 4 +#define SCROLL_VMAX 31 +#define SCROLL_HMAX 15 +#define NEW 2 +#define OLD 1 +#define BUSY 1 +#define DRAG 1 +#define SCROLL 0 + +/* miscellaneous defines */ + +#define ALL_PLANES 0xffffffff +#define UNITY 0x1fff /* Adder scale factor */ +#define MAX_SCREEN_X 1024 +#define MAX_SCREEN_Y 864 +#define FONT_HEIGHT 32 + + struct adder { + + /* adder control registers */ + + u_short register_address; /* ADDER reg pntr for use by DGA */ + u_short request_enable; /* DMA request enables */ + u_short interrupt_enable; /* interrupt enables */ + u_short status; /* ADDER status bits */ + u_short reserved1; /* test function only */ + u_short spare1; /* spare address (what else?) */ + + u_short reserved2; /* test function only */ + u_short id_data; /* data path to I/D bus */ + u_short command; /* ADDER chip command register */ + u_short rasterop_mode; /* sets rasterop execution modes */ + u_short cmd; /* duplicate path to above cmd reg */ + u_short reserved3; /* test function only */ + + /* scroll registers */ + + u_short ID_scroll_data; /* I/D bus scroll data */ + u_short ID_scroll_command; /* I/D bus scroll command */ + u_short scroll_x_min; /* X scroll min - left boundary */ + u_short scroll_x_max; /* X scroll max - right boundary */ + u_short scroll_y_min; /* Y scroll min - upper boundary */ + u_short scroll_y_max; /* Y scroll max - lower boundary */ + u_short pause; /* Y coord to set stat when scanned */ + u_short y_offset_pending; /* vertical scroll control */ + u_short y_scroll_constant; + + /* update control registers */ + + u_short x_index_pending; /* x pending index */ + u_short y_index_pending; /* y pending index */ + u_short x_index_new; /* new x index */ + u_short y_index_new; /* new y index */ + u_short x_index_old; /* old x index */ + u_short y_index_old; /* old y index */ + u_short x_clip_min; /* left clipping boundary */ + u_short x_clip_max; /* right clipping boundary */ + u_short y_clip_min; /* upper clipping boundary */ + u_short y_clip_max; /* lower clipping boundary */ + u_short spare2; /* spare address (another!) */ + + /* rasterop control registers */ + + u_short source_1_dx; /* source #1 x vector */ + u_short source_1_dy; /* source #1 y vector*/ + u_short source_1_x; /* source #1 x origin */ + u_short source_1_y; /* source #1 y origin */ + u_short destination_x; /* destination x origin */ + u_short destination_y; /* destination y origin */ + u_short fast_dest_dx; /* destination x fast vector */ + u_short fast_dest_dy; /* destination y fast vector */ + u_short slow_dest_dx; /* destination x slow vector */ + u_short slow_dest_dy; /* destination y slow vector */ + u_short fast_scale; /* scale factor for fast vector */ + u_short slow_scale; /* scale factor for slow vector */ + u_short source_2_x; /* source #2 x origin */ + u_short source_2_y; /* source #2 y origin */ + u_short source_2_size; /* source #2 height & width */ + u_short error_1; /* error regs (?) */ + u_short error_2; + + /* screen format control registers */ + + u_short y_scan_count_0; /* y scan counts for vert timing */ + u_short y_scan_count_1; + u_short y_scan_count_2; + u_short y_scan_count_3; + u_short x_scan_conf; /* x scan configuration */ + u_short x_limit; + u_short y_limit; + u_short x_scan_count_0; /* x scan count for horiz timing */ + u_short x_scan_count_1; + u_short x_scan_count_2; + u_short x_scan_count_3; + u_short x_scan_count_4; + u_short x_scan_count_5; + u_short x_scan_count_6; + u_short sync_phase_adj; /* sync phase (horiz sync count) */ + }; + +/*--------------------- +* DUART definitions */ + + /* command definitions */ + +#define EN_RCV 0x01 +#define DIS_RCV 0x02 +#define EN_XMT 0x04 +#define DIS_XMT 0x08 +#define RESET_M 0x10 +#define RESET_RCV 0x20 +#define RESET_XMT 0x30 +#define RESET_ERR 0x40 +#define RESET_BD 0x50 +#define START_BREAK 0x60 +#define STOP_BREAK 0x70 + + /* interupt bit definitions */ + +#define EI_XMT_A 0x01 +#define EI_RCV_A 0x02 +#define EI_XMT_B 0x10 +#define EI_RCV_B 0x20 + +#define XMT_RDY_A 0x01 +#define RCV_RDY_A 0x02 +#define XMT_RDY_B 0x10 +#define RCV_RDY_B 0x20 + + /* status register bit defintions */ + +#define RCV_RDY 0x01 +#define FIFO_FULL 0x02 +#define XMT_RDY 0x04 +#define XMT_EMT 0x08 +#define OVER_ERR 0x10 +#define ERR_PARITY 0x20 +#define FRAME_ERR 0x40 +#define RCVD_BREAK 0x80 + + + struct duart { + + /* channel A - LK201 */ + + short modeA; /* ch.A mode reg (read/write) */ + short statusA; /* ch.A status reg (read) */ +#define clkselA statusA /* ch.A clock slect reg (write) */ + short cmdA; /* ch.A command reg (write) */ + short dataA; /* rcv/xmt data ch.A (read/write) */ + short inchng; /* input change state reg (read) */ +#define auxctl inchng /* auxiliary control reg (write) */ + short istatus; /* interrupt status reg (read) */ +#define imask istatus /* interrupt mask reg (write) */ + short CThi; /* counter/timer hi byte (read) */ +#define CTRhi CThi /* counter/timer hi reg (write) */ + short CTlo; /* counter/timer lo byte (read) */ +#define CTRlo CTlo /* counter/timer lo reg (write) */ + + /* channel B - pointing device */ + + short modeB; /* ch.B mode reg (read/write) */ + short statusB; /* ch.B status reg (read) */ +#define clkselB statusB /* ch.B clock select reg (write) */ + short cmdB; /* ch.B command reg (write) */ + short dataB; /* ch.B rcv/xmt data (read/write) */ + short rsrvd; + short inport; /* input port (read) */ +#define outconf inport /* output port config reg (write) */ + short strctr; /* start counter command (read) */ +#define setbits setctr /* output bits set command (write) */ + short stpctr; /* stop counter command (read) */ +#define resetbits stpctr /* output bits reset cmd (write) */ + +}; diff --git a/sys/arch/vax/qbus/qduser.h b/sys/arch/vax/qbus/qduser.h new file mode 100644 index 00000000000..fbf83c7b095 --- /dev/null +++ b/sys/arch/vax/qbus/qduser.h @@ -0,0 +1,514 @@ +/* $OpenBSD: qduser.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */ +/* $NetBSD: qduser.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)qduser.h 7.1 (Berkeley) 5/9/91 + */ + +/* derived from: @(#)qduser.h 6.1 (ULTRIX) 11/24/87 */ +/************************************************************************ + * * + * Copyright (c) 1986 by * + * Digital Equipment Corporation, Maynard, MA * + * All rights reserved. * + * * + * This software is furnished under a license and may be used and * + * copied only in accordance with the terms of such license and * + * with the inclusion of the above copyright notice. This * + * software or any other copies thereof may not be provided or * + * otherwise made available to any other person. No title to and * + * ownership of the software is hereby transferred. * + * * + * The information in this software is subject to change without * + * notice and should not be construed as a commitment by Digital * + * Equipment Corporation. * + * * + * Digital assumes no responsibility for the use or reliability * + * of its software on equipment which is not supplied by Digital. * + * * + ************************************************************************/ + +/*************************************************************************** +* +* QDUSER... +* This file defines values shared between the driver and a client +* +***************************************************************************/ + +/*************************************************************************** +* revision history: +**************************************************************************** +* +* 21 jul 86 ram fixed define of CURSOR_MIN_Y +* 25 nov 85 longo added macro and bit defines for DMA error flags +* 11 nov 85 longo renamed _vs_eventqueue to "qdinput" struct +* 23 oct 85 longo added more defines to the DMA stuff +* 17 oct 85 longo changed "struct rgb" chars to be unsigned +* 16 oct 85 longo added new TABLET support definitions +* 15 oct 85 longo re-wrote DMA queue access macros +* 08 oct 85 longo added status flag manipulation macros to DMA stuff +* 02 oct 85 longo added support for color map write buffer loading +* 26 sep 85 longo removed adder sertup params from DMA request struct +* 23 sep 85 longo added DMA queue access macros +* 30 aug 85 longo fixed crock in "qdiobuf" struct compile-time sizing. Also +* removed DMAcontrol struct from DMA buffer for field test +* 26 aug 85 longo put in conditional include of "qevent.h" for user prg's +* 18 jul 85 longo changed semantics so that head is tail and tail is head +* 12 jul 85 longo moved "mouse_report" struct and defs over to qd_data.c +* 11 jul 85 longo added device coordinate to gate array cursor coordinate +* transformation macros +* 03 jul 85 longo changed kernel typdef's for data types to long-hand +* 10 may 85 longo created +* +***************************************************************************/ + +#ifdef KERNEL +#include "../include/qevent.h" /* include event struct defs */ +#else +#include <vax/uba/qevent.h> +#endif + +/*--------------------- +* QDSS device map */ + + struct qdmap { /* map of register blocks in QDSS */ + + char *template; + char *adder; + char *dga; + char *duart; + char *memcsr; + char *red; + char *blue; + char *green; + }; + +/*-------------------------------------------- +* DGA CSR bit definitions and register map */ + +#define DMADONE 0x8000 /* DMA done status */ +#define SET_DONE_FIFO 0x4000 /* set DMADONE when FIFO empty.. */ + /* ..AND count = 0 */ + +#define PTOB_ENB 0x0600 /* host-to-bitmap DMA xfer */ +#define BTOP_ENB 0x0400 /* bitmap-to-host DMA xfer */ +#define DL_ENB 0x0200 /* display list DMA xfer */ +#define HALT 0x0000 /* halt DGA */ + +#define BYTE_DMA 0x0100 /* byte/word DMA xfer */ + +#define DMA_ERR 0x0080 /* DMA error bits */ +#define PARITY_ERR 0x0040 /* memory parity error in DMA */ +#define BUS_ERR 0x0020 /* bus timeout error in DMA */ + +#define GLOBAL_IE 0x0004 /* global interrupt enable */ +#define DMA_IE 0x0002 /* DMA interrupt enable */ +#define CURS_ENB 0x0001 /* cursor enable */ + +/* QDSS memcsr bit definitions */ + +#define UNBLANK 0x0020 +#define SYNC_ON 0x0008 + + struct dga { + + unsigned short csr; + unsigned short adrs_lo; /* destination address of bitmap to */ + unsigned short adrs_hi; /* host DMA */ + unsigned short bytcnt_lo; /* byte length of requested DMA */ + unsigned short bytcnt_hi; /* (WO = bytcnt) (RO = fifo count) */ + unsigned short fifo; /* FIFO register */ + unsigned short x_cursor; /* cursor position registers */ + unsigned short y_cursor; + unsigned short ivr; /* interrupt vector register */ + unsigned short memadr; /* memory base address register */ + }; + +/*------------------------------------------------------------------------- +* macros to transform device coordinates to hardware cursor coordinates */ + +#define CURS_MIN_X 232 /* device coordinate x = 0 */ +#define CURS_MIN_Y 16 /* device coordinate y = 0 */ + +#define TRANX(x) ( -(((int)(x)+CURS_MIN_X) & ~0x0003) | \ + (((int)(x)+CURS_MIN_X) & 0x0003) ) + +#define TRANY(y) ( -((y)+CURS_MIN_Y) ) + +/********************************************************************* +* +* EVENT QUEUE DEFINITIONS +* +********************************************************************** +* most of the event queue definitions are found in "qevent.h". But a +* few things not found there are here. */ + +/* The event queue header */ + +struct qdinput { + + struct _vs_eventqueue header; /* event queue ring handling */ + + /* for VS100 and QVSS compatability reasons, additions to this + * structure must be made below this point. */ + + struct _vs_cursor curs_pos; /* current mouse position */ + struct _vs_box curs_box; /* cursor reporting box */ + + }; + +/* vse_key field. definitions for mouse buttons */ + +#define VSE_LEFT_BUTTON 0 +#define VSE_MIDDLE_BUTTON 1 +#define VSE_RIGHT_BUTTON 2 + +/* vse_key field. definitions for mouse buttons */ + +#define VSE_T_LEFT_BUTTON 0 +#define VSE_T_FRONT_BUTTON 1 +#define VSE_T_RIGHT_BUTTON 2 +#define VSE_T_BACK_BUTTON 4 + +#define VSE_T_BARREL_BUTTON VSE_T_LEFT_BUTTON +#define VSE_T_TIP_BUTTON VSE_T_FRONT_BUTTON + +/*-------------------------------------------------------------------------- +* These are the macros to be used for loading and extracting from the event +* queue. It is presumed that the macro user will only use the access macros +* if the event queue is non-empty ( ISEMPTY(eq) == FALSE ), and that the +* driver will only load the event queue after checking that it is not full +* ( ISFULL(eq) == FALSE ). ("eq" is a pointer to the event queue header.) +* +* Before an event access session for a particular event, the macro users +* must use the xxxBEGIN macro, and the xxxEND macro after an event is through +* with. As seen below, the xxxBEGIN and xxxEND macros maintain the event +* queue access mechanism. +* +* First, the macros to be used by the event queue reader +*/ + +#define ISEMPTY(eq) ((eq)->header.head == (eq)->header.tail) +#define GETBEGIN(eq) (&(eq)->header.events[(eq)->header.head]) + +#define GET_X(event) ((event)->vse_x) /* get x position */ +#define GET_Y(event) ((event)->vse_y) /* get y position */ +#define GET_TIME(event) ((event)->vse_time) /* get time */ +#define GET_TYPE(event) ((event)->vse_type) /* get entry type */ +#define GET_KEY(event) ((event)->vse_key) /* get keycode */ +#define GET_DIR(event) ((event)->vse_direction) /* get direction */ +#define GET_DEVICE(event) ((event)->vse_device) /* get device */ + +#define GETEND(eq) (++(eq)->header.head >= (eq)->header.size ? \ + (eq)->header.head = 0 : 0 ) + +/*------------------------------------------------ +* macros to be used by the event queue loader */ + + /* ISFULL yields TRUE if queue is full */ + +#define ISFULL(eq) ((eq)->header.tail+1 == (eq)->header.head || \ + ((eq)->header.tail+1 == (eq)->header.size && \ + (eq)->header.head == 0)) + + /* get address of the billet for NEXT event */ + +#define PUTBEGIN(eq) (&(eq)->header.events[(eq)->header.tail]) + +#define PUT_X(event, value) ((event)->vse_x = value) /* put X pos */ +#define PUT_Y(event, value) ((event)->vse_y = value) /* put Y pos */ +#define PUT_TIME(event, value) ((event)->vse_time = value) /* put time */ +#define PUT_TYPE(event, value) ((event)->vse_type = value) /* put type */ +#define PUT_KEY(event, value) ((event)->vse_key = value) /* put input key */ +#define PUT_DIR(event, value) ((event)->vse_direction = value) /* put dir */ +#define PUT_DEVICE(event, value) ((event)->vse_device = value) /* put dev */ + +#define PUTEND(eq) (++(eq)->header.tail >= (eq)->header.size ? \ + (eq)->header.tail = 0 : 0) + +/****************************************************************** +* +* DMA I/O DEFINITIONS +* +******************************************************************/ + +/*--------------------------------------------------------------------- +* The DMA request queue is implemented as a ring buffer of "DMAreq" + structures. The queue is accessed using ring indices located in the + "DMAreq_header" structure. Access is implemented using access macros + similar to the event queue access macros above. */ + + struct DMAreq { + + short DMAtype; /* DMA type code (for QDSS) */ + short DMAdone; /* DMA done parameter */ + char *bufp; /* virtual adrs of buffer */ + int length; /* transfer buffer length */ + }; + +/* DMA type command codes */ + +#define DISPLIST 1 /* display list DMA */ +#define PTOB 2 /* 1 plane Qbus to bitmap DMA */ +#define BTOP 3 /* 1 plane bitmap to Qbus DMA */ + +/* DMA done notification code */ + +#define FIFO_EMPTY 0x01 /* DONE when FIFO becomes empty */ +#define COUNT_ZERO 0x02 /* DONE when count becomes zero */ +#define WORD_PACK 0x04 /* program the gate array for word packing */ +#define BYTE_PACK 0x08 /* program gate array for byte packing */ +#define REQUEST_DONE 0x100 /* clear when driver has processed request */ +#define HARD_ERROR 0x200 /* DMA hardware error occurred */ + +/* DMA request queue is a ring buffer of request structures */ + + struct DMAreq_header { + + int QBAreg; /* cookie Qbus map reg for this buffer */ + short status; /* master DMA status word */ + int shared_size; /* size of shared memory in bytes */ + struct DMAreq *DMAreq; /* start address of request queue */ + int used; /* # of queue entries currently used */ + int size; /* # of "DMAreq"'s in the request queue */ + int oldest; /* index to oldest queue'd request */ + int newest; /* index to newest queue'd request */ + }; + +/* bit definitions for DMAstatus word in DMAreq_header */ + +#define DMA_ACTIVE 0x0004 /* DMA in progress */ +#define DMA_ERROR 0x0080 /* DMA hardware error */ +#define DMA_IGNORE 0x0002 /* flag to ignore this interrupt */ + +/*------------------------------------------ +* macros for DMA request queue fiddling */ + + /* DMA status set/check macros */ + +#define DMA_SETACTIVE(header) ((header)->status |= DMA_ACTIVE) +#define DMA_CLRACTIVE(header) ((header)->status &= ~DMA_ACTIVE) +#define DMA_ISACTIVE(header) ((header)->status & DMA_ACTIVE) + +#define DMA_SETERROR(header) ((header)->status |= DMA_ERROR) +#define DMA_CLRERROR(header) ((header)->status &= ~DMA_ERROR) +#define DMA_ISERROR(header) ((header)->status & DMA_ERROR) + +#define DMA_SETIGNORE(header) ((header)->status |= DMA_IGNORE) +#define DMA_CLRIGNORE(header) ((header)->status &= ~DMA_IGNORE) +#define DMA_ISIGNORE(header) ((header)->status & DMA_IGNORE) + + /* yields TRUE if queue is empty (ISEMPTY) or full (ISFULL) */ + +#define DMA_ISEMPTY(header) ((header)->used == 0) +#define DMA_ISFULL(header) ((header)->used >= (header)->size) + + /* returns address of the billet for next (PUT) + * or oldest (GET) request */ + +#define DMA_PUTBEGIN(header) (&(header)->DMAreq[(header)->newest]) +#define DMA_GETBEGIN(header) (&(header)->DMAreq[(header)->oldest]) + + /* does queue access pointer maintenance */ + +#define DMA_GETEND(header) (++(header)->oldest >= (header)->size \ + ? (header)->oldest = 0 : 0); \ + --(header)->used; + +#define DMA_PUTEND(header) (++(header)->newest >= (header)->size \ + ? (header)->newest = 0 : 0); \ + ++(header)->used; + +/****************************************************************** +* +* COLOR MAP WRITE BUFFER DEFINITIONS +* +******************************************************************/ + + struct rgb { + + unsigned char offset; /* color map address for load */ + unsigned char red; /* data for red map */ + unsigned char green; /* data for green map */ + unsigned char blue; /* data for blue map */ + }; + + struct color_buf { + + char status; /* load request/service status */ + short count; /* number of entries to br loaded */ + struct rgb rgb[256]; + }; + +#define LOAD_COLOR_MAP 0x0001 + +/****************************************************************** +* +* SCROLL ASSIST DEFINITIONS +* +******************************************************************/ + + struct scroll { + + short status; + short viper_constant; + short y_scroll_constant; + short y_offset; + short x_index_pending; + short y_index_pending; + }; + +#define LOAD_REGS 0x0001 +#define LOAD_INDEX 0x0002 + +/****************************************************************** +* +* MOUSE/TABLET/KBD PROGRAMMING DEFINITIONS +* +******************************************************************/ + +/*----------------------------------- +* LK201 programmming definitions */ + +#define LK_UPDOWN 0x86 /* bits for setting lk201 modes */ +#define LK_AUTODOWN 0x82 +#define LK_DOWN 0x80 +#define LK_DEFAULTS 0xD3 /* reset (some) default settings */ +#define LK_AR_ENABLE 0xE3 /* global auto repeat enable */ +#define LK_CL_ENABLE 0x1B /* keyclick enable */ +#define LK_KBD_ENABLE 0x8B /* keyboard enable */ +#define LK_BELL_ENABLE 0x23 /* the bell */ +#define LK_RING_BELL 0xA7 /* ring keyboard bell */ + +#define LK_LED_ENABLE 0x13 /* light led */ +#define LK_LED_DISABLE 0x11 /* turn off led */ +#define LED_1 0x81 /* led bits */ +#define LED_2 0x82 +#define LED_3 0x84 +#define LED_4 0x88 +#define LED_ALL 0x8F +#define LK_LED_HOLD LED_4 +#define LK_LED_LOCK LED_3 +#define LK_LED_COMPOSE LED_2 +#define LK_LED_WAIT LED_1 + +#define LK_KDOWN_ERROR 0x3D /* key down on powerup error */ +#define LK_POWER_ERROR 0x3E /* keyboard failure on powerup test */ +#define LK_OUTPUT_ERROR 0xB5 /* keystrokes lost during inhibit */ +#define LK_INPUT_ERROR 0xB6 /* garbage command to keyboard */ +#define LK_LOWEST 0x56 /* lowest significant keycode */ +#define LK_DIV6_START 0xAD /* start of div 6 */ +#define LK_DIV5_END 0xB2 /* end of div 5 */ + +#define LAST_PARAM 0x80 /* "no more params" bit */ + + struct prgkbd { + + short cmd; /* LK201 command opcode */ + short param1; /* 1st cmd parameter (can be null) */ + short param2; /* 2nd cmd parameter (can be null) */ + }; + +/*------------------------- +* "special" LK-201 keys */ + +#define SHIFT 174 +#define LOCK 176 +#define REPEAT 180 +#define CNTRL 175 +#define ALLUP 179 + +/*-------------------------------- +* cursor programming structure */ + + struct prg_cursor { + + unsigned short acc_factor; /* cursor aceleration factor */ + unsigned short threshold; /* threshold to trigger acc at */ + }; + +/*--------------------- +* mouse definitions */ + +#define INC_STREAM_MODE 'R' /* stream mode reports (55 hz) */ +#define PROMPT_MODE 'D' /* report when prompted */ +#define REQUEST_POS 'P' /* request position report */ +#define SELF_TEST 'T' /* request self test */ + +#define MOUSE_ID 0x2 /* mouse ID in lo 4 bits */ + +#define START_FRAME 0x80 /* start of report frame bit */ +#define X_SIGN 0x10 /* position sign bits */ +#define Y_SIGN 0x08 + +#define RIGHT_BUTTON 0x01 /* mouse buttons */ +#define MIDDLE_BUTTON 0x02 +#define LEFT_BUTTON 0x04 + + /* mouse report structure definition */ + + struct mouse_report { + + char state; /* buttons and sign bits */ + short dx; /* delta X since last change */ + short dy; /* delta Y since last change */ + char bytcnt; /* mouse report byte count */ + }; + +/*----------------------------------------- +* tablet command/interface definitions */ + +#define T_STREAM 'R' /* continuous stream report mode */ +#define T_POINT 'D' /* enter report-on-request mode */ +#define T_REQUEST 'P' /* request position report */ + +#define T_BAUD 'B' /* increase baud to 9600 from 4800 */ +#define T_RATE_55 'K' /* report rate: 55/sec */ +#define T_RATE_72 'L' /* report rate: 72/sec */ +#define T_RATE_120 'M' /* report rate: 120/sec (9600 only) */ + +#define T_TEST SELF_TEST /* do self test */ + +#define TABLET_ID 0x4 /* tablet ID in lo 4 bits */ + +#define T_START_FRAME 0x80 /* start of report frame bit */ +#define T_PROXIMITY 0x01 /* state pointer in proximity */ + +#define T_LEFT_BUTTON 0x02 /* puck buttons */ +#define T_FRONT_BUTTON 0x04 +#define T_RIGHT_BUTTON 0x08 +#define T_BACK_BUTTON 0x10 + +#define T_BARREL_BUTTON T_LEFT_BUTTON /* stylus buttons */ +#define T_TIP_BUTTON T_FRONT_BUTTON + diff --git a/sys/arch/vax/qbus/qevent.h b/sys/arch/vax/qbus/qevent.h new file mode 100644 index 00000000000..93e7c30acdd --- /dev/null +++ b/sys/arch/vax/qbus/qevent.h @@ -0,0 +1,120 @@ +/* $OpenBSD: qevent.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */ +/* $NetBSD: qevent.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)qevent.h 7.1 (Berkeley) 5/9/91 + */ + +/************************************************************************ +* * +* Copyright (c) 1985 by * +* Digital Equipment Corporation, Maynard, MA * +* All rights reserved. * +* * +* This software is furnished under a license and may be used and * +* copied only in accordance with the terms of such license and * +* with the inclusion of the above copyright notice. This * +* software or any other copies thereof may not be provided or * +* otherwise made available to any other person. No title to and * +* ownership of the software is hereby transferred. * +* * +* The information in this software is subject to change without * +* notice and should not be construed as a commitment by Digital * +* Equipment Corporation. * +* * +* Digital assumes no responsibility for the use or reliability * +* of its software on equipment which is not supplied by Digital. * +* * +************************************************************************/ + +/* + * Event queue entries + */ + +#ifndef _QEVENT_ +#define _QEVENT_ + +typedef struct _vs_event { + unsigned short vse_x; /* x position */ + unsigned short vse_y; /* y position */ + unsigned short vse_time;/* 10 millisecond units (button only) */ + char vse_type; /* button or motion? */ + unsigned char vse_key; /* the key (button only) */ + char vse_direction; /* which direction (button only) */ + char vse_device; /* which device (button only) */ +} vsEvent; + +/* vse_type field */ +#define VSE_BUTTON 0 /* button moved */ +#define VSE_MMOTION 1 /* mouse moved */ +#define VSE_TMOTION 2 /* tablet moved */ + +/* vse_direction field */ +#define VSE_KBTUP 0 /* up */ +#define VSE_KBTDOWN 1 /* down */ +#define VSE_KBTRAW 2 /* undetermined */ + +/* vse_device field */ +#define VSE_NULL 0 /* NULL event (for QD_GETEVENT ret) */ +#define VSE_MOUSE 1 /* mouse */ +#define VSE_DKB 2 /* main keyboard */ +#define VSE_TABLET 3 /* graphics tablet */ +#define VSE_AUX 4 /* auxiliary */ +#define VSE_CONSOLE 5 /* console */ + +/* The event queue */ + +typedef struct _vs_eventqueue { + vsEvent *events; /* input event buffer */ + int size; /* size of event buffer */ + int head; /* index into events */ + int tail; /* index into events */ +} vsEventQueue; + +/* mouse cursor position */ + +typedef struct _vs_cursor { + short x; + short y; +} vsCursor; + +/* mouse motion rectangle */ + +typedef struct _vs_box { + short bottom; + short right; + short left; + short top; +} vsBox; + +#endif /*_QEVENT_*/ diff --git a/sys/arch/vax/qbus/qfont.c b/sys/arch/vax/qbus/qfont.c new file mode 100644 index 00000000000..f7abecff5e7 --- /dev/null +++ b/sys/arch/vax/qbus/qfont.c @@ -0,0 +1,3294 @@ +/* $OpenBSD: qfont.c,v 1.1 2000/04/27 03:14:48 bjc Exp $ */ +/* $NetBSD: qfont.c,v 1.4 1999/06/20 17:58:57 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)qfont.c 7.2 (Berkeley) 1/21/94 + */ + +/* + * derived from: "@(#)qfont.c 6.2 ULTRIX 2/4/88" + */ + +/************************************************************************ + * * + * Copyright (c) 1984, 1987 by * + * Digital Equipment Corporation, Maynard, MA * + * All rights reserved. * + * * + * This software is furnished under a license and may be used and * + * copied only in accordance with the terms of such license and * + * with the inclusion of the above copyright notice. This * + * software or any other copies thereof may not be provided or * + * otherwise made available to any other person. No title to and * + * ownership of the software is hereby transferred. * + * * + * This software is derived from software received from the * + * University of California, Berkeley, and from Bell * + * Laboratories. Use, duplication, or disclosure is subject to * + * restrictions under license agreements with University of * + * California and with AT&T. * + * * + * The information in this software is subject to change without * + * notice and should not be construed as a commitment by Digital * + * Equipment Corporation. * + * * + * Digital assumes no responsibility for the use or reliability * + * of its software on equipment which is not supplied by Digital. * + * * + ************************************************************************/ + +/* + * The following tables are used to translate LK201 key strokes + * into ascii characters. The tables also support the special + * function keys. + */ + +unsigned short q_key[]={ + 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 0 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 8 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 16 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 24 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 32 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 40 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 48 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 56 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 64 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 72 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x101 ,0x102 /* 80 */ + ,0x103 ,0x104 ,0x105 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 88 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x106 ,0x107 ,0x108 ,0x109 /* 96 */ + ,0x10a ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 104 */ + ,0x00 ,0x1b ,0x08 ,0x0a ,0x10b ,0x00 ,0x00 ,0x00 /* 112 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x10c ,0x10d ,0x00 ,0x00 /* 120 */ + ,0x10e ,0x10f ,0x110 ,0x111 ,0x00 ,0x00 ,0x00 ,0x00 /* 128 */ + ,0x00 ,0x00 ,0x112 ,0x113 ,0x114 ,0x115 ,0x116 ,0x117 /* 136 */ + ,0x00 ,0x00 ,0x120 ,0x00 ,0x121 ,0x122 ,0x123 ,0x124 /* 144 */ + ,0x125 ,0x126 ,0x127 ,0x128 ,0x129 ,0x12a ,0x12b ,0x12c /* 152 */ + ,0x12d ,0x118 ,0x119 ,0x11a ,0x11b ,0x00 ,0x00 ,0x11c /* 160 */ + ,0x11d ,0x11e ,0x11f ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 168 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 176 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,'\r' ,0x09 ,'`' /* 184 */ + ,'1' ,'q' ,'a' ,'z' ,0x00 ,'2' ,'w' ,'s' /* 192 */ + ,'x' ,'<' ,0x00 ,'3' ,'e' ,'d' ,'c' ,0x00 /* 200 */ + ,'4' ,'r' ,'f' ,'v' ,' ' ,0x00 ,'5' ,'t' /* 208 */ + ,'g' ,'b' ,0x00 ,'6' ,'y' ,'h' ,'n' ,0x00 /* 216 */ + ,'7' ,'u' ,'j' ,'m' ,0x00 ,'8' ,'i' ,'k' /* 224 */ + ,',' ,0x00 ,'9' ,'o' ,'l' ,'.' ,0x00 ,'0' /* 232 */ + ,'p' ,0x00 ,';' ,'/' ,0x00 ,'=' ,']' ,'\\' /* 240 */ + ,0x00 ,'-' ,'[' ,'\'' ,0x00 ,0x00 ,0x00 ,0x00 /* 248 */ +}; + +unsigned short q_shift_key[]={ + 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 0 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 8 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 16 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 24 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 32 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 40 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 48 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 56 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 64 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 72 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x101 ,0x102 /* 80 */ + ,0x103 ,0x104 ,0x105 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 88 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x106 ,0x107 ,0x108 ,0x109 /* 96 */ + ,0x10a ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 104 */ + ,0x00 ,0x1b ,0x08 ,0x0a ,0x10b ,0x00 ,0x00 ,0x00 /* 112 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x10c ,0x10d ,0x00 ,0x00 /* 120 */ + ,0x10e ,0x10f ,0x110 ,0x111 ,0x00 ,0x00 ,0x00 ,0x00 /* 128 */ + ,0x00 ,0x00 ,0x112 ,0x113 ,0x114 ,0x115 ,0x116 ,0x117 /* 136 */ + ,0x00 ,0x00 ,0x120 ,0x00 ,0x121 ,0x122 ,0x123 ,0x124 /* 144 */ + ,0x125 ,0x126 ,0x127 ,0x128 ,0x129 ,0x12a ,0x12b ,0x12c /* 152 */ + ,0x12d ,0x118 ,0x119 ,0x11a ,0x11b ,0x00 ,0x00 ,0x11c /* 160 */ + ,0x11d ,0x11e ,0x11f ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 168 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 176 */ + ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,'\r' ,0x09 ,'~' /* 184 */ + ,'!' ,'Q' ,'A' ,'Z' ,0x00 ,'@' ,'W' ,'S' /* 192 */ + ,'X' ,'>' ,0x00 ,'#' ,'E' ,'D' ,'C' ,0x00 /* 200 */ + ,'$' ,'R' ,'F' ,'V' ,' ' ,0x00 ,'%' ,'T' /* 208 */ + ,'G' ,'B' ,0x00 ,'^' ,'Y' ,'H' ,'N' ,0x00 /* 216 */ + ,'&' ,'U' ,'J' ,'M' ,0x00 ,'*' ,'I' ,'K' /* 224 */ + ,',' ,0x00 ,'(' ,'O' ,'L' ,'.' ,0x00 ,')' /* 232 */ + ,'P' ,0x00 ,':' ,'?' ,0x00 ,'+' ,'}' ,'|' /* 240 */ + ,0x00 ,'_' ,'{' ,'"' ,0x00 ,0x00 ,0x00 ,0x00 /* 248 */ +}; + +/* + * LK201 special purpose keys. Translations from the tables above + * includes codes for the function keys and other goodies. They can + * be determined by the presence of the 8th bit being set. The + * following table is accessed by removing that bit and using the + * result as the index to the following table. Note that table begins + * a null entry. + */ +char *q_special[]={ 0, + "\33[11~", /* f1 */ + "\33[12~", /* f2 */ + "\33[13~", /* f3 */ + "\33[14~", /* f4 */ + "\33[15~", /* f5 */ + "\33[17~", /* f6 */ + "\33[18~", /* f7 */ + "\33[19~", /* f8 */ + "\33[20~", /* f9 */ + "\33[21~", /* f10 */ + "\33[26~", /* f14 */ + "\33[28~", /* f15 */ + "\33[29~", /* f16 */ + "\33[31~", /* f17 */ + "\33[32~", /* f18 */ + "\33[33~", /* f19 */ + "\33[34~", /* f20 */ + "\33[1~", /* find */ + "\33[2~", /* insert */ + "\33[3~", /* remove */ + "\33[4~", /* select */ + "\33[5~", /* prev */ + "\33[6~", /* next */ + "\33OP", /* pf1 */ + "\33OQ", /* pf2 */ + "\33OR", /* pf3 */ + "\33OS", /* pf4 */ + "\33[D", /* left */ + "\33[C", /* right */ + "\33[B", /* down */ + "\33[A", /* up */ + "\33Op", /* key pad 0 */ + "\33On", /* key pad . */ + "\33OM", /* key pad enter */ + "\33Oq", /* key pad 1 */ + "\33Or", /* key pad 2 */ + "\33Os", /* key pad 3 */ + "\33Ot", /* key pad 4 */ + "\33Ou", /* key pad 5 */ + "\33Ov", /* key pad 6 */ + "\33O/*", /* key pad , */ + "\33Ow", /* key pad 7 */ + "\33Ox", /* key pad 8 */ + "\33Oy", /* key pad 9 */ + "\33Om", /* key pad - */ + /* + * The following strings are to allow a numeric keypad + * mode and still use the same translation tables + */ + "0", + ".", + "\r", + "1", + "2", + "3", + "4", + "5", + "6", + ",", + "7", + "8", + "9", + "-" +}; + + +/* + * QVSS font table of displayable characters. + */ +char q_font[]={ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ + 0x00, /* 0x00000000 */ +/* */ + 0x00, /* 0x00000000 ! */ + 0x00, /* 0x00000000 ! */ + 0x08, /* 0x00001000 ! */ + 0x08, /* 0x00001000 ! */ + 0x08, /* 0x00001000 ! */ + 0x08, /* 0x00001000 ! */ + 0x08, /* 0x00001000 ! */ + 0x08, /* 0x00001000 ! */ + 0x08, /* 0x00001000 ! */ + 0x08, /* 0x00001000 ! */ + 0x00, /* 0x00000000 ! */ + 0x08, /* 0x00001000 ! */ + 0x00, /* 0x00000000 ! */ + 0x00, /* 0x00000000 ! */ + 0x00, /* 0x00000000 ! */ +/* */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ + 0x24, /* 0x00100100 " */ + 0x24, /* 0x00100100 " */ + 0x24, /* 0x00100100 " */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ + 0x00, /* 0x00000000 " */ +/* */ + 0x00, /* 0x00000000 # */ + 0x00, /* 0x00000000 # */ + 0x00, /* 0x00000000 # */ + 0x12, /* 0x00010010 # */ + 0x12, /* 0x00010010 # */ + 0x3f, /* 0x00111111 # */ + 0x12, /* 0x00010010 # */ + 0x12, /* 0x00010010 # */ + 0x3f, /* 0x00111111 # */ + 0x12, /* 0x00010010 # */ + 0x12, /* 0x00010010 # */ + 0x00, /* 0x00000000 # */ + 0x00, /* 0x00000000 # */ + 0x00, /* 0x00000000 # */ + 0x00, /* 0x00000000 # */ +/* */ + 0x00, /* 0x00000000 $ */ + 0x00, /* 0x00000000 $ */ + 0x00, /* 0x00000000 $ */ + 0x08, /* 0x00001000 $ */ + 0x3e, /* 0x00111110 $ */ + 0x09, /* 0x00001001 $ */ + 0x09, /* 0x00001001 $ */ + 0x3e, /* 0x00111110 $ */ + 0x48, /* 0x01001000 $ */ + 0x48, /* 0x01001000 $ */ + 0x3e, /* 0x00111110 $ */ + 0x08, /* 0x00001000 $ */ + 0x00, /* 0x00000000 $ */ + 0x00, /* 0x00000000 $ */ + 0x00, /* 0x00000000 $ */ +/* */ + 0x00, /* 0x00000000 % */ + 0x00, /* 0x00000000 % */ + 0x42, /* 0x01000010 % */ + 0x25, /* 0x00100101 % */ + 0x25, /* 0x00100101 % */ + 0x12, /* 0x00010010 % */ + 0x08, /* 0x00001000 % */ + 0x08, /* 0x00001000 % */ + 0x24, /* 0x00100100 % */ + 0x52, /* 0x01010010 % */ + 0x52, /* 0x01010010 % */ + 0x21, /* 0x00100001 % */ + 0x00, /* 0x00000000 % */ + 0x00, /* 0x00000000 % */ + 0x00, /* 0x00000000 % */ +/* */ + 0x00, /* 0x00000000 & */ + 0x00, /* 0x00000000 & */ + 0x0e, /* 0x00001110 & */ + 0x11, /* 0x00010001 & */ + 0x11, /* 0x00010001 & */ + 0x11, /* 0x00010001 & */ + 0x0e, /* 0x00001110 & */ + 0x11, /* 0x00010001 & */ + 0x51, /* 0x01010001 & */ + 0x21, /* 0x00100001 & */ + 0x31, /* 0x00110001 & */ + 0x4e, /* 0x01001110 & */ + 0x00, /* 0x00000000 & */ + 0x00, /* 0x00000000 & */ + 0x00, /* 0x00000000 & */ +/* */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ + 0x38, /* 0x00111000 ' */ + 0x18, /* 0x00011000 ' */ + 0x04, /* 0x00000100 ' */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ + 0x00, /* 0x00000000 ' */ +/* */ + 0x00, /* 0x00000000 ( */ + 0x00, /* 0x00000000 ( */ + 0x10, /* 0x00010000 ( */ + 0x08, /* 0x00001000 ( */ + 0x08, /* 0x00001000 ( */ + 0x04, /* 0x00000100 ( */ + 0x04, /* 0x00000100 ( */ + 0x04, /* 0x00000100 ( */ + 0x04, /* 0x00000100 ( */ + 0x08, /* 0x00001000 ( */ + 0x08, /* 0x00001000 ( */ + 0x10, /* 0x00010000 ( */ + 0x00, /* 0x00000000 ( */ + 0x00, /* 0x00000000 ( */ + 0x00, /* 0x00000000 ( */ +/* */ + 0x00, /* 0x00000000 ) */ + 0x00, /* 0x00000000 ) */ + 0x04, /* 0x00000100 ) */ + 0x08, /* 0x00001000 ) */ + 0x08, /* 0x00001000 ) */ + 0x10, /* 0x00010000 ) */ + 0x10, /* 0x00010000 ) */ + 0x10, /* 0x00010000 ) */ + 0x10, /* 0x00010000 ) */ + 0x08, /* 0x00001000 ) */ + 0x08, /* 0x00001000 ) */ + 0x04, /* 0x00000100 ) */ + 0x00, /* 0x00000000 ) */ + 0x00, /* 0x00000000 ) */ + 0x00, /* 0x00000000 ) */ +/* */ + 0x00, /* 0x00000000 * */ + 0x00, /* 0x00000000 * */ + 0x00, /* 0x00000000 * */ + 0x00, /* 0x00000000 * */ + 0x00, /* 0x00000000 * */ + 0x22, /* 0x00100010 * */ + 0x14, /* 0x00010100 * */ + 0x7f, /* 0x01111111 * */ + 0x14, /* 0x00010100 * */ + 0x22, /* 0x00100010 * */ + 0x00, /* 0x00000000 * */ + 0x00, /* 0x00000000 * */ + 0x00, /* 0x00000000 * */ + 0x00, /* 0x00000000 * */ + 0x00, /* 0x00000000 * */ +/* */ + 0x00, /* 0x00000000 + */ + 0x00, /* 0x00000000 + */ + 0x00, /* 0x00000000 + */ + 0x00, /* 0x00000000 + */ + 0x08, /* 0x00001000 + */ + 0x08, /* 0x00001000 + */ + 0x08, /* 0x00001000 + */ + 0x7f, /* 0x01111111 + */ + 0x08, /* 0x00001000 + */ + 0x08, /* 0x00001000 + */ + 0x08, /* 0x00001000 + */ + 0x00, /* 0x00000000 + */ + 0x00, /* 0x00000000 + */ + 0x00, /* 0x00000000 + */ + 0x00, /* 0x00000000 + */ +/* */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ + 0x1c, /* 0x00011100 , */ + 0x0c, /* 0x00001100 , */ + 0x02, /* 0x00000010 , */ + 0x00, /* 0x00000000 , */ + 0x00, /* 0x00000000 , */ +/* */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x7f, /* 0x01111111 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ + 0x00, /* 0x00000000 - */ +/* */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ + 0x08, /* 0x00001000 . */ + 0x1c, /* 0x00011100 . */ + 0x08, /* 0x00001000 . */ + 0x00, /* 0x00000000 . */ + 0x00, /* 0x00000000 . */ +/* */ + 0x00, /* 0x00000000 / */ + 0x00, /* 0x00000000 / */ + 0x40, /* 0x01000000 / */ + 0x40, /* 0x01000000 / */ + 0x20, /* 0x00100000 / */ + 0x10, /* 0x00010000 / */ + 0x08, /* 0x00001000 / */ + 0x04, /* 0x00000100 / */ + 0x02, /* 0x00000010 / */ + 0x01, /* 0x00000001 / */ + 0x01, /* 0x00000001 / */ + 0x01, /* 0x00000001 / */ + 0x00, /* 0x00000000 / */ + 0x00, /* 0x00000000 / */ + 0x00, /* 0x00000000 / */ +/* */ + 0x00, /* 0x00000000 0 */ + 0x00, /* 0x00000000 0 */ + 0x0c, /* 0x00001100 0 */ + 0x12, /* 0x00010010 0 */ + 0x21, /* 0x00100001 0 */ + 0x21, /* 0x00100001 0 */ + 0x21, /* 0x00100001 0 */ + 0x21, /* 0x00100001 0 */ + 0x21, /* 0x00100001 0 */ + 0x21, /* 0x00100001 0 */ + 0x12, /* 0x00010010 0 */ + 0x0c, /* 0x00001100 0 */ + 0x00, /* 0x00000000 0 */ + 0x00, /* 0x00000000 0 */ + 0x00, /* 0x00000000 0 */ +/* */ + 0x00, /* 0x00000000 1 */ + 0x00, /* 0x00000000 1 */ + 0x08, /* 0x00001000 1 */ + 0x0c, /* 0x00001100 1 */ + 0x0a, /* 0x00001010 1 */ + 0x08, /* 0x00001000 1 */ + 0x08, /* 0x00001000 1 */ + 0x08, /* 0x00001000 1 */ + 0x08, /* 0x00001000 1 */ + 0x08, /* 0x00001000 1 */ + 0x08, /* 0x00001000 1 */ + 0x3e, /* 0x00111110 1 */ + 0x00, /* 0x00000000 1 */ + 0x00, /* 0x00000000 1 */ + 0x00, /* 0x00000000 1 */ +/* */ + 0x00, /* 0x00000000 2 */ + 0x00, /* 0x00000000 2 */ + 0x3e, /* 0x00111110 2 */ + 0x41, /* 0x01000001 2 */ + 0x41, /* 0x01000001 2 */ + 0x40, /* 0x01000000 2 */ + 0x20, /* 0x00100000 2 */ + 0x10, /* 0x00010000 2 */ + 0x0c, /* 0x00001100 2 */ + 0x02, /* 0x00000010 2 */ + 0x01, /* 0x00000001 2 */ + 0x7f, /* 0x01111111 2 */ + 0x00, /* 0x00000000 2 */ + 0x00, /* 0x00000000 2 */ + 0x00, /* 0x00000000 2 */ +/* */ + 0x00, /* 0x00000000 3 */ + 0x00, /* 0x00000000 3 */ + 0x7f, /* 0x01111111 3 */ + 0x40, /* 0x01000000 3 */ + 0x20, /* 0x00100000 3 */ + 0x10, /* 0x00010000 3 */ + 0x38, /* 0x00111000 3 */ + 0x40, /* 0x01000000 3 */ + 0x40, /* 0x01000000 3 */ + 0x40, /* 0x01000000 3 */ + 0x41, /* 0x01000001 3 */ + 0x3e, /* 0x00111110 3 */ + 0x00, /* 0x00000000 3 */ + 0x00, /* 0x00000000 3 */ + 0x00, /* 0x00000000 3 */ +/* */ + 0x00, /* 0x00000000 4 */ + 0x00, /* 0x00000000 4 */ + 0x20, /* 0x00100000 4 */ + 0x30, /* 0x00110000 4 */ + 0x28, /* 0x00101000 4 */ + 0x24, /* 0x00100100 4 */ + 0x22, /* 0x00100010 4 */ + 0x21, /* 0x00100001 4 */ + 0x7f, /* 0x01111111 4 */ + 0x20, /* 0x00100000 4 */ + 0x20, /* 0x00100000 4 */ + 0x20, /* 0x00100000 4 */ + 0x00, /* 0x00000000 4 */ + 0x00, /* 0x00000000 4 */ + 0x00, /* 0x00000000 4 */ +/* */ + 0x00, /* 0x00000000 5 */ + 0x00, /* 0x00000000 5 */ + 0x7f, /* 0x01111111 5 */ + 0x01, /* 0x00000001 5 */ + 0x01, /* 0x00000001 5 */ + 0x3d, /* 0x00111101 5 */ + 0x43, /* 0x01000011 5 */ + 0x40, /* 0x01000000 5 */ + 0x40, /* 0x01000000 5 */ + 0x40, /* 0x01000000 5 */ + 0x41, /* 0x01000001 5 */ + 0x3e, /* 0x00111110 5 */ + 0x00, /* 0x00000000 5 */ + 0x00, /* 0x00000000 5 */ + 0x00, /* 0x00000000 5 */ +/* */ + 0x00, /* 0x00000000 6 */ + 0x00, /* 0x00000000 6 */ + 0x3c, /* 0x00111100 6 */ + 0x02, /* 0x00000010 6 */ + 0x01, /* 0x00000001 6 */ + 0x01, /* 0x00000001 6 */ + 0x3d, /* 0x00111101 6 */ + 0x43, /* 0x01000011 6 */ + 0x41, /* 0x01000001 6 */ + 0x41, /* 0x01000001 6 */ + 0x41, /* 0x01000001 6 */ + 0x3e, /* 0x00111110 6 */ + 0x00, /* 0x00000000 6 */ + 0x00, /* 0x00000000 6 */ + 0x00, /* 0x00000000 6 */ +/* */ + 0x00, /* 0x00000000 7 */ + 0x00, /* 0x00000000 7 */ + 0x7f, /* 0x01111111 7 */ + 0x40, /* 0x01000000 7 */ + 0x40, /* 0x01000000 7 */ + 0x20, /* 0x00100000 7 */ + 0x10, /* 0x00010000 7 */ + 0x08, /* 0x00001000 7 */ + 0x04, /* 0x00000100 7 */ + 0x04, /* 0x00000100 7 */ + 0x02, /* 0x00000010 7 */ + 0x02, /* 0x00000010 7 */ + 0x00, /* 0x00000000 7 */ + 0x00, /* 0x00000000 7 */ + 0x00, /* 0x00000000 7 */ +/* */ + 0x00, /* 0x00000000 8 */ + 0x00, /* 0x00000000 8 */ + 0x3e, /* 0x00111110 8 */ + 0x41, /* 0x01000001 8 */ + 0x41, /* 0x01000001 8 */ + 0x41, /* 0x01000001 8 */ + 0x3e, /* 0x00111110 8 */ + 0x41, /* 0x01000001 8 */ + 0x41, /* 0x01000001 8 */ + 0x41, /* 0x01000001 8 */ + 0x41, /* 0x01000001 8 */ + 0x3e, /* 0x00111110 8 */ + 0x00, /* 0x00000000 8 */ + 0x00, /* 0x00000000 8 */ + 0x00, /* 0x00000000 8 */ +/* */ + 0x00, /* 0x00000000 9 */ + 0x00, /* 0x00000000 9 */ + 0x3e, /* 0x00111110 9 */ + 0x41, /* 0x01000001 9 */ + 0x41, /* 0x01000001 9 */ + 0x41, /* 0x01000001 9 */ + 0x61, /* 0x01100001 9 */ + 0x5e, /* 0x01011110 9 */ + 0x40, /* 0x01000000 9 */ + 0x40, /* 0x01000000 9 */ + 0x20, /* 0x00100000 9 */ + 0x1e, /* 0x00011110 9 */ + 0x00, /* 0x00000000 9 */ + 0x00, /* 0x00000000 9 */ + 0x00, /* 0x00000000 9 */ +/* */ + 0x00, /* 0x00000000 : */ + 0x00, /* 0x00000000 : */ + 0x00, /* 0x00000000 : */ + 0x00, /* 0x00000000 : */ + 0x00, /* 0x00000000 : */ + 0x08, /* 0x00001000 : */ + 0x1c, /* 0x00011100 : */ + 0x08, /* 0x00001000 : */ + 0x00, /* 0x00000000 : */ + 0x00, /* 0x00000000 : */ + 0x08, /* 0x00001000 : */ + 0x1c, /* 0x00011100 : */ + 0x08, /* 0x00001000 : */ + 0x00, /* 0x00000000 : */ + 0x00, /* 0x00000000 : */ +/* */ + 0x00, /* 0x00000000 ; */ + 0x00, /* 0x00000000 ; */ + 0x00, /* 0x00000000 ; */ + 0x00, /* 0x00000000 ; */ + 0x00, /* 0x00000000 ; */ + 0x08, /* 0x00001000 ; */ + 0x1c, /* 0x00011100 ; */ + 0x08, /* 0x00001000 ; */ + 0x00, /* 0x00000000 ; */ + 0x00, /* 0x00000000 ; */ + 0x1c, /* 0x00011100 ; */ + 0x0c, /* 0x00001100 ; */ + 0x02, /* 0x00000010 ; */ + 0x00, /* 0x00000000 ; */ + 0x00, /* 0x00000000 ; */ +/* */ + 0x00, /* 0x00000000 < */ + 0x00, /* 0x00000000 < */ + 0x20, /* 0x00100000 < */ + 0x10, /* 0x00010000 < */ + 0x08, /* 0x00001000 < */ + 0x04, /* 0x00000100 < */ + 0x02, /* 0x00000010 < */ + 0x02, /* 0x00000010 < */ + 0x04, /* 0x00000100 < */ + 0x08, /* 0x00001000 < */ + 0x10, /* 0x00010000 < */ + 0x20, /* 0x00100000 < */ + 0x00, /* 0x00000000 < */ + 0x00, /* 0x00000000 < */ + 0x00, /* 0x00000000 < */ +/* */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ + 0x7f, /* 0x01111111 = */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ + 0x7f, /* 0x01111111 = */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ + 0x00, /* 0x00000000 = */ +/* */ + 0x00, /* 0x00000000 > */ + 0x00, /* 0x00000000 > */ + 0x02, /* 0x00000010 > */ + 0x04, /* 0x00000100 > */ + 0x08, /* 0x00001000 > */ + 0x10, /* 0x00010000 > */ + 0x20, /* 0x00100000 > */ + 0x20, /* 0x00100000 > */ + 0x10, /* 0x00010000 > */ + 0x08, /* 0x00001000 > */ + 0x04, /* 0x00000100 > */ + 0x02, /* 0x00000010 > */ + 0x00, /* 0x00000000 > */ + 0x00, /* 0x00000000 > */ + 0x00, /* 0x00000000 > */ +/* */ + 0x00, /* 0x00000000 ? */ + 0x00, /* 0x00000000 ? */ + 0x3e, /* 0x00111110 ? */ + 0x41, /* 0x01000001 ? */ + 0x41, /* 0x01000001 ? */ + 0x40, /* 0x01000000 ? */ + 0x20, /* 0x00100000 ? */ + 0x10, /* 0x00010000 ? */ + 0x08, /* 0x00001000 ? */ + 0x08, /* 0x00001000 ? */ + 0x00, /* 0x00000000 ? */ + 0x08, /* 0x00001000 ? */ + 0x00, /* 0x00000000 ? */ + 0x00, /* 0x00000000 ? */ + 0x00, /* 0x00000000 ? */ +/* */ + 0x00, /* 0x00000000 @ */ + 0x00, /* 0x00000000 @ */ + 0x3e, /* 0x00111110 @ */ + 0x41, /* 0x01000001 @ */ + 0x41, /* 0x01000001 @ */ + 0x79, /* 0x01111001 @ */ + 0x45, /* 0x01000101 @ */ + 0x65, /* 0x01100101 @ */ + 0x59, /* 0x01011001 @ */ + 0x01, /* 0x00000001 @ */ + 0x01, /* 0x00000001 @ */ + 0x3e, /* 0x00111110 @ */ + 0x00, /* 0x00000000 @ */ + 0x00, /* 0x00000000 @ */ + 0x00, /* 0x00000000 @ */ +/* */ + 0x00, /* 0x00000000 A */ + 0x00, /* 0x00000000 A */ + 0x08, /* 0x00001000 A */ + 0x14, /* 0x00010100 A */ + 0x22, /* 0x00100010 A */ + 0x41, /* 0x01000001 A */ + 0x41, /* 0x01000001 A */ + 0x41, /* 0x01000001 A */ + 0x7f, /* 0x01111111 A */ + 0x41, /* 0x01000001 A */ + 0x41, /* 0x01000001 A */ + 0x41, /* 0x01000001 A */ + 0x00, /* 0x00000000 A */ + 0x00, /* 0x00000000 A */ + 0x00, /* 0x00000000 A */ +/* */ + 0x00, /* 0x00000000 B */ + 0x00, /* 0x00000000 B */ + 0x3f, /* 0x00111111 B */ + 0x42, /* 0x01000010 B */ + 0x42, /* 0x01000010 B */ + 0x42, /* 0x01000010 B */ + 0x3e, /* 0x00111110 B */ + 0x42, /* 0x01000010 B */ + 0x42, /* 0x01000010 B */ + 0x42, /* 0x01000010 B */ + 0x42, /* 0x01000010 B */ + 0x3f, /* 0x00111111 B */ + 0x00, /* 0x00000000 B */ + 0x00, /* 0x00000000 B */ + 0x00, /* 0x00000000 B */ +/* */ + 0x00, /* 0x00000000 C */ + 0x00, /* 0x00000000 C */ + 0x3e, /* 0x00111110 C */ + 0x41, /* 0x01000001 C */ + 0x01, /* 0x00000001 C */ + 0x01, /* 0x00000001 C */ + 0x01, /* 0x00000001 C */ + 0x01, /* 0x00000001 C */ + 0x01, /* 0x00000001 C */ + 0x01, /* 0x00000001 C */ + 0x41, /* 0x01000001 C */ + 0x3e, /* 0x00111110 C */ + 0x00, /* 0x00000000 C */ + 0x00, /* 0x00000000 C */ + 0x00, /* 0x00000000 C */ +/* */ + 0x00, /* 0x00000000 D */ + 0x00, /* 0x00000000 D */ + 0x3f, /* 0x00111111 D */ + 0x42, /* 0x01000010 D */ + 0x42, /* 0x01000010 D */ + 0x42, /* 0x01000010 D */ + 0x42, /* 0x01000010 D */ + 0x42, /* 0x01000010 D */ + 0x42, /* 0x01000010 D */ + 0x42, /* 0x01000010 D */ + 0x42, /* 0x01000010 D */ + 0x3f, /* 0x00111111 D */ + 0x00, /* 0x00000000 D */ + 0x00, /* 0x00000000 D */ + 0x00, /* 0x00000000 D */ +/* */ + 0x00, /* 0x00000000 E */ + 0x00, /* 0x00000000 E */ + 0x7e, /* 0x01111110 E */ + 0x02, /* 0x00000010 E */ + 0x02, /* 0x00000010 E */ + 0x02, /* 0x00000010 E */ + 0x1e, /* 0x00011110 E */ + 0x02, /* 0x00000010 E */ + 0x02, /* 0x00000010 E */ + 0x02, /* 0x00000010 E */ + 0x02, /* 0x00000010 E */ + 0x7e, /* 0x01111110 E */ + 0x00, /* 0x00000000 E */ + 0x00, /* 0x00000000 E */ + 0x00, /* 0x00000000 E */ +/* */ + 0x00, /* 0x00000000 F */ + 0x00, /* 0x00000000 F */ + 0x7e, /* 0x01111110 F */ + 0x02, /* 0x00000010 F */ + 0x02, /* 0x00000010 F */ + 0x02, /* 0x00000010 F */ + 0x1e, /* 0x00011110 F */ + 0x02, /* 0x00000010 F */ + 0x02, /* 0x00000010 F */ + 0x02, /* 0x00000010 F */ + 0x02, /* 0x00000010 F */ + 0x02, /* 0x00000010 F */ + 0x00, /* 0x00000000 F */ + 0x00, /* 0x00000000 F */ + 0x00, /* 0x00000000 F */ +/* */ + 0x00, /* 0x00000000 G */ + 0x00, /* 0x00000000 G */ + 0x3e, /* 0x00111110 G */ + 0x41, /* 0x01000001 G */ + 0x01, /* 0x00000001 G */ + 0x01, /* 0x00000001 G */ + 0x01, /* 0x00000001 G */ + 0x71, /* 0x01110001 G */ + 0x41, /* 0x01000001 G */ + 0x41, /* 0x01000001 G */ + 0x41, /* 0x01000001 G */ + 0x3e, /* 0x00111110 G */ + 0x00, /* 0x00000000 G */ + 0x00, /* 0x00000000 G */ + 0x00, /* 0x00000000 G */ +/* */ + 0x00, /* 0x00000000 H */ + 0x00, /* 0x00000000 H */ + 0x41, /* 0x01000001 H */ + 0x41, /* 0x01000001 H */ + 0x41, /* 0x01000001 H */ + 0x41, /* 0x01000001 H */ + 0x7f, /* 0x01111111 H */ + 0x41, /* 0x01000001 H */ + 0x41, /* 0x01000001 H */ + 0x41, /* 0x01000001 H */ + 0x41, /* 0x01000001 H */ + 0x41, /* 0x01000001 H */ + 0x00, /* 0x00000000 H */ + 0x00, /* 0x00000000 H */ + 0x00, /* 0x00000000 H */ +/* */ + 0x00, /* 0x00000000 I */ + 0x00, /* 0x00000000 I */ + 0x3e, /* 0x00111110 I */ + 0x08, /* 0x00001000 I */ + 0x08, /* 0x00001000 I */ + 0x08, /* 0x00001000 I */ + 0x08, /* 0x00001000 I */ + 0x08, /* 0x00001000 I */ + 0x08, /* 0x00001000 I */ + 0x08, /* 0x00001000 I */ + 0x08, /* 0x00001000 I */ + 0x3e, /* 0x00111110 I */ + 0x00, /* 0x00000000 I */ + 0x00, /* 0x00000000 I */ + 0x00, /* 0x00000000 I */ +/* */ + 0x00, /* 0x00000000 J */ + 0x00, /* 0x00000000 J */ + 0x78, /* 0x01111000 J */ + 0x20, /* 0x00100000 J */ + 0x20, /* 0x00100000 J */ + 0x20, /* 0x00100000 J */ + 0x20, /* 0x00100000 J */ + 0x20, /* 0x00100000 J */ + 0x20, /* 0x00100000 J */ + 0x20, /* 0x00100000 J */ + 0x21, /* 0x00100001 J */ + 0x1e, /* 0x00011110 J */ + 0x00, /* 0x00000000 J */ + 0x00, /* 0x00000000 J */ + 0x00, /* 0x00000000 J */ +/* */ + 0x00, /* 0x00000000 K */ + 0x00, /* 0x00000000 K */ + 0x41, /* 0x01000001 K */ + 0x21, /* 0x00100001 K */ + 0x11, /* 0x00010001 K */ + 0x09, /* 0x00001001 K */ + 0x07, /* 0x00000111 K */ + 0x05, /* 0x00000101 K */ + 0x09, /* 0x00001001 K */ + 0x11, /* 0x00010001 K */ + 0x21, /* 0x00100001 K */ + 0x41, /* 0x01000001 K */ + 0x00, /* 0x00000000 K */ + 0x00, /* 0x00000000 K */ + 0x00, /* 0x00000000 K */ +/* */ + 0x00, /* 0x00000000 L */ + 0x00, /* 0x00000000 L */ + 0x01, /* 0x00000001 L */ + 0x01, /* 0x00000001 L */ + 0x01, /* 0x00000001 L */ + 0x01, /* 0x00000001 L */ + 0x01, /* 0x00000001 L */ + 0x01, /* 0x00000001 L */ + 0x01, /* 0x00000001 L */ + 0x01, /* 0x00000001 L */ + 0x01, /* 0x00000001 L */ + 0x7f, /* 0x01111111 L */ + 0x00, /* 0x00000000 L */ + 0x00, /* 0x00000000 L */ + 0x00, /* 0x00000000 L */ +/* */ + 0x00, /* 0x00000000 M */ + 0x00, /* 0x00000000 M */ + 0x41, /* 0x01000001 M */ + 0x41, /* 0x01000001 M */ + 0x63, /* 0x01100011 M */ + 0x55, /* 0x01010101 M */ + 0x55, /* 0x01010101 M */ + 0x49, /* 0x01001001 M */ + 0x49, /* 0x01001001 M */ + 0x41, /* 0x01000001 M */ + 0x41, /* 0x01000001 M */ + 0x41, /* 0x01000001 M */ + 0x00, /* 0x00000000 M */ + 0x00, /* 0x00000000 M */ + 0x00, /* 0x00000000 M */ +/* */ + 0x00, /* 0x00000000 N */ + 0x00, /* 0x00000000 N */ + 0x41, /* 0x01000001 N */ + 0x41, /* 0x01000001 N */ + 0x43, /* 0x01000011 N */ + 0x45, /* 0x01000101 N */ + 0x49, /* 0x01001001 N */ + 0x51, /* 0x01010001 N */ + 0x61, /* 0x01100001 N */ + 0x41, /* 0x01000001 N */ + 0x41, /* 0x01000001 N */ + 0x41, /* 0x01000001 N */ + 0x00, /* 0x00000000 N */ + 0x00, /* 0x00000000 N */ + 0x00, /* 0x00000000 N */ +/* */ + 0x00, /* 0x00000000 O */ + 0x00, /* 0x00000000 O */ + 0x3e, /* 0x00111110 O */ + 0x41, /* 0x01000001 O */ + 0x41, /* 0x01000001 O */ + 0x41, /* 0x01000001 O */ + 0x41, /* 0x01000001 O */ + 0x41, /* 0x01000001 O */ + 0x41, /* 0x01000001 O */ + 0x41, /* 0x01000001 O */ + 0x41, /* 0x01000001 O */ + 0x3e, /* 0x00111110 O */ + 0x00, /* 0x00000000 O */ + 0x00, /* 0x00000000 O */ + 0x00, /* 0x00000000 O */ +/* */ + 0x00, /* 0x00000000 P */ + 0x00, /* 0x00000000 P */ + 0x3f, /* 0x00111111 P */ + 0x41, /* 0x01000001 P */ + 0x41, /* 0x01000001 P */ + 0x41, /* 0x01000001 P */ + 0x3f, /* 0x00111111 P */ + 0x01, /* 0x00000001 P */ + 0x01, /* 0x00000001 P */ + 0x01, /* 0x00000001 P */ + 0x01, /* 0x00000001 P */ + 0x01, /* 0x00000001 P */ + 0x00, /* 0x00000000 P */ + 0x00, /* 0x00000000 P */ + 0x00, /* 0x00000000 P */ +/* */ + 0x00, /* 0x00000000 Q */ + 0x00, /* 0x00000000 Q */ + 0x3e, /* 0x00111110 Q */ + 0x41, /* 0x01000001 Q */ + 0x41, /* 0x01000001 Q */ + 0x41, /* 0x01000001 Q */ + 0x41, /* 0x01000001 Q */ + 0x41, /* 0x01000001 Q */ + 0x41, /* 0x01000001 Q */ + 0x49, /* 0x01001001 Q */ + 0x51, /* 0x01010001 Q */ + 0x3e, /* 0x00111110 Q */ + 0x40, /* 0x01000000 Q */ + 0x00, /* 0x00000000 Q */ + 0x00, /* 0x00000000 Q */ +/* */ + 0x00, /* 0x00000000 R */ + 0x00, /* 0x00000000 R */ + 0x3f, /* 0x00111111 R */ + 0x41, /* 0x01000001 R */ + 0x41, /* 0x01000001 R */ + 0x41, /* 0x01000001 R */ + 0x3f, /* 0x00111111 R */ + 0x09, /* 0x00001001 R */ + 0x11, /* 0x00010001 R */ + 0x21, /* 0x00100001 R */ + 0x41, /* 0x01000001 R */ + 0x41, /* 0x01000001 R */ + 0x00, /* 0x00000000 R */ + 0x00, /* 0x00000000 R */ + 0x00, /* 0x00000000 R */ +/* */ + 0x00, /* 0x00000000 S */ + 0x00, /* 0x00000000 S */ + 0x3e, /* 0x00111110 S */ + 0x41, /* 0x01000001 S */ + 0x01, /* 0x00000001 S */ + 0x01, /* 0x00000001 S */ + 0x3e, /* 0x00111110 S */ + 0x40, /* 0x01000000 S */ + 0x40, /* 0x01000000 S */ + 0x40, /* 0x01000000 S */ + 0x41, /* 0x01000001 S */ + 0x3e, /* 0x00111110 S */ + 0x00, /* 0x00000000 S */ + 0x00, /* 0x00000000 S */ + 0x00, /* 0x00000000 S */ +/* */ + 0x00, /* 0x00000000 T */ + 0x00, /* 0x00000000 T */ + 0x7f, /* 0x01111111 T */ + 0x08, /* 0x00001000 T */ + 0x08, /* 0x00001000 T */ + 0x08, /* 0x00001000 T */ + 0x08, /* 0x00001000 T */ + 0x08, /* 0x00001000 T */ + 0x08, /* 0x00001000 T */ + 0x08, /* 0x00001000 T */ + 0x08, /* 0x00001000 T */ + 0x08, /* 0x00001000 T */ + 0x00, /* 0x00000000 T */ + 0x00, /* 0x00000000 T */ + 0x00, /* 0x00000000 T */ +/* */ + 0x00, /* 0x00000000 U */ + 0x00, /* 0x00000000 U */ + 0x41, /* 0x01000001 U */ + 0x41, /* 0x01000001 U */ + 0x41, /* 0x01000001 U */ + 0x41, /* 0x01000001 U */ + 0x41, /* 0x01000001 U */ + 0x41, /* 0x01000001 U */ + 0x41, /* 0x01000001 U */ + 0x41, /* 0x01000001 U */ + 0x41, /* 0x01000001 U */ + 0x3e, /* 0x00111110 U */ + 0x00, /* 0x00000000 U */ + 0x00, /* 0x00000000 U */ + 0x00, /* 0x00000000 U */ +/* */ + 0x00, /* 0x00000000 V */ + 0x00, /* 0x00000000 V */ + 0x41, /* 0x01000001 V */ + 0x41, /* 0x01000001 V */ + 0x41, /* 0x01000001 V */ + 0x22, /* 0x00100010 V */ + 0x22, /* 0x00100010 V */ + 0x22, /* 0x00100010 V */ + 0x14, /* 0x00010100 V */ + 0x14, /* 0x00010100 V */ + 0x14, /* 0x00010100 V */ + 0x08, /* 0x00001000 V */ + 0x00, /* 0x00000000 V */ + 0x00, /* 0x00000000 V */ + 0x00, /* 0x00000000 V */ +/* */ + 0x00, /* 0x00000000 W */ + 0x00, /* 0x00000000 W */ + 0x41, /* 0x01000001 W */ + 0x41, /* 0x01000001 W */ + 0x41, /* 0x01000001 W */ + 0x41, /* 0x01000001 W */ + 0x49, /* 0x01001001 W */ + 0x49, /* 0x01001001 W */ + 0x49, /* 0x01001001 W */ + 0x49, /* 0x01001001 W */ + 0x55, /* 0x01010101 W */ + 0x22, /* 0x00100010 W */ + 0x00, /* 0x00000000 W */ + 0x00, /* 0x00000000 W */ + 0x00, /* 0x00000000 W */ +/* */ + 0x00, /* 0x00000000 X */ + 0x00, /* 0x00000000 X */ + 0x41, /* 0x01000001 X */ + 0x41, /* 0x01000001 X */ + 0x22, /* 0x00100010 X */ + 0x14, /* 0x00010100 X */ + 0x08, /* 0x00001000 X */ + 0x08, /* 0x00001000 X */ + 0x14, /* 0x00010100 X */ + 0x22, /* 0x00100010 X */ + 0x41, /* 0x01000001 X */ + 0x41, /* 0x01000001 X */ + 0x00, /* 0x00000000 X */ + 0x00, /* 0x00000000 X */ + 0x00, /* 0x00000000 X */ +/* */ + 0x00, /* 0x00000000 Y */ + 0x00, /* 0x00000000 Y */ + 0x41, /* 0x01000001 Y */ + 0x41, /* 0x01000001 Y */ + 0x22, /* 0x00100010 Y */ + 0x14, /* 0x00010100 Y */ + 0x08, /* 0x00001000 Y */ + 0x08, /* 0x00001000 Y */ + 0x08, /* 0x00001000 Y */ + 0x08, /* 0x00001000 Y */ + 0x08, /* 0x00001000 Y */ + 0x08, /* 0x00001000 Y */ + 0x00, /* 0x00000000 Y */ + 0x00, /* 0x00000000 Y */ + 0x00, /* 0x00000000 Y */ +/* */ + 0x00, /* 0x00000000 Z */ + 0x00, /* 0x00000000 Z */ + 0x7f, /* 0x01111111 Z */ + 0x40, /* 0x01000000 Z */ + 0x20, /* 0x00100000 Z */ + 0x10, /* 0x00010000 Z */ + 0x08, /* 0x00001000 Z */ + 0x04, /* 0x00000100 Z */ + 0x02, /* 0x00000010 Z */ + 0x01, /* 0x00000001 Z */ + 0x01, /* 0x00000001 Z */ + 0x7f, /* 0x01111111 Z */ + 0x00, /* 0x00000000 Z */ + 0x00, /* 0x00000000 Z */ + 0x00, /* 0x00000000 Z */ +/* */ + 0x00, /* 0x00000000 [ */ + 0x00, /* 0x00000000 [ */ + 0x3c, /* 0x00111100 [ */ + 0x04, /* 0x00000100 [ */ + 0x04, /* 0x00000100 [ */ + 0x04, /* 0x00000100 [ */ + 0x04, /* 0x00000100 [ */ + 0x04, /* 0x00000100 [ */ + 0x04, /* 0x00000100 [ */ + 0x04, /* 0x00000100 [ */ + 0x04, /* 0x00000100 [ */ + 0x3c, /* 0x00111100 [ */ + 0x00, /* 0x00000000 [ */ + 0x00, /* 0x00000000 [ */ + 0x00, /* 0x00000000 [ */ +/* */ + 0x00, /* 0x00000000 \ */ + 0x00, /* 0x00000000 \ */ + 0x01, /* 0x00000001 \ */ + 0x02, /* 0x00000010 \ */ + 0x02, /* 0x00000010 \ */ + 0x04, /* 0x00000100 \ */ + 0x08, /* 0x00001000 \ */ + 0x08, /* 0x00001000 \ */ + 0x10, /* 0x00010000 \ */ + 0x20, /* 0x00100000 \ */ + 0x20, /* 0x00100000 \ */ + 0x40, /* 0x01000000 \ */ + 0x00, /* 0x00000000 \ */ + 0x00, /* 0x00000000 \ */ + 0x00, /* 0x00000000 \ */ +/* */ + 0x00, /* 0x00000000 ] */ + 0x00, /* 0x00000000 ] */ + 0x1e, /* 0x00011110 ] */ + 0x10, /* 0x00010000 ] */ + 0x10, /* 0x00010000 ] */ + 0x10, /* 0x00010000 ] */ + 0x10, /* 0x00010000 ] */ + 0x10, /* 0x00010000 ] */ + 0x10, /* 0x00010000 ] */ + 0x10, /* 0x00010000 ] */ + 0x10, /* 0x00010000 ] */ + 0x1e, /* 0x00011110 ] */ + 0x00, /* 0x00000000 ] */ + 0x00, /* 0x00000000 ] */ + 0x00, /* 0x00000000 ] */ +/* */ + 0x00, /* 0x00000000 ^ */ + 0x00, /* 0x00000000 ^ */ + 0x08, /* 0x00001000 ^ */ + 0x14, /* 0x00010100 ^ */ + 0x22, /* 0x00100010 ^ */ + 0x41, /* 0x01000001 ^ */ + 0x00, /* 0x00000000 ^ */ + 0x00, /* 0x00000000 ^ */ + 0x00, /* 0x00000000 ^ */ + 0x00, /* 0x00000000 ^ */ + 0x00, /* 0x00000000 ^ */ + 0x00, /* 0x00000000 ^ */ + 0x00, /* 0x00000000 ^ */ + 0x00, /* 0x00000000 ^ */ + 0x00, /* 0x00000000 ^ */ +/* */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ + 0x7f, /* 0x01111111 _ */ + 0x00, /* 0x00000000 _ */ + 0x00, /* 0x00000000 _ */ +/* */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ + 0x0e, /* 0x00001110 ` */ + 0x0c, /* 0x00001100 ` */ + 0x10, /* 0x00010000 ` */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ + 0x00, /* 0x00000000 ` */ +/* */ + 0x00, /* 0x00000000 a */ + 0x00, /* 0x00000000 a */ + 0x00, /* 0x00000000 a */ + 0x00, /* 0x00000000 a */ + 0x00, /* 0x00000000 a */ + 0x3e, /* 0x00111110 a */ + 0x40, /* 0x01000000 a */ + 0x40, /* 0x01000000 a */ + 0x7e, /* 0x01111110 a */ + 0x41, /* 0x01000001 a */ + 0x61, /* 0x01100001 a */ + 0x5e, /* 0x01011110 a */ + 0x00, /* 0x00000000 a */ + 0x00, /* 0x00000000 a */ + 0x00, /* 0x00000000 a */ +/* */ + 0x00, /* 0x00000000 b */ + 0x00, /* 0x00000000 b */ + 0x01, /* 0x00000001 b */ + 0x01, /* 0x00000001 b */ + 0x01, /* 0x00000001 b */ + 0x3d, /* 0x00111101 b */ + 0x43, /* 0x01000011 b */ + 0x41, /* 0x01000001 b */ + 0x41, /* 0x01000001 b */ + 0x41, /* 0x01000001 b */ + 0x43, /* 0x01000011 b */ + 0x3d, /* 0x00111101 b */ + 0x00, /* 0x00000000 b */ + 0x00, /* 0x00000000 b */ + 0x00, /* 0x00000000 b */ +/* */ + 0x00, /* 0x00000000 c */ + 0x00, /* 0x00000000 c */ + 0x00, /* 0x00000000 c */ + 0x00, /* 0x00000000 c */ + 0x00, /* 0x00000000 c */ + 0x3e, /* 0x00111110 c */ + 0x41, /* 0x01000001 c */ + 0x01, /* 0x00000001 c */ + 0x01, /* 0x00000001 c */ + 0x01, /* 0x00000001 c */ + 0x41, /* 0x01000001 c */ + 0x3e, /* 0x00111110 c */ + 0x00, /* 0x00000000 c */ + 0x00, /* 0x00000000 c */ + 0x00, /* 0x00000000 c */ +/* */ + 0x00, /* 0x00000000 d */ + 0x00, /* 0x00000000 d */ + 0x40, /* 0x01000000 d */ + 0x40, /* 0x01000000 d */ + 0x40, /* 0x01000000 d */ + 0x5e, /* 0x01011110 d */ + 0x61, /* 0x01100001 d */ + 0x41, /* 0x01000001 d */ + 0x41, /* 0x01000001 d */ + 0x41, /* 0x01000001 d */ + 0x61, /* 0x01100001 d */ + 0x5e, /* 0x01011110 d */ + 0x00, /* 0x00000000 d */ + 0x00, /* 0x00000000 d */ + 0x00, /* 0x00000000 d */ +/* */ + 0x00, /* 0x00000000 e */ + 0x00, /* 0x00000000 e */ + 0x00, /* 0x00000000 e */ + 0x00, /* 0x00000000 e */ + 0x00, /* 0x00000000 e */ + 0x3e, /* 0x00111110 e */ + 0x41, /* 0x01000001 e */ + 0x41, /* 0x01000001 e */ + 0x7f, /* 0x01111111 e */ + 0x01, /* 0x00000001 e */ + 0x01, /* 0x00000001 e */ + 0x3e, /* 0x00111110 e */ + 0x00, /* 0x00000000 e */ + 0x00, /* 0x00000000 e */ + 0x00, /* 0x00000000 e */ +/* */ + 0x00, /* 0x00000000 f */ + 0x00, /* 0x00000000 f */ + 0x38, /* 0x00111000 f */ + 0x44, /* 0x01000100 f */ + 0x44, /* 0x01000100 f */ + 0x04, /* 0x00000100 f */ + 0x04, /* 0x00000100 f */ + 0x1f, /* 0x00011111 f */ + 0x04, /* 0x00000100 f */ + 0x04, /* 0x00000100 f */ + 0x04, /* 0x00000100 f */ + 0x04, /* 0x00000100 f */ + 0x00, /* 0x00000000 f */ + 0x00, /* 0x00000000 f */ + 0x00, /* 0x00000000 f */ +/* */ + 0x00, /* 0x00000000 g */ + 0x00, /* 0x00000000 g */ + 0x00, /* 0x00000000 g */ + 0x00, /* 0x00000000 g */ + 0x00, /* 0x00000000 g */ + 0x5e, /* 0x01011110 g */ + 0x21, /* 0x00100001 g */ + 0x21, /* 0x00100001 g */ + 0x21, /* 0x00100001 g */ + 0x1e, /* 0x00011110 g */ + 0x01, /* 0x00000001 g */ + 0x3e, /* 0x00111110 g */ + 0x41, /* 0x01000001 g */ + 0x41, /* 0x01000001 g */ + 0x3e, /* 0x00111110 g */ +/* */ + 0x00, /* 0x00000000 h */ + 0x00, /* 0x00000000 h */ + 0x01, /* 0x00000001 h */ + 0x01, /* 0x00000001 h */ + 0x01, /* 0x00000001 h */ + 0x3d, /* 0x00111101 h */ + 0x43, /* 0x01000011 h */ + 0x41, /* 0x01000001 h */ + 0x41, /* 0x01000001 h */ + 0x41, /* 0x01000001 h */ + 0x41, /* 0x01000001 h */ + 0x41, /* 0x01000001 h */ + 0x00, /* 0x00000000 h */ + 0x00, /* 0x00000000 h */ + 0x00, /* 0x00000000 h */ +/* */ + 0x00, /* 0x00000000 i */ + 0x00, /* 0x00000000 i */ + 0x00, /* 0x00000000 i */ + 0x08, /* 0x00001000 i */ + 0x00, /* 0x00000000 i */ + 0x0c, /* 0x00001100 i */ + 0x08, /* 0x00001000 i */ + 0x08, /* 0x00001000 i */ + 0x08, /* 0x00001000 i */ + 0x08, /* 0x00001000 i */ + 0x08, /* 0x00001000 i */ + 0x3e, /* 0x00111110 i */ + 0x00, /* 0x00000000 i */ + 0x00, /* 0x00000000 i */ + 0x00, /* 0x00000000 i */ +/* */ + 0x00, /* 0x00000000 j */ + 0x00, /* 0x00000000 j */ + 0x00, /* 0x00000000 j */ + 0x20, /* 0x00100000 j */ + 0x00, /* 0x00000000 j */ + 0x38, /* 0x00111000 j */ + 0x20, /* 0x00100000 j */ + 0x20, /* 0x00100000 j */ + 0x20, /* 0x00100000 j */ + 0x20, /* 0x00100000 j */ + 0x20, /* 0x00100000 j */ + 0x21, /* 0x00100001 j */ + 0x21, /* 0x00100001 j */ + 0x21, /* 0x00100001 j */ + 0x1e, /* 0x00011110 j */ +/* */ + 0x00, /* 0x00000000 k */ + 0x00, /* 0x00000000 k */ + 0x01, /* 0x00000001 k */ + 0x01, /* 0x00000001 k */ + 0x01, /* 0x00000001 k */ + 0x41, /* 0x01000001 k */ + 0x31, /* 0x00110001 k */ + 0x0d, /* 0x00001101 k */ + 0x03, /* 0x00000011 k */ + 0x0d, /* 0x00001101 k */ + 0x31, /* 0x00110001 k */ + 0x41, /* 0x01000001 k */ + 0x00, /* 0x00000000 k */ + 0x00, /* 0x00000000 k */ + 0x00, /* 0x00000000 k */ +/* */ + 0x00, /* 0x00000000 l */ + 0x00, /* 0x00000000 l */ + 0x0c, /* 0x00001100 l */ + 0x08, /* 0x00001000 l */ + 0x08, /* 0x00001000 l */ + 0x08, /* 0x00001000 l */ + 0x08, /* 0x00001000 l */ + 0x08, /* 0x00001000 l */ + 0x08, /* 0x00001000 l */ + 0x08, /* 0x00001000 l */ + 0x08, /* 0x00001000 l */ + 0x3e, /* 0x00111110 l */ + 0x00, /* 0x00000000 l */ + 0x00, /* 0x00000000 l */ + 0x00, /* 0x00000000 l */ +/* */ + 0x00, /* 0x00000000 m */ + 0x00, /* 0x00000000 m */ + 0x00, /* 0x00000000 m */ + 0x00, /* 0x00000000 m */ + 0x00, /* 0x00000000 m */ + 0x37, /* 0x00110111 m */ + 0x49, /* 0x01001001 m */ + 0x49, /* 0x01001001 m */ + 0x49, /* 0x01001001 m */ + 0x49, /* 0x01001001 m */ + 0x49, /* 0x01001001 m */ + 0x41, /* 0x01000001 m */ + 0x00, /* 0x00000000 m */ + 0x00, /* 0x00000000 m */ + 0x00, /* 0x00000000 m */ +/* */ + 0x00, /* 0x00000000 n */ + 0x00, /* 0x00000000 n */ + 0x00, /* 0x00000000 n */ + 0x00, /* 0x00000000 n */ + 0x00, /* 0x00000000 n */ + 0x3d, /* 0x00111101 n */ + 0x43, /* 0x01000011 n */ + 0x41, /* 0x01000001 n */ + 0x41, /* 0x01000001 n */ + 0x41, /* 0x01000001 n */ + 0x41, /* 0x01000001 n */ + 0x41, /* 0x01000001 n */ + 0x00, /* 0x00000000 n */ + 0x00, /* 0x00000000 n */ + 0x00, /* 0x00000000 n */ +/* */ + 0x00, /* 0x00000000 o */ + 0x00, /* 0x00000000 o */ + 0x00, /* 0x00000000 o */ + 0x00, /* 0x00000000 o */ + 0x00, /* 0x00000000 o */ + 0x3e, /* 0x00111110 o */ + 0x41, /* 0x01000001 o */ + 0x41, /* 0x01000001 o */ + 0x41, /* 0x01000001 o */ + 0x41, /* 0x01000001 o */ + 0x41, /* 0x01000001 o */ + 0x3e, /* 0x00111110 o */ + 0x00, /* 0x00000000 o */ + 0x00, /* 0x00000000 o */ + 0x00, /* 0x00000000 o */ +/* */ + 0x00, /* 0x00000000 p */ + 0x00, /* 0x00000000 p */ + 0x00, /* 0x00000000 p */ + 0x00, /* 0x00000000 p */ + 0x00, /* 0x00000000 p */ + 0x3d, /* 0x00111101 p */ + 0x43, /* 0x01000011 p */ + 0x41, /* 0x01000001 p */ + 0x41, /* 0x01000001 p */ + 0x41, /* 0x01000001 p */ + 0x43, /* 0x01000011 p */ + 0x3d, /* 0x00111101 p */ + 0x01, /* 0x00000001 p */ + 0x01, /* 0x00000001 p */ + 0x01, /* 0x00000001 p */ +/* */ + 0x00, /* 0x00000000 q */ + 0x00, /* 0x00000000 q */ + 0x00, /* 0x00000000 q */ + 0x00, /* 0x00000000 q */ + 0x00, /* 0x00000000 q */ + 0x5e, /* 0x01011110 q */ + 0x61, /* 0x01100001 q */ + 0x41, /* 0x01000001 q */ + 0x41, /* 0x01000001 q */ + 0x41, /* 0x01000001 q */ + 0x61, /* 0x01100001 q */ + 0x5e, /* 0x01011110 q */ + 0x40, /* 0x01000000 q */ + 0x40, /* 0x01000000 q */ + 0x40, /* 0x01000000 q */ +/* */ + 0x00, /* 0x00000000 r */ + 0x00, /* 0x00000000 r */ + 0x00, /* 0x00000000 r */ + 0x00, /* 0x00000000 r */ + 0x00, /* 0x00000000 r */ + 0x39, /* 0x00111001 r */ + 0x46, /* 0x01000110 r */ + 0x42, /* 0x01000010 r */ + 0x02, /* 0x00000010 r */ + 0x02, /* 0x00000010 r */ + 0x02, /* 0x00000010 r */ + 0x02, /* 0x00000010 r */ + 0x00, /* 0x00000000 r */ + 0x00, /* 0x00000000 r */ + 0x00, /* 0x00000000 r */ +/* */ + 0x00, /* 0x00000000 s */ + 0x00, /* 0x00000000 s */ + 0x00, /* 0x00000000 s */ + 0x00, /* 0x00000000 s */ + 0x00, /* 0x00000000 s */ + 0x3e, /* 0x00111110 s */ + 0x41, /* 0x01000001 s */ + 0x01, /* 0x00000001 s */ + 0x3e, /* 0x00111110 s */ + 0x40, /* 0x01000000 s */ + 0x41, /* 0x01000001 s */ + 0x3e, /* 0x00111110 s */ + 0x00, /* 0x00000000 s */ + 0x00, /* 0x00000000 s */ + 0x00, /* 0x00000000 s */ +/* */ + 0x00, /* 0x00000000 t */ + 0x00, /* 0x00000000 t */ + 0x00, /* 0x00000000 t */ + 0x04, /* 0x00000100 t */ + 0x04, /* 0x00000100 t */ + 0x3f, /* 0x00111111 t */ + 0x04, /* 0x00000100 t */ + 0x04, /* 0x00000100 t */ + 0x04, /* 0x00000100 t */ + 0x04, /* 0x00000100 t */ + 0x44, /* 0x01000100 t */ + 0x38, /* 0x00111000 t */ + 0x00, /* 0x00000000 t */ + 0x00, /* 0x00000000 t */ + 0x00, /* 0x00000000 t */ +/* */ + 0x00, /* 0x00000000 u */ + 0x00, /* 0x00000000 u */ + 0x00, /* 0x00000000 u */ + 0x00, /* 0x00000000 u */ + 0x00, /* 0x00000000 u */ + 0x21, /* 0x00100001 u */ + 0x21, /* 0x00100001 u */ + 0x21, /* 0x00100001 u */ + 0x21, /* 0x00100001 u */ + 0x21, /* 0x00100001 u */ + 0x21, /* 0x00100001 u */ + 0x5e, /* 0x01011110 u */ + 0x00, /* 0x00000000 u */ + 0x00, /* 0x00000000 u */ + 0x00, /* 0x00000000 u */ +/* */ + 0x00, /* 0x00000000 v */ + 0x00, /* 0x00000000 v */ + 0x00, /* 0x00000000 v */ + 0x00, /* 0x00000000 v */ + 0x00, /* 0x00000000 v */ + 0x41, /* 0x01000001 v */ + 0x41, /* 0x01000001 v */ + 0x22, /* 0x00100010 v */ + 0x22, /* 0x00100010 v */ + 0x14, /* 0x00010100 v */ + 0x14, /* 0x00010100 v */ + 0x08, /* 0x00001000 v */ + 0x00, /* 0x00000000 v */ + 0x00, /* 0x00000000 v */ + 0x00, /* 0x00000000 v */ +/* */ + 0x00, /* 0x00000000 w */ + 0x00, /* 0x00000000 w */ + 0x00, /* 0x00000000 w */ + 0x00, /* 0x00000000 w */ + 0x00, /* 0x00000000 w */ + 0x41, /* 0x01000001 w */ + 0x41, /* 0x01000001 w */ + 0x49, /* 0x01001001 w */ + 0x49, /* 0x01001001 w */ + 0x49, /* 0x01001001 w */ + 0x55, /* 0x01010101 w */ + 0x22, /* 0x00100010 w */ + 0x00, /* 0x00000000 w */ + 0x00, /* 0x00000000 w */ + 0x00, /* 0x00000000 w */ +/* */ + 0x00, /* 0x00000000 x */ + 0x00, /* 0x00000000 x */ + 0x00, /* 0x00000000 x */ + 0x00, /* 0x00000000 x */ + 0x00, /* 0x00000000 x */ + 0x41, /* 0x01000001 x */ + 0x22, /* 0x00100010 x */ + 0x14, /* 0x00010100 x */ + 0x08, /* 0x00001000 x */ + 0x14, /* 0x00010100 x */ + 0x22, /* 0x00100010 x */ + 0x41, /* 0x01000001 x */ + 0x00, /* 0x00000000 x */ + 0x00, /* 0x00000000 x */ + 0x00, /* 0x00000000 x */ +/* */ + 0x00, /* 0x00000000 y */ + 0x00, /* 0x00000000 y */ + 0x00, /* 0x00000000 y */ + 0x00, /* 0x00000000 y */ + 0x00, /* 0x00000000 y */ + 0x21, /* 0x00100001 y */ + 0x21, /* 0x00100001 y */ + 0x21, /* 0x00100001 y */ + 0x21, /* 0x00100001 y */ + 0x21, /* 0x00100001 y */ + 0x31, /* 0x00110001 y */ + 0x2e, /* 0x00101110 y */ + 0x20, /* 0x00100000 y */ + 0x21, /* 0x00100001 y */ + 0x1e, /* 0x00011110 y */ +/* */ + 0x00, /* 0x00000000 z */ + 0x00, /* 0x00000000 z */ + 0x00, /* 0x00000000 z */ + 0x00, /* 0x00000000 z */ + 0x00, /* 0x00000000 z */ + 0x7f, /* 0x01111111 z */ + 0x20, /* 0x00100000 z */ + 0x10, /* 0x00010000 z */ + 0x08, /* 0x00001000 z */ + 0x04, /* 0x00000100 z */ + 0x02, /* 0x00000010 z */ + 0x7f, /* 0x01111111 z */ + 0x00, /* 0x00000000 z */ + 0x00, /* 0x00000000 z */ + 0x00, /* 0x00000000 z */ +/* */ + 0x00, /* 0x00000000 { */ + 0x00, /* 0x00000000 { */ + 0x70, /* 0x01110000 { */ + 0x08, /* 0x00001000 { */ + 0x08, /* 0x00001000 { */ + 0x10, /* 0x00010000 { */ + 0x0c, /* 0x00001100 { */ + 0x0c, /* 0x00001100 { */ + 0x10, /* 0x00010000 { */ + 0x08, /* 0x00001000 { */ + 0x08, /* 0x00001000 { */ + 0x70, /* 0x01110000 { */ + 0x00, /* 0x00000000 { */ + 0x00, /* 0x00000000 { */ + 0x00, /* 0x00000000 { */ +/* */ + 0x00, /* 0x00000000 | */ + 0x00, /* 0x00000000 | */ + 0x08, /* 0x00001000 | */ + 0x08, /* 0x00001000 | */ + 0x08, /* 0x00001000 | */ + 0x08, /* 0x00001000 | */ + 0x08, /* 0x00001000 | */ + 0x08, /* 0x00001000 | */ + 0x08, /* 0x00001000 | */ + 0x08, /* 0x00001000 | */ + 0x08, /* 0x00001000 | */ + 0x08, /* 0x00001000 | */ + 0x00, /* 0x00000000 | */ + 0x00, /* 0x00000000 | */ + 0x00, /* 0x00000000 | */ +/* */ + 0x00, /* 0x00000000 } */ + 0x00, /* 0x00000000 } */ + 0x07, /* 0x00000111 } */ + 0x08, /* 0x00001000 } */ + 0x08, /* 0x00001000 } */ + 0x04, /* 0x00000100 } */ + 0x18, /* 0x00011000 } */ + 0x18, /* 0x00011000 } */ + 0x04, /* 0x00000100 } */ + 0x08, /* 0x00001000 } */ + 0x08, /* 0x00001000 } */ + 0x07, /* 0x00000111 } */ + 0x00, /* 0x00000000 } */ + 0x00, /* 0x00000000 } */ + 0x00, /* 0x00000000 } */ +/* */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x46, /* 0x01000110 ~ */ + 0x49, /* 0x01001001 ~ */ + 0x31, /* 0x00110001 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ + 0x00, /* 0x00000000 ~ */ +/* */ +/* ascii0241 */ + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x00, + 0x00, +/* ascii0242 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x10, + 0x10, + 0x3c, + 0x42, + 0x02, + 0x02, + 0x42, + 0x3c, + 0x10, + 0x10, + 0x00, +/* ascii0243 */ + 0x00, + 0x00, + 0x70, + 0x88, + 0x08, + 0x08, + 0x08, + 0x3e, + 0x08, + 0x08, + 0x08, + 0xdc, + 0x76, + 0x00, + 0x00, +/* ascii0244 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0245 */ + 0x00, + 0x00, + 0x00, + 0x44, + 0x44, + 0x44, + 0x28, + 0x10, + 0x7c, + 0x10, + 0x7c, + 0x10, + 0x10, + 0x00, + 0x00, +/* ascii0246 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0247 */ + 0x00, + 0x1c, + 0x22, + 0x02, + 0x04, + 0x1c, + 0x22, + 0x22, + 0x1c, + 0x10, + 0x20, + 0x22, + 0x1c, + 0x00, + 0x00, +/* ascii0250 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x82, + 0x44, + 0x38, + 0x44, + 0x44, + 0x44, + 0x38, + 0x44, + 0x82, + 0x00, + 0x00, +/* ascii0251 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x82, + 0xb2, + 0x8a, + 0x8a, + 0xb2, + 0x82, + 0x7c, + 0x00, + 0x00, +/* ascii0252 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x40, + 0x7c, + 0x42, + 0x42, + 0x7c, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x00, + 0x00, +/* ascii0253 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x48, + 0x24, + 0x12, + 0x09, + 0x12, + 0x24, + 0x48, + 0x00, + 0x00, + 0x00, +/* ascii0254 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0255 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0256 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0257 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0260 */ + 0x00, + 0x18, + 0x24, + 0x24, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +/* ascii0261 */ + 0x00, + 0x00, + 0x00, + 0x08, + 0x08, + 0x08, + 0x3e, + 0x08, + 0x08, + 0x08, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x00, +/* ascii0262 */ + 0x00, + 0x00, + 0x0c, + 0x12, + 0x08, + 0x04, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +/* ascii0263 */ + 0x00, + 0x00, + 0x1e, + 0x10, + 0x08, + 0x10, + 0x12, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +/* ascii0264 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0265 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x44, + 0x44, + 0x44, + 0x44, + 0x44, + 0x7c, + 0xc2, + 0x01, +/* ascii0266 */ + 0x00, + 0x00, + 0x00, + 0x7c, + 0x4e, + 0x4e, + 0x4e, + 0x4e, + 0x7c, + 0x48, + 0x48, + 0x48, + 0x48, + 0x00, + 0x00, +/* ascii0267 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +/* ascii0270 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0271 */ + 0x00, + 0x00, + 0x08, + 0x0c, + 0x08, + 0x08, + 0x08, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +/* ascii0272 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x00, +/* ascii0273 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x12, + 0x24, + 0x48, + 0x90, + 0x48, + 0x24, + 0x12, + 0x00, + 0x00, +/* ascii0274 */ + 0x00, + 0x04, + 0x06, + 0x04, + 0x04, + 0x4e, + 0x20, + 0x10, + 0x48, + 0x64, + 0x52, + 0xf8, + 0x40, + 0x40, + 0x00, +/* ascii0275 */ + 0x00, + 0x04, + 0x06, + 0x04, + 0x04, + 0x4e, + 0x20, + 0x10, + 0x08, + 0x74, + 0x82, + 0x60, + 0x10, + 0xf0, + 0x00, +/* ascii0276 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0277 */ + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x10, + 0x10, + 0x08, + 0x04, + 0x02, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0300 */ + 0x00, + 0x08, + 0x10, + 0x20, + 0x18, + 0x24, + 0x42, + 0x42, + 0x42, + 0x7e, + 0x42, + 0x42, + 0x42, + 0x00, + 0x00, +/* ascii0301 */ + 0x00, + 0x10, + 0x08, + 0x04, + 0x18, + 0x24, + 0x42, + 0x42, + 0x42, + 0x7e, + 0x42, + 0x42, + 0x42, + 0x00, + 0x00, +/* ascii0302 */ + 0x00, + 0x18, + 0x24, + 0x42, + 0x18, + 0x24, + 0x42, + 0x42, + 0x42, + 0x7e, + 0x42, + 0x42, + 0x42, + 0x00, + 0x00, +/* ascii0303 */ + 0x00, + 0x4c, + 0x32, + 0x00, + 0x18, + 0x24, + 0x42, + 0x42, + 0x42, + 0x7e, + 0x42, + 0x42, + 0x42, + 0x00, + 0x00, +/* ascii0304 */ + 0x00, + 0x00, + 0x66, + 0x00, + 0x18, + 0x24, + 0x42, + 0x42, + 0x42, + 0x7e, + 0x42, + 0x42, + 0x42, + 0x00, + 0x00, +/* ascii0305 */ + 0x18, + 0x24, + 0x18, + 0x00, + 0x18, + 0x24, + 0x42, + 0x42, + 0x42, + 0x7e, + 0x42, + 0x42, + 0x42, + 0x00, + 0x00, +/* ascii0306 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x14, + 0x12, + 0x12, + 0x7e, + 0x12, + 0x12, + 0x12, + 0xf2, + 0x00, + 0x00, +/* ascii0307 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x42, + 0x3c, + 0x10, + 0x0c, +/* ascii0310 */ + 0x08, + 0x10, + 0x20, + 0x00, + 0x7e, + 0x02, + 0x02, + 0x02, + 0x1e, + 0x02, + 0x02, + 0x02, + 0x7e, + 0x00, + 0x00, +/* ascii0311 */ + 0x10, + 0x08, + 0x04, + 0x00, + 0x7e, + 0x02, + 0x02, + 0x02, + 0x1e, + 0x02, + 0x02, + 0x02, + 0x7e, + 0x00, + 0x00, +/* ascii0312 */ + 0x18, + 0x24, + 0x42, + 0x00, + 0x7e, + 0x02, + 0x02, + 0x02, + 0x1e, + 0x02, + 0x02, + 0x02, + 0x7e, + 0x00, + 0x00, +/* ascii0313 */ + 0x00, + 0x66, + 0x00, + 0x00, + 0x7e, + 0x02, + 0x02, + 0x02, + 0x1e, + 0x02, + 0x02, + 0x02, + 0x7e, + 0x00, + 0x00, +/* ascii0314 */ + 0x08, + 0x10, + 0x20, + 0x00, + 0x3c, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x3c, + 0x00, + 0x00, +/* ascii0315 */ + 0x40, + 0x20, + 0x10, + 0x00, + 0x3c, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x3c, + 0x00, + 0x00, +/* ascii0316 */ + 0x18, + 0x24, + 0x42, + 0x00, + 0x3c, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x3c, + 0x00, + 0x00, +/* ascii0317 */ + 0x00, + 0x66, + 0x00, + 0x00, + 0x3c, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x3c, + 0x00, + 0x00, +/* ascii0320 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0321 */ + 0x00, + 0x4c, + 0x32, + 0x00, + 0x42, + 0x42, + 0x46, + 0x4a, + 0x52, + 0x62, + 0x42, + 0x42, + 0x42, + 0x00, + 0x00, +/* ascii0322 */ + 0x08, + 0x10, + 0x20, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0323 */ + 0x10, + 0x08, + 0x04, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0324 */ + 0x18, + 0x24, + 0x42, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0325 */ + 0x00, + 0x4c, + 0x32, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0326 */ + 0x00, + 0x66, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0327 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0xfc, + 0x12, + 0x12, + 0x12, + 0x72, + 0x12, + 0x12, + 0x12, + 0xfc, + 0x00, + 0x00, +/* ascii0330 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0xbc, + 0x42, + 0x62, + 0x52, + 0x52, + 0x4a, + 0x46, + 0x42, + 0x3d, + 0x00, + 0x00, +/* ascii0331 */ + 0x00, + 0x04, + 0x08, + 0x10, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0332 */ + 0x00, + 0x20, + 0x10, + 0x08, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0333 */ + 0x00, + 0x18, + 0x24, + 0x42, + 0x00, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0334 */ + 0x00, + 0x66, + 0x00, + 0x00, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0335 */ + 0x00, + 0xc6, + 0x00, + 0x00, + 0x82, + 0x82, + 0x44, + 0x28, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x00, + 0x00, +/* ascii0336 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0337 */ + 0x00, + 0x00, + 0x70, + 0x88, + 0x84, + 0x84, + 0x44, + 0x74, + 0x84, + 0x84, + 0x84, + 0x94, + 0x74, + 0x04, + 0x02, +/* ascii0340 */ + 0x00, + 0x00, + 0x00, + 0x08, + 0x10, + 0x20, + 0x00, + 0x3c, + 0x40, + 0x7c, + 0x42, + 0x42, + 0x7c, + 0x00, + 0x00, +/* ascii0341 */ + 0x00, + 0x00, + 0x00, + 0x10, + 0x08, + 0x04, + 0x00, + 0x3c, + 0x40, + 0x7c, + 0x42, + 0x42, + 0x7c, + 0x00, + 0x00, +/* ascii0342 */ + 0x00, + 0x00, + 0x00, + 0x18, + 0x24, + 0x42, + 0x00, + 0x3c, + 0x40, + 0x7c, + 0x42, + 0x42, + 0x7c, + 0x00, + 0x00, +/* ascii0343 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x32, + 0x00, + 0x3c, + 0x40, + 0x7c, + 0x42, + 0x42, + 0x7c, + 0x00, + 0x00, +/* ascii0344 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x3c, + 0x40, + 0x7c, + 0x42, + 0x42, + 0x7c, + 0x00, + 0x00, +/* ascii0345 */ + 0x00, + 0x00, + 0x00, + 0x18, + 0x24, + 0x18, + 0x00, + 0x3c, + 0x40, + 0x7c, + 0x42, + 0x42, + 0x7c, + 0x00, + 0x00, +/* ascii0346 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6e, + 0x90, + 0xfc, + 0x12, + 0x12, + 0xec, + 0x00, + 0x00, +/* ascii0347 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x02, + 0x02, + 0x42, + 0x3c, + 0x10, + 0x0c, +/* ascii0350 */ + 0x00, + 0x00, + 0x00, + 0x08, + 0x10, + 0x20, + 0x00, + 0x3c, + 0x42, + 0x7e, + 0x02, + 0x02, + 0x3c, + 0x00, + 0x00, +/* ascii0351 */ + 0x00, + 0x00, + 0x00, + 0x10, + 0x08, + 0x04, + 0x00, + 0x3c, + 0x42, + 0x7e, + 0x02, + 0x02, + 0x3c, + 0x00, + 0x00, +/* ascii0352 */ + 0x00, + 0x00, + 0x00, + 0x18, + 0x24, + 0x42, + 0x00, + 0x3c, + 0x42, + 0x7e, + 0x02, + 0x02, + 0x3c, + 0x00, + 0x00, +/* ascii0353 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x7e, + 0x02, + 0x02, + 0x3c, + 0x00, + 0x00, +/* ascii0354 */ + 0x00, + 0x00, + 0x00, + 0x04, + 0x08, + 0x10, + 0x00, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x3c, + 0x00, + 0x00, +/* ascii0355 */ + 0x00, + 0x00, + 0x00, + 0x10, + 0x08, + 0x04, + 0x00, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x3c, + 0x00, + 0x00, +/* ascii0356 */ + 0x00, + 0x00, + 0x00, + 0x18, + 0x24, + 0x42, + 0x00, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x3c, + 0x00, + 0x00, +/* ascii0357 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x3c, + 0x00, + 0x00, +/* ascii0360 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0361 */ + 0x00, + 0x00, + 0x00, + 0x4c, + 0x32, + 0x00, + 0x00, + 0x3e, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x00, + 0x00, +/* ascii0362 */ + 0x00, + 0x00, + 0x00, + 0x08, + 0x10, + 0x20, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0363 */ + 0x00, + 0x00, + 0x00, + 0x10, + 0x08, + 0x04, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0364 */ + 0x00, + 0x00, + 0x00, + 0x18, + 0x24, + 0x42, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0365 */ + 0x00, + 0x00, + 0x00, + 0x4c, + 0x32, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0366 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0367 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x92, + 0xf2, + 0x12, + 0x12, + 0xec, + 0x00, + 0x00, +/* ascii0370 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xbc, + 0x62, + 0x52, + 0x4a, + 0x46, + 0x3c, + 0x02, + 0x00, +/* ascii0371 */ + 0x00, + 0x00, + 0x00, + 0x04, + 0x08, + 0x10, + 0x00, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0372 */ + 0x00, + 0x00, + 0x00, + 0x20, + 0x10, + 0x08, + 0x00, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0373 */ + 0x00, + 0x00, + 0x00, + 0x18, + 0x24, + 0x42, + 0x00, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0374 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, +/* ascii0375 */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x40, + 0x40, + 0x3e, +/* ascii0376 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, +/* ascii0377 */ + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x42, + 0x02, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, + +}; + +/* + * Default Cursor + */ +unsigned short q_cursor[] = { + 0x0000, + 0x0000, + 0x00ff, + 0x00ff, + 0x00ff, + 0x00ff, + 0x00ff, + 0x00ff, + 0x00ff, + 0x00ff, + 0x00ff, + 0x00ff, + 0x00ff, + 0x0000, + 0x0000, + 0x0000 +}; + diff --git a/sys/arch/vax/qbus/uba.c b/sys/arch/vax/qbus/uba.c new file mode 100644 index 00000000000..13844d68105 --- /dev/null +++ b/sys/arch/vax/qbus/uba.c @@ -0,0 +1,264 @@ +/* $OpenBSD: uba.c,v 1.1 2000/04/27 03:14:49 bjc Exp $ */ +/* $NetBSD: uba.c,v 1.49 2000/01/24 02:40:30 matt Exp $ */ +/* + * Copyright (c) 1996 Jonathan Stone. + * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uba.c 7.10 (Berkeley) 12/16/90 + * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/systm.h> +#include <sys/map.h> +#include <sys/buf.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/conf.h> +#include <sys/dkstat.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/device.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/bus.h> +#include <machine/scb.h> +#include <machine/cpu.h> + +#include <arch/vax/qbus/ubavar.h> + +static int ubasearch __P((struct device *, struct cfdata *, void *)); +static int ubaprint __P((void *, const char *)); + +struct cfdriver uba_cd = { + NULL, "uba", DV_DULL +}; + +/* + * If we failed to allocate uba resources, put us on a queue to wait + * until there is available resources. Resources to compete about + * are map registers and BDPs. This is normally only a problem on + * Unibus systems, Qbus systems have more map registers than usable. + */ +void +uba_enqueue(uu) + struct uba_unit *uu; +{ + struct uba_softc *uh; + int s; + + uh = (void *)((struct device *)(uu->uu_softc))->dv_parent; + + s = splimp(); + SIMPLEQ_INSERT_TAIL(&uh->uh_resq, uu, uu_resq); + splx(s); +} + +/* + * When a routine that uses resources is finished, the next device + * in queue for map registers etc is called. If it succeeds to get + * resources, call next, and next, and next... + * This routine must be called at splimp. + */ +void +uba_done(uh) + struct uba_softc *uh; +{ + struct uba_unit *uu; + + while ((uu = SIMPLEQ_FIRST(&uh->uh_resq))) { + SIMPLEQ_REMOVE_HEAD(&uh->uh_resq, uu, uu_resq); + if ((*uu->uu_ready)(uu) == 0) { + SIMPLEQ_INSERT_HEAD(&uh->uh_resq, uu, uu_resq); + break; + } + } +} + +/* + * Generate a reset on uba number uban. Then + * call each device that asked to be called during attach, + * giving it a chance to clean up so as to be able to continue. + */ +void +ubareset(uban) + int uban; +{ + register struct uba_softc *uh = uba_cd.cd_devs[uban]; + int s, i; + + s = splimp(); + SIMPLEQ_INIT(&uh->uh_resq); + printf("%s: reset", uh->uh_dev.dv_xname); + (*uh->uh_ubainit)(uh); + + for (i = 0; i < uh->uh_resno; i++) + (*uh->uh_reset[i])(uh->uh_resarg[i]); + printf("\n"); + splx(s); +} + +/* + * The common attach routine: + * Calls the scan routine to search for uba devices. + */ +void +uba_attach(sc, iopagephys) + struct uba_softc *sc; + paddr_t iopagephys; +{ + + /* + * Set last free interrupt vector for devices with + * programmable interrupt vectors. Use is to decrement + * this number and use result as interrupt vector. + */ + sc->uh_lastiv = 0x200; + SIMPLEQ_INIT(&sc->uh_resq); + + /* + * Allocate place for unibus I/O space in virtual space. + */ + if (bus_space_map(sc->uh_iot, iopagephys, UBAIOSIZE, 0, &sc->uh_ioh)) + return; + + if (sc->uh_beforescan) + (*sc->uh_beforescan)(sc); + /* + * Now start searching for devices. + */ + config_search((cfmatch_t)ubasearch,(struct device *)sc, NULL); + + if (sc->uh_afterscan) + (*sc->uh_afterscan)(sc); +} + +int +ubasearch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct uba_softc *sc = (struct uba_softc *)parent; + struct uba_attach_args ua; + int i, vec, br; + + ua.ua_ioh = ubdevreg(cf->cf_loc[0]) + sc->uh_ioh; + ua.ua_iot = sc->uh_iot; + ua.ua_dmat = sc->uh_dmat; + ua.ua_reset = NULL; + + if (badaddr((caddr_t)ua.ua_ioh, 2) || + (sc->uh_errchk ? (*sc->uh_errchk)(sc):0)) + goto forgetit; + + scb_vecref(0, 0); /* Clear vector ref */ + i = (*cf->cf_attach->ca_match) (parent, cf, &ua); + + if (sc->uh_errchk) + if ((*sc->uh_errchk)(sc)) + goto forgetit; + if (i == 0) + goto forgetit; + + i = scb_vecref(&vec, &br); + if (i == 0) + goto fail; + if (vec == 0) + goto fail; + + if (ua.ua_reset) { /* device wants ubareset */ + if (sc->uh_resno == 0) { +#define RESETSIXE 128 + sc->uh_reset = malloc(sizeof(void *) * RESETSIXE, + M_DEVBUF, M_NOWAIT); + sc->uh_resarg = malloc(sizeof(void *) * RESETSIXE, + M_DEVBUF, M_NOWAIT); + } + if (sc->uh_resno < RESETSIXE) { + sc->uh_resarg[sc->uh_resno] = cf->cf_unit; + sc->uh_reset[sc->uh_resno++] = ua.ua_reset; + } else { + printf("%s: Expand reset table, skipping reset %s%d\n", + sc->uh_dev.dv_xname, cf->cf_driver->cd_name, + cf->cf_unit); + } + } + + ua.ua_br = br; + ua.ua_cvec = vec; + ua.ua_iaddr = cf->cf_loc[0]; + + config_attach(parent, cf, &ua, ubaprint); + return 0; + +fail: + printf("%s%d at %s csr %o %s\n", + cf->cf_driver->cd_name, cf->cf_unit, parent->dv_xname, + cf->cf_loc[0], (i ? "zero vector" : "didn't interrupt")); + +forgetit: + return 0; +} + +/* + * Print out some interesting info common to all unibus devices. + */ +int +ubaprint(aux, uba) + void *aux; + const char *uba; +{ + struct uba_attach_args *ua = aux; + + printf(" csr %o vec %o ipl %x", ua->ua_iaddr, + ua->ua_cvec & 511, ua->ua_br); + return UNCONF; +} + +/* + * Move to machdep eventually + */ +void +uba_intr_establish(icookie, vec, ifunc, iarg) + void *icookie; + int vec; + void (*ifunc)(void *iarg); + void *iarg; +{ + scb_vecalloc(vec, ifunc, iarg, SCB_ISTACK); +} diff --git a/sys/arch/vax/qbus/ubavar.h b/sys/arch/vax/qbus/ubavar.h new file mode 100644 index 00000000000..942b8eb7af7 --- /dev/null +++ b/sys/arch/vax/qbus/ubavar.h @@ -0,0 +1,148 @@ +/* $OpenBSD: ubavar.h,v 1.1 2000/04/27 03:14:49 bjc Exp $ */ +/* $NetBSD: ubavar.h,v 1.26 2000/01/24 02:40:30 matt Exp $ */ + +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ubavar.h 7.7 (Berkeley) 6/28/90 + */ +#ifndef _QBUS_UBAVAR_H +#define _QBUS_UBAVAR_H + +/* + * This file contains definitions related to the kernel structures + * for dealing with the unibus adapters. + * + * Each uba has a uba_softc structure. + * Each unibus controller which is not a device has a uba_ctlr structure. + * Each unibus device has a uba_device structure. + */ + +/* + * Per-uba structure. + * + * This structure holds the interrupt vector for the uba, + * and its address in physical and virtual space. At boot time + * we determine the devices attached to the uba's and their + * interrupt vectors, filling in uh_vec. We free the map + * register and bdp resources of the uba into the structures + * defined here. + * + * During normal operation, resources are allocated and returned + * to the structures here. We watch the number of passive releases + * on each uba, and if the number is excessive may reset the uba. + * + * When uba resources are needed and not available, or if a device + * which can tolerate no other uba activity (rk07) gets on the bus, + * then device drivers may have to wait to get to the bus and are + * queued here. It is also possible for processes to block in + * the unibus driver in resource wait (mrwant, bdpwant); these + * wait states are also recorded here. + */ +struct uba_softc { + struct device uh_dev; /* Device struct, autoconfig */ + SIMPLEQ_HEAD(, uba_unit) uh_resq; /* resource wait chain */ + void (**uh_reset) __P((int));/* UBA reset function array */ + int *uh_resarg; /* array of ubareset args */ + int uh_resno; /* Number of devices to reset */ + int uh_lastiv; /* last free interrupt vector */ + int (*uh_errchk) __P((struct uba_softc *)); + void (*uh_beforescan) __P((struct uba_softc *)); + void (*uh_afterscan) __P((struct uba_softc *)); + void (*uh_ubainit) __P((struct uba_softc *)); + void (*uh_ubapurge) __P((struct uba_softc *, int)); + short uh_nr; /* Unibus sequential number */ + bus_space_tag_t uh_iot; /* Tag for this Unibus */ + bus_space_handle_t uh_ioh; /* Handle for I/O space */ + bus_dma_tag_t uh_dmat; +}; + +/* + * Per-controller structure. + * The unit struct is common to both the adapter and the controller + * to which it belongs. It is only used on controllers that handles + * BDP's, and calls the adapter queueing subroutines. + */ +struct uba_unit { + SIMPLEQ_ENTRY(uba_unit) uu_resq;/* Queue while waiting for resources */ + void *uu_softc; /* Pointer to units softc */ + int uu_bdp; /* for controllers that hang on to bdp's */ + int (*uu_ready) __P((struct uba_unit *)); + void *uu_ref; /* Buffer this is related to */ + short uu_xclu; /* want exclusive use of bdp's */ + short uu_keepbdp; /* hang on to bdp's once allocated */ +}; + +/* + * uba_attach_args is used during autoconfiguration. It is sent + * from ubascan() to each (possible) device. + */ +struct uba_attach_args { + bus_space_tag_t ua_iot; /* Tag for this bus I/O-space */ + bus_addr_t ua_ioh; /* I/O regs addr */ + bus_dma_tag_t ua_dmat; + void *ua_icookie; /* Cookie for interrupt establish */ + /* UBA reset routine, filled in by probe */ + void (*ua_reset) __P((int)); + int ua_iaddr; /* Full CSR address of device */ + int ua_br; /* IPL this dev interrupted on */ + int ua_cvec; /* Vector for this device */ +}; + +/* + * Flags to UBA map/bdp allocation routines + */ +#define UBA_NEEDBDP 0x01 /* transfer needs a bdp */ +#define UBA_CANTWAIT 0x02 /* don't block me */ +#define UBA_NEED16 0x04 /* need 16 bit addresses only */ +#define UBA_HAVEBDP 0x08 /* use bdp specified in high bits */ +#define UBA_DONTQUE 0x10 /* Do not enqueue xfer */ + +/* + * Some common defines for all subtypes of U/Q-buses/adapters. + */ +#define MAXUBAXFER (63*1024) /* Max transfer size in bytes */ +#define UBAIOSIZE (8*1024) /* 8K I/O space */ +#define ubdevreg(addr) ((addr) & 017777) + +#ifdef _KERNEL +#define b_forw b_hash.le_next /* Nice to have when handling uba queues */ + +void uba_intr_establish __P((void *, int, void (*)(void *), void *)); +void uba_attach __P((struct uba_softc *, unsigned long)); +void uba_enqueue __P((struct uba_unit *)); +void uba_done __P((struct uba_softc *)); +void ubareset __P((int)); + +#endif /* _KERNEL */ + +#endif /* _QBUS_UBAVAR_H */ diff --git a/sys/arch/vax/qbus/uda.c b/sys/arch/vax/qbus/uda.c new file mode 100644 index 00000000000..ae91879ef04 --- /dev/null +++ b/sys/arch/vax/qbus/uda.c @@ -0,0 +1,509 @@ +/* $OpenBSD: uda.c,v 1.1 2000/04/27 03:14:49 bjc Exp $ */ +/* $NetBSD: uda.c,v 1.32 2000/01/24 02:40:30 matt Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uda.c 7.32 (Berkeley) 2/13/91 + */ + +/* + * UDA50 disk device driver + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/buf.h> +#include <sys/malloc.h> + +#include <machine/bus.h> +#include <machine/sid.h> + +#include <arch/vax/qbus/ubavar.h> +#include <arch/vax/mscp/mscp.h> +#include <arch/vax/mscp/mscpreg.h> +#include <arch/vax/mscp/mscpvar.h> + +/* + * Software status, per controller. + */ +struct uda_softc { + struct device sc_dev; /* Autoconfig info */ + struct uba_unit sc_unit; /* Struct common for UBA to communicate */ + struct mscp_pack *sc_uuda; /* Unibus address of uda struct */ + struct mscp_pack sc_uda; /* Struct for uda communication */ + bus_dma_tag_t sc_dmat; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_iph; + bus_space_handle_t sc_sah; + bus_dmamap_t sc_cmap;/* Control structures */ + struct mscp *sc_mscp; /* Keep pointer to active mscp */ + struct mscp_softc *sc_softc; /* MSCP info (per mscpvar.h) */ + int sc_wticks; /* watchdog timer ticks */ + int sc_inq; +}; + +static int udamatch __P((struct device *, struct cfdata *, void *)); +static void udaattach __P((struct device *, struct device *, void *)); +static void udareset __P((int)); +static void mtcreset __P((int)); +static void reset __P((struct uda_softc *)); +static void intr __P((void *)); +int udaready __P((struct uba_unit *)); +void udactlrdone __P((struct device *)); +int udaprint __P((void *, const char *)); +void udasaerror __P((struct device *, int)); +void udago __P((struct device *, struct mscp_xi *)); + +struct cfattach mtc_ca = { + sizeof(struct uda_softc), (cfmatch_t)udamatch, udaattach +}; + +struct cfdriver mtc_cd = { + NULL, "mtc", DV_TAPE +}; + +struct cfattach uda_ca = { + sizeof(struct uda_softc), (cfmatch_t)udamatch, udaattach +}; + +struct cfdriver uda_cd = { + NULL, "uda", DV_DISK +}; + +/* + * More driver definitions, for generic MSCP code. + */ +struct mscp_ctlr uda_mscp_ctlr = { + udactlrdone, + udago, + udasaerror, +}; + +/* + * Miscellaneous private variables. + */ +static int ivec_no; + +int +udaprint(aux, name) + void *aux; + const char *name; +{ + if (name) + printf("%s: mscpbus", name); + return UNCONF; +} + +/* + * Poke at a supposed UDA50 to see if it is there. + */ +int +udamatch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct uba_attach_args *ua = aux; + struct mscp_softc mi; /* Nice hack */ + struct uba_softc *ubasc; + int tries; + + /* Get an interrupt vector. */ + ubasc = (void *)parent; + ivec_no = ubasc->uh_lastiv - 4; + + mi.mi_iot = ua->ua_iot; + mi.mi_iph = ua->ua_ioh; + mi.mi_sah = ua->ua_ioh + 2; + mi.mi_swh = ua->ua_ioh + 2; + + /* + * Initialise the controller (partially). The UDA50 programmer's + * manual states that if initialisation fails, it should be retried + * at least once, but after a second failure the port should be + * considered `down'; it also mentions that the controller should + * initialise within ten seconds. Or so I hear; I have not seen + * this manual myself. + */ + tries = 0; +again: + + bus_space_write_2(mi.mi_iot, mi.mi_iph, 0, 0); /* Start init */ + if (mscp_waitstep(&mi, MP_STEP1, MP_STEP1) == 0) + return 0; /* Nothing here... */ + + bus_space_write_2(mi.mi_iot, mi.mi_sah, 0, + MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | MP_IE | (ivec_no >> 2)); + + if (mscp_waitstep(&mi, MP_STEP2, MP_STEP2) == 0) { + printf("udaprobe: init step2 no change. sa=%x\n", + bus_space_read_2(mi.mi_iot, mi.mi_sah, 0)); + goto bad; + } + + /* should have interrupted by now */ + if (strcmp(cf->cf_driver->cd_name, mtc_cd.cd_name)) { + ua->ua_reset = udareset; + } else { + ua->ua_reset = mtcreset; + } + + return 1; +bad: + if (++tries < 2) + goto again; + return 0; +} + +void +udaattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct uda_softc *sc = (void *)self; + struct uba_attach_args *ua = aux; + struct uba_softc *uh = (void *)parent; + struct mscp_attach_args ma; + int ctlr, error, rseg; + bus_dma_segment_t seg; + + printf("\n"); + + uh->uh_lastiv -= 4; /* remove dynamic interrupt vector */ + + uba_intr_establish(ua->ua_icookie, ua->ua_cvec, intr, sc); + + sc->sc_iot = ua->ua_iot; + sc->sc_iph = ua->ua_ioh; + sc->sc_sah = ua->ua_ioh + 2; + sc->sc_dmat = ua->ua_dmat; + ctlr = sc->sc_dev.dv_unit; + + /* + * Fill in the uba_unit struct, so we can communicate with the uba. + */ + sc->sc_unit.uu_softc = sc; /* Backpointer to softc */ + sc->sc_unit.uu_ready = udaready;/* go routine called from adapter */ + sc->sc_unit.uu_keepbdp = vax_cputype == VAX_750 ? 1 : 0; + + /* + * Map the communication area and command and + * response packets into Unibus space. + */ + if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct mscp_pack), + NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { + printf("Alloc ctrl area %d\n", error); + return; + } + if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, + sizeof(struct mscp_pack), (caddr_t *) &sc->sc_uda, + BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { + printf("Map ctrl area %d\n", error); +err: bus_dmamem_free(sc->sc_dmat, &seg, rseg); + return; + } + if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct mscp_pack), + 1, sizeof(struct mscp_pack), 0, BUS_DMA_NOWAIT, &sc->sc_cmap))) { + printf("Create DMA map %d\n", error); +err2: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)&sc->sc_uda, + sizeof(struct mscp_pack)); + goto err; + } + if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap, + &sc->sc_uda, sizeof(struct mscp_pack), 0, BUS_DMA_NOWAIT))) { + printf("Load ctrl map %d\n", error); + bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap); + goto err2; + } + + bzero(&sc->sc_uda, sizeof (struct mscp_pack)); + + /* + * The only thing that differ UDA's and Tape ctlr's is + * their vcid. Beacuse there are no way to determine which + * ctlr type it is, we check what is generated and later + * set the correct vcid. + */ + ma.ma_type = (strcmp(self->dv_cfdata->cf_driver->cd_name, + mtc_cd.cd_name) ? MSCPBUS_DISK : MSCPBUS_TAPE); + + ma.ma_mc = &uda_mscp_ctlr; + ma.ma_type |= MSCPBUS_UDA; + ma.ma_uda = &sc->sc_uda; + ma.ma_softc = &sc->sc_softc; + ma.ma_iot = sc->sc_iot; + ma.ma_iph = sc->sc_iph; + ma.ma_sah = sc->sc_sah; + ma.ma_swh = sc->sc_sah; + ma.ma_dmat = sc->sc_dmat; + ma.ma_dmam = sc->sc_cmap; + ma.ma_ivec = ivec_no; + ma.ma_ctlrnr = (ua->ua_iaddr == 0172150 ? 0 : 1); /* XXX */ + ma.ma_adapnr = uh->uh_nr; + config_found(&sc->sc_dev, &ma, udaprint); +} + +/* + * Start a transfer if there are free resources available, otherwise + * let it go in udaready, forget it for now. + * Called from mscp routines. + */ +void +udago(usc, mxi) + struct device *usc; + struct mscp_xi *mxi; +{ + struct uda_softc *sc = (void *)usc; + struct uba_unit *uu; + struct buf *bp = mxi->mxi_bp; + int err; + + /* + * If we already have transfers queued, don't try to load + * the map again. + */ + if (sc->sc_inq == 0) { + err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam, + bp->b_un.b_addr, + bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT); + if (err == 0) { + mscp_dgo(sc->sc_softc, mxi); + return; + } + } + uu = malloc(sizeof(struct uba_unit), M_DEVBUF, M_NOWAIT); + if (uu == 0) + panic("udago: no mem"); + uu->uu_ready = udaready; + uu->uu_softc = sc; + uu->uu_ref = mxi; + uba_enqueue(uu); + sc->sc_inq++; +} + +/* + * Called if we have been blocked for resources, and resources + * have been freed again. Return 1 if we could start all + * transfers again, 0 if we still are waiting. + * Called from uba resource free routines. + */ +int +udaready(uu) + struct uba_unit *uu; +{ + struct uda_softc *sc = uu->uu_softc; + struct mscp_xi *mxi = uu->uu_ref; + struct buf *bp = mxi->mxi_bp; + int err; + + err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam, bp->b_un.b_addr, + bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT); + if (err) + return 0; + mscp_dgo(sc->sc_softc, mxi); + sc->sc_inq--; + free(uu, M_DEVBUF); + return 1; +} + +static struct saerr { + int code; /* error code (including UDA_ERR) */ + char *desc; /* what it means: Efoo => foo error */ +} saerr[] = { + { 0100001, "Eunibus packet read" }, + { 0100002, "Eunibus packet write" }, + { 0100003, "EUDA ROM and RAM parity" }, + { 0100004, "EUDA RAM parity" }, + { 0100005, "EUDA ROM parity" }, + { 0100006, "Eunibus ring read" }, + { 0100007, "Eunibus ring write" }, + { 0100010, " unibus interrupt master failure" }, + { 0100011, "Ehost access timeout" }, + { 0100012, " host exceeded command limit" }, + { 0100013, " unibus bus master failure" }, + { 0100014, " DM XFC fatal error" }, + { 0100015, " hardware timeout of instruction loop" }, + { 0100016, " invalid virtual circuit id" }, + { 0100017, "Eunibus interrupt write" }, + { 0104000, "Efatal sequence" }, + { 0104040, " D proc ALU" }, + { 0104041, "ED proc control ROM parity" }, + { 0105102, "ED proc w/no BD#2 or RAM parity" }, + { 0105105, "ED proc RAM buffer" }, + { 0105152, "ED proc SDI" }, + { 0105153, "ED proc write mode wrap serdes" }, + { 0105154, "ED proc read mode serdes, RSGEN & ECC" }, + { 0106040, "EU proc ALU" }, + { 0106041, "EU proc control reg" }, + { 0106042, " U proc DFAIL/cntl ROM parity/BD #1 test CNT" }, + { 0106047, " U proc const PROM err w/D proc running SDI test" }, + { 0106055, " unexpected trap" }, + { 0106071, "EU proc const PROM" }, + { 0106072, "EU proc control ROM parity" }, + { 0106200, "Estep 1 data" }, + { 0107103, "EU proc RAM parity" }, + { 0107107, "EU proc RAM buffer" }, + { 0107115, " test count wrong (BD 12)" }, + { 0112300, "Estep 2" }, + { 0122240, "ENPR" }, + { 0122300, "Estep 3" }, + { 0142300, "Estep 4" }, + { 0, " unknown error code" } +}; + +/* + * If the error bit was set in the controller status register, gripe, + * then (optionally) reset the controller and requeue pending transfers. + */ +void +udasaerror(usc, doreset) + struct device *usc; + int doreset; +{ + struct uda_softc *sc = (void *)usc; + register int code = bus_space_read_2(sc->sc_iot, sc->sc_sah, 0); + register struct saerr *e; + + if ((code & MP_ERR) == 0) + return; + for (e = saerr; e->code; e++) + if (e->code == code) + break; + printf("%s: controller error, sa=0%o (%s%s)\n", + sc->sc_dev.dv_xname, code, e->desc + 1, + *e->desc == 'E' ? " error" : ""); +#if 0 /* XXX we just avoid panic when autoconfig non-existent KFQSA devices */ + if (doreset) { + mscp_requeue(sc->sc_softc); +/* (void) udainit(sc); XXX */ + } +#endif +} + +/* + * Interrupt routine. Depending on the state of the controller, + * continue initialisation, or acknowledge command and response + * interrupts, and process responses. + */ +static void +intr(arg) + void *arg; +{ + struct uda_softc *sc = arg; + struct uba_softc *uh; + struct mscp_pack *ud; + + sc->sc_wticks = 0; /* reset interrupt watchdog */ + + /* ctlr fatal error */ + if (bus_space_read_2(sc->sc_iot, sc->sc_sah, 0) & MP_ERR) { + udasaerror(&sc->sc_dev, 1); + return; + } + ud = &sc->sc_uda; + /* + * Handle buffer purge requests. + * XXX - should be done in bus_dma_sync(). + */ + uh = (void *)sc->sc_dev.dv_parent; + if (ud->mp_ca.ca_bdp) { + if (uh->uh_ubapurge) + (*uh->uh_ubapurge)(uh, ud->mp_ca.ca_bdp); + ud->mp_ca.ca_bdp = 0; + /* signal purge complete */ + bus_space_write_2(sc->sc_iot, sc->sc_sah, 0, 0); + } + + mscp_intr(sc->sc_softc); +} + +/* + * A Unibus reset has occurred on UBA uban. Reinitialise the controller(s) + * on that Unibus, and requeue outstanding I/O. + */ +void +udareset(ctlr) + int ctlr; +{ + reset(uda_cd.cd_devs[ctlr]); +} + +void +mtcreset(ctlr) + int ctlr; +{ + reset(mtc_cd.cd_devs[ctlr]); +} + +static void +reset(sc) + struct uda_softc *sc; +{ + printf(" %s", sc->sc_dev.dv_xname); + + /* + * Our BDP (if any) is gone; our command (if any) is + * flushed; the device is no longer mapped; and the + * UDA50 is not yet initialised. + */ + if (sc->sc_unit.uu_bdp) { + /* printf("<%d>", UBAI_BDP(sc->sc_unit.uu_bdp)); */ + sc->sc_unit.uu_bdp = 0; + } + + /* reset queues and requeue pending transfers */ + mscp_requeue(sc->sc_softc); + + /* + * If it fails to initialise we will notice later and + * try again (and again...). Do not call udastart() + * here; it will be done after the controller finishes + * initialisation. + */ +/* XXX if (udainit(sc)) */ + printf(" (hung)"); +} + +void +udactlrdone(usc) + struct device *usc; +{ + struct uda_softc *sc = (void *)usc; + + uba_done((struct uba_softc *)sc->sc_dev.dv_parent); +} diff --git a/sys/arch/vax/uba/uba.c b/sys/arch/vax/uba/uba.c index 98b8f4b5a1c..5d06ea578aa 100644 --- a/sys/arch/vax/uba/uba.c +++ b/sys/arch/vax/uba/uba.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uba.c,v 1.8 1997/05/29 00:05:09 niklas Exp $ */ -/* $NetBSD: uba.c,v 1.29 1996/10/13 03:35:24 christos Exp $ */ +/* $OpenBSD: uba.c,v 1.9 2000/04/27 03:14:51 bjc Exp $ */ +/* $NetBSD: uba.c,v 1.42 1999/02/02 18:37:20 ragge Exp $ */ /* * Copyright (c) 1996 Jonathan Stone. * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. @@ -67,33 +67,30 @@ #include <vax/uba/ubareg.h> #include <vax/uba/ubavar.h> -volatile int rbr, rcvec, svec; +volatile int /* rbr, rcvec,*/ svec; -static void ubascan __P((struct device *, void *)); +static int ubasearch __P((struct device *, struct cfdata *, void *)); static int ubaprint __P((void *, const char *)); +#if 0 static void ubastray __P((int)); +#endif static void ubainitmaps __P((struct uba_softc *)); -static void uba_attach __P((struct uba_softc *, unsigned long)); -static int ubasetup __P((struct uba_softc *, struct buf *, int)); - -struct cfdriver uba_cd = { - NULL, "uba", DV_DULL, 1 -}; +extern struct cfdriver uba_cd; #define spluba spl7 #if defined(DW780) || defined(DW750) -int dw_match __P((struct device *, void *, void *)); +int dw_match __P((struct device *, struct cfdata *, void *)); int -dw_match(parent, vcf, aux) +dw_match(parent, cf, aux) struct device *parent; - void *vcf, *aux; + struct cfdata *cf; + void *aux; { struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; - struct cfdata *cf = vcf; if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 )) return 0; @@ -136,6 +133,7 @@ dw780_attach(parent, self, aux) struct uba_softc *sc = (void *)self; struct sbi_attach_args *sa = aux; int ubaddr = sa->type & 3; + int i; printf(": DW780\n"); @@ -152,18 +150,15 @@ dw780_attach(parent, self, aux) sc->uh_ubainit = dw780_init; sc->uh_type = DW780; sc->uh_memsize = UBAPAGES; - sc->uh_iarea = (void *)scb + NBPG + ubaddr * NBPG; + sc->uh_ibase = VAX_NBPG + ubaddr * VAX_NBPG; sc->uh_mr = sc->uh_uba->uba_map; - bcopy(&idsptch, &sc->uh_dw780, sizeof(struct ivec_dsp)); - sc->uh_dw780.pushlarg = sc->uh_dev.dv_unit; - sc->uh_dw780.hoppaddr = uba_dw780int; - scb->scb_nexvec[0][sa->nexnum] = scb->scb_nexvec[1][sa->nexnum] - = scb->scb_nexvec[2][sa->nexnum] - = scb->scb_nexvec[3][sa->nexnum] = &sc->uh_dw780; + for (i = 0; i < 4; i++) + scb_vecalloc(256 + i * 64 + sa->nexnum * 4, uba_dw780int, + sc->uh_dev.dv_unit, SCB_ISTACK); uba_attach(sc, (parent->dv_unit ? UMEMB8600(ubaddr) : - UMEMA8600(ubaddr)) + (UBAPAGES * NBPG)); + UMEMA8600(ubaddr)) + (UBAPAGES * VAX_NBPG)); } void @@ -172,20 +167,17 @@ dw780_beforescan(sc) { volatile int *hej = &sc->uh_uba->uba_sr; - if (sc->uh_type == DW780) { - *hej = *hej; - sc->uh_uba->uba_cr = UBACR_IFS|UBACR_BRIE; - } + *hej = *hej; + sc->uh_uba->uba_cr = UBACR_IFS|UBACR_BRIE; } void dw780_afterscan(sc) struct uba_softc *sc; { - if (sc->uh_type == DW780) - sc->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | - UBACR_USEFIE | UBACR_SUEFIE | - (sc->uh_uba->uba_cr & 0x7c000000); + sc->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | + UBACR_USEFIE | UBACR_SUEFIE | + (sc->uh_uba->uba_cr & 0x7c000000); } /* @@ -198,7 +190,7 @@ dw780_errchk(sc) { volatile int *hej = &sc->uh_uba->uba_sr; - if (sc->uh_type == DW780 && *hej) { + if (*hej) { *hej = *hej; return 1; } @@ -215,18 +207,20 @@ uba_dw780int(uba) void (*func) __P((int)); br = mfpr(PR_IPL); - svec = ur->uba_brrvr[br - 0x14]; - if (svec <= 0) { - ubaerror(sc, &br, (int *)&svec); + vec = ur->uba_brrvr[br - 0x14]; + if (vec <= 0) { + ubaerror(sc, &br, (int *)&vec); if (svec == 0) return; } - vec = svec >> 2; if (cold) - rcvec = vec; - func = sc->uh_idsp[vec].hoppaddr; - arg = sc->uh_idsp[vec].pushlarg; - (*func)(arg); + scb_fake(vec + sc->uh_ibase, br); + else { + struct ivec_dsp *scb_vec = (struct ivec_dsp *)((int)scb + 512); + func = scb_vec[vec/4].hoppaddr; + arg = scb_vec[vec/4].pushlarg; + (*func)(arg); + } } void @@ -266,7 +260,7 @@ ubaerror(uh, ipl, uvec) int *ipl, *uvec; { struct uba_regs *uba = uh->uh_uba; - register sr, s; + register int sr, s; if (*uvec == 0) { /* @@ -356,10 +350,9 @@ dw750_attach(parent, self, aux) sc->uh_ubainit = dw750_init; sc->uh_type = DW750; sc->uh_memsize = UBAPAGES; - sc->uh_iarea = (void *)scb + NBPG + ubaddr * NBPG; sc->uh_mr = sc->uh_uba->uba_map; - uba_attach(sc, UMEM750(ubaddr) + (UBAPAGES * NBPG)); + uba_attach(sc, UMEM750(ubaddr) + (UBAPAGES * VAX_NBPG)); } void @@ -387,19 +380,20 @@ dw750_purge(sc, bdp) * This driver can only handle map registers up to 1MB due to map info * storage, but that should be enough for normal purposes. */ -int qba_match __P((struct device *, void *, void *)); +int qba_match __P((struct device *, struct cfdata *, void *)); void qba_attach __P((struct device *, struct device *, void *)); void qba_beforescan __P((struct uba_softc*)); void qba_init __P((struct uba_softc*)); -struct cfattach uba_backplane_ca = { +struct cfattach uba_mainbus_ca = { sizeof(struct uba_softc), qba_match, qba_attach }; int qba_match(parent, vcf, aux) struct device *parent; - void *vcf, *aux; + struct cfdata *vcf; + void *aux; { struct bp_conf *bp = aux; @@ -415,11 +409,8 @@ qba_attach(parent, self, aux) void *aux; { struct uba_softc *sc = (void *)self; - vm_offset_t mini, maxi; printf(": Q22\n"); - - /* * Fill in bus specific data. */ @@ -432,16 +423,12 @@ qba_attach(parent, self, aux) sc->uh_ubainit = qba_init; sc->uh_type = QBA; sc->uh_memsize = QBAPAGES; - sc->uh_iarea = (void *)scb + NBPG; /* * Map in the UBA page map into kernel space. On other UBAs, * the map registers are in the bus IO space. */ - (void)kmem_suballoc(kernel_map, &mini, &maxi, - QBAPAGES * sizeof(struct pte), FALSE); - pmap_map(mini, QBAMAP, QBAMAP + QBAPAGES * sizeof(struct pte), - VM_PROT_READ | VM_PROT_WRITE); - sc->uh_mr = (void *)mini; + sc->uh_mr = (void *)vax_map_physmem(QBAMAP, + (QBAPAGES * sizeof(struct pte)) / VAX_NBPG); uba_attach(sc, QIOPAGE); } @@ -466,36 +453,12 @@ qba_init(sc) qba_beforescan(sc); } #endif -#ifdef DWBUA -int bua_match __P((struct device *, void *, void *)); -void bua_attach __P((struct device *, struct device *, void *)); - -struct cfattach uba_bi_ca = { - sizeof(struct uba_softc), bua_match, bua_attach -}; - -bua_beforescan(sc) - struct uba_softc *sc; -{ - if (sc->uh_type == DWBUA) - BUA(ubar)->bua_offset = (int)sc->uh_vec - (int)&scb[0]; -} - -void -bua_init(sc) - struct uba_softc *sc; -{ - BUA(uba)->bua_csr |= BUACSR_UPI; - /* give devices time to recover from power fail */ - DELAY(500000); - break; -} -#endif #ifdef DW730 struct cfattach uba_dw730_ca = { sizeof(struct uba_softc), dw730_match, dw730_attach }; #endif +#if 0 /* * Stray interrupt vector handler, used when nowhere else to go to. */ @@ -524,7 +487,7 @@ ubastray(arg) printf("uba%d: unexpected interrupt, vector 0x%x, br 0x%x\n", arg, svec, rbr); } - +#endif /* * Do transfer on device argument. The controller * and uba involved are implied by the device. @@ -623,8 +586,8 @@ ubasetup(uh, bp, flags) if (uh->uh_nbdp == 0) flags &= ~UBA_NEEDBDP; - o = (int)bp->b_un.b_addr & PGOFSET; - npf = btoc(bp->b_bcount + o) + 1; + o = (int)bp->b_un.b_addr & VAX_PGOFSET; + npf = vax_btoc(bp->b_bcount + o) + 1; if (npf > UBA_MAXNMR) panic("uba xfer too big"); a = spluba(); @@ -831,10 +794,8 @@ qbgetpri() void uba_attach(sc, iopagephys) struct uba_softc *sc; - unsigned long iopagephys; + paddr_t iopagephys; { - vm_offset_t mini, maxi; - extern struct ivec_dsp idsptch; /* * Set last free interrupt vector for devices with @@ -845,34 +806,11 @@ uba_attach(sc, iopagephys) SIMPLEQ_INIT(&sc->uh_resq); /* - * Create interrupt dispatchers for this uba. - */ -#define NO_IVEC 128 - { - vm_offset_t iarea; - int i; - - iarea = kmem_alloc(kernel_map, - NO_IVEC * sizeof(struct ivec_dsp)); - sc->uh_idsp = (struct ivec_dsp *)iarea; - - for (i = 0; i < NO_IVEC; i++) { - bcopy(&idsptch, &sc->uh_idsp[i], - sizeof(struct ivec_dsp)); - sc->uh_idsp[i].pushlarg = sc->uh_dev.dv_unit; - sc->uh_idsp[i].hoppaddr = ubastray; - sc->uh_iarea[i] = (unsigned int)&sc->uh_idsp[i]; - } - } - /* * Allocate place for unibus memory in virtual space. - * This is done with kmem_suballoc() but after that - * never used in the vm system. Is it OK to do so? */ - (void)kmem_suballoc(kernel_map, &mini, &maxi, UBAIOPAGES * NBPG, FALSE); - pmap_map(mini, iopagephys, iopagephys + UBAIOPAGES * NBPG, - VM_PROT_READ|VM_PROT_WRITE); - sc->uh_iopage = (void *)mini; + sc->uh_iopage = (caddr_t)vax_map_physmem(iopagephys, UBAIOPAGES); + if (sc->uh_iopage == 0) + return; /* vax_map_physmem() will complain for us */ /* * Initialize the UNIBUS, by freeing the map * registers and the buffered data path registers @@ -893,22 +831,21 @@ uba_attach(sc, iopagephys) /* * Now start searching for devices. */ - config_scan(ubascan,(struct device *)sc); + config_search(ubasearch,(struct device *)sc, NULL); if (sc->uh_afterscan) (*sc->uh_afterscan)(sc); } -void -ubascan(parent, match) +int +ubasearch(parent, cf, aux) struct device *parent; - void *match; + struct cfdata *cf; + void *aux; { - struct device *dev = match; - struct cfdata *cf = dev->dv_cfdata; struct uba_softc *sc = (struct uba_softc *)parent; struct uba_attach_args ua; - int i; + int i, vec, br; ua.ua_addr = (caddr_t)((int)sc->uh_iopage + ubdevreg(cf->cf_loc[0])); ua.ua_reset = NULL; @@ -916,8 +853,8 @@ ubascan(parent, match) if (badaddr(ua.ua_addr, 2) || (sc->uh_errchk ? (*sc->uh_errchk)(sc):0)) goto forgetit; - rcvec = 0x200; - i = (*cf->cf_attach->ca_match) (parent, dev, &ua); + scb_vecref(0, 0); /* Clear vector ref */ + i = (*cf->cf_attach->ca_match) (parent, cf, &ua); if (sc->uh_errchk) if ((*sc->uh_errchk)(sc)) @@ -925,58 +862,44 @@ ubascan(parent, match) if (i == 0) goto forgetit; - if (rcvec == 0 || rcvec == 0x200) + i = scb_vecref(&vec, &br); + if (i == 0) + goto fail; + if (vec == 0) goto fail; - sc->uh_idsp[rcvec].hoppaddr = ua.ua_ivec; - sc->uh_idsp[rcvec].pushlarg = dev->dv_unit; - if (ua.ua_reset) { /* device wants ubraeset */ + scb_vecalloc(vec, ua.ua_ivec, cf->cf_unit, SCB_ISTACK); + if (ua.ua_reset) { /* device wants ubareset */ if (sc->uh_resno == 0) { sc->uh_reset = malloc(1024, M_DEVBUF, M_NOWAIT); sc->uh_resarg = (int *)sc->uh_reset + 128; } #ifdef DIAGNOSTIC if (sc->uh_resno > 127) { - printf("%s: Expand reset table, skipping reset %s\n", - sc->uh_dev.dv_xname, dev->dv_xname); + printf("%s: Expand reset table, skipping reset %s%d\n", + sc->uh_dev.dv_xname, cf->cf_driver->cd_name, + cf->cf_unit); } else #endif { - sc->uh_resarg[sc->uh_resno] = dev->dv_unit; + sc->uh_resarg[sc->uh_resno] = cf->cf_unit; sc->uh_reset[sc->uh_resno++] = ua.ua_reset; } } - ua.ua_br = rbr; - ua.ua_cvec = rcvec; - ua.ua_iaddr = dev->dv_cfdata->cf_loc[0]; + ua.ua_br = br; + ua.ua_cvec = vec; + ua.ua_iaddr = cf->cf_loc[0]; - config_attach(parent, dev, &ua, ubaprint); - return; + config_attach(parent, cf, &ua, ubaprint); + return 0; fail: - printf("%s at %s csr %o %s\n", dev->dv_cfdata->cf_driver->cd_name, - parent->dv_xname, dev->dv_cfdata->cf_loc[0], - rcvec ? "didn't interrupt\n" : "zero vector\n"); + printf("%s%d at %s csr %o %s\n", + cf->cf_driver->cd_name, cf->cf_unit, parent->dv_xname, + cf->cf_loc[0], (i ? "zero vector" : "didn't interrupt")); forgetit: - free(dev, M_DEVBUF); -} - -/* - * Called when a device needs more than one interrupt vector. - * (Like DHU11, DMF32). Argument is the device's softc, vector - * number and a function pointer to the interrupt catcher. - */ -void -ubasetvec(dev, vec, func) - struct device *dev; - int vec; - void (*func) __P((int)); -{ - struct uba_softc *sc = (void *)dev->dv_parent; - - sc->uh_idsp[vec].hoppaddr = func; - sc->uh_idsp[vec].pushlarg = dev->dv_unit; + return 0; } /* @@ -990,6 +913,6 @@ ubaprint(aux, uba) struct uba_attach_args *ua = aux; printf(" csr %o vec %o ipl %x", ua->ua_iaddr, - ua->ua_cvec << 2, ua->ua_br); + ua->ua_cvec & 511, ua->ua_br); return UNCONF; } diff --git a/sys/arch/vax/uba/uba_cmi.c b/sys/arch/vax/uba/uba_cmi.c new file mode 100644 index 00000000000..22ce4ee8897 --- /dev/null +++ b/sys/arch/vax/uba/uba_cmi.c @@ -0,0 +1,147 @@ +/* $OpenBSD: uba_cmi.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */ +/* $NetBSD: uba_cmi.c,v 1.2 1999/08/14 11:31:48 ragge Exp $ */ +/* + * Copyright (c) 1996 Jonathan Stone. + * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uba.c 7.10 (Berkeley) 12/16/90 + * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/systm.h> + +#define _VAX_BUS_DMA_PRIVATE +#include <machine/bus.h> +#include <machine/mtpr.h> +#include <machine/nexus.h> +#include <machine/cpu.h> +#include <machine/sgmap.h> + +#include <arch/vax/qbus/ubavar.h> + +#include <arch/vax/uba/uba_common.h> + +/* Some CMI-specific defines */ +#define UBASIZE ((UBAPAGES + UBAIOPAGES) * VAX_NBPG) +#define UMEM750(i) (0xfc0000 - (i) * UBASIZE) +#define UIOPAGE(x) (UMEM750(x) + (UBAPAGES * VAX_NBPG)) + +/* + * The DW780 and DW750 are quite similar to their function from + * a programmers point of view. Differencies are number of BDP's + * and bus status/command registers, the latter are (partly) IPR's + * on 750. + */ +static int dw750_match __P((struct device *, struct cfdata *, void *)); +static void dw750_attach __P((struct device *, struct device *, void *)); +static void dw750_init __P((struct uba_softc*)); +#ifdef notyet +static void dw750_purge __P((struct uba_softc *, int)); +#endif + +struct cfattach uba_cmi_ca = { + sizeof(struct uba_vsoftc), dw750_match, dw750_attach +}; + +extern struct vax_bus_space vax_mem_bus_space; + +int +dw750_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; + + if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 )) + return 0; + /* + * The uba type is actually only telling where the uba + * space is in nexus space. + */ + if ((sa->type & ~3) != NEX_UBA0) + return 0; + + return 1; +} + +void +dw750_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct uba_vsoftc *sc = (void *)self; + struct sbi_attach_args *sa = aux; + struct uba_regs *uh_uba = (void *)sa->nexaddr; + int ubaddr = sa->nexinfo & 1; + + printf(": DW750\n"); + /* + * Fill in bus specific data. + */ + sc->uv_sc.uh_ubainit = dw750_init; +#ifdef notyet + sc->uv_sc.uh_ubapurge = dw750_purge; +#endif + sc->uv_sc.uh_iot = &vax_mem_bus_space; + sc->uv_sc.uh_dmat = &sc->uv_dmat; + + /* + * Fill in variables used by the sgmap system. + */ + sc->uv_size = UBASIZE; /* Size in bytes of Qbus space */ + sc->uv_addr = (paddr_t)uh_uba->uba_map; /* Map regs physical address */ + + uba_dma_init(sc); + uba_attach(&sc->uv_sc, UIOPAGE(ubaddr)); +} + +void +dw750_init(sc) + struct uba_softc *sc; +{ + mtpr(0, PR_IUR); + DELAY(500000); +} + +#ifdef notyet +void +dw750_purge(sc, bdp) + struct uba_softc *sc; + int bdp; +{ + sc->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE | UBADPR_NXM | UBADPR_UCE; +} +#endif diff --git a/sys/arch/vax/uba/uba_common.h b/sys/arch/vax/uba/uba_common.h new file mode 100644 index 00000000000..deafdd2cf20 --- /dev/null +++ b/sys/arch/vax/uba/uba_common.h @@ -0,0 +1,88 @@ +/* $OpenBSD: uba_common.h,v 1.1 2000/04/27 03:14:51 bjc Exp $ */ +/* $NetBSD: uba_common.h,v 1.2 1999/06/21 16:23:01 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ubareg.h 7.8 (Berkeley) 5/9/91 + */ + +/* + * VAX-specific parts of the Unibus softc. + */ +struct uba_regs; + +struct uba_vsoftc { + struct uba_softc uv_sc;/* Common vars from arch/vax/qbus/ubavar.h */ + struct vax_bus_dma_tag uv_dmat; + struct vax_sgmap uv_sgmap; + int uv_size; /* Size of UBA addressable memory */ + paddr_t uv_addr; /* Physical address of map registers */ + struct uba_regs *uv_uba;/* Where applicable */ + int uh_ibase; + int uh_zvtime; + int uh_zvtotal; + int uh_zvcnt; +}; + +/* + * Size of unibus memory address space in pages + * (also number of map registers). + */ +#define UBAPAGES 496 +#define UBAIOADDR 0760000 /* start of I/O page */ +#define UBAIOPAGES 16 + +/* + * DW780/DW750 hardware registers + */ +struct uba_regs { + int uba_cnfgr; /* configuration register */ + int uba_cr; /* control register */ + int uba_sr; /* status register */ + int uba_dcr; /* diagnostic control register */ + int uba_fmer; /* failed map entry register */ + int uba_fubar; /* failed UNIBUS address register */ + int pad1[2]; + int uba_brsvr[4]; + int uba_brrvr[4]; /* receive vector registers */ + int uba_dpr[16]; /* buffered data path register */ + int pad2[480]; + struct pte uba_map[UBAPAGES]; /* unibus map register */ + int pad3[UBAIOPAGES]; /* no maps for device address space */ +}; + +void uba_dma_init __P((struct uba_vsoftc *)); diff --git a/sys/arch/vax/uba/uba_dma.c b/sys/arch/vax/uba/uba_dma.c new file mode 100644 index 00000000000..f0344dfff96 --- /dev/null +++ b/sys/arch/vax/uba/uba_dma.c @@ -0,0 +1,282 @@ +/* $OpenBSD: uba_dma.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */ +/* $NetBSD: uba_dma.c,v 1.2 1999/06/20 00:59:55 ragge Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPEUBAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <vm/vm.h> + +#define _VAX_BUS_DMA_PRIVATE +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/sgmap.h> + +#include <arch/vax/qbus/ubavar.h> + +#include <arch/vax/uba/uba_common.h> + +int uba_bus_dmamap_create_sgmap __P((bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *)); + +void uba_bus_dmamap_destroy_sgmap __P((bus_dma_tag_t, bus_dmamap_t)); + +int uba_bus_dmamap_load_sgmap __P((bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int)); + +int uba_bus_dmamap_load_mbuf_sgmap __P((bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int)); + +int uba_bus_dmamap_load_uio_sgmap __P((bus_dma_tag_t, bus_dmamap_t, + struct uio *, int)); + +int uba_bus_dmamap_load_raw_sgmap __P((bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int)); + +void uba_bus_dmamap_unload_sgmap __P((bus_dma_tag_t, bus_dmamap_t)); + +void uba_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int)); + +void +uba_dma_init(sc) + struct uba_vsoftc *sc; +{ + bus_dma_tag_t t; + struct pte *pte; + + /* + * Initialize the DMA tag used for sgmap-mapped DMA. + */ + t = &sc->uv_dmat; + t->_cookie = sc; + t->_wbase = 0; + t->_wsize = sc->uv_size; + t->_boundary = 0; + t->_sgmap = &sc->uv_sgmap; + t->_dmamap_create = uba_bus_dmamap_create_sgmap; + t->_dmamap_destroy = uba_bus_dmamap_destroy_sgmap; + t->_dmamap_load = uba_bus_dmamap_load_sgmap; + t->_dmamap_load_mbuf = uba_bus_dmamap_load_mbuf_sgmap; + t->_dmamap_load_uio = uba_bus_dmamap_load_uio_sgmap; + t->_dmamap_load_raw = uba_bus_dmamap_load_raw_sgmap; + t->_dmamap_unload = uba_bus_dmamap_unload_sgmap; + t->_dmamap_sync = uba_bus_dmamap_sync; + + t->_dmamem_alloc = _bus_dmamem_alloc; + t->_dmamem_free = _bus_dmamem_free; + t->_dmamem_map = _bus_dmamem_map; + t->_dmamem_unmap = _bus_dmamem_unmap; + t->_dmamem_mmap = _bus_dmamem_mmap; + + /* + * Map in Unibus map registers. + */ + pte = (struct pte *)vax_map_physmem(sc->uv_addr, sc->uv_size/VAX_NBPG); + if (pte == 0) + panic("uba_dma_init"); + /* + * Initialize the SGMAP. + */ + vax_sgmap_init(t, &sc->uv_sgmap, "uba_sgmap", 0, sc->uv_size, pte, 0); + +} + +/* + * Create a UBA SGMAP-mapped DMA map. + */ +int +uba_bus_dmamap_create_sgmap(t, size, nsegments, maxsegsz, boundary, + flags, dmamp) + bus_dma_tag_t t; + bus_size_t size; + int nsegments; + bus_size_t maxsegsz; + bus_size_t boundary; + int flags; + bus_dmamap_t *dmamp; +{ + bus_dmamap_t map; + int error; + + error = _bus_dmamap_create(t, size, nsegments, maxsegsz, + boundary, flags, dmamp); + if (error) + return (error); + + map = *dmamp; + + if (flags & BUS_DMA_ALLOCNOW) { + error = vax_sgmap_alloc(map, vax_round_page(size), + t->_sgmap, flags); + if (error) + uba_bus_dmamap_destroy_sgmap(t, map); + } + + return (error); +} + +/* + * Destroy a UBA SGMAP-mapped DMA map. + */ +void +uba_bus_dmamap_destroy_sgmap(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + if (map->_dm_flags & DMAMAP_HAS_SGMAP) + vax_sgmap_free(map, t->_sgmap); + + _bus_dmamap_destroy(t, map); +} + +/* + * Load a UBA SGMAP-mapped DMA map with a linear buffer. + */ +int +uba_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + void *buf; + bus_size_t buflen; + struct proc *p; + int flags; +{ + int error; + + error = vax_sgmap_load(t, map, buf, buflen, p, flags, t->_sgmap); + /* + * XXX - Set up BDPs. + */ + + return (error); +} + +/* + * Load a UBA SGMAP-mapped DMA map with an mbuf chain. + */ +int +uba_bus_dmamap_load_mbuf_sgmap(t, map, m, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct mbuf *m; + int flags; +{ + int error; + + error = vax_sgmap_load_mbuf(t, map, m, flags, t->_sgmap); + + return (error); +} + +/* + * Load a UBA SGMAP-mapped DMA map with a uio. + */ +int +uba_bus_dmamap_load_uio_sgmap(t, map, uio, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct uio *uio; + int flags; +{ + int error; + + error = vax_sgmap_load_uio(t, map, uio, flags, t->_sgmap); + + return (error); +} + +/* + * Load a UBA SGMAP-mapped DMA map with raw memory. + */ +int +uba_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + bus_dma_segment_t *segs; + int nsegs; + bus_size_t size; + int flags; +{ + int error; + + error = vax_sgmap_load_raw(t, map, segs, nsegs, size, flags, + t->_sgmap); + + return (error); +} + +/* + * Unload a UBA DMA map. + */ +void +uba_bus_dmamap_unload_sgmap(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + /* + * Invalidate any SGMAP page table entries used by this + * mapping. + */ + vax_sgmap_unload(t, map, t->_sgmap); + + /* + * Do the generic bits of the unload. + */ + _bus_dmamap_unload(t, map); +} + +/* + * Sync the bus map. This is only needed if BDP's are used. + */ +void +uba_bus_dmamap_sync(tag, dmam, offset, len, ops) + bus_dma_tag_t tag; + bus_dmamap_t dmam; + bus_addr_t offset; + bus_size_t len; + int ops; +{ + /* Only BDP handling, but not yet. */ +} diff --git a/sys/arch/vax/uba/uba_ibus.c b/sys/arch/vax/uba/uba_ibus.c new file mode 100644 index 00000000000..3b118e1caa1 --- /dev/null +++ b/sys/arch/vax/uba/uba_ibus.c @@ -0,0 +1,137 @@ +/* $OpenBSD: uba_ibus.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */ +/* $NetBSD: uba_ibus.c,v 1.1 1999/08/07 10:36:47 ragge Exp $ */ +/* + * Copyright (c) 1996 Jonathan Stone. + * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uba.c 7.10 (Berkeley) 12/16/90 + * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/systm.h> + +#define _VAX_BUS_DMA_PRIVATE +#include <machine/bus.h> +#include <machine/mtpr.h> +#include <machine/nexus.h> +#include <machine/cpu.h> +#include <machine/sgmap.h> + +#include <arch/vax/qbus/ubavar.h> + +#include <arch/vax/uba/uba_common.h> + +/* Some Qbus-specific defines */ +#define QBASIZE (8192 * VAX_NBPG) +#define QBAMAP 0x20088000 +#define QIOPAGE 0x20000000 + +/* + * The Q22 bus is the main IO bus on MicroVAX II/MicroVAX III systems. + * It has an address space of 4MB (22 address bits), therefore the name, + * and is hardware compatible with all 16 and 18 bits Q-bus devices. + */ +static int qba_match __P((struct device *, struct cfdata *, void *)); +static void qba_attach __P((struct device *, struct device *, void *)); +static void qba_beforescan __P((struct uba_softc*)); +static void qba_init __P((struct uba_softc*)); + +struct cfattach uba_ibus_ca = { + sizeof(struct uba_vsoftc), (cfmatch_t)qba_match, qba_attach +}; + +extern struct vax_bus_space vax_mem_bus_space; + +int +qba_match(parent, vcf, aux) + struct device *parent; + struct cfdata *vcf; + void *aux; +{ + struct bp_conf *bp = aux; + + if (strcmp(bp->type, "uba")) + return 0; + + return 1; +} + +void +qba_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct uba_vsoftc *sc = (void *)self; + + printf(": Q22\n"); + /* + * Fill in bus specific data. + */ + sc->uv_sc.uh_beforescan = qba_beforescan; + sc->uv_sc.uh_ubainit = qba_init; + sc->uv_sc.uh_iot = &vax_mem_bus_space; + sc->uv_sc.uh_dmat = &sc->uv_dmat; + + /* + * Fill in variables used by the sgmap system. + */ + sc->uv_size = QBASIZE; /* Size in bytes of Qbus space */ + sc->uv_addr = QBAMAP; /* Physical address of map registers */ + + uba_dma_init(sc); + uba_attach(&sc->uv_sc, QIOPAGE); +} + +/* + * Called when the QBA is set up; to enable DMA access from + * QBA devices to main memory. + */ +void +qba_beforescan(sc) + struct uba_softc *sc; +{ +#define QIPCR 0x1f40 +#define Q_LMEAE 0x20 + bus_space_write_2(sc->uh_tag, sc->uh_ioh, QIPCR, Q_LMEAE); +} + +void +qba_init(sc) + struct uba_softc *sc; +{ + mtpr(0, PR_IUR); + DELAY(500000); + qba_beforescan(sc); +} diff --git a/sys/arch/vax/uba/uba_mainbus.c b/sys/arch/vax/uba/uba_mainbus.c new file mode 100644 index 00000000000..c5f6daa57bd --- /dev/null +++ b/sys/arch/vax/uba/uba_mainbus.c @@ -0,0 +1,137 @@ +/* $OpenBSD: uba_mainbus.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */ +/* $NetBSD: uba_mainbus.c,v 1.2 1999/06/06 19:00:53 ragge Exp $ */ +/* + * Copyright (c) 1996 Jonathan Stone. + * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uba.c 7.10 (Berkeley) 12/16/90 + * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/systm.h> + +#define _VAX_BUS_DMA_PRIVATE +#include <machine/bus.h> +#include <machine/mtpr.h> +#include <machine/nexus.h> +#include <machine/cpu.h> +#include <machine/sgmap.h> + +#include <arch/vax/qbus/ubavar.h> + +#include <arch/vax/uba/uba_common.h> + +/* Some Qbus-specific defines */ +#define QBASIZE (8192 * VAX_NBPG) +#define QBAMAP 0x20088000 +#define QIOPAGE 0x20000000 + +/* + * The Q22 bus is the main IO bus on MicroVAX II/MicroVAX III systems. + * It has an address space of 4MB (22 address bits), therefore the name, + * and is hardware compatible with all 16 and 18 bits Q-bus devices. + */ +static int qba_match __P((struct device *, struct cfdata *, void *)); +static void qba_attach __P((struct device *, struct device *, void *)); +static void qba_beforescan __P((struct uba_softc*)); +static void qba_init __P((struct uba_softc*)); + +struct cfattach uba_mainbus_ca = { + sizeof(struct uba_vsoftc), qba_match, qba_attach +}; + +extern struct vax_bus_space vax_mem_bus_space; + +int +qba_match(parent, vcf, aux) + struct device *parent; + struct cfdata *vcf; + void *aux; +{ + struct bp_conf *bp = aux; + + if (strcmp(bp->type, "uba")) + return 0; + + return 1; +} + +void +qba_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct uba_vsoftc *sc = (void *)self; + + printf(": Q22\n"); + /* + * Fill in bus specific data. + */ + sc->uv_sc.uh_beforescan = qba_beforescan; + sc->uv_sc.uh_ubainit = qba_init; + sc->uv_sc.uh_iot = &vax_mem_bus_space; + sc->uv_sc.uh_dmat = &sc->uv_dmat; + + /* + * Fill in variables used by the sgmap system. + */ + sc->uv_size = QBASIZE; /* Size in bytes of Qbus space */ + sc->uv_addr = QBAMAP; /* Physical address of map registers */ + + uba_dma_init(sc); + uba_attach(&sc->uv_sc, QIOPAGE); +} + +/* + * Called when the QBA is set up; to enable DMA access from + * QBA devices to main memory. + */ +void +qba_beforescan(sc) + struct uba_softc *sc; +{ +#define QIPCR 0x1f40 +#define Q_LMEAE 0x20 + bus_space_write_2(sc->uh_tag, sc->uh_ioh, QIPCR, Q_LMEAE); +} + +void +qba_init(sc) + struct uba_softc *sc; +{ + mtpr(0, PR_IUR); + DELAY(500000); + qba_beforescan(sc); +} diff --git a/sys/arch/vax/uba/uba_sbi.c b/sys/arch/vax/uba/uba_sbi.c new file mode 100644 index 00000000000..6941e261e52 --- /dev/null +++ b/sys/arch/vax/uba/uba_sbi.c @@ -0,0 +1,327 @@ +/* $OpenBSD: uba_sbi.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */ +/* $NetBSD: uba_sbi.c,v 1.1 1999/06/21 16:23:01 ragge Exp $ */ +/* + * Copyright (c) 1996 Jonathan Stone. + * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uba.c 7.10 (Berkeley) 12/16/90 + * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <sys/kernel.h> + +#define _VAX_BUS_DMA_PRIVATE +#include <machine/bus.h> +#include <machine/mtpr.h> +#include <machine/nexus.h> +#include <machine/cpu.h> +#include <machine/sgmap.h> +#include <machine/scb.h> + +#include <arch/vax/qbus/ubavar.h> + +#include <arch/vax/uba/uba_common.h> + +/* Some SBI-specific defines */ +#define UBASIZE (UBAPAGES * VAX_NBPG) +#define UMEMA8600(i) (0x20100000+(i)*0x40000) +#define UMEMB8600(i) (0x22100000+(i)*0x40000) + +/* + * Some status registers. + */ +#define UBACNFGR_UBIC 0x00010000 /* unibus init complete */ +#define UBACNFGR_BITS \ +"\40\40PARFLT\37WSQFLT\36URDFLT\35ISQFLT\34MXTFLT\33XMTFLT\30ADPDN\27ADPUP\23UBINIT\22UBPDN\21UBIC" + +#define UBACR_IFS 0x00000040 /* interrupt field switch */ +#define UBACR_BRIE 0x00000020 /* BR interrupt enable */ +#define UBACR_USEFIE 0x00000010 /* UNIBUS to SBI error field IE */ +#define UBACR_SUEFIE 0x00000008 /* SBI to UNIBUS error field IE */ +#define UBACR_ADINIT 0x00000001 /* adapter init */ + +#define UBADPR_BNE 0x80000000 /* buffer not empty - purge */ + +#define UBABRRVR_DIV 0x0000ffff /* device interrupt vector field */ + +#define UBASR_BITS \ +"\20\13RDTO\12RDS\11CRD\10CXTER\7CXTMO\6DPPE\5IVMR\4MRPF\3LEB\2UBSTO\1UBSSYNTO" + +char ubasr_bits[] = UBASR_BITS; + +/* + * The DW780 are directly connected to the SBI on 11/780 and 8600. + */ +static int dw780_match __P((struct device *, struct cfdata *, void *)); +static void dw780_attach __P((struct device *, struct device *, void *)); +static void dw780_init __P((struct uba_softc*)); +static void dw780_beforescan __P((struct uba_softc *)); +static void dw780_afterscan __P((struct uba_softc *)); +static int dw780_errchk __P((struct uba_softc *)); +static void uba_dw780int __P((int)); +static void ubaerror __P((struct uba_softc *, int *, int *)); +#ifdef notyet +static void dw780_purge __P((struct uba_softc *, int)); +#endif + +struct cfattach uba_sbi_ca = { + sizeof(struct uba_vsoftc), dw780_match, dw780_attach +}; + +extern struct vax_bus_space vax_mem_bus_space; + +volatile int svec; + +int +dw780_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; + + if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 )) + return 0; + /* + * The uba type is actually only telling where the uba + * space is in nexus space. + */ + if ((sa->type & ~3) != NEX_UBA0) + return 0; + + return 1; +} + +void +dw780_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct uba_vsoftc *sc = (void *)self; + struct sbi_attach_args *sa = aux; + int ubaddr = sa->type & 3; + int i; + + printf(": DW780\n"); + /* + * Fill in bus specific data. + */ + sc->uv_sc.uh_ubainit = dw780_init; +#ifdef notyet + sc->uv_sc.uh_ubapurge = dw780_purge; +#endif + sc->uv_sc.uh_beforescan = dw780_beforescan; + sc->uv_sc.uh_afterscan = dw780_afterscan; + sc->uv_sc.uh_errchk = dw780_errchk; + sc->uv_sc.uh_iot = &vax_mem_bus_space; + sc->uv_sc.uh_dmat = &sc->uv_dmat; + sc->uv_uba = (void *)sa->nexaddr; + sc->uh_ibase = VAX_NBPG + ubaddr * VAX_NBPG; + + /* + * Set up dispatch vectors for DW780. + */ + for (i = 0; i < 4; i++) + scb_vecalloc(256 + i * 64 + sa->nexnum * 4, uba_dw780int, + sc->uv_sc.uh_dev.dv_unit, SCB_ISTACK); + /* + * Fill in variables used by the sgmap system. + */ + sc->uv_size = UBASIZE; /* Size in bytes of Qbus space */ + sc->uv_addr = (paddr_t)sc->uv_uba->uba_map; + + uba_dma_init(sc); + uba_attach(&sc->uv_sc, (parent->dv_unit ? UMEMB8600(ubaddr) : + UMEMA8600(ubaddr)) + (UBAPAGES * VAX_NBPG)); +} + +void +dw780_beforescan(sc) + struct uba_softc *sc; +{ + struct uba_vsoftc *vc = (void *)sc; + volatile int *hej = &vc->uv_uba->uba_sr; + + *hej = *hej; + vc->uv_uba->uba_cr = UBACR_IFS|UBACR_BRIE; +} + +void +dw780_afterscan(sc) + struct uba_softc *sc; +{ + struct uba_vsoftc *vc = (void *)sc; + + vc->uv_uba->uba_cr = UBACR_IFS | UBACR_BRIE | + UBACR_USEFIE | UBACR_SUEFIE | + (vc->uv_uba->uba_cr & 0x7c000000); +} + + +int +dw780_errchk(sc) + struct uba_softc *sc; +{ + struct uba_vsoftc *vc = (void *)sc; + volatile int *hej = &vc->uv_uba->uba_sr; + + if (*hej) { + *hej = *hej; + return 1; + } + return 0; +} + +void +uba_dw780int(uba) + int uba; +{ + int br, vec, arg; + struct uba_vsoftc *vc = uba_cd.cd_devs[uba]; + struct uba_regs *ur = vc->uv_uba; + void (*func) __P((int)); + + br = mfpr(PR_IPL); + vec = ur->uba_brrvr[br - 0x14]; + if (vec <= 0) { + ubaerror(&vc->uv_sc, &br, (int *)&vec); + if (svec == 0) + return; + } + if (cold) + scb_fake(vec + vc->uh_ibase, br); + else { + struct ivec_dsp *scb_vec = (struct ivec_dsp *)((int)scb + 512); + func = scb_vec[vec/4].hoppaddr; + arg = scb_vec[vec/4].pushlarg; + (*func)(arg); + } +} + +void +dw780_init(sc) + struct uba_softc *sc; +{ + struct uba_vsoftc *vc = (void *)sc; + + vc->uv_uba->uba_cr = UBACR_ADINIT; + vc->uv_uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; + while ((vc->uv_uba->uba_cnfgr & UBACNFGR_UBIC) == 0) + ; +} + +#ifdef notyet +void +dw780_purge(sc, bdp) + struct uba_softc *sc; + int bdp; +{ + struct uba_vsoftc *vc = (void *)sc; + + vc->uv_uba->uba_dpr[bdp] |= UBADPR_BNE; +} +#endif + +int ubawedgecnt = 10; +int ubacrazy = 500; +int zvcnt_max = 5000; /* in 8 sec */ +int ubaerrcnt; +/* + * This routine is called by the locore code to process a UBA + * error on an 11/780 or 8600. The arguments are passed + * on the stack, and value-result (through some trickery). + * In particular, the uvec argument is used for further + * uba processing so the result aspect of it is very important. + * It must not be declared register. + */ +/*ARGSUSED*/ +void +ubaerror(uh, ipl, uvec) + register struct uba_softc *uh; + int *ipl, *uvec; +{ + struct uba_vsoftc *vc = (void *)uh; + struct uba_regs *uba = vc->uv_uba; + register int sr, s; + + if (*uvec == 0) { + /* + * Declare dt as unsigned so that negative values + * are handled as >8 below, in case time was set back. + */ + u_long dt = time.tv_sec - vc->uh_zvtime; + + vc->uh_zvtotal++; + if (dt > 8) { + vc->uh_zvtime = time.tv_sec; + vc->uh_zvcnt = 0; + } + if (++vc->uh_zvcnt > zvcnt_max) { + printf("%s: too many zero vectors (%d in <%d sec)\n", + vc->uv_sc.uh_dev.dv_xname, vc->uh_zvcnt, (int)dt + 1); + printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n", + *ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, + uba->uba_cnfgr&0xff); + printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n", + uba->uba_sr, ubasr_bits, uba->uba_dcr, + (uba->uba_dcr&0x8000000)?"":"NOT "); + ubareset(vc->uv_sc.uh_dev.dv_unit); + } + return; + } + if (uba->uba_cnfgr & NEX_CFGFLT) { + printf("%s: sbi fault sr=%b cnfgr=%b\n", + vc->uv_sc.uh_dev.dv_xname, uba->uba_sr, ubasr_bits, + uba->uba_cnfgr, NEXFLT_BITS); + ubareset(vc->uv_sc.uh_dev.dv_unit); + *uvec = 0; + return; + } + sr = uba->uba_sr; + s = splimp(); + printf("%s: uba error sr=%b fmer=%x fubar=%o\n", vc->uv_sc.uh_dev.dv_xname, + uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); + splx(s); + uba->uba_sr = sr; + *uvec &= UBABRRVR_DIV; + if (++ubaerrcnt % ubawedgecnt == 0) { + if (ubaerrcnt > ubacrazy) + panic("uba crazy"); + printf("ERROR LIMIT "); + ubareset(vc->uv_sc.uh_dev.dv_unit); + *uvec = 0; + } +} diff --git a/sys/arch/vax/uba/ubareg.h b/sys/arch/vax/uba/ubareg.h index 2dd5b52f4d2..fc882153aff 100644 --- a/sys/arch/vax/uba/ubareg.h +++ b/sys/arch/vax/uba/ubareg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ubareg.h,v 1.7 1997/05/29 00:05:10 niklas Exp $ */ -/* $NetBSD: ubareg.h,v 1.9 1996/08/20 13:38:02 ragge Exp $ */ +/* $OpenBSD: ubareg.h,v 1.8 2000/04/27 03:14:51 bjc Exp $ */ +/* $NetBSD: ubareg.h,v 1.10 1998/10/18 18:51:30 ragge Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. @@ -71,10 +71,6 @@ #define QBA 4 /* 22-bit Q-bus, no adaptor regs: uVAX II */ #endif -#if 0 /* XXX VAX8200 || VAX8500 || VAX8800 */ -#define DWBUA 5 /* BI UNIBUS adaptor: 8200/8500/8800 */ -#endif - /* * Size of unibus memory address space in pages * (also number of map registers). @@ -94,57 +90,6 @@ #ifndef _LOCORE /* - * DWBUA hardware registers. - */ -struct dwbua_regs { - int pad1[456]; /* actually bii regs + pad */ - int bua_csr; /* control and status register */ - int bua_offset; /* vector offset register */ - int bua_fubar; /* failed UNIBUS address register */ - int bua_bifar; /* BI failed address register */ - int bua_udiag[5]; /* micro diagnostics (R/O) */ - int pad2[3]; -/* dpr[0] is for DDP; dpr's 1 through 5 are for BPD's 1 through 5 */ - int bua_dpr[6]; /* data path registers */ - int pad3[10]; - int bua_bdps[20]; /* buffered data path space *//*???*/ - int pad4[8]; - struct pte bua_map[UBAPAGES]; /* unibus map registers */ - int pad5[UBAIOPAGES]; /* no maps for device address space */ -}; - -#ifdef DWBUA -/* bua_csr */ -#define BUACSR_ERR 0x80000000 /* composite error */ -#define BUACSR_BIF 0x10000000 /* BI failure */ -#define BUACSR_SSYNTO 0x08000000 /* slave sync timeout */ -#define BUACSR_UIE 0x04000000 /* unibus interlock error */ -#define BUACSR_IVMR 0x02000000 /* invalid map register */ -#define BUACSR_BADBDP 0x01000000 /* bad BDP select */ -#define BUACSR_BUAEIE 0x00100000 /* bua error interrupt enable (?) */ -#define BUACSR_UPI 0x00020000 /* unibus power init */ -#define BUACSR_UREGDUMP 0x00010000 /* microdiag register dump */ -#define BUACSR_IERRNO 0x000000ff /* mask for internal errror number */ - -/* bua_offset */ -#define BUAOFFSET_MASK 0x00003e00 /* hence max offset = 15872 */ - -/* bua_dpr */ -#define BUADPR_DPSEL 0x00e00000 /* data path select (?) */ -#define BUADPR_PURGE 0x00000001 /* purge bdp */ - -/* bua_map -- in particular, those bits that are not in DW780s & DW750s */ -#define BUAMR_IOADR 0x40000000 /* I/O address space */ -#define BUAMR_LAE 0x04000000 /* longword access enable */ - /* I see no reason to use either one, though ... act 6 Aug 1987 */ - -#define UBA_PURGEBUA(uba, bdp) \ - (((struct dwbua_regs *)(uba))->bua_dpr[bdp] |= BUADPR_PURGE) -#else -#define UBA_PURGEBUA(uba, bdp) -#endif - -/* * DW780/DW750 hardware registers */ struct uba_regs { diff --git a/sys/arch/vax/uba/ubavar.h b/sys/arch/vax/uba/ubavar.h index 55f72ef2d34..24975cd99eb 100644 --- a/sys/arch/vax/uba/ubavar.h +++ b/sys/arch/vax/uba/ubavar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ubavar.h,v 1.7 1997/05/29 00:05:10 niklas Exp $ */ -/* $NetBSD: ubavar.h,v 1.18 1996/08/20 13:38:04 ragge Exp $ */ +/* $OpenBSD: ubavar.h,v 1.8 2000/04/27 03:14:52 bjc Exp $ */ +/* $NetBSD: ubavar.h,v 1.21 1999/01/19 21:04:48 ragge Exp $ */ /* * Copyright (c) 1982, 1986 Regents of the University of California. @@ -81,8 +81,6 @@ struct uba_softc { void (**uh_reset) __P((int));/* UBA reset function array */ int *uh_resarg; /* array of ubareset args */ int uh_resno; /* Number of devices to reset */ - struct ivec_dsp *uh_idsp; /* Interrupt dispatch area */ - u_int *uh_iarea; /* Interrupt vector array */ short uh_mrwant; /* someone is waiting for map reg */ short uh_bdpwant; /* someone awaits bdp's */ int uh_bdpfree; /* free bdp's */ @@ -99,19 +97,13 @@ struct uba_softc { void (*uh_afterscan) __P((struct uba_softc *)); void (*uh_ubainit) __P((struct uba_softc *)); void (*uh_ubapurge) __P((struct uba_softc *, int)); -#ifdef DW780 - struct ivec_dsp uh_dw780; /* Interrupt handles for DW780 */ -#endif short uh_nr; /* Unibus sequential number */ short uh_nbdp; /* # of BDP's */ + int uh_ibase; /* Base address for vectors */ }; #define UAMSIZ 100 -/* given a pointer to uba_regs, find DWBUA registers */ -/* this should be replaced with a union in uba_softc */ -#define BUA(uba) ((struct dwbua_regs *)(uba)) - /* * Per-controller structure. * The unit struct is common to both the adapter and the controller @@ -181,14 +173,13 @@ struct ubinfo { #define ubago(ui) ubaqueue(ui) #define b_forw b_hash.le_next /* Nice to have when handling uba queues */ -extern struct cfdriver uba_cd; - -void ubasetvec __P((struct device *, int, void (*) __P((int)))); +void uba_attach __P((struct uba_softc *, unsigned long)); int uballoc __P((struct uba_softc *, caddr_t, int, int)); void ubarelse __P((struct uba_softc *, int *)); int ubaqueue __P((struct uba_unit *, struct buf *)); void ubadone __P((struct uba_unit *)); void ubareset __P((int)); +int ubasetup __P((struct uba_softc *, struct buf *, int)); #endif /* _KERNEL */ #endif !_LOCORE |