summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>1998-07-17 21:33:12 +0000
committerJason Wright <jason@cvs.openbsd.org>1998-07-17 21:33:12 +0000
commitdea46a95aecc2f88c901f933c4c3370264eb6fe2 (patch)
treea18bb0b6db9d95b73e9f2b69e34893a388511e9f /sys
parentec887d96c4d670aa2d9e143581e4b658b8069bc0 (diff)
Moved most of the DMA functions to a chipset driver so that
'hme' and 'be' can share the same logic.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc/conf/files.sparc14
-rw-r--r--sys/arch/sparc/dev/hme.c412
-rw-r--r--sys/arch/sparc/dev/hmereg.h44
-rw-r--r--sys/arch/sparc/dev/hmevar.h8
-rw-r--r--sys/arch/sparc/dev/stp2002base.c386
-rw-r--r--sys/arch/sparc/dev/stp2002var.h92
6 files changed, 557 insertions, 399 deletions
diff --git a/sys/arch/sparc/conf/files.sparc b/sys/arch/sparc/conf/files.sparc
index e4d6926eeb8..66c80577b31 100644
--- a/sys/arch/sparc/conf/files.sparc
+++ b/sys/arch/sparc/conf/files.sparc
@@ -1,4 +1,4 @@
-# $OpenBSD: files.sparc,v 1.18 1998/07/10 19:20:11 jason Exp $
+# $OpenBSD: files.sparc,v 1.19 1998/07/17 21:33:05 jason Exp $
# $NetBSD: files.sparc,v 1.44 1997/08/31 21:29:16 pk Exp $
# @(#)files.sparc 8.1 (Berkeley) 7/19/93
@@ -113,6 +113,13 @@ device me {}
attach me at qec
file arch/sparc/dev/me.c me
+# HappyMeal (hme) ethernet
+device hme
+attach hme at sbus
+file arch/sparc/dev/hme.c hme
+
+file arch/sparc/dev/stp2002base.c hme | be
+
device esp: scsi, ncr53c9x
attach esp at sbus, dma, obio
file arch/sparc/dev/esp.c esp
@@ -122,11 +129,6 @@ attach audioamd at mainbus, obio, sbus
file arch/sparc/dev/amd7930.c audio
file arch/sparc/sparc/amd7930intr.s audio
-# HappyMeal (hme) ethernet
-device hme
-attach hme at sbus
-file arch/sparc/dev/hme.c hme
-
# Brooktree DAC attribute
define bt_dac
diff --git a/sys/arch/sparc/dev/hme.c b/sys/arch/sparc/dev/hme.c
index a34c6386e3e..06583bf08e1 100644
--- a/sys/arch/sparc/dev/hme.c
+++ b/sys/arch/sparc/dev/hme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hme.c,v 1.3 1998/07/13 02:27:41 jason Exp $ */
+/* $OpenBSD: hme.c,v 1.4 1998/07/17 21:33:07 jason Exp $ */
/*
* Copyright (c) 1998 Jason L. Wright (jason@thought.net)
@@ -72,6 +72,7 @@
#include <sparc/sparc/cpuvar.h>
#include <sparc/dev/sbusvar.h>
#include <sparc/dev/dmareg.h> /* for SBUS_BURST_* */
+#include <sparc/dev/stp2002var.h>
#include <sparc/dev/hmereg.h>
#include <sparc/dev/hmevar.h>
@@ -80,42 +81,36 @@ void hmeattach __P((struct device *, struct device *, void *));
void hmewatchdog __P((struct ifnet *));
int hmeintr __P((void *));
int hmeioctl __P((struct ifnet *, u_long, caddr_t));
-void hmereset __P((struct hme_softc *sc));
+void hmereset __P((struct hme_softc *));
void hmestart __P((struct ifnet *));
-void hmestop __P((struct hme_softc *sc));
-void hmeinit __P((struct hme_softc *sc));
+void hmestop __P((struct hme_softc *));
+void hmeinit __P((struct hme_softc *));
-static void hme_tcvr_write __P((struct hme_softc *sc, int reg,
+static void hme_tcvr_write __P((struct hme_softc *, int reg,
u_short val));
-static int hme_tcvr_read __P((struct hme_softc *sc, int reg));
-static void hme_tcvr_bb_write __P((struct hme_softc *sc, int reg,
+static int hme_tcvr_read __P((struct hme_softc *, int reg));
+static void hme_tcvr_bb_write __P((struct hme_softc *, int reg,
u_short val));
-static int hme_tcvr_bb_read __P((struct hme_softc *sc, int reg));
-static void hme_tcvr_bb_writeb __P((struct hme_softc *sc, int b));
-static int hme_tcvr_bb_readb __P((struct hme_softc *sc));
-static void hme_tcvr_check __P((struct hme_softc *sc));
-static int hme_tcvr_reset __P((struct hme_softc *sc));
+static int hme_tcvr_bb_read __P((struct hme_softc *, int reg));
+static void hme_tcvr_bb_writeb __P((struct hme_softc *, int b));
+static int hme_tcvr_bb_readb __P((struct hme_softc *));
+static void hme_tcvr_check __P((struct hme_softc *));
+static int hme_tcvr_reset __P((struct hme_softc *));
static void hme_poll_stop __P((struct hme_softc *sc));
static int hme_mint __P((struct hme_softc *, u_int32_t));
-static int hme_tint __P((struct hme_softc *, u_int32_t));
-static int hme_rint __P((struct hme_softc *, u_int32_t));
static int hme_eint __P((struct hme_softc *, u_int32_t));
-static void hme_auto_negotiate __P((struct hme_softc *sc));
-static void hme_manual_negotiate __P((struct hme_softc *sc));
-static void hme_negotiate_watchdog __P((void *arg));
-static void hme_print_link_mode __P((struct hme_softc *sc));
-static void hme_set_initial_advertisement __P((struct hme_softc *sc));
+static void hme_auto_negotiate __P((struct hme_softc *));
+static void hme_manual_negotiate __P((struct hme_softc *));
+static void hme_negotiate_watchdog __P((void *));
+static void hme_print_link_mode __P((struct hme_softc *));
+static void hme_set_initial_advertisement __P((struct hme_softc *));
-static void hme_reset_rx __P((struct hme_softc *sc));
-static void hme_reset_tx __P((struct hme_softc *sc));
-static void hme_meminit __P((struct hme_softc *sc));
-
-static int hme_put __P((struct hme_softc *sc, int idx, struct mbuf *m));
-static struct mbuf *hme_get __P((struct hme_softc *sc, int idx, int len));
-static void hme_read __P((struct hme_softc *sc, int idx, int len));
+static void hme_reset_rx __P((struct hme_softc *));
+static void hme_reset_tx __P((struct hme_softc *));
+static void hme_tx_dmawakeup __P((void *v));
static void hme_mcreset __P((struct hme_softc *));
@@ -150,7 +145,7 @@ hmeattach(parent, self, aux)
{
struct confargs *ca = aux;
struct hme_softc *sc = (struct hme_softc *)self;
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ struct ifnet *ifp = &sc->sc_stp.stp_arpcom.ac_if;
int pri;
/* XXX the following declaration should be elsewhere */
extern void myetheraddr __P((u_char *));
@@ -189,11 +184,8 @@ hmeattach(parent, self, aux)
sc->sc_burst = ((struct sbus_softc *)parent)->sc_burst;
- sc->sc_desc_dva = (struct hme_desc *) dvma_malloc(
- sizeof(struct hme_desc), &(sc->sc_desc), M_NOWAIT);
- sc->sc_bufs_dva = (struct hme_bufs *) dvma_malloc(
- sizeof(struct hme_bufs) + RX_ALIGN_SIZE, &(sc->sc_bufs),
- M_NOWAIT); /* XXX must be aligned on 64 byte boundary */
+ sc->sc_stp.stp_tx_dmawakeup = hme_tx_dmawakeup;
+ stp2002_meminit(&sc->sc_stp);
hme_set_initial_advertisement(sc);
@@ -208,8 +200,8 @@ hmeattach(parent, self, aux)
* Otherwise, use the machine's builtin MAC.
*/
if (getprop(ca->ca_ra.ra_node, "local-mac-address",
- sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0) {
- myetheraddr(sc->sc_arpcom.ac_enaddr);
+ sc->sc_stp.stp_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0) {
+ myetheraddr(sc->sc_stp.stp_arpcom.ac_enaddr);
}
bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
@@ -228,7 +220,7 @@ hmeattach(parent, self, aux)
sc->sc_an_ticks = 0;
printf(" pri %d: address %s rev %d\n", pri,
- ether_sprintf(sc->sc_arpcom.ac_enaddr), sc->sc_rev);
+ ether_sprintf(sc->sc_stp.stp_arpcom.ac_enaddr), sc->sc_rev);
#if NBPFILTER > 0
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
@@ -248,55 +240,18 @@ void
hmestart(ifp)
struct ifnet *ifp;
{
- struct hme_softc *sc = ifp->if_softc;
- struct mbuf *m;
- int bix, len;
-
- if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
- return;
+ struct hme_softc *sc = (struct hme_softc *)ifp->if_softc;
- bix = sc->sc_last_td;
-
- for (;;) {
- IF_DEQUEUE(&ifp->if_snd, m);
- if (m == 0)
- break;
-#if NBPFILTER > 0
- /*
- * If BPF is listening on this interface, let it see the
- * packet before we commit it to the wire.
- */
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m);
-#endif
-
- /*
- * Copy the mbuf chain into the transmit buffer.
- */
- len = hme_put(sc, bix, m);
-
- /*
- * Initialize transmit registers and start transmission
- */
- sc->sc_desc->hme_txd[bix].tx_addr = (u_long) sc->sc_bufs_dva +
- (((u_long) &(sc->sc_bufs->tx_buf[bix])) -
- ((u_long) sc->sc_bufs));
- sc->sc_desc->hme_txd[bix].tx_flags =
- TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP |
- (len & TXFLAG_SIZE);
-
- sc->sc_txr->tx_pnding = TXR_TP_DMAWAKEUP;
-
- if (++bix == TX_RING_SIZE)
- bix = 0;
+ stp2002_start(&sc->sc_stp);
+}
- if (++sc->sc_no_td == TX_RING_SIZE) {
- ifp->if_flags |= IFF_OACTIVE;
- break;
- }
- }
+void
+hme_tx_dmawakeup(v)
+ void *v;
+{
+ struct hme_softc *sc = (struct hme_softc *)v;
- sc->sc_last_td = bix;
+ sc->sc_txr->tx_pnding = TXR_TP_DMAWAKEUP;
}
#define MAX_STOP_TRIES 16
@@ -340,7 +295,7 @@ hmewatchdog(ifp)
struct hme_softc *sc = ifp->if_softc;
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
- ++sc->sc_arpcom.ac_if.if_oerrors;
+ ++sc->sc_stp.stp_arpcom.ac_if.if_oerrors;
hmereset(sc);
}
@@ -358,7 +313,7 @@ hmeioctl(ifp, cmd, data)
s = splimp();
- if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
+ if ((error = ether_ioctl(ifp, &sc->sc_stp.stp_arpcom, cmd, data)) > 0) {
splx(s);
return error;
}
@@ -370,7 +325,7 @@ hmeioctl(ifp, cmd, data)
#ifdef INET
case AF_INET:
hmeinit(sc);
- arp_ifinit(&sc->sc_arpcom, ifa);
+ arp_ifinit(&sc->sc_stp.stp_arpcom, ifa);
break;
#endif /* INET */
#ifdef NS
@@ -381,11 +336,11 @@ hmeioctl(ifp, cmd, data)
if (ns_nullhost(*ina))
ina->x_host =
- *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
+ *(union ns_host *)(sc->sc_stp.stp_arpcom.ac_enaddr);
else
bcopy(ina->x_host.c_host,
- sc->sc_arpcom.ac_enaddr,
- sizeof(sc->sc_arpcom.ac_enaddr));
+ sc->sc_stp.stp_arpcom.ac_enaddr,
+ sizeof(sc->sc_stp.stp_arpcom.ac_enaddr));
/* Set new address. */
hmeinit(sc);
break;
@@ -433,8 +388,8 @@ hmeioctl(ifp, cmd, data)
case SIOCADDMULTI:
case SIOCDELMULTI:
error = (cmd == SIOCADDMULTI) ?
- ether_addmulti(ifr, &sc->sc_arpcom):
- ether_delmulti(ifr, &sc->sc_arpcom);
+ ether_addmulti(ifr, &sc->sc_stp.stp_arpcom):
+ ether_delmulti(ifr, &sc->sc_stp.stp_arpcom);
if (error == ENETRESET) {
/*
@@ -466,7 +421,7 @@ hmeinit(sc)
hme_poll_stop(sc);
hmestop(sc);
- hme_meminit(sc);
+ stp2002_meminit(&sc->sc_stp);
tcvr->int_mask = 0xffff;
@@ -493,14 +448,14 @@ hmeinit(sc)
hme_reset_tx(sc);
hme_reset_rx(sc);
- cr->rand_seed = sc->sc_arpcom.ac_enaddr[5] |
- ((sc->sc_arpcom.ac_enaddr[4] << 8) & 0x3f00);
- cr->mac_addr0 = (sc->sc_arpcom.ac_enaddr[0] << 8) |
- sc->sc_arpcom.ac_enaddr[1];
- cr->mac_addr1 = (sc->sc_arpcom.ac_enaddr[2] << 8) |
- sc->sc_arpcom.ac_enaddr[3];
- cr->mac_addr2 = (sc->sc_arpcom.ac_enaddr[4] << 8) |
- sc->sc_arpcom.ac_enaddr[5];
+ cr->rand_seed = sc->sc_stp.stp_arpcom.ac_enaddr[5] |
+ ((sc->sc_stp.stp_arpcom.ac_enaddr[4] << 8) & 0x3f00);
+ cr->mac_addr0 = (sc->sc_stp.stp_arpcom.ac_enaddr[0] << 8) |
+ sc->sc_stp.stp_arpcom.ac_enaddr[1];
+ cr->mac_addr1 = (sc->sc_stp.stp_arpcom.ac_enaddr[2] << 8) |
+ sc->sc_stp.stp_arpcom.ac_enaddr[3];
+ cr->mac_addr2 = (sc->sc_stp.stp_arpcom.ac_enaddr[4] << 8) |
+ sc->sc_stp.stp_arpcom.ac_enaddr[5];
cr->jsize = HME_DEFAULT_JSIZE;
cr->ipkt_gap1 = HME_DEFAULT_IPKT_GAP1;
@@ -510,12 +465,8 @@ hmeinit(sc)
cr->htable1 = 0;
cr->htable0 = 0;
- rxr->rx_ring = (u_long) sc->sc_desc_dva +
- (((u_long) &sc->sc_desc->hme_rxd[0])
- - ((u_long)sc->sc_desc));
- txr->tx_ring = (u_long) sc->sc_desc_dva +
- (((u_long) &sc->sc_desc->hme_txd[0])
- - ((u_long)sc->sc_desc));
+ rxr->rx_ring = sc->sc_stp.stp_rx_dvma;
+ txr->tx_ring = sc->sc_stp.stp_tx_dvma;
if (sc->sc_burst & SBUS_BURST_64)
gr->cfg = GR_CFG_BURST64;
@@ -531,20 +482,20 @@ hmeinit(sc)
gr->imask = GR_IMASK_SENTFRAME | GR_IMASK_TXPERR |
GR_IMASK_GOTFRAME | GR_IMASK_RCNTEXP;
- txr->tx_rsize = (TX_RING_SIZE >> TXR_RSIZE_SHIFT) - 1;
+ txr->tx_rsize = (STP_TX_RING_SIZE >> TXR_RSIZE_SHIFT) - 1;
txr->cfg |= TXR_CFG_DMAENABLE;
- c = RXR_CFG_DMAENABLE | (RX_OFFSET << 3) | (RX_CSUMLOC << 16);
-#if RX_RING_SIZE == 32
+ c = RXR_CFG_DMAENABLE | (STP_RX_OFFSET << 3) | (STP_RX_CSUMLOC << 16);
+#if STP_RX_RING_SIZE == 32
c |= RXR_CFG_RINGSIZE32;
-#elif RX_RING_SIZE == 64
+#elif STP_RX_RING_SIZE == 64
c |= RXR_CFG_RINGSIZE64;
-#elif RX_RING_SIZE == 128
+#elif STP_RX_RING_SIZE == 128
c |= RXR_CFG_RINGSIZE128;
-#elif RX_RING_SIZE == 256
+#elif STP_RX_RING_SIZE == 256
c |= RXR_CFG_RINGSIZE256;
#else
-#error "RX_RING_SIZE must be 32, 64, 128, or 256."
+#error "STP_RX_RING_SIZE must be 32, 64, 128, or 256."
#endif
rxr->cfg = c;
DELAY(20);
@@ -1032,7 +983,7 @@ hme_negotiate_watchdog(arg)
void *arg;
{
struct hme_softc *sc = (struct hme_softc *)arg;
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ struct ifnet *ifp = &sc->sc_stp.stp_arpcom.ac_if;
sc->sc_an_ticks++;
switch (sc->sc_an_state) {
@@ -1119,108 +1070,6 @@ hme_reset_rx(sc)
printf("%s: reset rx failed\n", sc->sc_dev.dv_xname);
}
-static void
-hme_meminit(sc)
- struct hme_softc *sc;
-{
- struct hme_desc *desc = sc->sc_desc;
- int i;
-
- /* setup tx descriptors */
- sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
- for (i = 0; i < TX_RING_SIZE; i++)
- desc->hme_txd[i].tx_flags = 0;
-
- /* setup rx descriptors */
- sc->sc_last_rd = 0;
- for (i = 0; i < RX_RING_SIZE; i++) {
-
- desc->hme_rxd[i].rx_addr = (u_long) sc->sc_bufs_dva +
- (((u_long) &(sc->sc_bufs->rx_buf[i])) -
- ((u_long) sc->sc_bufs));
-
- desc->hme_rxd[i].rx_flags =
- RXFLAG_OWN | ((RX_PKT_BUF_SZ - RX_OFFSET) << 16);
- }
-
-}
-
-/*
- * Pull data off an interface.
- * Len is the length of data, with local net header stripped.
- * We copy the data into mbufs. When full cluster sized units are present,
- * we copy into clusters.
- */
-static struct mbuf *
-hme_get(sc, idx, totlen)
- struct hme_softc *sc;
- int idx, totlen;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- struct mbuf *m;
- struct mbuf *top, **mp;
- int len, pad, boff = 0;
-
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return (NULL);
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = totlen;
- pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
- m->m_data += pad;
- len = MHLEN - pad;
- top = NULL;
- mp = &top;
-
- while (totlen > 0) {
- if (top) {
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
- m_freem(top);
- return NULL;
- }
- len = MLEN;
- }
- if (top && totlen >= MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if (m->m_flags & M_EXT)
- len = MCLBYTES;
- }
- m->m_len = len = min(totlen, len);
- bcopy(&(sc->sc_bufs->rx_buf[idx][boff + RX_OFFSET]),
- mtod(m, caddr_t), len);
- boff += len;
- totlen -= len;
- *mp = m;
- mp = &m->m_next;
- }
-
- return (top);
-}
-
-static int
-hme_put(sc, idx, m)
- struct hme_softc *sc;
- int idx;
- struct mbuf *m;
-{
- struct mbuf *n;
- int len, tlen = 0, boff = 0;
-
- for (; m; m = n) {
- len = m->m_len;
- if (len == 0) {
- MFREE(m, n);
- continue;
- }
- bcopy(mtod(m, caddr_t), &(sc->sc_bufs->tx_buf[idx][boff]), len);
- boff += len;
- tlen += len;
- MFREE(m, n);
- }
- return tlen;
-}
-
/*
* mif interrupt
*/
@@ -1247,45 +1096,6 @@ hme_mint(sc, why)
}
/*
- * receive interrupt
- */
-static int
-hme_rint(sc, why)
- struct hme_softc *sc;
- u_int32_t why;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- int bix, len;
- struct hme_rxd rxd;
-
- bix = sc->sc_last_rd;
-
- /* Process all buffers with valid data. */
- for (;;) {
- bcopy(&(sc->sc_desc->hme_rxd[bix]), &rxd, sizeof(rxd));
- len = rxd.rx_flags >> 16;
-
- if (rxd.rx_flags & RXFLAG_OWN)
- break;
-
- if (rxd.rx_flags & RXFLAG_OVERFLOW)
- ifp->if_ierrors++;
- else
- hme_read(sc, bix, len);
-
- rxd.rx_flags = RXFLAG_OWN|((RX_PKT_BUF_SZ - RX_OFFSET) << 16);
- bcopy(&rxd, &(sc->sc_desc->hme_rxd[bix]), sizeof(rxd));
-
- if (++bix == RX_RING_SIZE)
- bix = 0;
- }
-
- sc->sc_last_rd = bix;
-
- return 1;
-}
-
-/*
* error interrupt
*/
static int
@@ -1362,49 +1172,7 @@ hme_eint(sc, why)
}
/*
- * transmit interrupt
- */
-static int
-hme_tint(sc, why)
- struct hme_softc *sc;
- u_int32_t why;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- int bix;
- struct hme_txd txd;
-
- bix = sc->sc_first_td;
-
- for (;;) {
- if (sc->sc_no_td <= 0)
- break;
-
- bcopy(&(sc->sc_desc->hme_txd[bix]), &txd, sizeof(txd));
-
- if (txd.tx_flags & TXFLAG_OWN)
- break;
-
- ifp->if_flags &= ~IFF_OACTIVE;
- ifp->if_opackets++;
-
- if (++bix == TX_RING_SIZE)
- bix = 0;
-
- --sc->sc_no_td;
- }
-
- sc->sc_first_td = bix;
-
- hmestart(ifp);
-
- if (sc->sc_no_td == 0)
- ifp->if_timer = 0;
-
- return 1;
-}
-
-/*
- * Interrup handler
+ * Interrupt handler
*/
int
hmeintr(v)
@@ -1424,58 +1192,14 @@ hmeintr(v)
r |= hme_mint(sc, why);
if (why & (GR_STAT_TXALL | GR_STAT_HOSTTOTX))
- r |= hme_tint(sc, why);
+ r |= stp2002_tint(&sc->sc_stp);
if (why & GR_STAT_RXTOHOST)
- r |= hme_rint(sc, why);
+ r |= stp2002_rint(&sc->sc_stp);
return (r);
}
-static void
-hme_read(sc, idx, len)
- struct hme_softc *sc;
- int idx, len;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- struct ether_header *eh;
- struct mbuf *m;
-
- if (len <= sizeof(struct ether_header) ||
- len > ETHERMTU + sizeof(struct ether_header)) {
-
- printf("%s: invalid packet size %d; dropping\n",
- sc->sc_dev.dv_xname, len);
-
- ifp->if_ierrors++;
- return;
- }
-
- /* Pull packet off interface. */
- m = hme_get(sc, idx, len);
- if (m == NULL) {
- ifp->if_ierrors++;
- return;
- }
-
- ifp->if_ipackets++;
-
- /* We assume that the header fit entirely in one mbuf. */
- eh = mtod(m, struct ether_header *);
-
-#if NBPFILTER > 0
- /*
- * Check if there's a BPF listener on this interface.
- * If so, hand off the raw packet to BPF.
- */
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m);
-#endif
- /* Pass the packet up, with the ether header sort-of removed. */
- m_adj(m, sizeof(struct ether_header));
- ether_input(ifp, eh, m);
-}
-
/*
* Program the multicast receive filter.
*/
@@ -1483,8 +1207,8 @@ static void
hme_mcreset(sc)
struct hme_softc *sc;
{
- struct arpcom *ac = &sc->sc_arpcom;
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ struct arpcom *ac = &sc->sc_stp.stp_arpcom;
+ struct ifnet *ifp = &sc->sc_stp.stp_arpcom.ac_if;
struct hme_cr *cr = sc->sc_cr;
struct ether_multi *enm;
struct ether_multistep step;
diff --git a/sys/arch/sparc/dev/hmereg.h b/sys/arch/sparc/dev/hmereg.h
index 6fe9b0c9af1..ac5327dba67 100644
--- a/sys/arch/sparc/dev/hmereg.h
+++ b/sys/arch/sparc/dev/hmereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hmereg.h,v 1.3 1998/07/13 02:27:42 jason Exp $ */
+/* $OpenBSD: hmereg.h,v 1.4 1998/07/17 21:33:08 jason Exp $ */
/*
* Copyright (c) 1998 Jason L. Wright (jason@thought.net)
@@ -312,48 +312,6 @@ struct hme_tcvr {
#define TCVR_STAT_BASIC 0xffff0000 /* The "basic" part */
#define TCVR_STAT_NORMAL 0x0000ffff /* The "non-basic" part */
-struct hme_rxd {
- volatile u_int32_t rx_flags;
- volatile u_int32_t rx_addr;
-};
-#define RXFLAG_OWN 0x80000000 /* desc owner: 1=hw,0=sw */
-#define RXFLAG_OVERFLOW 0x40000000 /* 1 = buffer over flow */
-#define RXFLAG_SIZE 0x3fff0000 /* desciptor size */
-#define RXFLAG_CSUM 0x0000ffff /* checksum mask */
-
-struct hme_txd {
- volatile u_int32_t tx_flags;
- volatile u_int32_t tx_addr;
-};
-#define TXFLAG_OWN 0x80000000 /* desc owner: 1=hw,0=sw */
-#define TXFLAG_SOP 0x40000000 /* 1 = start of pkt */
-#define TXFLAG_EOP 0x20000000 /* 1 = end of pkt */
-#define TXFLAG_CSENABLE 0x10000000 /* 1 = use hw checksums */
-#define TXFLAG_CSLOCATION 0x0ff00000 /* checksum location mask */
-#define TXFLAG_CSBUFBEGIN 0x000fc000 /* checksum begin mask */
-#define TXFLAG_SIZE 0x00003fff /* pkt size mask */
-
-#define RX_RING_SIZE 32 /* Must be 32, 64, 128, or 256 */
-#define TX_RING_SIZE 32 /* Must be 16<=x<=255, and divisible by 16 */
-#define RX_RING_MAX 256 /* maximum ring size: rx */
-#define TX_RING_MAX 256 /* maximum ring size: tx */
-#define RX_PKT_BUF_SZ 2048 /* size of a rx buffer */
-#define RX_OFFSET 2 /* packet offset */
-#define RX_CSUMLOC 0x00 /* checksum location */
-#define TX_PKT_BUF_SZ 1546 /* size of a tx buffer */
-#define RX_ALIGN_SIZE 64 /* rx packet buffers must align on 64 bytes */
-#define RX_ALIGN_MASK (~(RX_ALIGN_SIZE - 1))
-
-struct hme_desc {
- struct hme_rxd hme_rxd[RX_RING_MAX];
- struct hme_txd hme_txd[TX_RING_MAX];
-};
-
-struct hme_bufs {
- char rx_buf[RX_RING_SIZE][RX_PKT_BUF_SZ];
- char tx_buf[TX_RING_SIZE][TX_PKT_BUF_SZ];
-};
-
/* hme flags */
#define HME_FLAG_POLL 0x00000001 /* polling mif? */
#define HME_FLAG_FENABLE 0x00000002 /* MII frame enabled? */
diff --git a/sys/arch/sparc/dev/hmevar.h b/sys/arch/sparc/dev/hmevar.h
index cfc44033062..8f18d2a76dd 100644
--- a/sys/arch/sparc/dev/hmevar.h
+++ b/sys/arch/sparc/dev/hmevar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hmevar.h,v 1.1 1998/07/10 19:09:12 jason Exp $ */
+/* $OpenBSD: hmevar.h,v 1.2 1998/07/17 21:33:10 jason Exp $ */
/*
* Copyright (c) 1998 Jason L. Wright (jason@thought.net)
@@ -33,7 +33,6 @@
struct hme_softc {
struct device sc_dev; /* base device */
- struct arpcom sc_arpcom; /* ethernet common */
struct sbusdev sc_sd; /* sbus device */
struct intrhand sc_ih; /* interrupt vectoring */
int sc_node; /* which sbus node */
@@ -61,8 +60,5 @@ struct hme_softc {
/*
* RX/TX ring buffers, descriptors, and counters
*/
- struct hme_desc *sc_desc, *sc_desc_dva; /* descriptors */
- struct hme_bufs *sc_bufs, *sc_bufs_dva; /* buffers */
- int sc_first_td, sc_last_td, sc_no_td; /* tx counters */
- int sc_last_rd; /* rx counter */
+ struct stp_base sc_stp;
};
diff --git a/sys/arch/sparc/dev/stp2002base.c b/sys/arch/sparc/dev/stp2002base.c
new file mode 100644
index 00000000000..eb8524f5252
--- /dev/null
+++ b/sys/arch/sparc/dev/stp2002base.c
@@ -0,0 +1,386 @@
+/* $OpenBSD: stp2002base.c,v 1.1 1998/07/17 21:33:11 jason Exp $ */
+
+/*
+ * Copyright (c) 1998 Jason L. Wright (jason@thought.net)
+ * 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 Jason L. Wright
+ * 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 STP2002QFP chips found in both the hme and qec+be ethernet
+ * controllers.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <sparc/dev/stp2002var.h>
+
+static struct mbuf *stp2002_get __P((struct stp_base *, int, int));
+static int stp2002_put __P((struct stp_base *, int, struct mbuf *));
+static void stp2002_read __P((struct stp_base *, int, int));
+
+/*
+ * Allocate and initialize buffers and descriptor rings
+ */
+void
+stp2002_meminit(stp)
+ struct stp_base *stp;
+{
+ struct stp_desc *desc;
+ int i;
+
+ if (stp->stp_desc_dva == NULL)
+ stp->stp_desc_dva = (struct stp_desc *) dvma_malloc(
+ sizeof(struct stp_desc), &(stp->stp_desc), M_NOWAIT);
+
+ if (stp->stp_bufs_dva == NULL)
+ stp->stp_bufs_dva = (struct stp_bufs *) dvma_malloc(
+ sizeof(struct stp_bufs) + STP_RX_ALIGN_SIZE,
+ &(stp->stp_bufs),
+ M_NOWAIT); /* XXX must be aligned on 64 byte boundary */
+
+
+ stp->stp_rx_dvma = (u_long) stp->stp_desc_dva +
+ (((u_long) &stp->stp_desc->stp_rxd[0]) - ((u_long)stp->stp_desc));
+ stp->stp_tx_dvma = (u_long) stp->stp_desc_dva +
+ (((u_long) &stp->stp_desc->stp_txd[0]) - ((u_long)stp->stp_desc));
+
+ desc = stp->stp_desc;
+
+ /* setup tx descriptors */
+ stp->stp_first_td = stp->stp_last_td = stp->stp_no_td = 0;
+ for (i = 0; i < STP_TX_RING_SIZE; i++)
+ desc->stp_txd[i].tx_flags = 0;
+
+ /* setup rx descriptors */
+ stp->stp_last_rd = 0;
+ for (i = 0; i < STP_RX_RING_SIZE; i++) {
+ desc->stp_rxd[i].rx_addr = (u_long) stp->stp_bufs_dva +
+ (((u_long) &(stp->stp_bufs->rx_buf[i])) -
+ ((u_long) stp->stp_bufs));
+ desc->stp_rxd[i].rx_flags =
+ STP_RXFLAG_OWN |
+ ((STP_RX_PKT_BUF_SZ - STP_RX_OFFSET) << 16);
+ }
+}
+
+/*
+ * Pull data off an interface.
+ * Len is the length of data, with local net header stripped.
+ * We copy the data into mbufs. When full cluster sized units are present,
+ * we copy into clusters.
+ */
+static struct mbuf *
+stp2002_get(stp, idx, totlen)
+ struct stp_base *stp;
+ int idx, totlen;
+{
+ struct ifnet *ifp = &stp->stp_arpcom.ac_if;
+ struct mbuf *m;
+ struct mbuf *top, **mp;
+ int len, pad, boff = 0;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL)
+ return (NULL);
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = totlen;
+ pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
+ m->m_data += pad;
+ len = MHLEN - pad;
+ top = NULL;
+ mp = &top;
+
+ while (totlen > 0) {
+ if (top) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+ m_freem(top);
+ return NULL;
+ }
+ len = MLEN;
+ }
+ if (top && totlen >= MINCLSIZE) {
+ MCLGET(m, M_DONTWAIT);
+ if (m->m_flags & M_EXT)
+ len = MCLBYTES;
+ }
+ m->m_len = len = min(totlen, len);
+ bcopy(&(stp->stp_bufs->rx_buf[idx][boff + STP_RX_OFFSET]),
+ mtod(m, caddr_t), len);
+ boff += len;
+ totlen -= len;
+ *mp = m;
+ mp = &m->m_next;
+ }
+
+ return (top);
+}
+
+static int
+stp2002_put(stp, idx, m)
+ struct stp_base *stp;
+ int idx;
+ struct mbuf *m;
+{
+ struct mbuf *n;
+ int len, tlen = 0, boff = 0;
+
+ for (; m; m = n) {
+ len = m->m_len;
+ if (len == 0) {
+ MFREE(m, n);
+ continue;
+ }
+ bcopy(mtod(m, caddr_t), &(stp->stp_bufs->tx_buf[idx][boff]), len);
+ boff += len;
+ tlen += len;
+ MFREE(m, n);
+ }
+ return tlen;
+}
+
+/*
+ * receive interrupt
+ */
+int
+stp2002_rint(stp)
+ struct stp_base *stp;
+{
+ struct ifnet *ifp = &stp->stp_arpcom.ac_if;
+ int bix, len;
+ struct stp_rxd rxd;
+
+ bix = stp->stp_last_rd;
+
+ /* Process all buffers with valid data. */
+ for (;;) {
+ bcopy(&(stp->stp_desc->stp_rxd[bix]), &rxd, sizeof(rxd));
+ len = rxd.rx_flags >> 16;
+
+ if (rxd.rx_flags & STP_RXFLAG_OWN)
+ break;
+
+ if (rxd.rx_flags & STP_RXFLAG_OVERFLOW)
+ ifp->if_ierrors++;
+ else
+ stp2002_read(stp, bix, len);
+
+ rxd.rx_flags = STP_RXFLAG_OWN |
+ ((STP_RX_PKT_BUF_SZ - STP_RX_OFFSET) << 16);
+ bcopy(&rxd, &(stp->stp_desc->stp_rxd[bix]), sizeof(rxd));
+
+ if (++bix == STP_RX_RING_SIZE)
+ bix = 0;
+ }
+
+ stp->stp_last_rd = bix;
+
+ return 1;
+}
+
+/*
+ * transmit interrupt
+ */
+int
+stp2002_tint(stp)
+ struct stp_base *stp;
+{
+ struct ifnet *ifp = &stp->stp_arpcom.ac_if;
+ int bix;
+ struct stp_txd txd;
+
+ bix = stp->stp_first_td;
+
+ for (;;) {
+ if (stp->stp_no_td <= 0)
+ break;
+
+ bcopy(&(stp->stp_desc->stp_txd[bix]), &txd, sizeof(txd));
+
+ if (txd.tx_flags & STP_TXFLAG_OWN)
+ break;
+
+ ifp->if_flags &= ~IFF_OACTIVE;
+ ifp->if_opackets++;
+
+ if (++bix == STP_TX_RING_SIZE)
+ bix = 0;
+
+ --stp->stp_no_td;
+ }
+
+ stp->stp_first_td = bix;
+
+ stp2002_start(stp);
+
+ if (stp->stp_no_td == 0)
+ ifp->if_timer = 0;
+
+ return 1;
+}
+
+/*
+ * Start output on interface.
+ * We make two assumptions here:
+ * 1) that the current priority is set to splnet _before_ this code
+ * is called *and* is returned to the appropriate priority after
+ * return
+ * 2) that the IFF_OACTIVE flag is checked before this code is called
+ * (i.e. that the output part of the interface is idle)
+ *
+ * This function returns 1 if at least one packet has been placed in the
+ * descriptor ring, and 0 otherwise. The intent is that upon return, the
+ * caller can conditionally wake up the DMA engine.
+ */
+void
+stp2002_start(stp)
+ struct stp_base *stp;
+{
+ struct ifnet *ifp = &stp->stp_arpcom.ac_if;
+ struct mbuf *m;
+ int bix, len;
+
+ if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
+ return;
+
+ bix = stp->stp_last_td;
+
+ for (;;) {
+ IF_DEQUEUE(&ifp->if_snd, m);
+ if (m == 0)
+ break;
+#if NBPFILTER > 0
+ /*
+ * If BPF is listening on this interface, let it see the
+ * packet before we commit it to the wire.
+ */
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+
+ /*
+ * Copy the mbuf chain into the transmit buffer.
+ */
+ len = stp2002_put(stp, bix, m);
+
+ /*
+ * Initialize transmit registers and start transmission
+ */
+ stp->stp_desc->stp_txd[bix].tx_addr = (u_long) stp->stp_bufs_dva +
+ (((u_long) &(stp->stp_bufs->tx_buf[bix])) -
+ ((u_long) stp->stp_bufs));
+ stp->stp_desc->stp_txd[bix].tx_flags =
+ STP_TXFLAG_OWN | STP_TXFLAG_SOP | STP_TXFLAG_EOP |
+ (len & STP_TXFLAG_SIZE);
+
+ (*stp->stp_tx_dmawakeup)(ifp->if_softc);
+
+ if (++bix == STP_TX_RING_SIZE)
+ bix = 0;
+
+ if (++stp->stp_no_td == STP_TX_RING_SIZE) {
+ ifp->if_flags |= IFF_OACTIVE;
+ break;
+ }
+ }
+
+ stp->stp_last_td = bix;
+}
+
+static void
+stp2002_read(stp, idx, len)
+ struct stp_base *stp;
+ int idx, len;
+{
+ struct ifnet *ifp = &stp->stp_arpcom.ac_if;
+ struct ether_header *eh;
+ struct mbuf *m;
+
+ if (len <= sizeof(struct ether_header) ||
+ len > ETHERMTU + sizeof(struct ether_header)) {
+
+ printf("%s: invalid packet size %d; dropping\n",
+ ifp->if_xname, len);
+
+ ifp->if_ierrors++;
+ return;
+ }
+
+ /* Pull packet off interface. */
+ m = stp2002_get(stp, idx, len);
+ if (m == NULL) {
+ ifp->if_ierrors++;
+ return;
+ }
+
+ ifp->if_ipackets++;
+
+ /* We assume that the header fit entirely in one mbuf. */
+ eh = mtod(m, struct ether_header *);
+
+#if NBPFILTER > 0
+ /*
+ * Check if there's a BPF listener on this interface.
+ * If so, hand off the raw packet to BPF.
+ */
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+ /* Pass the packet up, with the ether header sort-of removed. */
+ m_adj(m, sizeof(struct ether_header));
+ ether_input(ifp, eh, m);
+}
diff --git a/sys/arch/sparc/dev/stp2002var.h b/sys/arch/sparc/dev/stp2002var.h
new file mode 100644
index 00000000000..58a98d99875
--- /dev/null
+++ b/sys/arch/sparc/dev/stp2002var.h
@@ -0,0 +1,92 @@
+/* $OpenBSD: stp2002var.h,v 1.1 1998/07/17 21:33:11 jason Exp $ */
+
+/*
+ * Copyright (c) 1998 Jason L. Wright (jason@thought.net)
+ * 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 Jason L. Wright
+ * 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.
+ */
+
+struct stp_rxd {
+ volatile u_int32_t rx_flags;
+ volatile u_int32_t rx_addr;
+};
+#define STP_RXFLAG_OWN 0x80000000 /* desc owner: 1=hw,0=sw */
+#define STP_RXFLAG_OVERFLOW 0x40000000 /* 1 = buffer over flow */
+#define STP_RXFLAG_SIZE 0x3fff0000 /* desciptor size */
+#define STP_RXFLAG_CSUM 0x0000ffff /* checksum mask */
+
+struct stp_txd {
+ volatile u_int32_t tx_flags;
+ volatile u_int32_t tx_addr;
+};
+#define STP_TXFLAG_OWN 0x80000000 /* desc owner: 1=hw,0=sw */
+#define STP_TXFLAG_SOP 0x40000000 /* 1 = start of pkt */
+#define STP_TXFLAG_EOP 0x20000000 /* 1 = end of pkt */
+#define STP_TXFLAG_CSENABLE 0x10000000 /* 1 = use hw checksums */
+#define STP_TXFLAG_CSLOCATION 0x0ff00000 /* checksum location mask */
+#define STP_TXFLAG_CSBUFBEGIN 0x000fc000 /* checksum begin mask */
+#define STP_TXFLAG_SIZE 0x00003fff /* pkt size mask */
+
+#define STP_RX_RING_SIZE 32 /* Must be 32, 64, 128, or 256 */
+#define STP_TX_RING_SIZE 32 /* 16<=x<=256 and divisible by 16 */
+#define STP_RX_RING_MAX 256 /* maximum ring size: rx */
+#define STP_TX_RING_MAX 256 /* maximum ring size: tx */
+#define STP_RX_PKT_BUF_SZ 2048 /* size of a rx buffer */
+#define STP_RX_OFFSET 2 /* packet offset */
+#define STP_RX_CSUMLOC 0x00 /* checksum location */
+#define STP_TX_PKT_BUF_SZ 1546 /* size of a tx buffer */
+#define STP_RX_ALIGN_SIZE 64 /* rx buffers must align 64 XXX */
+#define STP_RX_ALIGN_MASK (~(RX_ALIGN_SIZE - 1))
+
+struct stp_desc {
+ struct stp_rxd stp_rxd[STP_RX_RING_MAX];
+ struct stp_txd stp_txd[STP_TX_RING_MAX];
+};
+
+struct stp_bufs {
+ char rx_buf[STP_RX_RING_SIZE][STP_RX_PKT_BUF_SZ];
+ char tx_buf[STP_TX_RING_SIZE][STP_TX_PKT_BUF_SZ];
+};
+
+struct stp_base {
+ /* public members */
+ struct arpcom stp_arpcom; /* ethernet common */
+ u_long stp_rx_dvma, stp_tx_dvma; /* ring dva pointers */
+ void (*stp_tx_dmawakeup) __P((void *)); /* func to start tx */
+
+ /* internal use */
+ struct stp_desc *stp_desc, *stp_desc_dva; /* ring descriptors */
+ struct stp_bufs *stp_bufs, *stp_bufs_dva; /* packet buffers */
+ int stp_first_td, stp_last_td, stp_no_td; /* tx counters */
+ int stp_last_rd; /* rx counters */
+};
+
+void stp2002_meminit __P((struct stp_base *));
+int stp2002_rint __P((struct stp_base *));
+int stp2002_tint __P((struct stp_base *));
+void stp2002_start __P((struct stp_base *));