Module Name:    src
Committed By:   martin
Date:           Sun Nov  9 12:03:18 UTC 2014

Modified Files:
        src/share/man/man4 [netbsd-6]: wm.4
        src/sys/dev/pci [netbsd-6]: if_wm.c if_wmreg.h if_wmvar.h pcidevs

Log Message:
Pullup the following revisions, requested by msaitoh in ticket #1188:
sys/dev/pci/pcidevs                     1.1172
sys/dev/pci/if_wm.c                     1.263-1.266 via patch
sys/dev/pci/if_wmreg.h                  1.55-1.56
sys/dev/pci/if_wmvar.h                  1.17
share/man/man4/wm.4                     1.26-1.27 and 1.29 via patch

- Add I354 support.
- Insert completion barrier between register write and delay().
- Fix the definition of CTRL_GIO_M_DIS. This bit is not bit 3 but bit 2.
- Cleanup


To generate a diff of this commit:
cvs rdiff -u -r1.21.6.1 -r1.21.6.2 src/share/man/man4/wm.4
cvs rdiff -u -r1.227.2.11 -r1.227.2.12 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.46.2.5 -r1.46.2.6 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.12.10.3 -r1.12.10.4 src/sys/dev/pci/if_wmvar.h
cvs rdiff -u -r1.1102.2.13 -r1.1102.2.14 src/sys/dev/pci/pcidevs

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

Modified files:

Index: src/share/man/man4/wm.4
diff -u src/share/man/man4/wm.4:1.21.6.1 src/share/man/man4/wm.4:1.21.6.2
--- src/share/man/man4/wm.4:1.21.6.1	Thu Jun 28 16:06:36 2012
+++ src/share/man/man4/wm.4	Sun Nov  9 12:03:18 2014
@@ -1,4 +1,4 @@
-.\"	$NetBSD: wm.4,v 1.21.6.1 2012/06/28 16:06:36 riz Exp $
+.\"	$NetBSD: wm.4,v 1.21.6.2 2014/11/09 12:03:18 martin Exp $
 .\"
 .\" Copyright 2002, 2003 Wasabi Systems, Inc.
 .\" All rights reserved.
@@ -33,7 +33,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd June 20, 2012
+.Dd December 30, 2013
 .Dt WM 4
 .Os
 .Sh NAME
@@ -141,6 +141,14 @@ Intel 82580 Ethernet (Copper, Fiber)
 Intel 82583 1000BASE-T Ethernet
 .It
 Intel I350 Ethernet (Copper, Fiber)
+.It
+Intel I354 (C2000 Internal) Ethernet (Copper, Fiber)
+.It
+Intel I210 Ethernet (Copper, Fiber)
+.It
+Intel I211 Ethernet
+.It
+Intel I217 and I218 Ethernet
 .El
 .Pp
 In addition to Intel's own

Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.227.2.11 src/sys/dev/pci/if_wm.c:1.227.2.12
--- src/sys/dev/pci/if_wm.c:1.227.2.11	Tue Jun  3 14:57:09 2014
+++ src/sys/dev/pci/if_wm.c	Sun Nov  9 12:03:18 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.227.2.11 2014/06/03 14:57:09 msaitoh Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.227.2.12 2014/11/09 12:03:18 martin Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.227.2.11 2014/06/03 14:57:09 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.227.2.12 2014/11/09 12:03:18 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -543,11 +543,13 @@ static int	wm_gmii_hv_readreg(device_t, 
 static void	wm_gmii_hv_writereg(device_t, int, int, int);
 static int	wm_gmii_82580_readreg(device_t, int, int);
 static void	wm_gmii_82580_writereg(device_t, int, int, int);
+static bool	wm_sgmii_uses_mdio(struct wm_softc *);
 static int	wm_sgmii_readreg(device_t, int, int);
 static void	wm_sgmii_writereg(device_t, int, int, int);
 
 static void	wm_gmii_statchg(device_t);
 
+static int	wm_get_phy_id_82575(struct wm_softc *);
 static void	wm_gmii_mediainit(struct wm_softc *, pci_product_id_t);
 static int	wm_gmii_mediachange(struct ifnet *);
 static void	wm_gmii_mediastatus(struct ifnet *, struct ifmediareq *);
@@ -1024,6 +1026,9 @@ static const struct wm_product {
 	  "I350 Gigabit Connection",
 	  WM_T_I350,		WMP_F_1000T },
 #endif
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_C2000_SGMII,
+	  "I354 Gigabit Connection",
+	  WM_T_I354,		WMP_F_1000T },
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I210_T1,
 	  "I210-T1 Ethernet Server Adapter",
 	  WM_T_I210,		WMP_F_1000T },
@@ -1210,8 +1215,8 @@ wm_attach(device_t parent, device_t self
 
 	if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
 	    || (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
-	    || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210)
-	    || (sc->sc_type == WM_T_I211))
+	    || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354)
+	    || (sc->sc_type == WM_T_I210) || (sc->sc_type == WM_T_I211))
 		sc->sc_flags |= WM_F_NEWQUEUE;
 
 	/* Set device properties (mactype) */
