summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2008-07-15 13:21:18 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2008-07-15 13:21:18 +0000
commit434607293e7dfabc971823c6a1dffa41d58093d3 (patch)
treed7b9bd6d59ce5627ff12dd82b8eb8ddfc251849e
parent57ddc1a1b18015cea76122b8b3576cef80c1463c (diff)
Adapt some code from the FreeBSD driver required to make
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.
-rw-r--r--sys/dev/ic/re.c110
-rw-r--r--sys/dev/ic/rtl81x9reg.h20
2 files changed, 103 insertions, 27 deletions
diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c
index 10bafe10af3..e12b06ba394 100644
--- a/sys/dev/ic/re.c
+++ b/sys/dev/ic/re.c
@@ -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
diff --git a/sys/dev/ic/rtl81x9reg.h b/sys/dev/ic/rtl81x9reg.h
index ca7bdab6b71..b5492f9f2b4 100644
--- a/sys/dev/ic/rtl81x9reg.h
+++ b/sys/dev/ic/rtl81x9reg.h
@@ -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
@@ -419,6 +419,15 @@
#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;
};