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 | |
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')
-rw-r--r-- | sys/arch/sparc/conf/files.sparc | 14 | ||||
-rw-r--r-- | sys/arch/sparc/dev/hme.c | 412 | ||||
-rw-r--r-- | sys/arch/sparc/dev/hmereg.h | 44 | ||||
-rw-r--r-- | sys/arch/sparc/dev/hmevar.h | 8 | ||||
-rw-r--r-- | sys/arch/sparc/dev/stp2002base.c | 386 | ||||
-rw-r--r-- | sys/arch/sparc/dev/stp2002var.h | 92 |
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 = ⊤ - - 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 = ⊤ + + 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 *)); |