Author: yongari
Date: Thu Apr 29 18:00:42 2010
New Revision: 207379
URL: http://svn.freebsd.org/changeset/base/207379

Log:
  Enable FCS stripping and padding 10 bytes bit of RX MAC control
  register. Due to lack of SiS190 controller, I'm not sure whether
  this is also applicable to SiS190 so this feature is only activated
  on SiS191 controller.
  The controller can pad 10 bytes before DMAing a received frame to
  RX buffer and received bytes include the padded bytes. This padding
  is very useful on strict-alignment architectures because driver
  does not have to copy received frame to align IP header on 4 bytes
  boundary. It also gives better RX performance on non-strict
  alignment architectures. Special thanks to xclin to give me
  valuable register information. Without his enthusiastic trial and
  errors this wouldn't be even possible.
  
  While I'm here tighten validity check of received frame. Controller
  clears RDS_CRCOK bit when it received bad CRC frames. xclin found
  that using loop back testing.
  
  Tested by:    xclin <xclin <> cs dot nctu dot edu dot tw >

Modified:
  head/sys/dev/sge/if_sge.c
  head/sys/dev/sge/if_sgereg.h

Modified: head/sys/dev/sge/if_sge.c
==============================================================================
--- head/sys/dev/sge/if_sge.c   Thu Apr 29 17:51:06 2010        (r207378)
+++ head/sys/dev/sge/if_sge.c   Thu Apr 29 18:00:42 2010        (r207379)
@@ -1144,7 +1144,8 @@ sge_rxeof(struct sge_softc *sc)
                if ((rxinfo & RDC_OWN) != 0)
                        break;
                rxstat = le32toh(cur_rx->sge_sts_size);
-               if (SGE_RX_ERROR(rxstat) != 0 || SGE_RX_NSEGS(rxstat) != 1) {
+               if ((rxstat & RDS_CRCOK) == 0 || SGE_RX_ERROR(rxstat) != 0 ||
+                   SGE_RX_NSEGS(rxstat) != 1) {
                        /* XXX We don't support multi-segment frames yet. */
 #ifdef SGE_SHOW_ERRORS
                        device_printf(sc->sge_dev, "Rx error : 0x%b\n", rxstat,
@@ -1177,11 +1178,23 @@ sge_rxeof(struct sge_softc *sc)
                /*
                 * TODO : VLAN hardware tag stripping.
                 */
-               m->m_pkthdr.len = m->m_len =
-                   SGE_RX_BYTES(rxstat) - ETHER_CRC_LEN;
+               if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) {
+                       /*
+                        * Account for 10bytes auto padding which is used
+                        * to align IP header on 32bit boundary.  Also note,
+                        * CRC bytes is automatically removed by the
+                        * hardware.
+                        */
+                       m->m_data += SGE_RX_PAD_BYTES;
+                       m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) -
+                           SGE_RX_PAD_BYTES;
+               } else {
+                       m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) -
+                           ETHER_CRC_LEN;
 #ifndef __NO_STRICT_ALIGNMENT
-               sge_fixup_rx(m);
+                       sge_fixup_rx(m);
 #endif
+               }
                m->m_pkthdr.rcvif = ifp;
                ifp->if_ipackets++;
                SGE_UNLOCK(sc);
@@ -1503,6 +1516,7 @@ sge_init_locked(struct sge_softc *sc)
 {
        struct ifnet *ifp;
        struct mii_data *mii;
+       uint16_t rxfilt;
        int i;
 
        SGE_LOCK_ASSERT(sc);
@@ -1535,10 +1549,19 @@ sge_init_locked(struct sge_softc *sc)
        CSR_WRITE_4(sc, RxWakeOnLan, 0);
        CSR_WRITE_4(sc, RxWakeOnLanData, 0);
        /* Allow receiving VLAN frames. */
-       CSR_WRITE_2(sc, RxMPSControl, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
+       if ((sc->sge_flags & SGE_FLAG_SIS190) == 0)
+               CSR_WRITE_2(sc, RxMPSControl,
+                   ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN + SGE_RX_PAD_BYTES);
+       else
+               CSR_WRITE_2(sc, RxMPSControl, ETHER_MAX_LEN + 
ETHER_VLAN_ENCAP_LEN);
 
        for (i = 0; i < ETHER_ADDR_LEN; i++)
                CSR_WRITE_1(sc, RxMacAddr + i, IF_LLADDR(ifp)[i]);
+       /* Configure RX MAC. */
+       rxfilt = 0;
+       if ((sc->sge_flags & SGE_FLAG_SIS190) == 0)
+               rxfilt |= RXMAC_STRIP_FCS | RXMAC_PAD_ENB;
+       CSR_WRITE_2(sc, RxMacControl, rxfilt);
        sge_rxfilter(sc);
 
        /* Initialize default speed/duplex information. */

Modified: head/sys/dev/sge/if_sgereg.h
==============================================================================
--- head/sys/dev/sge/if_sgereg.h        Thu Apr 29 17:51:06 2010        
(r207378)
+++ head/sys/dev/sge/if_sgereg.h        Thu Apr 29 18:00:42 2010        
(r207379)
@@ -137,6 +137,10 @@
 #define        AcceptAllPhys           0x0100
 #define        AcceptErr               0x0020
 #define        AcceptRunt              0x0010
+#define        RXMAC_STRIP_FCS         0x0010
+#define        RXMAC_PAD_ENB           0x0004
+
+#define        SGE_RX_PAD_BYTES        10
 
 /* Station control register. */
 #define        SC_LOOPBACK             0x80000000
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to