@@ -1326,7 +1331,7 @@ wm_attach(device_t parent, device_t self
 	    || (sc->sc_type ==  WM_T_82571) || (sc->sc_type == WM_T_80003)
 	    || (sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
 	    || (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
-	    || (sc->sc_type == WM_T_I350))
+	    || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354))
 		sc->sc_funcid = (CSR_READ(sc, WMREG_STATUS)
 		    >> STATUS_FUNCID_SHIFT) & STATUS_FUNCID_MASK;
 	else
@@ -1597,6 +1602,7 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354: /* XXXX ok? */
 	case WM_T_80003:
 		/* SPI */
 		wm_set_spiaddrbits(sc);
@@ -1687,10 +1693,8 @@ wm_attach(device_t parent, device_t self
 	case WM_T_PCH:
 	case WM_T_PCH2:
 	case WM_T_PCH_LPT:
-		if (wm_check_mng_mode(sc) != 0) {
-			printf ("get hw control (1)\n");
+		if (wm_check_mng_mode(sc) != 0)
 			wm_get_hw_control(sc);
-		}
 		break;
 	default:
 		break;
@@ -1773,6 +1777,7 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354: /* XXX ok? */
 	case WM_T_ICH8:
 	case WM_T_ICH9:
 	case WM_T_ICH10:
@@ -1899,20 +1904,30 @@ wm_attach(device_t parent, device_t self
 		case WM_T_82580:
 		case WM_T_82580ER:
 		case WM_T_I350:
+		case WM_T_I354:
 		case WM_T_I210:
 		case WM_T_I211:
 			reg = CSR_READ(sc, WMREG_CTRL_EXT);
 			switch (reg & CTRL_EXT_LINK_MODE_MASK) {
-			case CTRL_EXT_LINK_MODE_SGMII:
-				aprint_verbose_dev(sc->sc_dev, "SGMII\n");
-				sc->sc_flags |= WM_F_SGMII;
+			case CTRL_EXT_LINK_MODE_1000KX:
+				aprint_verbose_dev(sc->sc_dev, "1000KX\n");
 				CSR_WRITE(sc, WMREG_CTRL_EXT,
 				    reg | CTRL_EXT_I2C_ENA);
-				wm_gmii_mediainit(sc, wmp->wmp_product);
+				panic("not supported yet\n");
 				break;
-			case CTRL_EXT_LINK_MODE_1000KX:
+			case CTRL_EXT_LINK_MODE_SGMII:
+				if (wm_sgmii_uses_mdio(sc)) {
+					aprint_verbose_dev(sc->sc_dev,
+					    "SGMII(MDIO)\n");
+					sc->sc_flags |= WM_F_SGMII;
+					wm_gmii_mediainit(sc,
+					    wmp->wmp_product);
+					break;
+				}
+				aprint_verbose_dev(sc->sc_dev, "SGMII(I2C)\n");
+				/*FALLTHROUGH*/
 			case CTRL_EXT_LINK_MODE_PCIE_SERDES:
-				aprint_verbose_dev(sc->sc_dev, "1000KX or SERDES\n");
+				aprint_verbose_dev(sc->sc_dev, "SERDES\n");
 				CSR_WRITE(sc, WMREG_CTRL_EXT,
 				    reg | CTRL_EXT_I2C_ENA);
 				panic("not supported yet\n");
@@ -1965,6 +1980,7 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354: /* XXXX ok? */
 	case WM_T_I210:
 	case WM_T_I211:
 	case WM_T_80003:
@@ -3708,7 +3724,8 @@ wm_rxintr(struct wm_softc *sc)
 		 * For an eratta, the RCTL_SECRC bit in RCTL register
 		 * is always set in I350, so we don't trim it.
 		 */
-		if ((sc->sc_type != WM_T_I350) && (sc->sc_type != WM_T_I210)
+		if ((sc->sc_type != WM_T_I350) && (sc->sc_type != WM_T_I354)
+		    && (sc->sc_type != WM_T_I210)
 		    && (sc->sc_type != WM_T_I211)) {
 			if (m->m_len < ETHER_CRC_LEN) {
 				sc->sc_rxtail->m_len
@@ -3759,6 +3776,7 @@ wm_rxintr(struct wm_softc *sc)
 		 * If VLANs are enabled, VLAN packets have been unwrapped
 		 * for us.  Associate the tag with the packet.
 		 */
+		/* XXXX should check for i350 and i354 */
 		if ((status & WRX_ST_VP) != 0) {
 			VLAN_INPUT_TAG(ifp, m,
 			    le16toh(vlantag),
@@ -4041,6 +4059,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82572:
 	case WM_T_82575:	/* XXX need special handing for jumbo frames */
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_80003:
 		sc->sc_pba = PBA_32K;
 		break;
@@ -4099,7 +4118,7 @@ wm_reset(struct wm_softc *sc)
 
 	/* Set the completion timeout for interface */
 	if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
-	    || (sc->sc_type == WM_T_I350))
+	    || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354))
 		wm_set_pcie_completion_timeout(sc);
 
 	/* Clear interrupt */
@@ -4107,8 +4126,9 @@ wm_reset(struct wm_softc *sc)
 
 	/* Stop the transmit and receive processes. */
 	CSR_WRITE(sc, WMREG_RCTL, 0);
-	CSR_WRITE(sc, WMREG_TCTL, TCTL_PSP);
 	sc->sc_rctl &= ~RCTL_EN;
+	CSR_WRITE(sc, WMREG_TCTL, TCTL_PSP);
+	CSR_WRITE_FLUSH(sc);
 
 	/* XXX set_tbi_sbp_82543() */
 
@@ -4133,6 +4153,7 @@ wm_reset(struct wm_softc *sc)
 	if ((sc->sc_type == WM_T_82541) || (sc->sc_type == WM_T_82547)) {
 		CSR_WRITE(sc, WMREG_CTRL,
 		    CSR_READ(sc, WMREG_CTRL) | CTRL_PHY_RESET);
+		CSR_WRITE_FLUSH(sc);
 		delay(5000);
 	}
 
@@ -4193,6 +4214,7 @@ wm_reset(struct wm_softc *sc)
 		}
 		wm_get_swfwhw_semaphore(sc);
 		CSR_WRITE(sc, WMREG_CTRL, reg);
+		/* Don't insert a completion barrier when reset */
 		delay(20*1000);
 		wm_put_swfwhw_semaphore(sc);
 		break;
@@ -4212,6 +4234,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82580ER:
 	case WM_T_82583:
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_I210:
 	case WM_T_I211:
 	default:
@@ -4242,6 +4265,7 @@ wm_reset(struct wm_softc *sc)
 		delay(10);
 		reg = CSR_READ(sc, WMREG_CTRL_EXT) | CTRL_EXT_EE_RST;
 		CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+		CSR_WRITE_FLUSH(sc);
 		delay(2000);
 		break;
 	case WM_T_82540:
@@ -4268,6 +4292,7 @@ wm_reset(struct wm_softc *sc)
 			delay(10);
 			reg = CSR_READ(sc, WMREG_CTRL_EXT) | CTRL_EXT_EE_RST;
 			CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+			CSR_WRITE_FLUSH(sc);
 		}
 		/* check EECD_EE_AUTORD */
 		wm_get_auto_rd_done(sc);
@@ -4284,6 +4309,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_I210:
 	case WM_T_I211:
 	case WM_T_80003:
@@ -4310,6 +4336,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82580ER:
 #endif
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_ICH8:
 	case WM_T_ICH9:
 		if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) {
@@ -4319,7 +4346,8 @@ wm_reset(struct wm_softc *sc)
 			    || (sc->sc_type == WM_T_82576)
 			    || (sc->sc_type == WM_T_82580)
 			    || (sc->sc_type == WM_T_82580ER)
-			    || (sc->sc_type == WM_T_I350))
+			    || (sc->sc_type == WM_T_I350)
+			    || (sc->sc_type == WM_T_I354))
 				wm_reset_init_script_82575(sc);
 		}
 		break;
