Adapt some code from the FreeBSD driver required to make
authorjsg <jsg@openbsd.org>
Tue, 15 Jul 2008 13:21:17 +0000 (13:21 +0000)
committerjsg <jsg@openbsd.org>
Tue, 15 Jul 2008 13:21:17 +0000 (13:21 +0000)
newer PCI Express adapters (ie 8168C*/8102*) work.

V2 Checksum offload format in RTL8102 devices not yet supported.

No objections from brad@. Thanks to everyone who tested.

sys/dev/ic/re.c
sys/dev/ic/rtl81x9reg.h

index 10bafe1..e12b06b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: re.c,v 1.83 2008/07/13 05:24:05 jsg Exp $     */
+/*     $OpenBSD: re.c,v 1.84 2008/07/15 13:21:17 jsg Exp $     */
 /*     $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $   */
 /*
  * Copyright (c) 1997, 1998-2003
@@ -568,16 +568,10 @@ re_setmulti(struct rl_softc *sc)
         * parts. This means we have to write the hash pattern in reverse
         * order for those devices.
         */
-       switch (sc->sc_hwrev) {
-       case RL_HWREV_8100E_SPIN1:
-       case RL_HWREV_8100E_SPIN2:
-       case RL_HWREV_8101E:
-       case RL_HWREV_8168_SPIN1:
-       case RL_HWREV_8168_SPIN2:
+       if (sc->rl_flags & RL_FLAG_INVMAR) {
                CSR_WRITE_4(sc, RL_MAR0, swap32(hashes[1]));
                CSR_WRITE_4(sc, RL_MAR4, swap32(hashes[0]));
-               break;
-       default:
+       } else {
                CSR_WRITE_4(sc, RL_MAR0, hashes[0]);
                CSR_WRITE_4(sc, RL_MAR4, hashes[1]);
        }
@@ -867,6 +861,53 @@ re_attach(struct rl_softc *sc, const char *intrstr)
 
        sc->sc_hwrev = CSR_READ_4(sc, RL_TXCFG) & RL_TXCFG_HWREV;
 
+       switch (sc->sc_hwrev) {
+       case RL_HWREV_8139CPLUS:
+               sc->rl_flags |= RL_FLAG_NOJUMBO;
+               break;
+       case RL_HWREV_8100E_SPIN1:
+       case RL_HWREV_8100E_SPIN2:
+       case RL_HWREV_8101E:
+               sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR |
+                   RL_FLAG_PHYWAKE;
+               break;
+       case RL_HWREV_8102E:
+       case RL_HWREV_8102EL:
+               sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR |
+                   RL_FLAG_PHYWAKE | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT;
+               break;
+       case RL_HWREV_8168_SPIN1:
+       case RL_HWREV_8168_SPIN2:
+       case RL_HWREV_8168_SPIN3:
+               sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE |
+                   RL_FLAG_MACSTAT;
+               break;
+       case RL_HWREV_8168C:
+       case RL_HWREV_8168C_SPIN2:
+       case RL_HWREV_8168CP:
+               sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE |
+                   RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT;
+               /*
+                * These controllers support jumbo frame but it seems
+                * that enabling it requires touching additional magic
+                * registers. Depending on MAC revisions some
+                * controllers need to disable checksum offload. So
+                * disable jumbo frame until I have better idea what
+                * it really requires to make it support.
+                * RTL8168C/CP : supports up to 6KB jumbo frame.
+                * RTL8111C/CP : supports up to 9KB jumbo frame.
+                */
+               sc->rl_flags |= RL_FLAG_NOJUMBO;
+               break;
+       case RL_HWREV_8169_8110SB:
+       case RL_HWREV_8169_8110SCd:
+       case RL_HWREV_8169_8110SBL:
+               sc->rl_flags |= RL_FLAG_PHYWAKE;
+               break;
+       default:
+               break;
+       }
+
        /*
         * Set RX length mask, TX poll request register
         * and TX descriptor count.
@@ -1007,13 +1048,16 @@ re_attach(struct rl_softc *sc, const char *intrstr)
        ifp->if_start = re_start;
        ifp->if_watchdog = re_watchdog;
        ifp->if_init = re_init;
-       if (sc->sc_hwrev != RL_HWREV_8139CPLUS)
+       if ((sc->rl_flags & RL_FLAG_NOJUMBO) == 0)
                ifp->if_hardmtu = RL_JUMBO_MTU;
        IFQ_SET_MAXLEN(&ifp->if_snd, RL_TX_QLEN);
        IFQ_SET_READY(&ifp->if_snd);
 
-       ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_IPv4 |
-                              IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
+       
+       ifp->if_capabilities = IFCAP_VLAN_MTU;
+       if ((sc->rl_flags & RL_FLAG_DESCV2) == 0)
+               ifp->if_capabilities |= IFCAP_CSUM_IPv4 |
+                   IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
 
 #if NVLAN > 0
        ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
@@ -1354,17 +1398,22 @@ re_rxeof(struct rl_softc *sc)
 
                /* Do RX checksumming */
 
-               /* Check IP header checksum */
-               if ((rxstat & RL_RDESC_STAT_PROTOID) &&
-                   !(rxstat & RL_RDESC_STAT_IPSUMBAD))
-                       m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
-
-               /* Check TCP/UDP checksum */
-               if ((RL_TCPPKT(rxstat) &&
-                   !(rxstat & RL_RDESC_STAT_TCPSUMBAD)) ||
-                   (RL_UDPPKT(rxstat) &&
-                   !(rxstat & RL_RDESC_STAT_UDPSUMBAD)))
-                       m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK;
+               if (sc->rl_flags & RL_FLAG_DESCV2) {
+                       /* XXX V2 CSUM */
+               } else {
+                       /* Check IP header checksum */
+                       if ((rxstat & RL_RDESC_STAT_PROTOID) &&
+                           !(rxstat & RL_RDESC_STAT_IPSUMBAD))
+                               m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
+
+                       /* Check TCP/UDP checksum */
+                       if ((RL_TCPPKT(rxstat) &&
+                           !(rxstat & RL_RDESC_STAT_TCPSUMBAD)) ||
+                           (RL_UDPPKT(rxstat) &&
+                           !(rxstat & RL_RDESC_STAT_UDPSUMBAD)))
+                               m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK |
+                                   M_UDP_CSUM_IN_OK;
+               }
 
 #if NBPFILTER > 0
                if (ifp->if_bpf)
@@ -1796,6 +1845,7 @@ re_init(struct ifnet *ifp)
 {
        struct rl_softc *sc = ifp->if_softc;
        u_int32_t       rxcfg = 0;
+       u_int16_t       cfg;
        int             s;
        union {
                u_int32_t align_dummy;
@@ -1813,9 +1863,17 @@ re_init(struct ifnet *ifp)
         * Enable C+ RX and TX mode, as well as RX checksum offload.
         * We must configure the C+ register before all others.
         */
-       CSR_WRITE_2(sc, RL_CPLUS_CMD, RL_CPLUSCMD_RXENB|
-           RL_CPLUSCMD_TXENB|RL_CPLUSCMD_PCI_MRW|
-           RL_CPLUSCMD_RXCSUM_ENB);
+       cfg = RL_CPLUSCMD_PCI_MRW;
+       if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
+               cfg |= RL_CPLUSCMD_RXCSUM_ENB;
+       if (sc->rl_flags & RL_FLAG_MACSTAT) {
+               cfg |= RL_CPLUSCMD_MACSTAT_DIS;
+               /* XXX magic. */
+               cfg |= 0x0001;
+       } else {
+               cfg |= RL_CPLUSCMD_RXENB | RL_CPLUSCMD_TXENB;
+       }
+       CSR_WRITE_2(sc, RL_CPLUS_CMD, cfg);
 
        /*
         * Init our MAC address.  Even though the chipset
index ca7bdab..b5492f9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rtl81x9reg.h,v 1.48 2008/07/13 05:24:05 jsg Exp $     */
+/*     $OpenBSD: rtl81x9reg.h,v 1.49 2008/07/15 13:21:17 jsg Exp $     */
 
 /*
  * Copyright (c) 1997, 1998
 #define RL_CPLUSCMD_PCI_DAC    0x0010  /* PCI dual-address cycle only */
 #define RL_CPLUSCMD_RXCSUM_ENB 0x0020  /* enable RX checksum offload */
 #define RL_CPLUSCMD_VLANSTRIP  0x0040  /* enable VLAN tag stripping */
+#define        RL_CPLUSCMD_MACSTAT_DIS 0x0080  /* 8168B/C/CP */
+#define        RL_CPLUSCMD_ASF         0x0100  /* 8168C/CP */
+#define        RL_CPLUSCMD_DBG_SEL     0x0200  /* 8168C/CP */
+#define        RL_CPLUSCMD_FORCE_TXFC  0x0400  /* 8168C/CP */
+#define        RL_CPLUSCMD_FORCE_RXFC  0x0800  /* 8168C/CP */
+#define        RL_CPLUSCMD_FORCE_HDPX  0x1000  /* 8168C/CP */
+#define        RL_CPLUSCMD_NORMAL_MODE 0x2000  /* 8168C/CP */
+#define        RL_CPLUSCMD_DBG_ENB     0x4000  /* 8168C/CP */
+#define        RL_CPLUSCMD_BIST_ENB    0x8000  /* 8168C/CP */
 
 /* C+ early transmit threshold */
 
@@ -749,6 +758,15 @@ struct rl_softc {
        struct timeout          timer_handle;
 
        int                     rl_txstart;
+       u_int32_t               rl_flags;
+#define        RL_FLAG_MSI             0x0001
+#define        RL_FLAG_INVMAR          0x0004
+#define        RL_FLAG_PHYWAKE         0x0008
+#define        RL_FLAG_NOJUMBO         0x0010
+#define        RL_FLAG_PAR             0x0020
+#define        RL_FLAG_DESCV2          0x0040
+#define        RL_FLAG_MACSTAT         0x0080
+#define        RL_FLAG_LINK            0x8000
        int                     rl_link;
 };