Module Name:    src
Committed By:   bouyer
Date:           Tue Aug 18 09:46:51 UTC 2009

Modified Files:
        src/sys/dev/ic [netbsd-4]: rtl8169.c rtl81x9reg.h rtl81x9var.h
        src/sys/dev/mii [netbsd-4]: rgephy.c rgephyreg.h
        src/sys/dev/pci [netbsd-4]: if_re_pci.c

Log Message:
Pull up following revision(s) (requested by tsutsui in ticket #1339):
        sys/dev/ic/rtl8169.c: revisions 1.107, 1.114, 1.115, 1.116,
                                        1.117 (via patch), 1.118 (via patch),
                                        1.119, 1.121
        sys/dev/ic/rtl81x9reg.h: revisions 1.36, 1.37, 1.38, 1.39
        sys/dev/ic/rtl81x9var.h: revision  1.47
        sys/dev/mii/rgephy.c: revisions    1.16, 1.18, 1.19, 1.27 (via patch)
        sys/dev/mii/rgephyreg.h: revision 1.3
        sys/dev/pci/if_re_pci.c: revision 1.36
- add support for RTL8211B(L) to rgephy(4)
- add a wakeup instruction for rgephy(4) on newer re(4) chips
- detect RTL8169CP, RTL8168D/8111D, and RTL8103E variants
- fix rgephy(4) problem on RTL8111D reported on current-users:
  http://mail-index.NetBSD.org/current-users/2009/04/12/msg008977.html
  http://mail-index.NetBSD.org/current-users/2009/04/19/msg009096.html
- pull more quirk handling from FreeBSD
- fix RX hwcksum for DESCV2 chips for PR kern/40605
- remove "B" suffix from RTL8168 device names in attach message


To generate a diff of this commit:
cvs rdiff -u -r1.72.2.10 -r1.72.2.11 src/sys/dev/ic/rtl8169.c
cvs rdiff -u -r1.25.2.5 -r1.25.2.6 src/sys/dev/ic/rtl81x9reg.h
cvs rdiff -u -r1.37.2.2 -r1.37.2.3 src/sys/dev/ic/rtl81x9var.h
cvs rdiff -u -r1.15 -r1.15.2.1 src/sys/dev/mii/rgephy.c
cvs rdiff -u -r1.2 -r1.2.2.1 src/sys/dev/mii/rgephyreg.h
cvs rdiff -u -r1.21.2.5 -r1.21.2.6 src/sys/dev/pci/if_re_pci.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/ic/rtl8169.c
diff -u src/sys/dev/ic/rtl8169.c:1.72.2.10 src/sys/dev/ic/rtl8169.c:1.72.2.11
--- src/sys/dev/ic/rtl8169.c:1.72.2.10	Tue Mar 31 18:22:02 2009
+++ src/sys/dev/ic/rtl8169.c	Tue Aug 18 09:46:51 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtl8169.c,v 1.72.2.10 2009/03/31 18:22:02 bouyer Exp $	*/
+/*	$NetBSD: rtl8169.c,v 1.72.2.11 2009/08/18 09:46:51 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1997, 1998-2003
@@ -576,43 +576,27 @@
 
 		/* Revision of 8169/8169S/8110s in bits 30..26, 23 */
 		hwrev = CSR_READ_4(sc, RTK_TXCFG) & RTK_TXCFG_HWREV;
-		/* These rev numbers are taken from Realtek's driver */
 		switch (hwrev) {
 		case RTK_HWREV_8169:
-			/* XXX not in the Realtek driver */
-			sc->sc_rev = 1;
 			sc->sc_quirk |= RTKQ_8169NONS;
 			break;
 		case RTK_HWREV_8169S:
 		case RTK_HWREV_8110S:
-			sc->sc_rev = 3;
-			sc->sc_quirk |= RTKQ_MACLDPS;
-			break;
 		case RTK_HWREV_8169_8110SB:
-			sc->sc_rev = 4;
-			sc->sc_quirk |= RTKQ_MACLDPS;
-			break;
 		case RTK_HWREV_8169_8110SC:
-			sc->sc_rev = 5;
 			sc->sc_quirk |= RTKQ_MACLDPS;
 			break;
-		case RTK_HWREV_8101E:
-			sc->sc_rev = 11;
-			sc->sc_quirk |= RTKQ_NOJUMBO;
-			break;
 		case RTK_HWREV_8168_SPIN1:
-			sc->sc_rev = 21;
-			break;
 		case RTK_HWREV_8168_SPIN2:
-			sc->sc_rev = 22;
-			break;
 		case RTK_HWREV_8168_SPIN3:
-			sc->sc_rev = 23;
+			sc->sc_quirk |= RTKQ_MACSTAT;
 			break;
 		case RTK_HWREV_8168C:
 		case RTK_HWREV_8168C_SPIN2:
-			sc->sc_rev = 24;
-			sc->sc_quirk |= RTKQ_DESCV2 | RTKQ_NOEECMD;
+		case RTK_HWREV_8168CP:
+		case RTK_HWREV_8168D:
+			sc->sc_quirk |= RTKQ_DESCV2 | RTKQ_NOEECMD |
+			    RTKQ_MACSTAT | RTKQ_CMDSTOP;
 			/*
 			 * From FreeBSD driver:
 			 * 
@@ -628,22 +612,23 @@
 			 */
 			sc->sc_quirk |= RTKQ_NOJUMBO;
 			break;
-		case RTK_HWREV_8102E:
-		case RTK_HWREV_8102EL:
-			sc->sc_rev = 25;
-			sc->sc_quirk |=
-			    RTKQ_DESCV2 | RTKQ_NOEECMD | RTKQ_NOJUMBO;
-			break;
 		case RTK_HWREV_8100E:
 		case RTK_HWREV_8100E_SPIN2:
-			/* XXX not in the Realtek driver */
-			sc->sc_rev = 0;
+		case RTK_HWREV_8101E:
 			sc->sc_quirk |= RTKQ_NOJUMBO;
 			break;
+		case RTK_HWREV_8102E:
+		case RTK_HWREV_8102EL:
+		case RTK_HWREV_8103E:
+			sc->sc_quirk |= RTKQ_DESCV2 | RTKQ_NOEECMD |
+			    RTKQ_MACSTAT | RTKQ_CMDSTOP | RTKQ_NOJUMBO;
+			break;
 		default:
 			aprint_normal("%s: Unknown revision (0x%08x)\n",
 			    sc->sc_dev.dv_xname, hwrev);
-			sc->sc_rev = 0;
+			/* assume the latest features */
+			sc->sc_quirk |= RTKQ_DESCV2 | RTKQ_NOEECMD;
+			sc->sc_quirk |= RTKQ_NOJUMBO;
 		}
 
 		/* Set RX length mask */
@@ -1332,25 +1317,49 @@
 		m->m_pkthdr.rcvif = ifp;
 
 		/* Do RX checksumming */
-
-		/* Check IP header checksum */
-		if ((rxstat & RE_RDESC_STAT_PROTOID) != 0 &&
-		    ((sc->sc_quirk & RTKQ_DESCV2) == 0 ||
-		     (rxvlan & RE_RDESC_VLANCTL_IPV4) != 0)) {
-			m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
-			if (rxstat & RE_RDESC_STAT_IPSUMBAD)
-				m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
-		}
-
-		/* Check TCP/UDP checksum */
-		if (RE_TCPPKT(rxstat)) {
-			m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
-			if (rxstat & RE_RDESC_STAT_TCPSUMBAD)
-				m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
-		} else if (RE_UDPPKT(rxstat)) {
-			m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
-			if (rxstat & RE_RDESC_STAT_UDPSUMBAD)
-				m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
+		if ((sc->sc_quirk & RTKQ_DESCV2) == 0) {
+			/* Check IP header checksum */
+			if ((rxstat & RE_RDESC_STAT_PROTOID) != 0) {
+				m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
+				if (rxstat & RE_RDESC_STAT_IPSUMBAD)
+					m->m_pkthdr.csum_flags |=
+					    M_CSUM_IPv4_BAD;
+
+				/* Check TCP/UDP checksum */
+				if (RE_TCPPKT(rxstat)) {
+					m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
+					if (rxstat & RE_RDESC_STAT_TCPSUMBAD)
+						m->m_pkthdr.csum_flags |=
+						    M_CSUM_TCP_UDP_BAD;
+				} else if (RE_UDPPKT(rxstat)) {
+					m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
+					if (rxstat & RE_RDESC_STAT_UDPSUMBAD)
+						m->m_pkthdr.csum_flags |=
+						    M_CSUM_TCP_UDP_BAD;
+				}
+			}
+		} else {
+			/* Check IPv4 header checksum */
+			if ((rxvlan & RE_RDESC_VLANCTL_IPV4) != 0) {
+				m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
+				if (rxstat & RE_RDESC_STAT_IPSUMBAD)
+					m->m_pkthdr.csum_flags |=
+					    M_CSUM_IPv4_BAD;
+
+				/* Check TCPv4/UDPv4 checksum */
+				if (RE_TCPPKT(rxstat)) {
+					m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
+					if (rxstat & RE_RDESC_STAT_TCPSUMBAD)
+						m->m_pkthdr.csum_flags |=
+						    M_CSUM_TCP_UDP_BAD;
+				} else if (RE_UDPPKT(rxstat)) {
+					m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
+					if (rxstat & RE_RDESC_STAT_UDPSUMBAD)
+						m->m_pkthdr.csum_flags |=
+						    M_CSUM_TCP_UDP_BAD;
+				}
+			}
+			/* XXX Check TCPv6/UDPv6 checksum? */
 		}
 
 		if (rxvlan & RE_RDESC_VLANCTL_TAG) {
@@ -1850,6 +1859,7 @@
 	uint8_t			*enaddr;
 	uint32_t		rxcfg = 0;
 	uint32_t		reg;
+	uint16_t cfg;
 	int error;
 
 	if ((error = re_enable(sc)) != 0)
@@ -1867,32 +1877,27 @@
 	 * RX checksum offload. We must configure the C+ register
 	 * before all others.
 	 */
-	reg = 0;
-
-	/*
-	 * XXX: Realtek docs say bits 0 and 1 are reserved, for 8169S/8110S.
-	 * FreeBSD  drivers set these bits anyway (for 8139C+?).
-	 * So far, it works.
-	 */
+	cfg = RE_CPLUSCMD_PCI_MRW;
 
 	/*
 	 * XXX: For old 8169 set bit 14.
 	 *      For 8169S/8110S and above, do not set bit 14.
 	 */
 	if ((sc->sc_quirk & RTKQ_8169NONS) != 0)
-		reg |= (0x1 << 14) | RTK_CPLUSCMD_PCI_MRW;;
+		cfg |= (0x1 << 14);
 
-	if (1)  {/* not for 8169S ? */
-		reg |=
-		    RTK_CPLUSCMD_VLANSTRIP |
-		    (ifp->if_capenable &
-		    (IFCAP_CSUM_IPv4_Rx | IFCAP_CSUM_TCPv4_Rx |
-		     IFCAP_CSUM_UDPv4_Rx) ?
-		    RTK_CPLUSCMD_RXCSUM_ENB : 0);
-	}
+	if ((ifp->if_capenable & ETHERCAP_VLAN_HWTAGGING) != 0)
+		cfg |= RE_CPLUSCMD_VLANSTRIP;
+	if ((ifp->if_capenable & (IFCAP_CSUM_IPv4_Rx |
+	     IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx)) != 0)
+		cfg |= RE_CPLUSCMD_RXCSUM_ENB;
+	if ((sc->sc_quirk & RTKQ_MACSTAT) != 0) {
+		cfg |= RE_CPLUSCMD_MACSTAT_DIS;
+		cfg |= RE_CPLUSCMD_TXENB;
+	} else
+		cfg |= RE_CPLUSCMD_RXENB | RE_CPLUSCMD_TXENB;
 
-	CSR_WRITE_2(sc, RTK_CPLUS_CMD,
-	    reg | RTK_CPLUSCMD_RXENB | RTK_CPLUSCMD_TXENB);
+	CSR_WRITE_2(sc, RTK_CPLUS_CMD, cfg);
 
 	/* XXX: from Realtek-supplied Linux driver. Wholly undocumented. */
 	if ((sc->sc_quirk & RTKQ_8139CPLUS) == 0)
@@ -2149,8 +2154,14 @@
 
 	mii_down(&sc->mii);
 
-	CSR_WRITE_1(sc, RTK_COMMAND, 0x00);
+	if ((sc->sc_quirk & RTKQ_CMDSTOP) != 0)
+		CSR_WRITE_1(sc, RTK_COMMAND, RTK_CMD_STOPREQ | RTK_CMD_TX_ENB |
+		    RTK_CMD_RX_ENB);
+	else
+		CSR_WRITE_1(sc, RTK_COMMAND, 0x00);
+	DELAY(1000);
 	CSR_WRITE_2(sc, RTK_IMR, 0x0000);
+	CSR_WRITE_2(sc, RTK_ISR, 0xFFFF);
 
 	if (sc->re_head != NULL) {
 		m_freem(sc->re_head);

Index: src/sys/dev/ic/rtl81x9reg.h
diff -u src/sys/dev/ic/rtl81x9reg.h:1.25.2.5 src/sys/dev/ic/rtl81x9reg.h:1.25.2.6
--- src/sys/dev/ic/rtl81x9reg.h:1.25.2.5	Wed Apr  1 20:27:08 2009
+++ src/sys/dev/ic/rtl81x9reg.h	Tue Aug 18 09:46:51 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtl81x9reg.h,v 1.25.2.5 2009/04/01 20:27:08 bouyer Exp $	*/
+/*	$NetBSD: rtl81x9reg.h,v 1.25.2.6 2009/08/18 09:46:51 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1997, 1998
@@ -158,6 +158,9 @@
 #define RTK_HWREV_8169_8110SB	0x10000000
 #define RTK_HWREV_8169_8110SC	0x18000000
 #define RTK_HWREV_8102EL	0x24800000
+#define RTK_HWREV_8103E		0x24C00000
+#define RTK_HWREV_8168D		0x28000000
+#define RTK_HWREV_8168DP	0x28800000
 #define RTK_HWREV_8168_SPIN1	0x30000000
 #define RTK_HWREV_8100E		0x30800000
 #define RTK_HWREV_8101E		0x34000000
@@ -167,6 +170,7 @@
 #define RTK_HWREV_8100E_SPIN2	0x38800000
 #define RTK_HWREV_8168C		0x3C000000
 #define RTK_HWREV_8168C_SPIN2	0x3C400000
+#define RTK_HWREV_8168CP	0x3C800000
 #define RTK_HWREV_8139		0x60000000
 #define RTK_HWREV_8139A		0x70000000
 #define RTK_HWREV_8139AG	0x70800000
@@ -306,6 +310,7 @@
 #define RTK_CMD_TX_ENB		0x0004
 #define RTK_CMD_RX_ENB		0x0008
 #define RTK_CMD_RESET		0x0010
+#define RTK_CMD_STOPREQ		0x0080
 
 /*
  * EEPROM control register
@@ -400,12 +405,21 @@
 
 /* C+ mode command register */
 
-#define RTK_CPLUSCMD_TXENB	0x0001	/* enable C+ transmit mode */
-#define RTK_CPLUSCMD_RXENB	0x0002	/* enable C+ receive mode */
-#define RTK_CPLUSCMD_PCI_MRW	0x0008	/* enable PCI multi-read/write */
-#define RTK_CPLUSCMD_PCI_DAC	0x0010	/* PCI dual-address cycle only */
-#define RTK_CPLUSCMD_RXCSUM_ENB	0x0020	/* enable RX checksum offload */
-#define RTK_CPLUSCMD_VLANSTRIP	0x0040	/* enable VLAN tag stripping */
+#define RE_CPLUSCMD_TXENB	0x0001	/* enable C+ transmit mode */
+#define RE_CPLUSCMD_RXENB	0x0002	/* enable C+ receive mode */
+#define RE_CPLUSCMD_PCI_MRW	0x0008	/* enable PCI multi-read/write */
+#define RE_CPLUSCMD_PCI_DAC	0x0010	/* PCI dual-address cycle only */
+#define RE_CPLUSCMD_RXCSUM_ENB	0x0020	/* enable RX checksum offload */
+#define RE_CPLUSCMD_VLANSTRIP	0x0040	/* enable VLAN tag stripping */
+#define RE_CPLUSCMD_MACSTAT_DIS	0x0080	/* 8168B/C/CP */
+#define RE_CPLUSCMD_ASF		0x0100	/* 8168C/CP */
+#define RE_CPLUSCMD_DBG_SEL	0x0200	/* 8168C/CP */
+#define RE_CPLUSCMD_FORCE_TXFC	0x0400	/* 8168C/CP */
+#define RE_CPLUSCMD_FORCE_RXFC	0x0800	/* 8168C/CP */
+#define RE_CPLUSCMD_FORCE_HDPX	0x1000	/* 8168C/CP */
+#define RE_CPLUSCMD_NORMAL_MODE	0x2000	/* 8168C/CP */
+#define RE_CPLUSCMD_DBG_ENB	0x4000	/* 8168C/CP */
+#define RE_CPLUSCMD_BIST_ENB	0x8000	/* 8168C/CP */
 
 /* C+ early transmit threshold */
 

Index: src/sys/dev/ic/rtl81x9var.h
diff -u src/sys/dev/ic/rtl81x9var.h:1.37.2.2 src/sys/dev/ic/rtl81x9var.h:1.37.2.3
--- src/sys/dev/ic/rtl81x9var.h:1.37.2.2	Tue Mar 31 18:22:02 2009
+++ src/sys/dev/ic/rtl81x9var.h	Tue Aug 18 09:46:51 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtl81x9var.h,v 1.37.2.2 2009/03/31 18:22:02 bouyer Exp $	*/
+/*	$NetBSD: rtl81x9var.h,v 1.37.2.3 2009/08/18 09:46:51 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1997, 1998
@@ -192,6 +192,8 @@
 #define RTKQ_DESCV2		0x00000020	/* has V2 TX/RX descriptor */
 #define RTKQ_NOJUMBO		0x00000040	/* no jumbo MTU support */
 #define RTKQ_NOEECMD		0x00000080	/* unusable EEPROM command */
+#define RTKQ_MACSTAT		0x00000100	/* set MACSTAT_DIS on init */
+#define RTKQ_CMDSTOP		0x00000200	/* set STOPREQ on stop */
 
 	bus_dma_tag_t 		sc_dmat;
 

Index: src/sys/dev/mii/rgephy.c
diff -u src/sys/dev/mii/rgephy.c:1.15 src/sys/dev/mii/rgephy.c:1.15.2.1
--- src/sys/dev/mii/rgephy.c:1.15	Wed Nov 29 13:57:59 2006
+++ src/sys/dev/mii/rgephy.c	Tue Aug 18 09:46:50 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: rgephy.c,v 1.15 2006/11/29 13:57:59 tsutsui Exp $	*/
+/*	$NetBSD: rgephy.c,v 1.15.2.1 2009/08/18 09:46:50 bouyer Exp $	*/
 
 /*
  * Copyright (c) 2003
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rgephy.c,v 1.15 2006/11/29 13:57:59 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rgephy.c,v 1.15.2.1 2009/08/18 09:46:50 bouyer Exp $");
 
 
 /*
@@ -61,7 +61,12 @@
 static int	rgephy_match(struct device *, struct cfdata *, void *);
 static void	rgephy_attach(struct device *, struct device *, void *);
 
-CFATTACH_DECL(rgephy, sizeof(struct mii_softc),
+struct rgephy_softc {
+	struct mii_softc mii_sc;
+	int mii_revision;
+};
+
+CFATTACH_DECL(rgephy, sizeof(struct rgephy_softc),
     rgephy_match, rgephy_attach, mii_phy_detach, mii_phy_activate);
 
 
@@ -72,8 +77,6 @@
 static void	rgephy_loop(struct mii_softc *);
 static void	rgephy_load_dspcode(struct mii_softc *);
 
-static int	rgephy_mii_model;
-
 static const struct mii_phy_funcs rgephy_funcs = {
 	rgephy_service, rgephy_status, rgephy_reset,
 };
@@ -103,19 +106,26 @@
 static void
 rgephy_attach(struct device *parent, struct device *self, void *aux)
 {
-	struct mii_softc *sc = device_private(self);
+	struct rgephy_softc *rsc = device_private(self);
+	struct mii_softc *sc = &rsc->mii_sc;
 	struct mii_attach_args *ma = aux;
 	struct mii_data *mii = ma->mii_data;
 	const struct mii_phydesc *mpd;
 	int rev;
 	const char *sep = "";
 
+	rsc = device_private(self);
+	sc = &rsc->mii_sc;
+	ma = aux;
+	mii = ma->mii_data;
+
 	rev = MII_REV(ma->mii_id2);
 	mpd = mii_phy_match(ma, rgephys);
 	aprint_naive(": Media interface\n");
 	aprint_normal(": %s, rev. %d\n", mpd->mpd_name, rev);
 
-	sc->mii_mpd_model = rev;	/* XXX miivar.h comment vs usage? */
+	rsc->mii_revision = rev;
+
 	sc->mii_inst = mii->mii_instance;
 	sc->mii_phy = ma->mii_phyno;
 	sc->mii_pdata = mii;
@@ -124,23 +134,14 @@
 
 	sc->mii_funcs = &rgephy_funcs;
 
-	/* Don't do isolate on this PHY. */
-	sc->mii_flags |= MIIF_NOISOLATE;
-
 #define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)
 #define	PRINT(n)	aprint_normal("%s%s", sep, (n)); sep = ", "
 
-#if 0
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
-	    BMCR_ISO);
-#endif
 #ifdef __FreeBSD__
 	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
 	    BMCR_LOOP|BMCR_S100);
 #endif
 
-	rgephy_mii_model = MII_MODEL(ma->mii_id2);
-
 	sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
 	sc->mii_capabilities &= ~BMSR_ANEG;
 
@@ -149,19 +150,11 @@
 	 * media explicitly. Why?
 	 */
 	aprint_normal("%s: ", sc->mii_dev.dv_xname);
-#ifdef __FreeBSD__
-	mii_phy_add_media(sc);
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
-	    RGEPHY_BMCR_FDX);
-	PRINT(", 1000baseTX");
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), 0);
-	PRINT("1000baseTX-FDX");
-#else
 	if (sc->mii_capabilities & BMSR_EXTSTAT) {
 		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
 	}
 	mii_phy_add_media(sc);