@@ -4328,7 +4356,7 @@ wm_reset(struct wm_softc *sc)
 	}
 
 	if ((sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
-	    || (sc->sc_type == WM_T_I350)) {
+	    || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354)) {
 		/* clear global device reset status bit */
 		CSR_WRITE(sc, WMREG_STATUS, STATUS_DEV_RST_SET);
 	}
@@ -4564,7 +4592,7 @@ wm_init(struct ifnet *ifp)
 	 * Clear out the VLAN table -- we don't use it (yet).
 	 */
 	CSR_WRITE(sc, WMREG_VET, 0);
-	if (sc->sc_type == WM_T_I350)
+	if ((sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354))
 		trynum = 10; /* Due to hw errata */
 	else
 		trynum = 1;
@@ -4763,7 +4791,8 @@ wm_init(struct ifnet *ifp)
 	 * The I350 has a bug where it always strips the CRC whether
 	 * asked to or not. So ask for stripped CRC here and cope in rxeof
 	 */
-	if ((sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210))
+	if ((sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354)
+	    || (sc->sc_type == WM_T_I210))
 		sc->sc_rctl |= RCTL_SECRC;
 
 	if (((sc->sc_ethercom.ec_capabilities & ETHERCAP_JUMBO_MTU) != 0)
@@ -4942,6 +4971,7 @@ wm_get_auto_rd_done(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_I210:
 	case WM_T_I211:
 	case WM_T_80003:
@@ -5033,6 +5063,7 @@ wm_get_cfg_done(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_I210:
 	case WM_T_I211:
 		if (sc->sc_type == WM_T_82571) {
@@ -5183,10 +5214,13 @@ wm_eeprom_sendbits(struct wm_softc *sc, 
 		else
 			reg &= ~EECD_DI;
 		CSR_WRITE(sc, WMREG_EECD, reg);
+		CSR_WRITE_FLUSH(sc);
 		delay(2);
 		CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
+		CSR_WRITE_FLUSH(sc);
 		delay(2);
 		CSR_WRITE(sc, WMREG_EECD, reg);
+		CSR_WRITE_FLUSH(sc);
 		delay(2);
 	}
 }
@@ -5207,10 +5241,12 @@ wm_eeprom_recvbits(struct wm_softc *sc, 
 	val = 0;
 	for (x = nbits; x > 0; x--) {
 		CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
+		CSR_WRITE_FLUSH(sc);
 		delay(2);
 		if (CSR_READ(sc, WMREG_EECD) & EECD_DO)
 			val |= (1U << (x - 1));
 		CSR_WRITE(sc, WMREG_EECD, reg);
+		CSR_WRITE_FLUSH(sc);
 		delay(2);
 	}
 	*valp = val;
@@ -5244,6 +5280,7 @@ wm_read_eeprom_uwire(struct wm_softc *sc
 			CSR_WRITE(sc, WMREG_EECD, reg);
 			reg &= ~EECD_SK;
 			CSR_WRITE(sc, WMREG_EECD, reg);
+			CSR_WRITE_FLUSH(sc);
 			delay(2);
 		}
 		/* XXX: end of workaround */
@@ -5251,6 +5288,7 @@ wm_read_eeprom_uwire(struct wm_softc *sc
 		/* Set CHIP SELECT. */
 		reg |= EECD_CS;
 		CSR_WRITE(sc, WMREG_EECD, reg);
+		CSR_WRITE_FLUSH(sc);
 		delay(2);
 
 		/* Shift in the READ command. */
@@ -5266,6 +5304,7 @@ wm_read_eeprom_uwire(struct wm_softc *sc
 		/* Clear CHIP SELECT. */
 		reg = CSR_READ(sc, WMREG_EECD) & ~EECD_CS;
 		CSR_WRITE(sc, WMREG_EECD, reg);
+		CSR_WRITE_FLUSH(sc);
 		delay(2);
 	}
 
@@ -5311,6 +5350,7 @@ wm_read_eeprom_spi(struct wm_softc *sc, 
 	/* Clear SK and CS. */
 	reg = CSR_READ(sc, WMREG_EECD) & ~(EECD_SK | EECD_CS);
 	CSR_WRITE(sc, WMREG_EECD, reg);
+	CSR_WRITE_FLUSH(sc);
 	delay(2);
 
 	if (wm_spi_eeprom_ready(sc))
@@ -5318,8 +5358,10 @@ wm_read_eeprom_spi(struct wm_softc *sc, 
 
 	/* Toggle CS to flush commands. */
 	CSR_WRITE(sc, WMREG_EECD, reg | EECD_CS);
+	CSR_WRITE_FLUSH(sc);
 	delay(2);
 	CSR_WRITE(sc, WMREG_EECD, reg);
+	CSR_WRITE_FLUSH(sc);
 	delay(2);
 
 	opc = SPI_OPC_READ;
@@ -5337,6 +5379,7 @@ wm_read_eeprom_spi(struct wm_softc *sc, 
 	/* Raise CS and clear SK. */
 	reg = (CSR_READ(sc, WMREG_EECD) & ~EECD_SK) | EECD_CS;
 	CSR_WRITE(sc, WMREG_EECD, reg);
+	CSR_WRITE_FLUSH(sc);
 	delay(2);
 
 	return 0;
@@ -5357,9 +5400,11 @@ wm_read_eeprom_spi(struct wm_softc *sc, 
 static int
 wm_validate_eeprom_checksum(struct wm_softc *sc)
 {
-	uint16_t checksum, valid_checksum;
+	uint16_t checksum;
 	uint16_t eeprom_data;
-	uint16_t csum_wordaddr;
+#ifdef WM_DEBUG
+	uint16_t csum_wordaddr, valid_checksum;
+#endif
 	int i;
 
 	checksum = 0;
@@ -5368,6 +5413,7 @@ wm_validate_eeprom_checksum(struct wm_so
 	if (sc->sc_type == WM_T_I211)
 		return 0;
 
+#ifdef WM_DEBUG
 	if (sc->sc_type == WM_T_PCH_LPT) {
 		csum_wordaddr = NVM_COMPAT;
 		valid_checksum = NVM_COMPAT_VALID_CHECKSUM;
@@ -5376,7 +5422,6 @@ wm_validate_eeprom_checksum(struct wm_so
 		valid_checksum = NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM;
 	}
 
-#ifdef WM_DEBUG
 	/* Dump EEPROM image for debug */
 	if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
 	    || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH)
@@ -5532,6 +5577,7 @@ wm_read_mac_addr(struct wm_softc *sc, ui
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 		switch (sc->sc_funcid) {
 		case 0:
 			/* default value (== EEPROM_OFF_MACADDR) */
@@ -5773,7 +5819,7 @@ wm_set_filter(struct wm_softc *sc)
 		size = WM_RAL_TABSIZE_82575;
 	else if ((sc->sc_type == WM_T_82576) || (sc->sc_type == WM_T_82580))
 		size = WM_RAL_TABSIZE_82576;
-	else if (sc->sc_type == WM_T_I350)
+	else if ((sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354))
 		size = WM_RAL_TABSIZE_I350;
 	else
 		size = WM_RAL_TABSIZE;
@@ -5955,12 +6001,14 @@ wm_tbi_mediachange(struct ifnet *ifp)
 		sc->sc_ctrl |= CTRL_SLU | CTRL_FD;
 		sc->sc_ctrl &= ~(CTRL_TFCE | CTRL_RFCE);
 		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+		CSR_WRITE_FLUSH(sc);
 		delay(1000);
 	}
 
 	DPRINTF(WM_DEBUG_LINK,("%s: sc_txcw = 0x%x after autoneg check\n",
 		    device_xname(sc->sc_dev),sc->sc_txcw));
 	CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw);
+	CSR_WRITE_FLUSH(sc);
 	delay(10000);
 
 	i = CSR_READ(sc, WMREG_CTRL) & CTRL_SWDPIN(1);
@@ -5979,9 +6027,11 @@ wm_tbi_mediachange(struct ifnet *ifp)
 			 */
 			sc->sc_ctrl |= CTRL_LRST;
 			CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+			CSR_WRITE_FLUSH(sc);
 			delay(1000);
 			sc->sc_ctrl &= ~CTRL_LRST;
 			CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+			CSR_WRITE_FLUSH(sc);
 			delay(1000);
 		}
 
@@ -6075,12 +6125,13 @@ wm_tbi_check_link(struct wm_softc *sc)
 {
 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 	struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur;
-	uint32_t rxcw, ctrl, status;
+	uint32_t status;
 
 	status = CSR_READ(sc, WMREG_STATUS);
 
-	rxcw = CSR_READ(sc, WMREG_RXCW);
-	ctrl = CSR_READ(sc, WMREG_CTRL);
+	/* XXX is this needed? */
+	(void)CSR_READ(sc, WMREG_RXCW);
+	(void)CSR_READ(sc, WMREG_CTRL);
 
 	/* set link status */
 	if ((status & STATUS_LU) == 0) {
@@ -6114,9 +6165,11 @@ wm_tbi_check_link(struct wm_softc *sc)
 				 */
 				sc->sc_ctrl |= CTRL_LRST;
 				CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+				CSR_WRITE_FLUSH(sc);
 				delay(1000);
 				sc->sc_ctrl &= ~CTRL_LRST;
 				CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+				CSR_WRITE_FLUSH(sc);
 				delay(1000);
 				CSR_WRITE(sc, WMREG_TXCW,
 				    sc->sc_txcw & ~TXCW_ANE);
@@ -6154,6 +6207,7 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_I210:
 	case WM_T_I211:
 	case WM_T_80003:
@@ -6200,9 +6254,11 @@ wm_gmii_reset(struct wm_softc *sc)
 		reg |= CTRL_EXT_SWDPIO(4);
 
 		CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+		CSR_WRITE_FLUSH(sc);
 		delay(10*1000);
 
 		CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_SWDPIN(4));
+		CSR_WRITE_FLUSH(sc);
 		delay(150);
 #if 0
 		sc->sc_ctrl_ext = reg | CTRL_EXT_SWDPIN(4);
@@ -6228,14 +6284,17 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_I210:
 	case WM_T_I211:
 	case WM_T_82583:
 	case WM_T_80003:
 		/* generic reset */
 		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET);
+		CSR_WRITE_FLUSH(sc);
 		delay(20000);
 		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+		CSR_WRITE_FLUSH(sc);
 		delay(20000);
 
 		if ((sc->sc_type == WM_T_82541)
@@ -6254,8 +6313,10 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_PCH_LPT:
 		/* generic reset */
 		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET);
+		CSR_WRITE_FLUSH(sc);
 		delay(100);
 		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+		CSR_WRITE_FLUSH(sc);
 		delay(150);
 		break;
 	default:
@@ -6279,6 +6340,7 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_I210:
 	case WM_T_I211:
 	case WM_T_80003:
@@ -6323,6 +6385,7 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_I210:
 	case WM_T_I211:
 	case WM_T_82583:
@@ -6381,6 +6444,45 @@ wm_gmii_reset(struct wm_softc *sc)
 }
 
 /*
+ * wm_get_phy_id_82575:
+ *
+ * Return PHY ID. Return -1 if it failed.
+ */
+static int
+wm_get_phy_id_82575(struct wm_softc *sc)
+{
+	uint32_t reg;
+	int phyid = -1;
+
+	/* XXX */
+	if ((sc->sc_flags & WM_F_SGMII) == 0)
+		return -1;
+
+	if (wm_sgmii_uses_mdio(sc)) {
+		switch (sc->sc_type) {
+		case WM_T_82575:
+		case WM_T_82576:
+			reg = CSR_READ(sc, WMREG_MDIC);
+			phyid = (reg & MDIC_PHY_MASK) >> MDIC_PHY_SHIFT;
+			break;
+		case WM_T_82580:
+		case WM_T_I350:
+		case WM_T_I354:
+		case WM_T_I210:
+		case WM_T_I211:
+			reg = CSR_READ(sc, WMREG_MDICNFG);
+			phyid = (reg & MDICNFG_PHY_MASK) >> MDICNFG_PHY_SHIFT;
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	return phyid;
+}
+
+
+/*
  * wm_gmii_mediainit:
  *
  *	Initialize media for use on 1000BASE-T devices.
@@ -6466,7 +6568,8 @@ wm_gmii_mediainit(struct wm_softc *sc, p
 		mii->mii_writereg = wm_gmii_bm_writereg;
 		break;
 	default:
-		if ((sc->sc_flags & WM_F_SGMII) != 0) {
+		if (((sc->sc_flags & WM_F_SGMII) != 0)
+		    && !wm_sgmii_uses_mdio(sc)){
 			mii->mii_readreg = wm_sgmii_readreg;
 			mii->mii_writereg = wm_sgmii_writereg;
 		} else if (sc->sc_type >= WM_T_80003) {
@@ -6498,30 +6601,39 @@ wm_gmii_mediainit(struct wm_softc *sc, p
 
 	if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
 	    || (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
-	    || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210)
-	    || (sc->sc_type == WM_T_I211)) {
+	    || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354)
+	    || (sc->sc_type == WM_T_I210) || (sc->sc_type == WM_T_I211)) {
 		if ((sc->sc_flags & WM_F_SGMII) == 0) {
 			/* Attach only one port */
 			mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, 1,
 			    MII_OFFSET_ANY, MIIF_DOPAUSE);
 		} else {
-			int i;
+			int i, id;
 			uint32_t ctrl_ext;
 
-			/* Power on sgmii phy if it is disabled */
-			ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT);
-			CSR_WRITE(sc, WMREG_CTRL_EXT,
-			    ctrl_ext &~ CTRL_EXT_SWDPIN(3));
-			CSR_WRITE_FLUSH(sc);
-			delay(300*1000); /* XXX too long */
-
-			/* from 1 to 8 */
-			for (i = 1; i < 8; i++)
+			id = wm_get_phy_id_82575(sc);
+			if (id != -1) {
 				mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff,
-				    i, MII_OFFSET_ANY, MIIF_DOPAUSE);
+				    id, MII_OFFSET_ANY, MIIF_DOPAUSE);
+			}
+			if ((id == -1)
+			    || (LIST_FIRST(&mii->mii_phys) == NULL)) {
+				/* Power on sgmii phy if it is disabled */
+				ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT);
+				CSR_WRITE(sc, WMREG_CTRL_EXT,
+				    ctrl_ext &~ CTRL_EXT_SWDPIN(3));
+				CSR_WRITE_FLUSH(sc);
+				delay(300*1000); /* XXX too long */
+
+				/* from 1 to 8 */
+				for (i = 1; i < 8; i++)
+					mii_attach(sc->sc_dev, &sc->sc_mii,
+					    0xffffffff, i, MII_OFFSET_ANY,
+					    MIIF_DOPAUSE);
 
-			/* restore previous sfp cage power state */
-			CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
+				/* restore previous sfp cage power state */
+				CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
+			}
 		}
 	} else {
 		mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
@@ -6661,10 +6773,13 @@ i82543_mii_sendbits(struct wm_softc *sc,
 		else
 			v &= ~MDI_IO;
 		CSR_WRITE(sc, WMREG_CTRL, v);
+		CSR_WRITE_FLUSH(sc);
 		delay(10);
 		CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK);
+		CSR_WRITE_FLUSH(sc);
 		delay(10);
 		CSR_WRITE(sc, WMREG_CTRL, v);
+		CSR_WRITE_FLUSH(sc);
 		delay(10);
 	}
 }
@@ -6679,25 +6794,32 @@ i82543_mii_recvbits(struct wm_softc *sc)
 	v |= CTRL_SWDPIO(3);
 
 	CSR_WRITE(sc, WMREG_CTRL, v);
+	CSR_WRITE_FLUSH(sc);
 	delay(10);
 	CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK);
+	CSR_WRITE_FLUSH(sc);
 	delay(10);
 	CSR_WRITE(sc, WMREG_CTRL, v);
+	CSR_WRITE_FLUSH(sc);
 	delay(10);
 
 	for (i = 0; i < 16; i++) {
 		data <<= 1;
 		CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK);
+		CSR_WRITE_FLUSH(sc);
 		delay(10);
 		if (CSR_READ(sc, WMREG_CTRL) & MDI_IO)
 			data |= 1;
 		CSR_WRITE(sc, WMREG_CTRL, v);
+		CSR_WRITE_FLUSH(sc);
 		delay(10);
 	}
 
 	CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK);
