Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Split the receive interrupt handler into two ver...



details:   https://anonhg.NetBSD.org/src/rev/933bfa223e45
branches:  trunk
changeset: 511955:933bfa223e45
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sat Jun 30 22:35:05 2001 +0000

description:
Split the receive interrupt handler into two versions, one for the
SiS900/DP83815, one for the DP83820.  In preparation for changes
to the DP83820 version for handling jumbo Ethernet frames.

diffstat:

 sys/dev/pci/if_sip.c |  266 ++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 211 insertions(+), 55 deletions(-)

diffs (truncated from 320 to 300 lines):

diff -r 988293be5d2d -r 933bfa223e45 sys/dev/pci/if_sip.c
--- a/sys/dev/pci/if_sip.c      Sat Jun 30 21:24:06 2001 +0000
+++ b/sys/dev/pci/if_sip.c      Sat Jun 30 22:35:05 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_sip.c,v 1.34 2001/06/18 01:58:08 simonb Exp $       */
+/*     $NetBSD: if_sip.c,v 1.35 2001/06/30 22:35:05 thorpej Exp $      */
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -1414,6 +1414,215 @@
                ifp->if_timer = 0;
 }
 
+#if defined(DP83820)
+/*
+ * sip_rxintr:
+ *
+ *     Helper; handle receive interrupts.
+ */
+void
+SIP_DECL(rxintr)(struct sip_softc *sc)
+{
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       struct sip_rxsoft *rxs;
+       struct mbuf *m;
+       u_int32_t cmdsts, extsts;
+       int i, len;
+
+       for (i = sc->sc_rxptr;; i = SIP_NEXTRX(i)) {
+               rxs = &sc->sc_rxsoft[i];
+
+               SIP_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+
+               cmdsts = le32toh(sc->sc_rxdescs[i].sipd_cmdsts);
+               extsts = le32toh(sc->sc_rxdescs[i].sipd_extsts);
+
+               /*
+                * NOTE: OWN is set if owned by _consumer_.  We're the
+                * consumer of the receive ring, so if the bit is clear,
+                * we have processed all of the packets.
+                */
+               if ((cmdsts & CMDSTS_OWN) == 0) {
+                       /*
+                        * We have processed all of the receive buffers.
+                        */
+                       break;
+               }
+
+               /*
+                * If an error occurred, update stats, clear the status
+                * word, and leave the packet buffer in place.  It will
+                * simply be reused the next time the ring comes around.
+                */
+               if (cmdsts & (CMDSTS_Rx_RXA|CMDSTS_Rx_LONG|CMDSTS_Rx_RUNT|
+                   CMDSTS_Rx_ISE|CMDSTS_Rx_CRCE|CMDSTS_Rx_FAE)) {
+                       ifp->if_ierrors++;
+                       if ((cmdsts & CMDSTS_Rx_RXA) != 0 &&
+                           (cmdsts & CMDSTS_Rx_RXO) == 0) {
+                               /* Receive overrun handled elsewhere. */
+                               printf("%s: receive descriptor error\n",
+                                   sc->sc_dev.dv_xname);
+                       }
+#define        PRINTERR(bit, str)                                              \
+                       if (cmdsts & (bit))                             \
+                               printf("%s: %s\n", sc->sc_dev.dv_xname, str)
+                       PRINTERR(CMDSTS_Rx_LONG, "packet too long");
+                       PRINTERR(CMDSTS_Rx_RUNT, "runt packet");
+                       PRINTERR(CMDSTS_Rx_ISE, "invalid symbol error");
+                       PRINTERR(CMDSTS_Rx_CRCE, "CRC error");
+                       PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");
+#undef PRINTERR
+                       SIP_INIT_RXDESC(sc, i);
+                       continue;
+               }
+
+               bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
+                   rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
+
+               /*
+                * No errors; receive the packet.  Note, the DP83820
+                * includes the CRC with every packet.
+                */
+               len = CMDSTS_SIZE(cmdsts);
+
+#ifdef __NO_STRICT_ALIGNMENT
+               /*
+                * If the packet is small enough to fit in a
+                * single header mbuf, allocate one and copy
+                * the data into it.  This greatly reduces
+                * memory consumption when we receive lots
+                * of small packets.
+                *
+                * Otherwise, we add a new buffer to the receive
+                * chain.  If this fails, we drop the packet and
+                * recycle the old buffer.
+                */
+               if (SIP_DECL(copy_small) != 0 && len <= MHLEN) {
+                       MGETHDR(m, M_DONTWAIT, MT_DATA);
+                       if (m == NULL)
+                               goto dropit;
+                       memcpy(mtod(m, caddr_t),
+                           mtod(rxs->rxs_mbuf, caddr_t), len);
+                       SIP_INIT_RXDESC(sc, i);
+                       bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
+                           rxs->rxs_dmamap->dm_mapsize,
+                           BUS_DMASYNC_PREREAD);
+               } else {
+                       m = rxs->rxs_mbuf;
+                       if (SIP_DECL(add_rxbuf)(sc, i) != 0) {
+ dropit:
+                               ifp->if_ierrors++;
+                               SIP_INIT_RXDESC(sc, i);
+                               bus_dmamap_sync(sc->sc_dmat,
+                                   rxs->rxs_dmamap, 0,
+                                   rxs->rxs_dmamap->dm_mapsize,
+                                   BUS_DMASYNC_PREREAD);
+                               continue;
+                       }
+               }
+#else
+               /*
+                * The SiS 900's receive buffers must be 4-byte aligned.
+                * But this means that the data after the Ethernet header
+                * is misaligned.  We must allocate a new buffer and
+                * copy the data, shifted forward 2 bytes.
+                */
+               MGETHDR(m, M_DONTWAIT, MT_DATA);
+               if (m == NULL) {
+ dropit:
+                       ifp->if_ierrors++;
+                       SIP_INIT_RXDESC(sc, i);
+                       bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
+                           rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
+                       continue;
+               }
+               if (len > (MHLEN - 2)) {
+                       MCLGET(m, M_DONTWAIT);
+                       if ((m->m_flags & M_EXT) == 0) {
+                               m_freem(m);
+                               goto dropit;
+                       }
+               }
+               m->m_data += 2;
+
+               /*
+                * Note that we use clusters for incoming frames, so the
+                * buffer is virtually contiguous.
+                */
+               memcpy(mtod(m, caddr_t), mtod(rxs->rxs_mbuf, caddr_t), len);
+
+               /* Allow the receive descriptor to continue using its mbuf. */
+               SIP_INIT_RXDESC(sc, i);
+               bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
+                   rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
+#endif /* __NO_STRICT_ALIGNMENT */
+
+               ifp->if_ipackets++;
+               m->m_flags |= M_HASFCS;
+               m->m_pkthdr.rcvif = ifp;
+               m->m_pkthdr.len = m->m_len = len;
+
+#if NBPFILTER > 0
+               /*
+                * Pass this up to any BPF listeners, but only
+                * pass if up the stack if it's for us.
+                */
+               if (ifp->if_bpf)
+                       bpf_mtap(ifp->if_bpf, m);
+#endif /* NBPFILTER > 0 */
+
+               /*
+                * If VLANs are enabled, VLAN packets have been unwrapped
+                * for us.  Associate the tag with the packet.
+                */
+               if (sc->sc_ethercom.ec_nvlans != 0 &&
+                   (extsts & EXTSTS_VPKT) != 0) {
+                       struct mbuf *vtag;
+
+                       vtag = m_aux_add(m, AF_LINK, ETHERTYPE_VLAN);
+                       if (vtag == NULL) {
+                               printf("%s: unable to allocate VLAN tag\n",
+                                   sc->sc_dev.dv_xname);
+                               m_freem(m);
+                               continue;
+                       }
+
+                       *mtod(vtag, int *) = ntohs(extsts & EXTSTS_VTCI);
+                       vtag->m_len = sizeof(int);
+               }
+
+               /*
+                * Set the incoming checksum information for the
+                * packet.
+                */
+               if ((extsts & EXTSTS_IPPKT) != 0) {
+                       SIP_EVCNT_INCR(&sc->sc_ev_rxipsum);
+                       m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
+                       if (extsts & EXTSTS_Rx_IPERR)
+                               m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
+                       if (extsts & EXTSTS_TCPPKT) {
+                               SIP_EVCNT_INCR(&sc->sc_ev_rxtcpsum);
+                               m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
+                               if (extsts & EXTSTS_Rx_TCPERR)
+                                       m->m_pkthdr.csum_flags |=
+                                           M_CSUM_TCP_UDP_BAD;
+                       } else if (extsts & EXTSTS_UDPPKT) {
+                               SIP_EVCNT_INCR(&sc->sc_ev_rxudpsum);
+                               m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
+                               if (extsts & EXTSTS_Rx_UDPERR)
+                                       m->m_pkthdr.csum_flags |=
+                                           M_CSUM_TCP_UDP_BAD;
+                       }
+               }
+
+               /* Pass it on. */
+               (*ifp->if_input)(ifp, m);
+       }
+
+       /* Update the receive pointer. */
+       sc->sc_rxptr = i;
+}
+#else /* ! DP83820 */
 /*
  * sip_rxintr:
  *
@@ -1426,9 +1635,6 @@
        struct sip_rxsoft *rxs;
        struct mbuf *m;
        u_int32_t cmdsts;
-#ifdef DP83820
-       u_int32_t extsts;
-#endif /* DP83820 */
        int i, len;
 
        for (i = sc->sc_rxptr;; i = SIP_NEXTRX(i)) {
@@ -1437,9 +1643,6 @@
                SIP_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
 
                cmdsts = le32toh(sc->sc_rxdescs[i].sipd_cmdsts);
-#ifdef DP83820
-               extsts = le32toh(sc->sc_rxdescs[i].sipd_extsts);
-#endif /* DP83820 */
 
                /*
                 * NOTE: OWN is set if owned by _consumer_.  We're the
@@ -1453,13 +1656,11 @@
                        break;
                }
 
-#if !defined(DP83820)
                /*
                 * If any collisions were seen on the wire, count one.
                 */
                if (cmdsts & CMDSTS_Rx_COL)
                        ifp->if_collisions++;
-#endif /* ! DP83820 */
 
                /*
                 * If an error occurred, update stats, clear the status
@@ -1583,52 +1784,6 @@
                        bpf_mtap(ifp->if_bpf, m);
 #endif /* NBPFILTER > 0 */
 
-#ifdef DP83820
-               /*
-                * If VLANs are enabled, VLAN packets have been unwrapped
-                * for us.  Associate the tag with the packet.
-                */
-               if (sc->sc_ethercom.ec_nvlans != 0 &&
-                   (extsts & EXTSTS_VPKT) != 0) {
-                       struct mbuf *vtag;
-
-                       vtag = m_aux_add(m, AF_LINK, ETHERTYPE_VLAN);
-                       if (vtag == NULL) {
-                               printf("%s: unable to allocate VLAN tag\n",
-                                   sc->sc_dev.dv_xname);
-                               m_freem(m);
-                               continue;
-                       }
-
-                       *mtod(vtag, int *) = ntohs(extsts & EXTSTS_VTCI);
-                       vtag->m_len = sizeof(int);
-               }
-
-               /*
-                * Set the incoming checksum information for the
-                * packet.
-                */
-               if ((extsts & EXTSTS_IPPKT) != 0) {
-                       SIP_EVCNT_INCR(&sc->sc_ev_rxipsum);
-                       m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
-                       if (extsts & EXTSTS_Rx_IPERR)
-                               m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
-                       if (extsts & EXTSTS_TCPPKT) {
-                               SIP_EVCNT_INCR(&sc->sc_ev_rxtcpsum);
-                               m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
-                               if (extsts & EXTSTS_Rx_TCPERR)
-                                       m->m_pkthdr.csum_flags |=
-                                           M_CSUM_TCP_UDP_BAD;
-                       } else if (extsts & EXTSTS_UDPPKT) {



Home | Main Index | Thread Index | Old Index