-#endif
+
 	/* rtl8169S does not report auto-sense; add manually.  */
 	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), MII_NMEDIA);
 	sep =", ";
@@ -177,9 +170,12 @@
 static int
 rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
 {
+	struct rgephy_softc *rsc;
 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
 	int reg, speed, gig, anar;
 
+	rsc = (struct rgephy_softc *)sc;
+
 	switch (cmd) {
 	case MII_POLLSTAT:
 		/*
@@ -254,7 +250,7 @@
 			}
 
 			/*
-			 * When settning the link manually, one side must
+			 * When setting the link manually, one side must
 			 * be the master and the other the slave. However
 			 * ifmedia doesn't give us a good way to specify
 			 * this, so we fake it by using one of the LINK
@@ -271,11 +267,9 @@
 			PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
 			    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
 			break;
-#ifdef foo
 		case IFM_NONE:
 			PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
 			break;
-#endif
 		case IFM_100_T4:
 		default:
 			return EINVAL;
@@ -306,9 +300,20 @@
 		 * need to restart the autonegotiation process.  Read
 		 * the BMSR twice in case it's latched.
 		 */
-		reg = PHY_READ(sc, RTK_GMEDIASTAT);
-		if ((reg & RTK_GMEDIASTAT_LINK) != 0)
-			break;
+		if (rsc->mii_revision >= 2) {
+			/* RTL8211B(L) */
+			reg = PHY_READ(sc, RGEPHY_MII_SSR);
+			if (reg & RGEPHY_SSR_LINK) {
+				sc->mii_ticks = 0;
+				break;
+			}
+		} else {
+			reg = PHY_READ(sc, RTK_GMEDIASTAT);
+			if ((reg & RTK_GMEDIASTAT_LINK) != 0) {
+				sc->mii_ticks = 0;
+				break;
+			}
+		}
 
 		/*
 		 * Only retry autonegotiation every 5 seconds.
@@ -333,7 +338,7 @@
 	    sc->mii_media_status != mii->mii_media_status ||
 	    cmd == MII_MEDIACHG) {
 	  	/* XXX only for v0/v1 phys. */
-		if (sc->mii_mpd_model < 2)
+		if (rsc->mii_revision < 2)
 		rgephy_load_dspcode(sc);
 	}
 	mii_phy_update(sc, cmd);
@@ -343,18 +348,27 @@
 static void
 rgephy_status(struct mii_softc *sc)
 {
+	struct rgephy_softc *rsc;
 	struct mii_data *mii = sc->mii_pdata;
-	int bmsr, bmcr;
+	int gstat, bmsr, bmcr;
+	uint16_t ssr;
 
 	mii->mii_media_status = IFM_AVALID;
 	mii->mii_media_active = IFM_ETHER;
 
-	bmsr = PHY_READ(sc, RTK_GMEDIASTAT);
+	rsc = (struct rgephy_softc *)sc;
+	if (rsc->mii_revision >= 2) {
+		ssr = PHY_READ(sc, RGEPHY_MII_SSR);
+		if (ssr & RGEPHY_SSR_LINK)
+			mii->mii_media_status |= IFM_ACTIVE;
+	} else {
+		gstat = PHY_READ(sc, RTK_GMEDIASTAT);
+		if ((gstat & RTK_GMEDIASTAT_LINK) != 0)
+			mii->mii_media_status |= IFM_ACTIVE;
+	}
 
-	if ((bmsr & RTK_GMEDIASTAT_LINK) != 0)
-		mii->mii_media_status |= IFM_ACTIVE;
 	bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
-
+	bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
 	bmcr = PHY_READ(sc, RGEPHY_MII_BMCR);
 
 	if ((bmcr & RGEPHY_BMCR_ISO) != 0) {
@@ -374,19 +388,39 @@
 		}
 	}
 
-	bmsr = PHY_READ(sc, RTK_GMEDIASTAT);
-	if ((bmsr & RTK_GMEDIASTAT_1000MBPS) != 0)
-		mii->mii_media_active |= IFM_1000_T;
-	else if ((bmsr & RTK_GMEDIASTAT_100MBPS) != 0)
-		mii->mii_media_active |= IFM_100_TX;
-	else if ((bmsr & RTK_GMEDIASTAT_10MBPS) != 0)
-		mii->mii_media_active |= IFM_10_T;
-	else
-		mii->mii_media_active |= IFM_NONE;
-	if ((bmsr & RTK_GMEDIASTAT_FDX) != 0)
-		mii->mii_media_active |= IFM_FDX;
-
-	return;
+	if (rsc->mii_revision >= 2) {
+		ssr = PHY_READ(sc, RGEPHY_MII_SSR);
+		switch (ssr & RGEPHY_SSR_SPD_MASK) {
+		case RGEPHY_SSR_S1000:
+			mii->mii_media_active |= IFM_1000_T;
+			break;
+		case RGEPHY_SSR_S100:
+			mii->mii_media_active |= IFM_100_TX;
+			break;
+		case RGEPHY_SSR_S10:
+			mii->mii_media_active |= IFM_10_T;
+			break;
+		default:
+			mii->mii_media_active |= IFM_NONE;
+			break;
+		}
+		if (ssr & RGEPHY_SSR_FDX)
+			mii->mii_media_active |= IFM_FDX;
+		else
+			mii->mii_media_active |= IFM_HDX;
+	} else {
+		gstat = PHY_READ(sc, RTK_GMEDIASTAT);
+		if ((gstat & RTK_GMEDIASTAT_1000MBPS) != 0)
+			mii->mii_media_active |= IFM_1000_T;
+		else if ((gstat & RTK_GMEDIASTAT_100MBPS) != 0)
+			mii->mii_media_active |= IFM_100_TX;
+		else if ((gstat & RTK_GMEDIASTAT_10MBPS) != 0)
+			mii->mii_media_active |= IFM_10_T;
+		else
+			mii->mii_media_active |= IFM_NONE;
+		if ((gstat & RTK_GMEDIASTAT_FDX) != 0)
+			mii->mii_media_active |= IFM_FDX;
+	}
 }
 
 