+	CSR_WRITE_FLUSH(sc);
 	delay(10);
 	CSR_WRITE(sc, WMREG_CTRL, v);
+	CSR_WRITE_FLUSH(sc);
 	delay(10);
 
 	return data;
@@ -7113,6 +7235,40 @@ wm_gmii_hv_writereg(device_t self, int p
 }
 
 /*
+ * wm_sgmii_uses_mdio
+ *
+ * Check whether the transaction is to the internal PHY or the external
+ * MDIO interface. Return true if it's MDIO.
+ */
+static bool
+wm_sgmii_uses_mdio(struct wm_softc *sc)
+{
+	uint32_t reg;
+	bool ismdio = false;
+
+	switch (sc->sc_type) {
+	case WM_T_82575:
+	case WM_T_82576:
+		reg = CSR_READ(sc, WMREG_MDIC);
+		ismdio = ((reg & MDIC_DEST) != 0);
+		break;
+	case WM_T_82580:
+	case WM_T_82580ER:
+	case WM_T_I350:
+	case WM_T_I354:
+	case WM_T_I210:
+	case WM_T_I211:
+		reg = CSR_READ(sc, WMREG_MDICNFG);
+		ismdio = ((reg & MDICNFG_DEST) != 0);
+		break;
+	default:
+		break;
+	}
+
+	return ismdio;
+}
+
+/*
  * wm_sgmii_readreg:	[mii interface function]
  *
  *	Read a PHY register on the SGMII
@@ -7338,6 +7494,7 @@ wm_kmrn_readreg(struct wm_softc *sc, int
 	CSR_WRITE(sc, WMREG_KUMCTRLSTA,
 	    ((reg << KUMCTRLSTA_OFFSET_SHIFT) & KUMCTRLSTA_OFFSET) |
 	    KUMCTRLSTA_REN);
+	CSR_WRITE_FLUSH(sc);
 	delay(2);
 
 	rv = CSR_READ(sc, WMREG_KUMCTRLSTA) & KUMCTRLSTA_MASK;
@@ -8359,10 +8516,12 @@ wm_configure_k1_ich8lan(struct wm_softc 
 
 	CSR_WRITE(sc, WMREG_CTRL, tmp);
 	CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext | CTRL_EXT_SPD_BYPS);
+	CSR_WRITE_FLUSH(sc);
 	delay(20);
 
 	CSR_WRITE(sc, WMREG_CTRL, ctrl);
 	CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
+	CSR_WRITE_FLUSH(sc);
 	delay(20);
 }
 
@@ -8377,9 +8536,11 @@ wm_smbustopci(struct wm_softc *sc)
 		sc->sc_ctrl |= CTRL_LANPHYPC_OVERRIDE;
 		sc->sc_ctrl &= ~CTRL_LANPHYPC_VALUE;
 		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+		CSR_WRITE_FLUSH(sc);
 		delay(10);
 		sc->sc_ctrl &= ~CTRL_LANPHYPC_OVERRIDE;
 		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+		CSR_WRITE_FLUSH(sc);
 		delay(50*1000);
 
 		/*
@@ -8511,6 +8672,7 @@ wm_get_wakeup(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 		if ((CSR_READ(sc, WMREG_FWSM) & FWSM_MODE_MASK) != 0)
 			sc->sc_flags |= WM_F_ARC_SUBSYS_VALID;
 		sc->sc_flags |= WM_F_ASF_FIRMWARE_PRES;

Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.46.2.5 src/sys/dev/pci/if_wmreg.h:1.46.2.6
--- src/sys/dev/pci/if_wmreg.h:1.46.2.5	Mon Jul 29 20:24:04 2013
+++ src/sys/dev/pci/if_wmreg.h	Sun Nov  9 12:03:18 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmreg.h,v 1.46.2.5 2013/07/29 20:24:04 jdc Exp $	*/
+/*	$NetBSD: if_wmreg.h,v 1.46.2.6 2014/11/09 12:03:18 martin Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -209,8 +209,8 @@ struct livengood_tcpip_ctxdesc {
 #define	CTRL_FD		(1U << 0)	/* full duplex */
 #define	CTRL_BEM	(1U << 1)	/* big-endian mode */
 #define	CTRL_PRIOR	(1U << 2)	/* 0 = receive, 1 = fair */
