summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorthorpej <thorpej@NetBSD.org>2001-06-30 14:47:23 +0000
committerthorpej <thorpej@NetBSD.org>2001-06-30 14:47:23 +0000
commitee9c81dd388a507461b1cb59cdf98907ec22289f (patch)
treeab842921c324819fe30d46239762c37b5b5f5b13 /sys/dev
parent291a21d3fb115f3f5c82b8da75ead657b28e83bc (diff)
Split the transmit encap routine into two versions: one for the Tigon 1
and another for the Tigon 2. This eliminates a conditional in the loop around the DMA segments, and will make further cleanup easier.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_ti.c203
-rw-r--r--sys/dev/pci/if_tireg.h24
2 files changed, 169 insertions, 58 deletions
diff --git a/sys/dev/pci/if_ti.c b/sys/dev/pci/if_ti.c
index 7a0fc4d4979..e725693e10d 100644
--- a/sys/dev/pci/if_ti.c
+++ b/sys/dev/pci/if_ti.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_ti.c,v 1.30 2001/06/30 14:16:55 thorpej Exp $ */
+/* $NetBSD: if_ti.c,v 1.31 2001/06/30 14:47:23 thorpej Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@@ -158,7 +158,9 @@ static void ti_txeof __P((struct ti_softc *));
static void ti_rxeof __P((struct ti_softc *));
static void ti_stats_update __P((struct ti_softc *));
-static int ti_encap __P((struct ti_softc *, struct mbuf *,
+static int ti_encap_tigon1 __P((struct ti_softc *, struct mbuf *,
+ u_int32_t *));
+static int ti_encap_tigon2 __P((struct ti_softc *, struct mbuf *,
u_int32_t *));
static int ti_intr __P((void *));
@@ -1727,8 +1729,26 @@ static void ti_attach(parent, self, aux)
printf("%s: chip initialization failed\n", self->dv_xname);
goto fail2;
}
- if (sc->ti_hwrev == TI_HWREV_TIGON && nolinear == 1) {
- printf("%s: memory space not mapped linear\n", self->dv_xname);
+
+ /*
+ * Deal with some chip diffrences.
+ */
+ switch (sc->ti_hwrev) {
+ case TI_HWREV_TIGON:
+ sc->sc_tx_encap = ti_encap_tigon1;
+ if (nolinear == 1)
+ printf("%s: memory space not mapped linear\n",
+ self->dv_xname);
+ break;
+
+ case TI_HWREV_TIGON_II:
+ sc->sc_tx_encap = ti_encap_tigon2;
+ break;
+
+ default:
+ printf("%s: Unknown chip version: %d\n", self->dv_xname,
+ sc->ti_hwrev);
+ goto fail2;
}
/* Zero out the NIC's on-board SRAM. */
@@ -2198,7 +2218,7 @@ static void ti_stats_update(sc)
* Encapsulate an mbuf chain in the tx ring by coupling the mbuf data
* pointers to descriptors.
*/
-static int ti_encap(sc, m_head, txidx)
+static int ti_encap_tigon1(sc, m_head, txidx)
struct ti_softc *sc;
struct mbuf *m_head;
u_int32_t *txidx;
@@ -2245,43 +2265,40 @@ static int ti_encap(sc, m_head, txidx)
* of fragments or hit the end of the mbuf chain.
*/
for (i = 0; i < dmamap->dm_nsegs; i++) {
- if (sc->ti_hwrev == TI_HWREV_TIGON) {
- if (frag > 383)
- CSR_WRITE_4(sc, TI_WINBASE,
- TI_TX_RING_BASE + 6144);
- else if (frag > 255)
- CSR_WRITE_4(sc, TI_WINBASE,
- TI_TX_RING_BASE + 4096);
- else if (frag > 127)
- CSR_WRITE_4(sc, TI_WINBASE,
- TI_TX_RING_BASE + 2048);
- else
- CSR_WRITE_4(sc, TI_WINBASE,
- TI_TX_RING_BASE);
- f = &sc->ti_tx_ring_nic[frag % 128];
- } else
- f = &sc->ti_rdata->ti_tx_ring[frag];
- if (sc->ti_cdata.ti_tx_chain[frag] != NULL)
- break;
- TI_HOSTADDR(f->ti_addr) = dmamap->dm_segs[i].ds_addr;
- f->ti_len = dmamap->dm_segs[i].ds_len;
- f->ti_flags = csum_flags;
- n = m_aux_find(m_head, AF_LINK, ETHERTYPE_VLAN);
- if (n) {
- f->ti_flags |= TI_BDFLAG_VLAN_TAG;
- f->ti_vlan_tag = *mtod(n, int *);
- } else {
- f->ti_vlan_tag = 0;
- }
- /*
- * Sanity check: avoid coming within 16 descriptors
- * of the end of the ring.
- */
- if ((TI_TX_RING_CNT - (sc->ti_txcnt + cnt)) < 16)
- return(ENOBUFS);
- cur = frag;
- TI_INC(frag, TI_TX_RING_CNT);
- cnt++;
+ if (frag > 383)
+ CSR_WRITE_4(sc, TI_WINBASE,
+ TI_TX_RING_BASE + 6144);
+ else if (frag > 255)
+ CSR_WRITE_4(sc, TI_WINBASE,
+ TI_TX_RING_BASE + 4096);
+ else if (frag > 127)
+ CSR_WRITE_4(sc, TI_WINBASE,
+ TI_TX_RING_BASE + 2048);
+ else
+ CSR_WRITE_4(sc, TI_WINBASE,
+ TI_TX_RING_BASE);
+ f = &sc->ti_tx_ring_nic[frag % 128];
+ if (sc->ti_cdata.ti_tx_chain[frag] != NULL)
+ break;
+ TI_HOSTADDR(f->ti_addr) = dmamap->dm_segs[i].ds_addr;
+ f->ti_len = dmamap->dm_segs[i].ds_len;
+ f->ti_flags = csum_flags;
+ n = m_aux_find(m_head, AF_LINK, ETHERTYPE_VLAN);
+ if (n) {
+ f->ti_flags |= TI_BDFLAG_VLAN_TAG;
+ f->ti_vlan_tag = *mtod(n, int *);
+ } else {
+ f->ti_vlan_tag = 0;
+ }
+ /*
+ * Sanity check: avoid coming within 16 descriptors
+ * of the end of the ring.
+ */
+ if ((TI_TX_RING_CNT - (sc->ti_txcnt + cnt)) < 16)
+ return(ENOBUFS);
+ cur = frag;
+ TI_INC(frag, TI_TX_RING_CNT);
+ cnt++;
}
if (i < dmamap->dm_nsegs)
@@ -2290,11 +2307,101 @@ static int ti_encap(sc, m_head, txidx)
if (frag == sc->ti_tx_saved_considx)
return(ENOBUFS);
- if (sc->ti_hwrev == TI_HWREV_TIGON)
- sc->ti_tx_ring_nic[cur % 128].ti_flags |=
- TI_BDFLAG_END;
- else
- sc->ti_rdata->ti_tx_ring[cur].ti_flags |= TI_BDFLAG_END;
+ sc->ti_tx_ring_nic[cur % 128].ti_flags |=
+ TI_BDFLAG_END;
+
+ /* Sync the packet's DMA map. */
+ bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
+ BUS_DMASYNC_PREWRITE);
+
+ sc->ti_cdata.ti_tx_chain[cur] = m_head;
+ SIMPLEQ_REMOVE_HEAD(&sc->txdma_list, dma, link);
+ sc->txdma[cur] = dma;
+ sc->ti_txcnt += cnt;
+
+ *txidx = frag;
+
+ return(0);
+}
+
+static int ti_encap_tigon2(sc, m_head, txidx)
+ struct ti_softc *sc;
+ struct mbuf *m_head;
+ u_int32_t *txidx;
+{
+ struct ti_tx_desc *f = NULL;
+ u_int32_t frag, cur, cnt = 0;
+ struct txdmamap_pool_entry *dma;
+ bus_dmamap_t dmamap;
+ int error, i;
+ struct mbuf *n;
+ u_int16_t csum_flags = 0;
+
+ dma = SIMPLEQ_FIRST(&sc->txdma_list);
+ if (dma == NULL) {
+ return ENOMEM;
+ }
+ dmamap = dma->dmamap;
+
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m_head, 0);
+ if (error) {
+ struct mbuf *m;
+ int i = 0;
+ for (m = m_head; m; m = m->m_next)
+ i++;
+ printf("ti_encap: bus_dmamap_load_mbuf (len %d, %d frags) "
+ "error %d\n", m_head->m_pkthdr.len, i, error);
+ return (ENOMEM);
+ }
+
+ cur = frag = *txidx;
+
+ if (m_head->m_pkthdr.csum_flags & M_CSUM_IPv4) {
+ /* IP header checksum field must be 0! */
+ csum_flags |= TI_BDFLAG_IP_CKSUM;
+ }
+ if (m_head->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4))
+ csum_flags |= TI_BDFLAG_TCP_UDP_CKSUM;
+
+ /* XXX fragmented packet checksum capability? */
+
+ /*
+ * Start packing the mbufs in this chain into
+ * the fragment pointers. Stop when we run out
+ * of fragments or hit the end of the mbuf chain.
+ */
+ for (i = 0; i < dmamap->dm_nsegs; i++) {
+ f = &sc->ti_rdata->ti_tx_ring[frag];
+ if (sc->ti_cdata.ti_tx_chain[frag] != NULL)
+ break;
+ TI_HOSTADDR(f->ti_addr) = dmamap->dm_segs[i].ds_addr;
+ f->ti_len = dmamap->dm_segs[i].ds_len;
+ f->ti_flags = csum_flags;
+ n = m_aux_find(m_head, AF_LINK, ETHERTYPE_VLAN);
+ if (n) {
+ f->ti_flags |= TI_BDFLAG_VLAN_TAG;
+ f->ti_vlan_tag = *mtod(n, int *);
+ } else {
+ f->ti_vlan_tag = 0;
+ }
+ /*
+ * Sanity check: avoid coming within 16 descriptors
+ * of the end of the ring.
+ */
+ if ((TI_TX_RING_CNT - (sc->ti_txcnt + cnt)) < 16)
+ return(ENOBUFS);
+ cur = frag;
+ TI_INC(frag, TI_TX_RING_CNT);
+ cnt++;
+ }
+
+ if (i < dmamap->dm_nsegs)
+ return(ENOBUFS);
+
+ if (frag == sc->ti_tx_saved_considx)
+ return(ENOBUFS);
+
+ sc->ti_rdata->ti_tx_ring[cur].ti_flags |= TI_BDFLAG_END;
/* Sync the packet's DMA map. */
bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
@@ -2335,7 +2442,7 @@ static void ti_start(ifp)
* don't have room, set the OACTIVE flag and wait
* for the NIC to drain the ring.
*/
- if (ti_encap(sc, m_head, &prodidx)) {
+ if ((*sc->sc_tx_encap)(sc, m_head, &prodidx)) {
ifp->if_flags |= IFF_OACTIVE;
break;
}
diff --git a/sys/dev/pci/if_tireg.h b/sys/dev/pci/if_tireg.h
index 2516eb62ae3..9b0ed0b1f25 100644
--- a/sys/dev/pci/if_tireg.h
+++ b/sys/dev/pci/if_tireg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: if_tireg.h,v 1.6 2001/06/30 14:16:55 thorpej Exp $ */
+/* $NetBSD: if_tireg.h,v 1.7 2001/06/30 14:47:24 thorpej Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@@ -1071,23 +1071,27 @@ struct ti_softc {
char *ti_vhandle;
bus_space_tag_t ti_btag;
void *ti_intrhand;
-#if 0
- struct resource *ti_irq;
- struct resource *ti_res;
-#endif
+
struct ifmedia ifmedia; /* media info */
-#if 0
- u_int8_t ti_unit; /* interface number */
-#endif
+
u_int8_t ti_hwrev; /* Tigon rev (1 or 2) */
u_int8_t ti_copper; /* 1000baseTX card */
u_int8_t ti_linkstat; /* Link state */
struct ti_ring_data *ti_rdata; /* rings */
- struct ti_tx_desc *ti_tx_ring_nic;/* pointer to shared mem */
- struct ti_chain_data ti_cdata; /* mbufs */
#define ti_ev_prodidx ti_rdata->ti_ev_prodidx_r
#define ti_return_prodidx ti_rdata->ti_return_prodidx_r
#define ti_tx_considx ti_rdata->ti_tx_considx_r
+
+ struct ti_tx_desc *ti_tx_ring_nic;/* pointer to shared mem */
+
+ struct ti_chain_data ti_cdata; /* mbufs */
+
+ /*
+ * Function pointers to deal with Tigon 1 vs. Tigon 2 differences.
+ */
+ int (*sc_tx_encap)(struct ti_softc *,
+ struct mbuf *, uint32_t *);
+
u_int16_t ti_tx_saved_considx;
u_int16_t ti_rx_saved_considx;
u_int16_t ti_ev_saved_considx;