diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2001-04-13 17:50:31 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2001-04-13 17:50:31 +0000 |
commit | 176cd6a2a5ea9b6a4efabf0893ae3b156904c713 (patch) | |
tree | 10af0984e0c77a429d0aa120571de16685925a2c /sys/dev | |
parent | f5aa3b21385f08174b4815bc04668b1cbff49962 (diff) |
- rx buffer ring management (working)
- simplify/encapsulate fully transmit ring handling
- initialize sc_xcvr to be auto
- initial rx descriptor ring handling (doesn't work yet)
status: firmware, boot, media, tx, and rx buffer management work
(actual received frames don't... yet).
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_txp.c | 136 | ||||
-rw-r--r-- | sys/dev/pci/if_txpreg.h | 12 |
2 files changed, 124 insertions, 24 deletions
diff --git a/sys/dev/pci/if_txp.c b/sys/dev/pci/if_txp.c index cafb959d8e7..4fe7c6450a4 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.15 2001/04/12 22:40:12 jason Exp $ */ +/* $OpenBSD: if_txp.c,v 1.16 2001/04/13 17:50:30 jason Exp $ */ /* * Copyright (c) 2001 @@ -39,6 +39,7 @@ */ #include "bpfilter.h" +#include "vlan.h" #include <sys/param.h> #include <sys/systm.h> @@ -68,6 +69,10 @@ #include <net/bpf.h> #endif +#if NVLAN > 0 +#include <net/if_vlan_var.h> +#endif + #include <vm/vm.h> /* for vtophys */ #include <vm/pmap.h> /* for vtophys */ #include <vm/vm_kern.h> @@ -118,8 +123,9 @@ 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 *)); -void txp_tx_reclaim __P((struct txp_softc *, struct txp_tx_ring *, u_int32_t)); +void txp_tx_reclaim __P((struct txp_softc *, struct txp_tx_ring *)); void txp_rxbuf_claim __P((struct txp_softc *)); +void txp_rx_reclaim __P((struct txp_softc *, struct txp_rx_ring *)); struct cfattach txp_ca = { sizeof(struct txp_softc), txp_probe, txp_attach, @@ -243,9 +249,11 @@ txp_attach(parent, self, aux) ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX|IFM_HDX, 0, NULL); ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); - ifmedia_set(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO); + + sc->sc_xcvr = TXP_XCVR_AUTO; txp_command(sc, TXP_CMD_XCVR_SELECT, TXP_XCVR_AUTO, 0, 0, NULL, NULL, NULL, 0); + ifmedia_set(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO); ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; @@ -516,7 +524,6 @@ txp_intr(vsc) void *vsc; { struct txp_softc *sc = vsc; - struct txp_hostvar *hv = sc->sc_hostvar; u_int32_t isr; int claimed = 0; @@ -532,9 +539,11 @@ txp_intr(vsc) claimed = 1; WRITE_REG(sc, TXP_ISR, isr); + txp_rx_reclaim(sc, &sc->sc_rxhir); + txp_rx_reclaim(sc, &sc->sc_rxlor); txp_rxbuf_claim(sc); - txp_tx_reclaim(sc, &sc->sc_txhir, hv->hv_tx_hi_desc_read_idx); - txp_tx_reclaim(sc, &sc->sc_txlor, hv->hv_tx_lo_desc_read_idx); + txp_tx_reclaim(sc, &sc->sc_txhir); + txp_tx_reclaim(sc, &sc->sc_txlor); isr = READ_REG(sc, TXP_ISR); } @@ -548,16 +557,87 @@ txp_intr(vsc) } void +txp_rx_reclaim(sc, r) + struct txp_softc *sc; + struct txp_rx_ring *r; +{ + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + struct txp_rx_desc *rxd; + struct ether_header *eh; + struct mbuf *m; + u_int32_t i, end; + + i = (*r->r_roff) / sizeof(struct txp_rx_desc); + end = (*r->r_woff) / sizeof(struct txp_rx_desc); + + while (i != end) { + printf("%s: rxd %u\n", sc->sc_dev.dv_xname, i); + + rxd = &r->r_desc[i]; + + if (rxd->rx_flags & RX_FLAGS_ERROR) { + printf("%s: error 0x%x\n", sc->sc_dev.dv_xname, + rxd->rx_stat); + ifp->if_ierrors++; + goto next; + } + + m = (struct mbuf *)rxd->rx_vaddrlo; + m->m_len = rxd->rx_len; + + + eh = mtod(m, struct ether_header *); + ifp->if_ipackets++; + +#if NBPFILTER > 0 + /* + * Handle BPF listeners. Let the BPF user see the packet. + */ + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m); +#endif + + m_adj(m, sizeof(struct ether_header)); + + if (rxd->rx_stat & RX_STAT_VLAN) { + printf("%s: vlan tag 0x%x\n", sc->sc_dev.dv_xname, + rxd->rx_vlan); +#if NVLAN > 0 + if (vlan_input_tag(eh, m, rxd->rx_stat & 0xffff) < 0) + ifp->if_data.ifi_noproto++; +#else + m_freem(m); +#endif + goto next; + } + + + ether_input(ifp, eh, m); + +next: + *r->r_roff = i * sizeof(struct txp_rx_desc); + + if (++i == RX_ENTRIES) + i = 0; + } + +} + +void txp_rxbuf_claim(sc) struct txp_softc *sc; { + struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct txp_hostvar *hv = sc->sc_hostvar; struct txp_rxbuf_desc *rbd; struct mbuf *m; u_int32_t i, end; - i = TXP_OFFSET2IDX(hv->hv_rx_buf_read_idx); - end = TXP_OFFSET2IDX(hv->hv_rx_buf_write_idx); + end = TXP_OFFSET2IDX(hv->hv_rx_buf_read_idx); + i = TXP_OFFSET2IDX(hv->hv_rx_buf_write_idx); + + if (++i == RXBUF_ENTRIES) + i = 0; while (i != end) { rbd = &sc->sc_rxbufs[i]; @@ -575,32 +655,30 @@ txp_rxbuf_claim(sc) sc->sc_dev.dv_xname); break; } - - printf("%s: rxbuf claim\n", i); + m->m_pkthdr.rcvif = ifp; rbd->rb_vaddrlo = (u_int32_t)m; rbd->rb_vaddrhi = 0; - rbd->rb_paddrlo = vtophys(m->m_data); + rbd->rb_paddrlo = vtophys(m->m_data + 2); rbd->rb_paddrhi = 0; + hv->hv_rx_buf_write_idx = TXP_IDX2OFFSET(i); + if (++i == RXBUF_ENTRIES) i = 0; } - - hv->hv_rx_buf_write_idx = TXP_IDX2OFFSET(i); } /* * Reclaim mbufs and entries from a transmit ring. */ void -txp_tx_reclaim(sc, r, off) +txp_tx_reclaim(sc, r) struct txp_softc *sc; struct txp_tx_ring *r; - u_int32_t off; { struct ifnet *ifp = &sc->sc_arpcom.ac_if; - u_int32_t idx = TXP_OFFSET2IDX(off); + u_int32_t idx = TXP_OFFSET2IDX(*(r->r_off)); struct txp_tx_desc *txd; struct mbuf *m; @@ -649,6 +727,7 @@ int txp_alloc_rings(sc) struct txp_softc *sc; { + struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct txp_boot_record *boot; u_int32_t r; int i; @@ -685,6 +764,7 @@ txp_alloc_rings(sc) sc->sc_txhir.r_reg = TXP_H2A_1; sc->sc_txhir.r_desc = (struct txp_tx_desc *)sc->sc_txhiring_dma.dma_vaddr; sc->sc_txhir.r_cons = sc->sc_txhir.r_prod = sc->sc_txhir.r_cnt = 0; + sc->sc_txhir.r_off = &sc->sc_hostvar->hv_tx_hi_desc_read_idx; /* low priority tx ring */ if (txp_dma_malloc(sc, sizeof(struct txp_tx_desc) * TX_ENTRIES, @@ -698,7 +778,8 @@ txp_alloc_rings(sc) boot->br_txlopri_siz = TX_ENTRIES * sizeof(struct txp_tx_desc); sc->sc_txlor.r_reg = TXP_H2A_3; sc->sc_txlor.r_desc = (struct txp_tx_desc *)sc->sc_txloring_dma.dma_vaddr; - sc->sc_txhir.r_cons = sc->sc_txhir.r_prod = sc->sc_txhir.r_cnt = 0; + sc->sc_txlor.r_cons = sc->sc_txlor.r_prod = sc->sc_txlor.r_cnt = 0; + sc->sc_txlor.r_off = &sc->sc_hostvar->hv_tx_lo_desc_read_idx; /* high priority rx ring */ if (txp_dma_malloc(sc, sizeof(struct txp_rx_desc) * RX_ENTRIES, @@ -710,6 +791,10 @@ txp_alloc_rings(sc) boot->br_rxhipri_lo = sc->sc_rxhiring_dma.dma_paddr & 0xffffffff; boot->br_rxhipri_hi = sc->sc_rxhiring_dma.dma_paddr >> 32; boot->br_rxhipri_siz = RX_ENTRIES * sizeof(struct txp_rx_desc); + sc->sc_rxhir.r_desc = + (struct txp_rx_desc *)sc->sc_rxhiring_dma.dma_vaddr; + sc->sc_rxhir.r_roff = &sc->sc_hostvar->hv_rx_hi_read_idx; + sc->sc_rxhir.r_woff = &sc->sc_hostvar->hv_rx_hi_write_idx; /* low priority rx ring */ if (txp_dma_malloc(sc, sizeof(struct txp_rx_desc) * RX_ENTRIES, @@ -721,6 +806,10 @@ txp_alloc_rings(sc) boot->br_rxlopri_lo = sc->sc_rxloring_dma.dma_paddr & 0xffffffff; boot->br_rxlopri_hi = sc->sc_rxloring_dma.dma_paddr >> 32; boot->br_rxlopri_siz = RX_ENTRIES * sizeof(struct txp_rx_desc); + sc->sc_rxlor.r_desc = + (struct txp_rx_desc *)sc->sc_rxloring_dma.dma_vaddr; + sc->sc_rxlor.r_roff = &sc->sc_hostvar->hv_rx_lo_read_idx; + sc->sc_rxlor.r_woff = &sc->sc_hostvar->hv_rx_lo_write_idx; /* command ring */ if (txp_dma_malloc(sc, sizeof(struct txp_cmd_desc) * CMD_ENTRIES, @@ -775,11 +864,14 @@ txp_alloc_rings(sc) m_freem(m); goto bail_rspring; } + m->m_pkthdr.rcvif = ifp; sc->sc_rxbufs[i].rb_vaddrlo = (u_int32_t)m; sc->sc_rxbufs[i].rb_vaddrhi = 0; - sc->sc_rxbufs[i].rb_paddrlo = vtophys(m->m_data); + sc->sc_rxbufs[i].rb_paddrlo = vtophys(m->m_data + 2); sc->sc_rxbufs[i].rb_paddrhi = 0; } + sc->sc_hostvar->hv_rx_buf_write_idx = (RXBUF_ENTRIES - 1) * + sizeof(struct txp_rxbuf_desc); /* zero dma */ if (txp_dma_malloc(sc, sizeof(u_int32_t), &sc->sc_zero_dma)) { @@ -993,12 +1085,12 @@ txp_init(sc) s = splimp(); - txp_set_filter(sc); - + txp_command(sc, TXP_CMD_XCVR_SELECT, sc->sc_xcvr, 0, 0, + NULL, NULL, NULL, 0); txp_command(sc, TXP_CMD_TX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1); -#if 0 txp_command(sc, TXP_CMD_RX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1); -#endif + + txp_set_filter(sc); WRITE_REG(sc, TXP_IER, TXP_INT_RESERVED | TXP_INT_SELF | TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 | diff --git a/sys/dev/pci/if_txpreg.h b/sys/dev/pci/if_txpreg.h index 692cb2e7bb9..1cd4cd74936 100644 --- a/sys/dev/pci/if_txpreg.h +++ b/sys/dev/pci/if_txpreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_txpreg.h,v 1.15 2001/04/12 22:40:12 jason Exp $ */ +/* $OpenBSD: if_txpreg.h,v 1.16 2001/04/13 17:50:30 jason Exp $ */ /* * Copyright (c) 2001 Aaron Campbell <aaron@monkey.org>. @@ -287,7 +287,7 @@ struct txp_rx_desc { #define RX_ERROR_ALIGN 0x00000006 /* alignment error */ #define RX_ERROR_DRIBBLE 0x00000007 /* dribble bit */ -/* txp_rx_desc.rx_stat (if rx_flags & RX_FLAGS_ERROR bit set) */ +/* txp_rx_desc.rx_stat (if rx_flags & RX_FLAGS_ERROR not bit set) */ #define RX_STAT_PROTO_M 0x00000003 /* protocol mask */ #define RX_STAT_PROTO_UK 0x00000000 /* unknown protocol */ #define RX_STAT_PROTO_IPX 0x00000001 /* IPX */ @@ -533,6 +533,13 @@ struct txp_tx_ring { u_int32_t r_prod; /* producer */ u_int32_t r_cons; /* consumer */ u_int32_t r_cnt; /* # descs in use */ + volatile u_int32_t *r_off; /* hostvar index pointer */ +}; + +struct txp_rx_ring { + struct txp_rx_desc *r_desc; /* base address of descs */ + volatile u_int32_t *r_roff; /* hv read offset ptr */ + volatile u_int32_t *r_woff; /* hv write offset ptr */ }; /* Software transmit list */ @@ -555,6 +562,7 @@ struct txp_softc { struct ifmedia sc_ifmedia; struct txp_tx_ring sc_txhir, sc_txlor; struct txp_rxbuf_desc *sc_rxbufs; + struct txp_rx_ring sc_rxhir, sc_rxlor; u_int16_t sc_xcvr; u_int16_t sc_seq; struct txp_dma_alloc sc_boot_dma, sc_host_dma, sc_zero_dma; |