+#define	CTRL_GIO_M_DIS	(1U << 2)	/* disabl PCI master access */
 #define	CTRL_LRST	(1U << 3)	/* link reset */
-#define	CTRL_GIO_M_DIS	(1U << 3)	/* disabl PCI master access */
 #define	CTRL_ASDE	(1U << 5)	/* auto speed detect enable */
 #define	CTRL_SLU	(1U << 6)	/* set link up */
 #define	CTRL_ILOS	(1U << 7)	/* invert loss of signal */
@@ -417,12 +417,15 @@ struct livengood_tcpip_ctxdesc {
 #define	WMREG_MDIC	0x0020	/* MDI Control Register */
 #define	MDIC_DATA(x)	((x) & 0xffff)
 #define	MDIC_REGADD(x)	((x) << 16)
+#define	MDIC_PHY_SHIFT	21
+#define	MDIC_PHY_MASK	__BITS(25, 21)
 #define	MDIC_PHYADD(x)	((x) << 21)
 #define	MDIC_OP_WRITE	(1U << 26)
 #define	MDIC_OP_READ	(2U << 26)
 #define	MDIC_READY	(1U << 28)
 #define	MDIC_I		(1U << 29)	/* interrupt on MDI complete */
 #define	MDIC_E		(1U << 30)	/* MDI error */
+#define	MDIC_DEST	(1U << 31)	/* Destination */
 
 #define WMREG_SCTL	0x0024	/* SerDes Control - RW */
 /*
@@ -705,6 +708,12 @@ struct livengood_tcpip_ctxdesc {
 
 #define	WMREG_VFTA	0x0600
 
+#define	WMREG_MDICNFG	0x0e04	/* MDC/MDIO Configuration Register */
+#define MDICNFG_PHY_SHIFT	21
+#define MDICNFG_PHY_MASK	__BITS(25, 21)
+#define MDICNFG_COM_MDIO	__BIT(30)
+#define MDICNFG_DEST		__BIT(31)
+
 #define	WM_MC_TABSIZE	128
 #define	WM_ICH8_MC_TABSIZE 32
 #define	WM_VLAN_TABSIZE	128

Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.12.10.3 src/sys/dev/pci/if_wmvar.h:1.12.10.4
--- src/sys/dev/pci/if_wmvar.h:1.12.10.3	Sun Jul 14 20:39:13 2013
+++ src/sys/dev/pci/if_wmvar.h	Sun Nov  9 12:03:18 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmvar.h,v 1.12.10.3 2013/07/14 20:39:13 riz Exp $	*/
+/*	$NetBSD: if_wmvar.h,v 1.12.10.4 2014/11/09 12:03:18 martin Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -121,6 +121,7 @@ typedef enum {
 	WM_T_82580,			/* i82580 */
 	WM_T_82580ER,			/* i82580ER */
 	WM_T_I350,			/* I350 */
+	WM_T_I354,			/* I354 */
 	WM_T_I210,			/* I210 */
 	WM_T_I211,			/* I211 */
 	WM_T_80003,			/* i80003 */

Index: src/sys/dev/pci/pcidevs
diff -u src/sys/dev/pci/pcidevs:1.1102.2.13 src/sys/dev/pci/pcidevs:1.1102.2.14
--- src/sys/dev/pci/pcidevs:1.1102.2.13	Sat Sep  7 16:39:32 2013
+++ src/sys/dev/pci/pcidevs	Sun Nov  9 12:03:18 2014
@@ -1,4 +1,4 @@
-$NetBSD: pcidevs,v 1.1102.2.13 2013/09/07 16:39:32 bouyer Exp $
+$NetBSD: pcidevs,v 1.1102.2.14 2014/11/09 12:03:18 martin Exp $
 
 /*
  * Copyright (c) 1995, 1996 Christopher G. Demetriou
@@ -2803,6 +2803,43 @@ product INTEL MOBILE_HM76_LPC	0x1e59	Mob
 product INTEL MOBILE_HM75_LPC	0x1e5d	Mobile HM75 LPC
 product INTEL MOBILE_HM70_LPC	0x1e5e	Mobile HM70 LPC
 product INTEL NM70_LPC		0x1e5f	NM70 LPC
+product INTEL C2000_TROUTER_0	0x1f00	C2000 Transaction Router
+product INTEL C2000_TROUTER_1	0x1f01	C2000 Transaction Router
+product INTEL C2000_TROUTER_2	0x1f02	C2000 Transaction Router
+product INTEL C2000_TROUTER_3	0x1f03	C2000 Transaction Router
+product INTEL C2000_TROUTER_4	0x1f04	C2000 Transaction Router
+product INTEL C2000_TROUTER_5	0x1f05	C2000 Transaction Router
+product INTEL C2000_TROUTER_6	0x1f06	C2000 Transaction Router
+product INTEL C2000_TROUTER_7	0x1f07	C2000 Transaction Router
+product INTEL C2000_TROUTER_8	0x1f08	C2000 Transaction Router
+product INTEL C2000_TROUTER_9	0x1f09	C2000 Transaction Router
+product INTEL C2000_TROUTER_A	0x1f0a	C2000 Transaction Router
+product INTEL C2000_TROUTER_B	0x1f0b	C2000 Transaction Router
+product INTEL C2000_TROUTER_C	0x1f0c	C2000 Transaction Router
+product INTEL C2000_TROUTER_D	0x1f0d	C2000 Transaction Router
+product INTEL C2000_TROUTER_E	0x1f0e	C2000 Transaction Router
+product INTEL C2000_TROUTER_F	0x1f0f	C2000 Transaction Router
+product INTEL C2000_PCIE_1	0x1f10	C2000 PCIe Root Port
+product INTEL C2000_PCIE_2	0x1f11	C2000 PCIe Root Port
+product INTEL C2000_PCIE_3	0x1f12	C2000 PCIe Root Port
+product INTEL C2000_PCIE_4	0x1f13	C2000 PCIe Root Port
+product INTEL C2000_RAS		0x1f14	C2000 RAS
+product INTEL C2000_SMBUS	0x1f15	C2000 SMBus 2.0
+product INTEL C2000_RCEC	0x1f16	C2000 RCEC
+product INTEL C2000_IQIA_PHYS	0x1f18	C2000 IQIA Physical Function
+product INTEL C2000_IQIA	0x1f19	C2000 IQIA
+product INTEL C2000_SATA2	0x1f22	C2000 SATA2
+product INTEL C2000_USB		0x1f2c	C2000 USB 2.0
+product INTEL C2000_SATA3	0x1f32	C2000 SATA3
+product INTEL C2000_PCU_1	0x1f38	C2000 PCU
+product INTEL C2000_PCU_2	0x1f39	C2000 PCU
+product INTEL C2000_PCU_3	0x1f3a	C2000 PCU
+product INTEL C2000_PCU_4	0x1f3b	C2000 PCU
+product INTEL C2000_PCU_SMBUS	0x1f3c	C2000 PCU SMBus
+product INTEL C2000_1000KX	0x1f40	C2000 Ethernet(1000BASE-KX)
+product INTEL C2000_SGMII	0x1f41	C2000 Ethernet(SGMII)
+product INTEL C2000_DUMMYGBE	0x1f42	C2000 Ethernet(Dummy function)
+product INTEL C2000_25GBE	0x1f45	C2000 Ethernet(2.5Gbe)
 product INTEL 82801AA_LPC	0x2410	82801AA LPC Interface Bridge
 product INTEL 82801AA_IDE	0x2411	82801AA IDE Controller
 product INTEL 82801AA_USB	0x2412	82801AA USB Controller

Reply via email to