summaryrefslogtreecommitdiff
path: root/sys/arch/sparc/dev/hme.c
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/arch/sparc/dev/hme.c
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/arch/sparc/dev/hme.c')
-rw-r--r--sys/arch/sparc/dev/hme.c412
1 files changed, 68 insertions, 344 deletions
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;