diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2001-04-12 20:36:07 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2001-04-12 20:36:07 +0000 |
commit | a3be44ce73188d085c6245b4ffff1ad0f96738bf (patch) | |
tree | 3f74c10b55aa79982ed28847081bf6072eab5e9e /sys | |
parent | e57cfb6e67a9083afbbf8ef90cc40f20f3cc0cae (diff) |
- complete rewrite of transmit routines (these really work, but need
optimization)
- add in IFF_OACTIVE and if_timer handling
status: firmware, boot, media, and transmit working
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_txp.c | 179 |
1 files changed, 66 insertions, 113 deletions
diff --git a/sys/dev/pci/if_txp.c b/sys/dev/pci/if_txp.c index fcf6954a748..ef70e09659c 100644 --- a/sys/dev/pci/if_txp.c +++ b/sys/dev/pci/if_txp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_txp.c,v 1.13 2001/04/12 15:01:19 jason Exp $ */ +/* $OpenBSD: if_txp.c,v 1.14 2001/04/12 20:36:06 jason Exp $ */ /* * Copyright (c) 2001 @@ -118,7 +118,6 @@ void txp_rsp_fixup __P((struct txp_softc *, struct txp_rsp_desc *)); void txp_ifmedia_sts __P((struct ifnet *, struct ifmediareq *)); int txp_ifmedia_upd __P((struct ifnet *)); void txp_show_descriptor __P((void *)); -int txp_encap __P((struct txp_softc *, struct txp_tx_ring *, struct mbuf *, u_int32_t *, u_int32_t *, u_int32_t *)); void txp_tx_reclaim __P((struct txp_softc *, struct txp_tx_ring *, u_int32_t)); struct cfattach txp_ca = { @@ -555,30 +554,33 @@ txp_tx_reclaim(sc, r, off) struct txp_tx_ring *r; u_int32_t off; { - u_int32_t i = r->r_cons, idx = TXP_OFFSET2IDX(off), cnt = r->r_cnt; - struct txp_tx_desc *txd = &r->r_desc[i]; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + u_int32_t idx = TXP_OFFSET2IDX(off); + struct txp_tx_desc *txd; struct mbuf *m; - while (i != idx) { - if (cnt == 0) + while (r->r_cons != idx) { + if (r->r_cnt == 0) break; + + txd = &r->r_desc[r->r_cons]; + r->r_cons = (r->r_cons + 1) % TX_ENTRIES; + r->r_cnt--; + if ((txd->tx_flags & TX_FLAGS_TYPE_M) == TX_FLAGS_TYPE_DATA) { - bcopy(&txd->tx_addrlo, &m, sizeof(struct mbuf *)); - if (m != NULL) + m = (struct mbuf *)txd->tx_addrlo; + if (m != NULL) { m_freem(m); - bzero(txd, sizeof(*txd)); + txd->tx_addrlo = 0; + ifp->if_opackets++; + } } - cnt--; - - if (++i == TX_ENTRIES) { - i = 0; - txd = r->r_desc; - } else - txd++; + ifp->if_flags &= ~IFF_OACTIVE; } - r->r_cons = i; - r->r_cnt = cnt; + + if (r->r_cnt == 0) + ifp->if_timer = 0; } void @@ -928,6 +930,7 @@ txp_init(sc) ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; + ifp->if_timer = 0; splx(s); } @@ -938,125 +941,75 @@ txp_start(ifp) struct ifnet *ifp; { struct txp_softc *sc = ifp->if_softc; - struct txp_tx_ring *r; + struct txp_tx_ring *r = &sc->sc_txhir; struct txp_tx_desc *txd; + struct txp_frag_desc *fxd; struct mbuf *m; - u_int32_t bix, totlen, cnt; + u_int32_t firstprod, firstcnt; if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) return; - r = &sc->sc_txhir; - bix = r->r_prod; - - while ((TX_ENTRIES - r->r_cnt) > 4) { - IF_DEQUEUE(&ifp->if_snd, m); + while (1) { + IF_DEQUEUE(&ifp->if_snd, m); /* no mbufs */ if (m == NULL) 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 - - txd = &r->r_desc[bix]; - if (++bix == TX_ENTRIES) - bix = 0; - - r->r_cnt++; - - if (txp_encap(sc, &sc->sc_txhir, m, &bix, &totlen, &cnt)) { - if (bix == 0) - bix = TX_ENTRIES; - bix--; - r->r_cnt--; - IF_PREPEND(&ifp->if_snd, m); + if ((TX_ENTRIES - r->r_cnt) < 4) { ifp->if_flags |= IFF_OACTIVE; break; } - bzero(txd, sizeof(*txd)); - txd->tx_flags = TX_FLAGS_TYPE_DATA; - txd->tx_totlen = totlen; - txd->tx_numdesc = cnt; - /* stash mbuf * in the descriptor */ - bcopy(&m, &txd->tx_addrlo, sizeof(struct mbuf *)); - - /* Kick the txp */ - WRITE_REG(sc, r->r_reg, TXP_IDX2OFFSET(bix)); + firstprod = r->r_prod; + firstcnt = r->r_cnt; - if (++bix == TX_ENTRIES) - bix = 0; - } - - r->r_prod = bix; -} - -int -txp_encap(sc, r, mhead, bixp, totlenp, cntp) - struct txp_softc *sc; - struct txp_tx_ring *r; - struct mbuf *mhead; - u_int32_t *bixp, *totlenp, *cntp; -{ - struct mbuf *m; - struct txp_frag_desc *fd; - u_int32_t cnt = 0, cur, frag, totlen = 0; - u_int64_t addr; - - cur = frag = *bixp; - fd = (struct txp_frag_desc *)&r->r_desc[frag]; - m = mhead; - - while (m != NULL) { - if (m->m_len == 0) { - m = m->m_next; - continue; + txd = &r->r_desc[r->r_prod]; + r->r_prod = (r->r_prod + 1) % TX_ENTRIES; + r->r_cnt++; + if (r->r_cnt == (TX_ENTRIES - 4)) { + goto oactive; } - totlen += m->m_len; + txd->tx_flags = TX_FLAGS_TYPE_DATA; + txd->tx_numdesc = 0; + txd->tx_addrlo = (u_int32_t)m; + txd->tx_addrhi = 0; + txd->tx_totlen = 0; + txd->tx_pflags = 0; + + while (m != NULL) { + if (m->m_len == 0) { + m = m->m_next; + continue; + } - if ((TX_ENTRIES - (r->r_cnt + cnt)) < 4) - goto err; + txd->tx_numdesc++; - bzero(fd, sizeof(*fd)); - fd->frag_flags = FRAG_FLAGS_TYPE_FRAG; - addr = vtophys(m->m_data); - fd->frag_addrlo = addr & 0xffffffff; - fd->frag_addrhi = addr >> 32; - fd->frag_len = m->m_len; + fxd = (struct txp_frag_desc *)&r->r_desc[r->r_prod]; + r->r_prod = (r->r_prod + 1) % TX_ENTRIES; + r->r_cnt++; + if (r->r_cnt == (TX_ENTRIES - 4)) + goto oactive; - cur = frag; - cnt++; - frag++; - if (frag == TX_ENTRIES) { - frag = 0; - fd = (struct txp_frag_desc *)r->r_desc; - } else { - fd++; + fxd->frag_flags = FRAG_FLAGS_TYPE_FRAG; + fxd->frag_rsvd1 = 0; + fxd->frag_len = m->m_len; + fxd->frag_addrlo = vtophys(m->m_data); + fxd->frag_addrhi = 0; + fxd->frag_rsvd2 = 0; + m = m->m_next; } - m = m->m_next; + ifp->if_timer = 5; + WRITE_REG(sc, r->r_reg, TXP_IDX2OFFSET(r->r_prod)); } - *bixp = frag; - *totlenp = totlen; - *cntp = cnt; - r->r_cnt += cnt; - return (0); - -err: - for (; cnt > 0; cnt--) { - if (frag == 0) - frag = TX_ENTRIES; - frag--; - } + return; - return (ENOBUFS); +oactive: + ifp->if_flags |= IFF_OACTIVE; + r->r_prod = firstprod; + r->r_cnt = firstcnt; } /* |