@@ -413,11 +447,15 @@
 static void
 rgephy_loop(struct mii_softc *sc)
 {
+	struct rgephy_softc *rsc;
 	uint32_t bmsr;
 	int i;
 
-	PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN);
-	DELAY(1000);
+	rsc = (struct rgephy_softc *)sc;
+	if (rsc->mii_revision < 2) {
+		PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN);
+		DELAY(1000);
+	}
 
 	for (i = 0; i < 15000; i++) {
 		bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
@@ -540,21 +578,17 @@
 static void
 rgephy_reset(struct mii_softc *sc)
 {
+	struct rgephy_softc *rsc;
 
 	mii_phy_reset(sc);
 	DELAY(1000);
 
-	if (sc->mii_mpd_model < 2)
+	rsc = (struct rgephy_softc *)sc;
+	if (rsc->mii_revision < 2)
 		rgephy_load_dspcode(sc);
 	else {
-		PHY_WRITE(sc, 0x1F, 0x0001);
-		PHY_WRITE(sc, 0x09, 0x273a);
-		PHY_WRITE(sc, 0x0e, 0x7bfb);
-		PHY_WRITE(sc, 0x1b, 0x841e);
-
-		PHY_WRITE(sc, 0x1F, 0x0002);
-		PHY_WRITE(sc, 0x01, 0x90D0);
 		PHY_WRITE(sc, 0x1F, 0x0000);
+		PHY_WRITE(sc, 0x0e, 0x0000);
 	}
 
 	/* Reset capabilities */

Index: src/sys/dev/mii/rgephyreg.h
diff -u src/sys/dev/mii/rgephyreg.h:1.2 src/sys/dev/mii/rgephyreg.h:1.2.2.1
--- src/sys/dev/mii/rgephyreg.h:1.2	Wed Nov 29 14:01:53 2006
+++ src/sys/dev/mii/rgephyreg.h	Tue Aug 18 09:46:50 2009
@@ -137,6 +137,17 @@
 #define RGEPHY_EXTSTS_T_FD_CAP	0x2000	/* 1000base-T FD capable */
 #define RGEPHY_EXTSTS_T_HD_CAP	0x1000	/* 1000base-T HD capable */
 
-
+/* RTL8211B(L) */
+#define RGEPHY_MII_SSR		0x11	/* PHY Specific status register */
+#define	RGEPHY_SSR_S1000	0x8000	/* 1000Mbps */
+#define	RGEPHY_SSR_S100		0x4000	/* 100Mbps */
+#define	RGEPHY_SSR_S10		0x0000	/* 10Mbps */
+#define	RGEPHY_SSR_SPD_MASK	0xc000
+#define	RGEPHY_SSR_FDX		0x2000	/* full duplex */
+#define	RGEPHY_SSR_PAGE_RECEIVED	0x1000	/* new page received */
+#define	RGEPHY_SSR_SPD_DPLX_RESOLVED	0x0800	/* speed/duplex resolved */
+#define	RGEPHY_SSR_LINK		0x0400	/* link up */
+#define	RGEPHY_SSR_MDI_XOVER	0x0040	/* MDI crossover */
+#define	RGEPHY_SSR_JABBER	0x0001	/* Jabber */
 
 #endif /* _DEV_MII_RGEPHYREG_H_ */

Index: src/sys/dev/pci/if_re_pci.c
diff -u src/sys/dev/pci/if_re_pci.c:1.21.2.5 src/sys/dev/pci/if_re_pci.c:1.21.2.6
--- src/sys/dev/pci/if_re_pci.c:1.21.2.5	Tue Mar 31 18:22:02 2009
+++ src/sys/dev/pci/if_re_pci.c	Tue Aug 18 09:46:51 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_re_pci.c,v 1.21.2.5 2009/03/31 18:22:02 bouyer Exp $	*/
+/*	$NetBSD: if_re_pci.c,v 1.21.2.6 2009/08/18 09:46:51 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1997, 1998-2003
@@ -103,7 +103,7 @@
 	    "RealTek 8100E/8101E/8102E/8102EL PCIe 10/100BaseTX" },
 	{ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8168,
 	    RTK_8168,
-	    "RealTek 8168B/8111B PCIe Gigabit Ethernet" },
+	    "RealTek 8168/8111 PCIe Gigabit Ethernet" },
 	{ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169,
 	    RTK_8169,
 	    "RealTek 8169/8110 Gigabit Ethernet" },

Reply via email to