diff options
author | Jason Wright <jason@cvs.openbsd.org> | 1998-07-17 21:33:12 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 1998-07-17 21:33:12 +0000 |
commit | dea46a95aecc2f88c901f933c4c3370264eb6fe2 (patch) | |
tree | a18bb0b6db9d95b73e9f2b69e34893a388511e9f /sys/arch/sparc/dev/hme.c | |
parent | ec887d96c4d670aa2d9e143581e4b658b8069bc0 (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.c | 412 |
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 = ⊤ - - 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; |