diff options
author | Hugh Graham <hugh@cvs.openbsd.org> | 2002-06-11 09:36:25 +0000 |
---|---|---|
committer | Hugh Graham <hugh@cvs.openbsd.org> | 2002-06-11 09:36:25 +0000 |
commit | 10ca5e5818bb80e596db244327a2663b6703bb18 (patch) | |
tree | c7ac330b34d73ea4e0c78d17a9eed0a3b6df63aa /sys/arch/vax/qbus | |
parent | 180b34af9885b092bee0f67c5b2ac8577d972cfe (diff) |
New boot code, mostly from ragge's work in NetBSD.
Some header syncing and a couple network drivers came along for the ride.
Assembly files have been renamed from .s to .S to facilitate diffs.
Kernel is backwards compat - with manual interaction.
OpenBSD features have been preserved.
Diffstat (limited to 'sys/arch/vax/qbus')
-rw-r--r-- | sys/arch/vax/qbus/if_de.c | 641 | ||||
-rw-r--r-- | sys/arch/vax/qbus/if_dereg.h | 221 |
2 files changed, 862 insertions, 0 deletions
diff --git a/sys/arch/vax/qbus/if_de.c b/sys/arch/vax/qbus/if_de.c new file mode 100644 index 00000000000..03c71f53728 --- /dev/null +++ b/sys/arch/vax/qbus/if_de.c @@ -0,0 +1,641 @@ +/* $OpenBSD: if_de.c,v 1.1 2002/06/11 09:36:24 hugh Exp $ */ +/* $NetBSD: if_de.c,v 1.11 2001/11/13 07:11:24 lukem Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * Copyright (c) 2000 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 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_de.c 7.12 (Berkeley) 12/16/90 + */ + +/* + * DEC DEUNA interface + * + * Lou Salkind + * New York University + * + * Rewritten by Ragge 30 April 2000 to match new world. + * + * TODO: + * timeout routine (get statistics) + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: if_de.c,v 1.11 2001/11/13 07:11:24 lukem Exp $"); + +#include "opt_inet.h" +#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 <net/if.h> +#include <net/if_ether.h> +#include <net/if_dl.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/if_inarp.h> +#endif + +#if NBPFILTER > 0 +#include <net/bpf.h> +#include <net/bpfdesc.h> +#endif + +#include <machine/bus.h> + +#include <dev/qbus/ubavar.h> +#include <dev/qbus/if_dereg.h> +#include <dev/qbus/if_uba.h> + +#include "ioconf.h" + +/* + * Be careful with transmit/receive buffers, each entry steals 4 map + * registers, and there is only 496 on one unibus... + */ +#define NRCV 7 /* number of receive buffers (must be > 1) */ +#define NXMT 3 /* number of transmit buffers */ + +/* + * Structure containing the elements that must be in DMA-safe memory. + */ +struct de_cdata { + /* the following structures are always mapped in */ + struct de_pcbb dc_pcbb; /* port control block */ + struct de_ring dc_xrent[NXMT]; /* transmit ring entrys */ + struct de_ring dc_rrent[NRCV]; /* receive ring entrys */ + struct de_udbbuf dc_udbbuf; /* UNIBUS data buffer */ + /* end mapped area */ +}; + +/* + * Ethernet software status per interface. + * + * Each interface is referenced by a network interface structure, + * ds_if, which the routing code uses to locate the interface. + * This structure contains the output queue for the interface, its address, ... + * We also have, for each interface, a UBA interface structure, which + * contains information about the UNIBUS resources held by the interface: + * map registers, buffered data paths, etc. Information is cached in this + * structure for use by the if_uba.c routines in running the interface + * efficiently. + */ +struct de_softc { + struct device sc_dev; /* Configuration common part */ + struct evcnt sc_intrcnt; /* Interrupt counting */ + struct ethercom sc_ec; /* Ethernet common part */ +#define sc_if sc_ec.ec_if /* network-visible interface */ + bus_space_tag_t sc_iot; + bus_addr_t sc_ioh; + bus_dma_tag_t sc_dmat; + int sc_flags; +#define DSF_MAPPED 1 + struct ubinfo sc_ui; + struct de_cdata *sc_dedata; /* Control structure */ + struct de_cdata *sc_pdedata; /* Bus-mapped control structure */ + struct ifubinfo sc_ifuba; /* UNIBUS resources */ + struct ifrw sc_ifr[NRCV]; /* UNIBUS receive buffer maps */ + struct ifxmt sc_ifw[NXMT]; /* UNIBUS receive buffer maps */ + + int sc_xindex; /* UNA index into transmit chain */ + int sc_rindex; /* UNA index into receive chain */ + int sc_xfree; /* index for next transmit buffer */ + int sc_nxmit; /* # of transmits in progress */ + void *sc_sh; /* shutdownhook cookie */ +}; + +static int dematch(struct device *, struct cfdata *, void *); +static void deattach(struct device *, struct device *, void *); +static void dewait(struct de_softc *, char *); +static int deinit(struct ifnet *); +static int deioctl(struct ifnet *, u_long, caddr_t); +static void dereset(struct device *); +static void destop(struct ifnet *, int); +static void destart(struct ifnet *); +static void derecv(struct de_softc *); +static void deintr(void *); +static void deshutdown(void *); + +struct cfattach de_ca = { + sizeof(struct de_softc), dematch, deattach +}; + +#define DE_WCSR(csr, val) \ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val) +#define DE_WLOW(val) \ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, DE_PCSR0, val) +#define DE_WHIGH(val) \ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, DE_PCSR0 + 1, val) +#define DE_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) & 0x3) +/* + * Interface exists: make available by filling in network interface + * record. System will initialize the interface when it is ready + * to accept packets. We get the ethernet address here. + */ +void +deattach(struct device *parent, struct device *self, void *aux) +{ + struct uba_attach_args *ua = aux; + struct de_softc *sc = (struct de_softc *)self; + struct ifnet *ifp = &sc->sc_if; + u_int8_t myaddr[ETHER_ADDR_LEN]; + int csr1, error; + char *c; + + sc->sc_iot = ua->ua_iot; + sc->sc_ioh = ua->ua_ioh; + sc->sc_dmat = ua->ua_dmat; + + /* + * What kind of a board is this? + * The error bits 4-6 in pcsr1 are a device id as long as + * the high byte is zero. + */ + csr1 = DE_RCSR(DE_PCSR1); + if (csr1 & 0xff60) + c = "broken"; + else if (csr1 & 0x10) + c = "delua"; + else + c = "deuna"; + + /* + * Reset the board and temporarily map + * the pcbb buffer onto the Unibus. + */ + DE_WCSR(DE_PCSR0, 0); /* reset INTE */ + DELAY(100); + DE_WCSR(DE_PCSR0, PCSR0_RSET); + dewait(sc, "reset"); + + sc->sc_ui.ui_size = sizeof(struct de_cdata); + if ((error = ubmemalloc((struct uba_softc *)parent, &sc->sc_ui, 0))) + return printf(": failed ubmemalloc(), error = %d\n", error); + sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr; + + /* + * Tell the DEUNA about our PCB + */ + DE_WCSR(DE_PCSR2, LOWORD(sc->sc_ui.ui_baddr)); + DE_WCSR(DE_PCSR3, HIWORD(sc->sc_ui.ui_baddr)); + DE_WLOW(CMD_GETPCBB); + dewait(sc, "pcbb"); + + sc->sc_dedata->dc_pcbb.pcbb0 = FC_RDPHYAD; + DE_WLOW(CMD_GETCMD); + dewait(sc, "read addr "); + + bcopy((caddr_t)&sc->sc_dedata->dc_pcbb.pcbb2, myaddr, sizeof (myaddr)); + printf("\n%s: %s, hardware address %s\n", sc->sc_dev.dv_xname, c, + ether_sprintf(myaddr)); + + uba_intr_establish(ua->ua_icookie, ua->ua_cvec, deintr, sc, + &sc->sc_intrcnt); + uba_reset_establish(dereset, &sc->sc_dev); + evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, + sc->sc_dev.dv_xname, "intr"); + + strcpy(ifp->if_xname, sc->sc_dev.dv_xname); + ifp->if_softc = sc; + ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI; + ifp->if_ioctl = deioctl; + ifp->if_start = destart; + ifp->if_init = deinit; + ifp->if_stop = destop; + IFQ_SET_READY(&ifp->if_snd); + + if_attach(ifp); + ether_ifattach(ifp, myaddr); + ubmemfree((struct uba_softc *)parent, &sc->sc_ui); + + sc->sc_sh = shutdownhook_establish(deshutdown, sc); +} + +void +destop(struct ifnet *ifp, int a) +{ + struct de_softc *sc = ifp->if_softc; + + DE_WLOW(0); + DELAY(5000); + DE_WLOW(PCSR0_RSET); +} + + +/* + * Reset of interface after UNIBUS reset. + */ +void +dereset(struct device *dev) +{ + struct de_softc *sc = (void *)dev; + + sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + sc->sc_flags &= ~DSF_MAPPED; + sc->sc_pdedata = NULL; /* All mappings lost */ + DE_WCSR(DE_PCSR0, PCSR0_RSET); + dewait(sc, "reset"); + deinit(&sc->sc_if); +} + +/* + * Initialization of interface; clear recorded pending + * operations, and reinitialize UNIBUS usage. + */ +int +deinit(struct ifnet *ifp) +{ + struct de_softc *sc = ifp->if_softc; + struct de_cdata *dc, *pdc; + struct ifrw *ifrw; + struct ifxmt *ifxp; + struct de_ring *rp; + int s, error; + + if (ifp->if_flags & IFF_RUNNING) + return 0; + if ((sc->sc_flags & DSF_MAPPED) == 0) { + if (if_ubaminit(&sc->sc_ifuba, (void *)sc->sc_dev.dv_parent, + MCLBYTES, sc->sc_ifr, NRCV, sc->sc_ifw, NXMT)) { + printf("%s: can't initialize\n", sc->sc_dev.dv_xname); + ifp->if_flags &= ~IFF_UP; + return 0; + } + sc->sc_ui.ui_size = sizeof(struct de_cdata); + if ((error = ubmemalloc((void *)sc->sc_dev.dv_parent, + &sc->sc_ui, 0))) { + printf(": unable to ubmemalloc(), error = %d\n", error); + return 0; + } + sc->sc_pdedata = (struct de_cdata *)sc->sc_ui.ui_baddr; + sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr; + sc->sc_flags |= DSF_MAPPED; + } + + /* + * Tell the DEUNA about our PCB + */ + DE_WCSR(DE_PCSR2, LOWORD(sc->sc_pdedata)); + DE_WCSR(DE_PCSR3, HIWORD(sc->sc_pdedata)); + DE_WLOW(0); /* reset INTE */ + DELAY(500); + DE_WLOW(CMD_GETPCBB); + dewait(sc, "pcbb"); + + dc = sc->sc_dedata; + pdc = sc->sc_pdedata; + /* set the transmit and receive ring header addresses */ + dc->dc_pcbb.pcbb0 = FC_WTRING; + dc->dc_pcbb.pcbb2 = LOWORD(&pdc->dc_udbbuf); + dc->dc_pcbb.pcbb4 = HIWORD(&pdc->dc_udbbuf); + + dc->dc_udbbuf.b_tdrbl = LOWORD(&pdc->dc_xrent[0]); + dc->dc_udbbuf.b_tdrbh = HIWORD(&pdc->dc_xrent[0]); + dc->dc_udbbuf.b_telen = sizeof (struct de_ring) / sizeof(u_int16_t); + dc->dc_udbbuf.b_trlen = NXMT; + dc->dc_udbbuf.b_rdrbl = LOWORD(&pdc->dc_rrent[0]); + dc->dc_udbbuf.b_rdrbh = HIWORD(&pdc->dc_rrent[0]); + dc->dc_udbbuf.b_relen = sizeof (struct de_ring) / sizeof(u_int16_t); + dc->dc_udbbuf.b_rrlen = NRCV; + + DE_WLOW(CMD_GETCMD); + dewait(sc, "wtring"); + + sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE; + sc->sc_dedata->dc_pcbb.pcbb2 = MOD_TPAD|MOD_HDX|MOD_DRDC|MOD_ENAL; + DE_WLOW(CMD_GETCMD); + dewait(sc, "wtmode"); + + /* set up the receive and transmit ring entries */ + ifxp = &sc->sc_ifw[0]; + for (rp = &dc->dc_xrent[0]; rp < &dc->dc_xrent[NXMT]; rp++) { + rp->r_segbl = LOWORD(ifxp->ifw_info); + rp->r_segbh = HIWORD(ifxp->ifw_info); + rp->r_flags = 0; + ifxp++; + } + ifrw = &sc->sc_ifr[0]; + for (rp = &dc->dc_rrent[0]; rp < &dc->dc_rrent[NRCV]; rp++) { + rp->r_slen = MCLBYTES - 2; + rp->r_segbl = LOWORD(ifrw->ifrw_info); + rp->r_segbh = HIWORD(ifrw->ifrw_info); + rp->r_flags = RFLG_OWN; + ifrw++; + } + + /* start up the board (rah rah) */ + s = splnet(); + sc->sc_rindex = sc->sc_xindex = sc->sc_xfree = sc->sc_nxmit = 0; + sc->sc_if.if_flags |= IFF_RUNNING; + DE_WLOW(PCSR0_INTE); /* avoid interlock */ + destart(&sc->sc_if); /* queue output packets */ + DE_WLOW(CMD_START|PCSR0_INTE); + splx(s); + return 0; +} + +/* + * Setup output on interface. + * Get another datagram to send off of the interface queue, + * and map it to the interface before starting the output. + * Must be called from ipl >= our interrupt level. + */ +void +destart(struct ifnet *ifp) +{ + struct de_softc *sc = ifp->if_softc; + struct de_cdata *dc; + struct de_ring *rp; + struct mbuf *m; + int nxmit, len; + + /* + * the following test is necessary, since + * the code is not reentrant and we have + * multiple transmission buffers. + */ + if (sc->sc_if.if_flags & IFF_OACTIVE) + return; + dc = sc->sc_dedata; + for (nxmit = sc->sc_nxmit; nxmit < NXMT; nxmit++) { + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == 0) + break; + + rp = &dc->dc_xrent[sc->sc_xfree]; + if (rp->r_flags & XFLG_OWN) + panic("deuna xmit in progress"); +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m); +#endif + + len = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[sc->sc_xfree], m); + rp->r_slen = len; + rp->r_tdrerr = 0; + rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; + + sc->sc_xfree++; + if (sc->sc_xfree == NXMT) + sc->sc_xfree = 0; + } + if (sc->sc_nxmit != nxmit) { + sc->sc_nxmit = nxmit; + if (ifp->if_flags & IFF_RUNNING) + DE_WLOW(PCSR0_INTE|CMD_PDMD); + } +} + +/* + * Command done interrupt. + */ +void +deintr(void *arg) +{ + struct ifxmt *ifxp; + struct de_cdata *dc; + struct de_softc *sc = arg; + struct de_ring *rp; + short csr0; + + /* save flags right away - clear out interrupt bits */ + csr0 = DE_RCSR(DE_PCSR0); + DE_WHIGH(csr0 >> 8); + + + sc->sc_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */ + /* + * if receive, put receive buffer on mbuf + * and hang the request again + */ + derecv(sc); + + /* + * Poll transmit ring and check status. + * Be careful about loopback requests. + * Then free buffer space and check for + * more transmit requests. + */ + dc = sc->sc_dedata; + for ( ; sc->sc_nxmit > 0; sc->sc_nxmit--) { + rp = &dc->dc_xrent[sc->sc_xindex]; + if (rp->r_flags & XFLG_OWN) + break; + + sc->sc_if.if_opackets++; + ifxp = &sc->sc_ifw[sc->sc_xindex]; + /* check for unusual conditions */ + if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { + if (rp->r_flags & XFLG_ERRS) { + /* output error */ + sc->sc_if.if_oerrors++; + } else if (rp->r_flags & XFLG_ONE) { + /* one collision */ + sc->sc_if.if_collisions++; + } else if (rp->r_flags & XFLG_MORE) { + /* more than one collision */ + sc->sc_if.if_collisions += 2; /* guess */ + } + } + if_ubaend(&sc->sc_ifuba, ifxp); + /* check if next transmit buffer also finished */ + sc->sc_xindex++; + if (sc->sc_xindex == NXMT) + sc->sc_xindex = 0; + } + sc->sc_if.if_flags &= ~IFF_OACTIVE; + destart(&sc->sc_if); + + if (csr0 & PCSR0_RCBI) { + DE_WLOW(PCSR0_INTE|CMD_PDMD); + } +} + +/* + * Ethernet interface receiver interface. + * If input error just drop packet. + * Otherwise purge input buffered data path and examine + * packet to determine type. 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 +derecv(struct de_softc *sc) +{ + struct ifnet *ifp = &sc->sc_if; + struct de_ring *rp; + struct de_cdata *dc; + struct mbuf *m; + int len; + + dc = sc->sc_dedata; + rp = &dc->dc_rrent[sc->sc_rindex]; + while ((rp->r_flags & RFLG_OWN) == 0) { + sc->sc_if.if_ipackets++; + len = (rp->r_lenerr&RERR_MLEN) - ETHER_CRC_LEN; + /* check for errors */ + if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || + (rp->r_lenerr & (RERR_BUFL|RERR_UBTO))) { + sc->sc_if.if_ierrors++; + goto next; + } + m = if_ubaget(&sc->sc_ifuba, &sc->sc_ifr[sc->sc_rindex], + ifp, len); + if (m == 0) { + sc->sc_if.if_ierrors++; + goto next; + } +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m); +#endif + + (*ifp->if_input)(ifp, m); + + /* hang the receive buffer again */ +next: rp->r_lenerr = 0; + rp->r_flags = RFLG_OWN; + + /* check next receive buffer */ + sc->sc_rindex++; + if (sc->sc_rindex == NRCV) + sc->sc_rindex = 0; + rp = &dc->dc_rrent[sc->sc_rindex]; + } +} + +/* + * Process an ioctl request. + */ +int +deioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + int s, error = 0; + + s = splnet(); + + error = ether_ioctl(ifp, cmd, data); + if (error == ENETRESET) + error = 0; + + splx(s); + return (error); +} + +/* + * Await completion of the named function + * and check for errors. + */ +void +dewait(struct de_softc *sc, char *fn) +{ + int csr0; + + while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0) + ; + csr0 = DE_RCSR(DE_PCSR0); + DE_WHIGH(csr0 >> 8); + if (csr0 & PCSR0_PCEI) { + char bits[64]; + printf("%s: %s failed, csr0=%s ", sc->sc_dev.dv_xname, fn, + bitmask_snprintf(csr0, PCSR0_BITS, bits, sizeof(bits))); + printf("csr1=%s\n", bitmask_snprintf(DE_RCSR(DE_PCSR1), + PCSR1_BITS, bits, sizeof(bits))); + } +} + +int +dematch(struct device *parent, struct cfdata *cf, void *aux) +{ + struct uba_attach_args *ua = aux; + struct de_softc ssc; + struct de_softc *sc = &ssc; + int i; + + sc->sc_iot = ua->ua_iot; + sc->sc_ioh = ua->ua_ioh; + /* + * Make sure self-test is finished before we screw with the board. + * Self-test on a DELUA can take 15 seconds (argh). + */ + for (i = 0; + (i < 160) && + (DE_RCSR(DE_PCSR0) & PCSR0_FATI) == 0 && + (DE_RCSR(DE_PCSR1) & PCSR1_STMASK) == STAT_RESET; + ++i) + DELAY(50000); + if (((DE_RCSR(DE_PCSR0) & PCSR0_FATI) != 0) || + (((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_READY) && + ((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_RUN))) + return(0); + + DE_WCSR(DE_PCSR0, 0); + DELAY(5000); + DE_WCSR(DE_PCSR0, PCSR0_RSET); + while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0) + ; + /* make board interrupt by executing a GETPCBB command */ + DE_WCSR(DE_PCSR0, PCSR0_INTE); + DE_WCSR(DE_PCSR2, 0); + DE_WCSR(DE_PCSR3, 0); + DE_WCSR(DE_PCSR0, PCSR0_INTE|CMD_GETPCBB); + DELAY(50000); + + return 1; +} + +void +deshutdown(void *arg) +{ + struct de_softc *sc = arg; + + DE_WCSR(DE_PCSR0, 0); + DELAY(1000); + DE_WCSR(DE_PCSR0, PCSR0_RSET); + dewait(sc, "shutdown"); +} diff --git a/sys/arch/vax/qbus/if_dereg.h b/sys/arch/vax/qbus/if_dereg.h new file mode 100644 index 00000000000..54da29f4bf1 --- /dev/null +++ b/sys/arch/vax/qbus/if_dereg.h @@ -0,0 +1,221 @@ +/* $OpenBSD: if_dereg.h,v 1.1 2002/06/11 09:36:24 hugh Exp $ */ +/* $NetBSD: if_dereg.h,v 1.2 2000/05/28 17:23:44 ragge 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. + * + * @(#)if_dereg.h 7.3 (Berkeley) 6/28/90 + */ + +/* + * DEC DEUNA interface + */ +#ifdef notdef +struct dedevice { + union { + short p0_w; + char p0_b[2]; + } u_p0; +#define pcsr0 u_p0.p0_w +#define pclow u_p0.p0_b[0] +#define pchigh u_p0.p0_b[1] + short pcsr1; + short pcsr2; + short pcsr3; +}; +#endif + +#define DE_PCSR0 0 +#define DE_PCSR1 2 +#define DE_PCSR2 4 +#define DE_PCSR3 6 + +/* + * PCSR 0 bit descriptions + */ +#define PCSR0_SERI 0x8000 /* Status error interrupt */ +#define PCSR0_PCEI 0x4000 /* Port command error interrupt */ +#define PCSR0_RXI 0x2000 /* Receive done interrupt */ +#define PCSR0_TXI 0x1000 /* Transmit done interrupt */ +#define PCSR0_DNI 0x0800 /* Done interrupt */ +#define PCSR0_RCBI 0x0400 /* Receive buffer unavail intrpt */ +#define PCSR0_FATI 0x0100 /* Fatal error interrupt */ +#define PCSR0_INTR 0x0080 /* Interrupt summary */ +#define PCSR0_INTE 0x0040 /* Interrupt enable */ +#define PCSR0_RSET 0x0020 /* DEUNA reset */ +#define PCSR0_CMASK 0x000f /* command mask */ + +#define PCSR0_BITS "\20\20SERI\17PCEI\16RXI\15TXI\14DNI\13RCBI\11FATI\10INTR\7INTE\6RSET" + +/* bits 0-3 are for the PORT_COMMAND */ +#define CMD_NOOP 0x0 +#define CMD_GETPCBB 0x1 /* Get PCB Block */ +#define CMD_GETCMD 0x2 /* Execute command in PCB */ +#define CMD_STEST 0x3 /* Self test mode */ +#define CMD_START 0x4 /* Reset xmit and receive ring ptrs */ +#define CMD_BOOT 0x5 /* Boot DEUNA */ +#define CMD_PDMD 0x8 /* Polling demand */ +#define CMD_TMRO 0x9 /* Sanity timer on */ +#define CMD_TMRF 0xa /* Sanity timer off */ +#define CMD_RSTT 0xb /* Reset sanity timer */ +#define CMD_STOP 0xf /* Suspend operation */ + +/* + * PCSR 1 bit descriptions + */ +#define PCSR1_XPWR 0x8000 /* Transceiver power BAD */ +#define PCSR1_ICAB 0x4000 /* Interconnect cabling BAD */ +#define PCSR1_STCODE 0x3f00 /* Self test error code */ +#define PCSR1_PCTO 0x0080 /* Port command timed out */ +#define PCSR1_ILLINT 0x0040 /* Illegal interrupt */ +#define PCSR1_TIMEOUT 0x0020 /* Timeout */ +#define PCSR1_POWER 0x0010 /* Power fail */ +#define PCSR1_RMTC 0x0008 /* Remote console reserved */ +#define PCSR1_STMASK 0x0007 /* State */ + +/* bit 0-3 are for STATE */ +#define STAT_RESET 0x0 +#define STAT_PRIMLD 0x1 /* Primary load */ +#define STAT_READY 0x2 +#define STAT_RUN 0x3 +#define STAT_UHALT 0x5 /* UNIBUS halted */ +#define STAT_NIHALT 0x6 /* NI halted */ +#define STAT_NIUHALT 0x7 /* NI and UNIBUS Halted */ + +#define PCSR1_BITS "\20\20XPWR\17ICAB\10PCTO\7ILLINT\6TIMEOUT\5POWER\4RMTC" + +/* + * Port Control Block Base + */ +struct de_pcbb { + int16_t pcbb0; /* function */ + int16_t pcbb2; /* command specific */ + int16_t pcbb4; + int16_t pcbb6; +}; + +/* PCBB function codes */ +#define FC_NOOP 0x00 /* NO-OP */ +#define FC_LSUADDR 0x01 /* Load and start microaddress */ +#define FC_RDDEFAULT 0x02 /* Read default physical address */ +#define FC_RDPHYAD 0x04 /* Read physical address */ +#define FC_WTPHYAD 0x05 /* Write physical address */ +#define FC_RDMULTI 0x06 /* Read multicast address list */ +#define FC_WTMULTI 0x07 /* Read multicast address list */ +#define FC_RDRING 0x08 /* Read ring format */ +#define FC_WTRING 0x09 /* Write ring format */ +#define FC_RDCNTS 0x0a /* Read counters */ +#define FC_RCCNTS 0x0b /* Read and clear counters */ +#define FC_RDMODE 0x0c /* Read mode */ +#define FC_WTMODE 0x0d /* Write mode */ +#define FC_RDSTATUS 0x0e /* Read port status */ +#define FC_RCSTATUS 0x0f /* Read and clear port status */ +#define FC_DUMPMEM 0x10 /* Dump internal memory */ +#define FC_LOADMEM 0x11 /* Load internal memory */ +#define FC_RDSYSID 0x12 /* Read system ID parameters */ +#define FC_WTSYSID 0x13 /* Write system ID parameters */ +#define FC_RDSERAD 0x14 /* Read load server address */ +#define FC_WTSERAD 0x15 /* Write load server address */ + +/* + * Unibus Data Block Base (UDBB) for ring buffers + */ +struct de_udbbuf { + int16_t b_tdrbl; /* Transmit desc ring base low 16 bits */ + int8_t b_tdrbh; /* Transmit desc ring base high 2 bits */ + int8_t b_telen; /* Length of each transmit entry */ + int16_t b_trlen; /* Number of entries in the XMIT desc ring */ + int16_t b_rdrbl; /* Receive desc ring base low 16 bits */ + int8_t b_rdrbh; /* Receive desc ring base high 2 bits */ + int8_t b_relen; /* Length of each receive entry */ + int16_t b_rrlen; /* Number of entries in the RECV desc ring */ +}; + +/* + * Transmit/Receive Ring Entry + */ +struct de_ring { + int16_t r_slen; /* Segment length */ + int16_t r_segbl; /* Segment address (low 16 bits) */ + int8_t r_segbh; /* Segment address (hi 2 bits) */ + u_int8_t r_flags; /* Status flags */ + u_int16_t r_tdrerr; /* Errors */ +#define r_lenerr r_tdrerr +}; + +#define XFLG_OWN 0x80 /* If 0 then owned by driver */ +#define XFLG_ERRS 0x40 /* Error summary */ +#define XFLG_MTCH 0x20 /* Address match on xmit request */ +#define XFLG_MORE 0x10 /* More than one entry required */ +#define XFLG_ONE 0x08 /* One collision encountered */ +#define XFLG_DEF 0x04 /* Transmit deferred */ +#define XFLG_STP 0x02 /* Start of packet */ +#define XFLG_ENP 0x01 /* End of packet */ + +#define XFLG_BITS "\10\10OWN\7ERRS\6MTCH\5MORE\4ONE\3DEF\2STP\1ENP" + +#define XERR_BUFL 0x8000 /* Buffer length error */ +#define XERR_UBTO 0x4000 /* UNIBUS tiemout */ +#define XERR_LCOL 0x1000 /* Late collision */ +#define XERR_LCAR 0x0800 /* Loss of carrier */ +#define XERR_RTRY 0x0400 /* Failed after 16 retries */ +#define XERR_TDR 0x03ff /* TDR value */ + +#define XERR_BITS "\20\20BUFL\17UBTO\15LCOL\14LCAR\13RTRY" + +#define RFLG_OWN 0x80 /* If 0 then owned by driver */ +#define RFLG_ERRS 0x40 /* Error summary */ +#define RFLG_FRAM 0x20 /* Framing error */ +#define RFLG_OFLO 0x10 /* Message overflow */ +#define RFLG_CRC 0x08 /* CRC error */ +#define RFLG_STP 0x02 /* Start of packet */ +#define RFLG_ENP 0x01 /* End of packet */ + +#define RFLG_BITS "\10\10OWN\7ERRS\6FRAM\5OFLO\4CRC\2STP\1ENP" + +#define RERR_BUFL 0x8000 /* Buffer length error */ +#define RERR_UBTO 0x4000 /* UNIBUS tiemout */ +#define RERR_NCHN 0x2000 /* No data chaining */ +#define RERR_MLEN 0x0fff /* Message length */ + +#define RERR_BITS "\20\20BUFL\17UBTO\16NCHN" + +/* mode description bits */ +#define MOD_HDX 0x0001 /* Half duplex mode */ +#define MOD_LOOP 0x0004 /* Enable internal loopback */ +#define MOD_DTCR 0x0008 /* Disables CRC generation */ +#define MOD_DMNT 0x0200 /* Disable maintenance features */ +#define MOD_ECT 0x0400 /* Enable collision test */ +#define MOD_TPAD 0x1000 /* Transmit message pad enable */ +#define MOD_DRDC 0x2000 /* Disable data chaining */ +#define MOD_ENAL 0x4000 /* Enable all multicast */ +#define MOD_PROM 0x8000 /* Enable promiscuous mode */ |