Module Name:    src
Committed By:   snj
Date:           Thu Apr 30 20:00:27 UTC 2015

Modified Files:
        src/sys/dev/pci [netbsd-5]: if_wm.c if_wmreg.h if_wmvar.h pcidevs

Log Message:
Pull up following revision(s) (requested by msaitoh in ticket #1962):
        sys/dev/pci/if_wm.c: revisions 1.259-1.266, 1.269, 1.271, 1.273-1.274, 
1.277-1.278, 1.282, 1.284-1.285, 1.287, 1.290, 1.294, 1.297-1.298, 1.300-1.301, 
1.304-1.307, 1.310, 1.312-1.314, 1.316 via patch
        sys/dev/pci/if_wmreg.c: revisions 1.54-1.57, 1.59-1.60, 1.62, 1.64-1.66 
via patch
        sys/dev/pci/if_wmvar.c: revisions 1.17, 1.20-1.21 via patch
        sys/dev/pci/pcidevs: revisions 1.1172, 1.1195, 1.1201 via patch
- Fix "MDIC write error" bug for 82574 and 82583. For those chips, the
  semaphore must be released after chip reset. Found and tested by
  Mark Davies.
- Fix BMC related bugs.
- Fix yet another NVM bank detect problem in wm(4). Use bank 0 if the detect
  function failed. It's the same as FreeBSD. Observed and tested with
  Asus P8P67 Deluxe motherboard and tested by jnemeth.
- Add support for I354 DH89xxCC and some new I218 devices.
- Fix definition of CTRL_GIO_M_DIS bit.
- Insert completion barrier between register write and delay().
- Bump max TX DMA size to avoid pathological condition with TSO. From dyoung.
- Fix semaphore related bugs.
- Call wm_set_pcie_completion_timeout() on I350, I354, I210 and I211, too.
  Same as FreeBSD and OpenBSD.
- Drop PHPM_GO_LINK_D bit in WMREG_PHPM on some chips. From FreeBSD.
-  Fix fiber link problem (PR#44776 and PR#30880).
- WM_T_82545 is not 1000base-SX but 1000base-LX. Same as FreeBSD.
- Set the WM_F_ATTACHED flag if wm_attach() finished succesfully and check
  the flag in wm_detach(). It will avoid to panic in wm_detach().
  Fixes PR#49102.
- It's not required to print "failed to detect NVM bank" with
  aprint_error_dev(). Use DPRINTF(). Same as {Free,Open}BSD.
- Fix a bug that the offset of alt MAC address is wrongly calculated to 0
  when alt MAC address function is really used. This bug does not appear
  as real bug if the same MAC address is written in the default location
  and alt MAC address's location.
- Initialize some hardware bits for 8257[1234], 82583, 80003, ICH* and PCH*.
  Some of them are workaround code. From other *BSDs, Linux and documents.
- Fix a bug that wm_sgmii_writereg() function doesn't pass the "val" argument
  to the I2CCMD register. Reported by Bernard Merindol in PR#49789.
- Delete 82580ER related code. It was from FreeBSD and was removed
  in r203049.
- Remove extra debug message.
- Remove unused variable.
- Remove a duplicated error message.
- Cleanup comments.
- Fix debug message.


To generate a diff of this commit:
cvs rdiff -u -r1.162.4.20 -r1.162.4.21 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.24.20.8 -r1.24.20.9 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.2.46.6 -r1.2.46.7 src/sys/dev/pci/if_wmvar.h
cvs rdiff -u -r1.962.4.19 -r1.962.4.20 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/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.162.4.20 src/sys/dev/pci/if_wm.c:1.162.4.21
--- src/sys/dev/pci/if_wm.c:1.162.4.20	Sun Apr 26 09:03:12 2015
+++ src/sys/dev/pci/if_wm.c	Thu Apr 30 20:00:26 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.162.4.20 2015/04/26 09:03:12 martin Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.162.4.21 2015/04/30 20:00:26 snj 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.162.4.20 2015/04/26 09:03:12 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.162.4.21 2015/04/30 20:00:26 snj Exp $");
 
 #include "bpfilter.h"
 #include "rnd.h"
@@ -176,7 +176,7 @@ int	wm_debug = WM_DEBUG_TX | WM_DEBUG_RX
 #define	WM_NEXTTX(sc, x)	(((x) + 1) & WM_NTXDESC_MASK(sc))
 #define	WM_NEXTTXS(sc, x)	(((x) + 1) & WM_TXQUEUELEN_MASK(sc))
 
-#define	WM_MAXTXDMA		round_page(IP_MAXPACKET) /* for TSO */
+#define	WM_MAXTXDMA		 (2 * round_page(IP_MAXPACKET)) /* for TSO */
 
 /*
  * Receive descriptor list size.  We have one Rx buffer for normal
@@ -273,6 +273,7 @@ struct wm_softc {
 	int sc_pcixe_capoff;		/* PCI[Xe] capability register offset */
 
 	const struct wm_product *sc_wmp; /* Pointer to the wm_product entry */
+	uint16_t sc_pcidevid;		/* PCI device ID */
 	wm_chip_type sc_type;		/* MAC type */
 	int sc_rev;			/* MAC revision */
 	wm_phy_type sc_phytype;		/* PHY type */
@@ -285,7 +286,8 @@ struct wm_softc {
 	void *sc_ih;			/* interrupt cookie */
 	callout_t sc_tick_ch;		/* tick callout */
 
-	int sc_ee_addrbits;		/* EEPROM address bits */
+	int sc_nvm_addrbits;		/* NVM address bits */
+	unsigned int sc_nvm_wordsize;		/* NVM word size */
 	int sc_ich8_flash_base;
 	int sc_ich8_flash_bank_size;
 	int sc_nvm_k1_enabled;
@@ -383,8 +385,6 @@ struct wm_softc {
 	int sc_tbi_linkup;		/* TBI link status */
 	int sc_tbi_anegticks;		/* autonegotiation ticks */
 	int sc_tbi_ticks;		/* tbi ticks */
-	int sc_tbi_nrxcfg;		/* count of ICR_RXCFG */
-	int sc_tbi_lastnrxcfg;		/* count of ICR_RXCFG (on last tick) */
 
 	int sc_mchash_type;		/* multicast filter offset */
 
@@ -520,7 +520,7 @@ static int	wm_add_rxbuf(struct wm_softc 
 static int	wm_read_eeprom(struct wm_softc *, int, int, u_int16_t *);
 static int	wm_read_eeprom_eerd(struct wm_softc *, int, int, u_int16_t *);
 static int	wm_validate_eeprom_checksum(struct wm_softc *);
-static int	wm_check_alt_mac_addr(struct wm_softc *);
+static uint16_t	wm_check_alt_mac_addr(struct wm_softc *);
 static int	wm_read_mac_addr(struct wm_softc *, uint8_t *);
 static void	wm_tick(void *);
 
@@ -553,11 +553,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 *);
@@ -565,7 +567,7 @@ static void	wm_gmii_mediastatus(struct i
 static int	wm_kmrn_readreg(struct wm_softc *, int);
 static void	wm_kmrn_writereg(struct wm_softc *, int, int);
 
-static void	wm_set_spiaddrbits(struct wm_softc *);
+static int	wm_nvm_set_addrbits_size_eecd(struct wm_softc *);
 static int	wm_match(device_t, cfdata_t, void *);
 static void	wm_attach(device_t, device_t, void *);
 static int	wm_detach(device_t, int);
@@ -573,6 +575,7 @@ static int	wm_is_onboard_nvm_eeprom(stru
 static void	wm_get_auto_rd_done(struct wm_softc *);
 static void	wm_lan_init_done(struct wm_softc *);
 static void	wm_get_cfg_done(struct wm_softc *);
+static void	wm_initialize_hardware_bits(struct wm_softc *);
 static int	wm_get_swsm_semaphore(struct wm_softc *);
 static void	wm_put_swsm_semaphore(struct wm_softc *);
 static int	wm_poll_eerd_eewr_done(struct wm_softc *, int);
@@ -580,6 +583,8 @@ static int	wm_get_swfw_semaphore(struct 
 static void	wm_put_swfw_semaphore(struct wm_softc *, uint16_t);
 static int	wm_get_swfwhw_semaphore(struct wm_softc *);
 static void	wm_put_swfwhw_semaphore(struct wm_softc *);
+static int	wm_get_hw_semaphore_82573(struct wm_softc *);
+static void	wm_put_hw_semaphore_82573(struct wm_softc *);
 
 static int	wm_read_eeprom_ich8(struct wm_softc *, int, int, uint16_t *);
 static int32_t	wm_ich8_cycle_init(struct wm_softc *);
@@ -797,14 +802,14 @@ static const struct wm_product {
 	  "Intel PRO/1000 QT (82571EB)",
 	  WM_T_82571,		WMP_F_1000T },
 
-	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82572EI_COPPER,
-	  "Intel i82572EI 1000baseT Ethernet",
-	  WM_T_82572,		WMP_F_1000T },
-
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82571GB_QUAD_COPPER,
 	  "Intel PRO/1000 PT Quad Port Server Adapter",
 	  WM_T_82571,		WMP_F_1000T, },
 
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82572EI_COPPER,
+	  "Intel i82572EI 1000baseT Ethernet",
+	  WM_T_82572,		WMP_F_1000T },
+
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82572EI_FIBER,
 	  "Intel i82572EI 1000baseX Ethernet",
 	  WM_T_82572,		WMP_F_1000X },
@@ -1009,15 +1014,14 @@ static const struct wm_product {
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_COPPER_DUAL,
 	  "82580 dual-1000BaseT Ethernet",
 	  WM_T_82580,		WMP_F_1000T },
-	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_ER,
-	  "82580 1000BaseT Ethernet",
-	  WM_T_82580ER,		WMP_F_1000T },
-	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_ER_DUAL,
-	  "82580 dual-1000BaseT Ethernet",
-	  WM_T_82580ER,		WMP_F_1000T },
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_QUAD_FIBER,
 	  "82580 quad-1000BaseX Ethernet",
 	  WM_T_82580,		WMP_F_1000X },
+
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_DH89XXCC_SGMII,
+	  "DH89XXCC Gigabit Ethernet (SGMII)",
+	  WM_T_82580,		WMP_F_1000T },
+
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I350_COPPER,
 	  "I350 Gigabit Network Connection",
 	  WM_T_I350,		WMP_F_1000T },
@@ -1032,6 +1036,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 },
@@ -1064,9 +1071,21 @@ static const struct wm_product {
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I218_V,
 	  "I218 V Ethernet Connection",
 	  WM_T_PCH_LPT,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I218_V2,
+	  "I218 V Ethernet Connection",
+	  WM_T_PCH_LPT,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I218_V3,
+	  "I218 V Ethernet Connection",
+	  WM_T_PCH_LPT,		WMP_F_1000T },
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I218_LM,
 	  "I218 LM Ethernet Connection",
 	  WM_T_PCH_LPT,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I218_LM2,
+	  "I218 LM Ethernet Connection",
+	  WM_T_PCH_LPT,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I218_LM3,
+	  "I218 LM Ethernet Connection",
+	  WM_T_PCH_LPT,		WMP_F_1000T },
 	{ 0,			0,
 	  NULL,
 	  0,			0 },
@@ -1126,14 +1145,68 @@ wm_set_dma_addr(volatile wiseman_addr_t 
 		wa->wa_high = 0;
 }
 
-static void
-wm_set_spiaddrbits(struct wm_softc *sc)
+/*
+ * Set SPI and FLASH related information from the EECD register.
+ * For 82541 and 82547, the word size is taken from EEPROM.
+ */
+static int
+wm_nvm_set_addrbits_size_eecd(struct wm_softc *sc)
 {
+	int size;
 	uint32_t reg;
+	uint16_t data;
 
-	sc->sc_flags |= WM_F_EEPROM_SPI;
 	reg = CSR_READ(sc, WMREG_EECD);
-	sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 16 : 8;
+	sc->sc_nvm_addrbits = (reg & EECD_EE_ABITS) ? 16 : 8;
+
+	/* Read the size of NVM from EECD by default */
+	size = __SHIFTOUT(reg, EECD_EE_SIZE_EX_MASK);
+	switch (sc->sc_type) {
+	case WM_T_82541:
+	case WM_T_82541_2:
+	case WM_T_82547:
+	case WM_T_82547_2:
+		/* Set dummy value to access EEPROM */
+		sc->sc_nvm_wordsize = 64;
+		wm_read_eeprom(sc, NVM_OFF_EEPROM_SIZE, 1, &data);
+		reg = data;
+		size = __SHIFTOUT(reg, EECD_EE_SIZE_EX_MASK);
+		if (size == 0)
+			size = 6; /* 64 word size */
+		else
+			size += NVM_WORD_SIZE_BASE_SHIFT + 1;
+		break;
+	case WM_T_80003:
+	case WM_T_82571:
+	case WM_T_82572:
+	case WM_T_82573: /* SPI case */
+	case WM_T_82574: /* SPI case */
+	case WM_T_82583: /* SPI case */
+		size += NVM_WORD_SIZE_BASE_SHIFT;
+		if (size > 14)
+			size = 14;
+		break;
+	case WM_T_82575:
+	case WM_T_82576:
+	case WM_T_82580:
+	case WM_T_I350:
+	case WM_T_I354:
+	case WM_T_I210:
+	case WM_T_I211:
+		size += NVM_WORD_SIZE_BASE_SHIFT;
+		if (size > 15)
+			size = 15;
+		break;
+	default:
+		aprint_error_dev(sc->sc_dev,
+		    "%s: unknown device(%d)?\n", __func__, sc->sc_type);
+		return -1;
+		break;
+	}
+
+	sc->sc_nvm_wordsize = 1 << size;
+
+	return 0;
 }
 
 static const struct wm_product *
@@ -1183,6 +1256,7 @@ wm_attach(device_t parent, device_t self
 	uint16_t cfg1, cfg2, swdpin, io3;
 	pcireg_t preg, memtype;
 	uint16_t eeprom_data, apme_mask;
+	bool force_clear_smbi;
 	uint32_t reg;
 
 	sc->sc_dev = self;
@@ -1202,6 +1276,7 @@ wm_attach(device_t parent, device_t self
 	else
 		sc->sc_dmat = pa->pa_dmat;
 
+	sc->sc_pcidevid = PCI_PRODUCT(pa->pa_id);
 	sc->sc_rev = PCI_REVISION(pci_conf_read(pc, pa->pa_tag, PCI_CLASS_REG));
 	aprint_naive(": Ethernet controller\n");
 	aprint_normal(": %s, rev. %d\n", wmp->wmp_name, sc->sc_rev);
@@ -1218,9 +1293,9 @@ 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_82580)
+	    || (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) */
@@ -1253,8 +1328,6 @@ wm_attach(device_t parent, device_t self
 		return;
 	}
 
-	wm_get_wakeup(sc);
-
 	/*
 	 * In addition, i82544 and later support I/O mapped indirect
 	 * register access.  It is not desirable (nor supported in
@@ -1336,8 +1409,8 @@ wm_attach(device_t parent, device_t self
 	if ((sc->sc_type == WM_T_82546) || (sc->sc_type == WM_T_82546_3)
 	    || (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_82580)
+	    || (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
@@ -1372,7 +1445,6 @@ wm_attach(device_t parent, device_t self
 		    && (sc->sc_type != WM_T_PCH)
 		    && (sc->sc_type != WM_T_PCH2)
 		    && (sc->sc_type != WM_T_PCH_LPT)) {
-			sc->sc_flags |= WM_F_EEPROM_SEMAPHORE;
 			/* ICH* and PCH* have no PCIe capability registers */
 			if (pci_get_capability(pa->pa_pc, pa->pa_tag,
 				PCI_CAP_PCIEXPRESS, &sc->sc_pcixe_capoff,
@@ -1549,26 +1621,6 @@ wm_attach(device_t parent, device_t self
 	 */
 	wm_reset(sc);
 
-	switch (sc->sc_type) {
-	case WM_T_82571:
-	case WM_T_82572:
-	case WM_T_82573:
-	case WM_T_82574:
-	case WM_T_82583:
-	case WM_T_80003:
-	case WM_T_ICH8:
-	case WM_T_ICH9:
-	case WM_T_ICH10:
-	case WM_T_PCH:
-	case WM_T_PCH2:
-	case WM_T_PCH_LPT:
-		if (wm_check_mng_mode(sc) != 0)
-			wm_get_hw_control(sc);
-		break;
-	default:
-		break;
-	}
-
 	/*
 	 * Get some information about the EEPROM.
 	 */
@@ -1578,7 +1630,8 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82543:
 	case WM_T_82544:
 		/* Microwire */
-		sc->sc_ee_addrbits = 6;
+		sc->sc_nvm_wordsize = 64;
+		sc->sc_nvm_addrbits = 6;
 		break;
 	case WM_T_82540:
 	case WM_T_82545:
@@ -1587,51 +1640,70 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82546_3:
 		/* Microwire */
 		reg = CSR_READ(sc, WMREG_EECD);
-		if (reg & EECD_EE_SIZE)
-			sc->sc_ee_addrbits = 8;
-		else
-			sc->sc_ee_addrbits = 6;
+		if (reg & EECD_EE_SIZE) {
+			sc->sc_nvm_wordsize = 256;
+			sc->sc_nvm_addrbits = 8;
+		} else {
+			sc->sc_nvm_wordsize = 64;
+			sc->sc_nvm_addrbits = 6;
+		}
 		sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
 		break;
 	case WM_T_82541:
 	case WM_T_82541_2:
 	case WM_T_82547:
 	case WM_T_82547_2:
+		sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
 		reg = CSR_READ(sc, WMREG_EECD);
 		if (reg & EECD_EE_TYPE) {
 			/* SPI */
-			wm_set_spiaddrbits(sc);
-		} else
+			sc->sc_flags |= WM_F_EEPROM_SPI;
+			wm_nvm_set_addrbits_size_eecd(sc);
+		} else {
 			/* Microwire */
-			sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 8 : 6;
-		sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
+			if ((reg & EECD_EE_ABITS) != 0) {
+				sc->sc_nvm_wordsize = 256;
+				sc->sc_nvm_addrbits = 8;
+			} else {
+				sc->sc_nvm_wordsize = 64;
+				sc->sc_nvm_addrbits = 6;
+			}
+		}
 		break;
 	case WM_T_82571:
 	case WM_T_82572:
 		/* SPI */
-		wm_set_spiaddrbits(sc);
+		sc->sc_flags |= WM_F_EEPROM_SPI;
+		wm_nvm_set_addrbits_size_eecd(sc);
+		sc->sc_flags |= WM_F_EEPROM_SEMAPHORE;
 		sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
 		break;
 	case WM_T_82573:
+		sc->sc_flags |= WM_F_EEPROM_SEMAPHORE;
+		/* FALLTHROUGH */
 	case WM_T_82574:
 	case WM_T_82583:
-		if (wm_is_onboard_nvm_eeprom(sc) == 0)
+		if (wm_is_onboard_nvm_eeprom(sc) == 0) {
 			sc->sc_flags |= WM_F_EEPROM_FLASH;
-		else {
+			sc->sc_nvm_wordsize = 2048;
+		} else {
 			/* SPI */
-			wm_set_spiaddrbits(sc);
+			sc->sc_flags |= WM_F_EEPROM_SPI;
+			wm_nvm_set_addrbits_size_eecd(sc);
 		}
 		sc->sc_flags |= WM_F_EEPROM_EERDEEWR;
 		break;
 	case WM_T_82575:
 	case WM_T_82576:
 	case WM_T_82580:
-	case WM_T_82580ER:
 	case WM_T_I350:
+	case WM_T_I354:
 	case WM_T_80003:
 		/* SPI */
-		wm_set_spiaddrbits(sc);
-		sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_SWFW_SYNC;
+		sc->sc_flags |= WM_F_EEPROM_SPI;
+		wm_nvm_set_addrbits_size_eecd(sc);
+		sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_SWFW_SYNC
+		    | WM_F_EEPROM_SEMAPHORE;
 		break;
 	case WM_T_ICH8:
 	case WM_T_ICH9:
@@ -1641,12 +1713,13 @@ wm_attach(device_t parent, device_t self
 	case WM_T_PCH_LPT:
 		/* FLASH */
 		sc->sc_flags |= WM_F_EEPROM_FLASH | WM_F_SWFWHW_SYNC;
+		sc->sc_nvm_wordsize = 2048;
 		memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, WM_ICH8_FLASH);
 		if (pci_mapreg_map(pa, WM_ICH8_FLASH, memtype, 0,
 		    &sc->sc_flasht, &sc->sc_flashh, NULL, NULL)) {
 			aprint_error_dev(sc->sc_dev,
 			    "can't map FLASH registers\n");
-			return;
+			goto fail_5;
 		}
 		reg = ICH8_FLASH_READ32(sc, ICH_FLASH_GFPREG);
 		sc->sc_ich8_flash_base = (reg & ICH_GFPREG_BASE_MASK) *
@@ -1660,6 +1733,7 @@ wm_attach(device_t parent, device_t self
 		break;
 	case WM_T_I210:
 	case WM_T_I211:
+		wm_nvm_set_addrbits_size_eecd(sc);
 		sc->sc_flags |= WM_F_EEPROM_FLASH_HW;
 		sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_SWFW_SYNC;
 		break;
@@ -1667,6 +1741,34 @@ wm_attach(device_t parent, device_t self
 		break;
 	}
 
+	/* Ensure the SMBI bit is clear before first NVM or PHY access */
+	switch (sc->sc_type) {
+	case WM_T_82571:
+	case WM_T_82572:
+		reg = CSR_READ(sc, WMREG_SWSM2);
+		if ((reg & SWSM2_LOCK) == 0) {
+			CSR_WRITE(sc, WMREG_SWSM2, reg | SWSM2_LOCK);
+			force_clear_smbi = true;
+		} else
+			force_clear_smbi = false;
+		break;
+	case WM_T_82573:
+	case WM_T_82574:
+	case WM_T_82583:
+		force_clear_smbi = true;
+		break;
+	default:
+		force_clear_smbi = false;
+		break;
+	}
+	if (force_clear_smbi) {
+		reg = CSR_READ(sc, WMREG_SWSM);
+		if ((reg & SWSM_SMBI) != 0)
+			aprint_error_dev(sc->sc_dev,
+			    "Please update the Bootagent\n");
+		CSR_WRITE(sc, WMREG_SWSM, reg & ~SWSM_SMBI);
+	}
+
 	/*
 	 * Defer printing the EEPROM type until after verifying the checksum
 	 * This allows the EEPROM type to be printed correctly in the case
@@ -1690,21 +1792,43 @@ wm_attach(device_t parent, device_t self
 
 	if (sc->sc_flags & WM_F_EEPROM_INVALID)
 		aprint_verbose_dev(sc->sc_dev, "No EEPROM\n");
-	else if (sc->sc_flags & WM_F_EEPROM_FLASH_HW) {
-		aprint_verbose_dev(sc->sc_dev, "FLASH(HW)\n");
-	} else if (sc->sc_flags & WM_F_EEPROM_FLASH) {
-		aprint_verbose_dev(sc->sc_dev, "FLASH\n");
-	} else {
-		if (sc->sc_flags & WM_F_EEPROM_SPI)
-			eetype = "SPI";
-		else
-			eetype = "MicroWire";
-		aprint_verbose_dev(sc->sc_dev,
-		    "%u word (%d address bits) %s EEPROM\n",
-		    1U << sc->sc_ee_addrbits,
-		    sc->sc_ee_addrbits, eetype);
+	else {
+		aprint_verbose_dev(sc->sc_dev, "%u words ",
+		    sc->sc_nvm_wordsize);
+		if (sc->sc_flags & WM_F_EEPROM_FLASH_HW) {
+			aprint_verbose("FLASH(HW)\n");
+		} else if (sc->sc_flags & WM_F_EEPROM_FLASH) {
+			aprint_verbose("FLASH\n");
+		} else {
+			if (sc->sc_flags & WM_F_EEPROM_SPI)
+				eetype = "SPI";
+			else
+				eetype = "MicroWire";
+			aprint_verbose("(%d address bits) %s EEPROM\n",
+			    sc->sc_nvm_addrbits, eetype);
+		}
 	}
 
+	switch (sc->sc_type) {
+	case WM_T_82571:
+	case WM_T_82572:
+	case WM_T_82573:
+	case WM_T_82574:
+	case WM_T_82583:
+	case WM_T_80003:
+	case WM_T_ICH8:
+	case WM_T_ICH9:
+	case WM_T_ICH10:
+	case WM_T_PCH:
+	case WM_T_PCH2:
+	case WM_T_PCH_LPT:
+		if (wm_check_mng_mode(sc) != 0)
+			wm_get_hw_control(sc);
+		break;
+	default:
+		break;
+	}
+	wm_get_wakeup(sc);
 	/*
 	 * Read the Ethernet address from the EEPROM, if not first found
 	 * in device properties.
@@ -1718,7 +1842,7 @@ wm_attach(device_t parent, device_t self
 		if (wm_read_mac_addr(sc, enaddr) != 0) {
 			aprint_error_dev(sc->sc_dev,
 			    "unable to read Ethernet address\n");
-			return;
+			goto fail_5;
 		}
 	}
 
@@ -1736,7 +1860,7 @@ wm_attach(device_t parent, device_t self
 	} else {
 		if (wm_read_eeprom(sc, EEPROM_OFF_CFG1, 1, &cfg1)) {
 			aprint_error_dev(sc->sc_dev, "unable to read CFG1\n");
-			return;
+			goto fail_5;
 		}
 	}
 
@@ -1747,7 +1871,7 @@ wm_attach(device_t parent, device_t self
 	} else {
 		if (wm_read_eeprom(sc, EEPROM_OFF_CFG2, 1, &cfg2)) {
 			aprint_error_dev(sc->sc_dev, "unable to read CFG2\n");
-			return;
+			goto fail_5;
 		}
 	}
 
@@ -1780,8 +1904,8 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82575:
 	case WM_T_82576:
 	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:
@@ -1816,7 +1940,7 @@ wm_attach(device_t parent, device_t self
 			if (wm_read_eeprom(sc, EEPROM_OFF_SWDPIN, 1, &swdpin)) {
 				aprint_error_dev(sc->sc_dev,
 				    "unable to read SWDPIN\n");
-				return;
+				goto fail_5;
 			}
 		}
 	}
@@ -1906,22 +2030,31 @@ wm_attach(device_t parent, device_t self
 		case WM_T_82575:
 		case WM_T_82576:
 		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");
@@ -1972,8 +2105,8 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82575:
 	case WM_T_82576:
 	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:
@@ -2116,6 +2249,7 @@ wm_attach(device_t parent, device_t self
 	else
 		pmf_class_network_register(self, ifp);
 
+	sc->sc_flags |= WM_F_ATTACHED;
 	return;
 
 	/*
@@ -2153,6 +2287,9 @@ wm_detach(device_t self, int flags __unu
 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 	int i, s;
 
+	if ((sc->sc_flags & WM_F_ATTACHED) == 0)
+		return 0;
+
 	s = splnet();
 	/* Stop the interface. Callouts are stopped in it. */
 	wm_stop(ifp, 1);
@@ -3517,7 +3654,7 @@ wm_intr(void *arg)
 #endif
 		wm_txintr(sc);
 
-		if (icr & (ICR_LSC|ICR_RXSEQ|ICR_RXCFG)) {
+		if (icr & (ICR_LSC|ICR_RXSEQ)) {
 			WM_EVCNT_INCR(&sc->sc_ev_linkintr);
 			wm_linkintr(sc, icr);
 		}
@@ -3736,7 +3873,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
@@ -3787,6 +3925,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),
@@ -3970,11 +4109,6 @@ wm_linkintr_tbi(struct wm_softc *sc, uin
 			sc->sc_tbi_linkup = 0;
 		}
 		wm_tbi_set_linkled(sc);
-	} else if (icr & ICR_RXCFG) {
-		DPRINTF(WM_DEBUG_LINK, ("%s: LINK: receiving /C/\n",
-		    device_xname(sc->sc_dev)));
-		sc->sc_tbi_nrxcfg++;
-		wm_check_for_link(sc);
 	} else if (icr & ICR_RXSEQ) {
 		DPRINTF(WM_DEBUG_LINK,
 		    ("%s: LINK: Receive sequence error\n",
@@ -4040,6 +4174,200 @@ wm_tick(void *arg)
 	callout_reset(&sc->sc_tick_ch, hz, wm_tick, sc);
 }
 
+/* Init hardware bits */
+void
+wm_initialize_hardware_bits(struct wm_softc *sc)
+{
+	uint32_t tarc0, tarc1, reg;
+	
+	/* For 82571 variant, 80003 and ICHs */
+	if (((sc->sc_type >= WM_T_82571) && (sc->sc_type <= WM_T_82583))
+	    || (sc->sc_type >= WM_T_80003)) {
+
+		/* Transmit Descriptor Control 0 */
+		reg = CSR_READ(sc, WMREG_TXDCTL(0));
+		reg |= TXDCTL_COUNT_DESC;
+		CSR_WRITE(sc, WMREG_TXDCTL(0), reg);
+
+		/* Transmit Descriptor Control 1 */
+		reg = CSR_READ(sc, WMREG_TXDCTL(1));
+		reg |= TXDCTL_COUNT_DESC;
+		CSR_WRITE(sc, WMREG_TXDCTL(1), reg);
+
+		/* TARC0 */
+		tarc0 = CSR_READ(sc, WMREG_TARC0);
+		switch (sc->sc_type) {
+		case WM_T_82571:
+		case WM_T_82572:
+		case WM_T_82573:
+		case WM_T_82574:
+		case WM_T_82583:
+		case WM_T_80003:
+			/* Clear bits 30..27 */
+			tarc0 &= ~__BITS(30, 27);
+			break;
+		default:
+			break;
+		}
+
+		switch (sc->sc_type) {
+		case WM_T_82571:
+		case WM_T_82572:
+			tarc0 |= __BITS(26, 23); /* TARC0 bits 23-26 */
+
+			tarc1 = CSR_READ(sc, WMREG_TARC1);
+			tarc1 &= ~__BITS(30, 29); /* Clear bits 30 and 29 */
+			tarc1 |= __BITS(26, 24); /* TARC1 bits 26-24 */
+			/* 8257[12] Errata No.7 */
+			tarc1 |= __BIT(22); /* TARC1 bits 22 */
+
+			/* TARC1 bit 28 */
+			if ((CSR_READ(sc, WMREG_TCTL) & TCTL_MULR) != 0)
+				tarc1 &= ~__BIT(28);
+			else
+				tarc1 |= __BIT(28);
+			CSR_WRITE(sc, WMREG_TARC1, tarc1);
+
+			/*
+			 * 8257[12] Errata No.13
+			 * Disable Dyamic Clock Gating.
+			 */
+			reg = CSR_READ(sc, WMREG_CTRL_EXT);
+			reg &= ~CTRL_EXT_DMA_DYN_CLK;
+			CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+			break;
+		case WM_T_82573:
+		case WM_T_82574:
+		case WM_T_82583:
+			if ((sc->sc_type == WM_T_82574)
+			    || (sc->sc_type == WM_T_82583))
+				tarc0 |= __BIT(26); /* TARC0 bit 26 */
+
+			/* Extended Device Control */
+			reg = CSR_READ(sc, WMREG_CTRL_EXT);
+			reg &= ~__BIT(23);	/* Clear bit 23 */
+			reg |= __BIT(22);	/* Set bit 22 */
+			CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+
+			/* Device Control */
+			sc->sc_ctrl &= ~__BIT(29);	/* Clear bit 29 */
+			CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+
+			/* PCIe Control Register */
+			if ((sc->sc_type == WM_T_82574)
+			    || (sc->sc_type == WM_T_82583)) {
+				/*
+				 * Document says this bit must be set for
+				 * proper operation.
+				 */
+				reg = CSR_READ(sc, WMREG_GCR);
+				reg |= __BIT(22);
+				CSR_WRITE(sc, WMREG_GCR, reg);
+
+				/*
+				 * Apply workaround for hardware errata
+				 * documented in errata docs Fixes issue where
+				 * some error prone or unreliable PCIe
+				 * completions are occurring, particularly
+				 * with ASPM enabled. Without fix, issue can
+				 * cause Tx timeouts.
+				 */
+				reg = CSR_READ(sc, WMREG_GCR2);
+				reg |= __BIT(0);
+				CSR_WRITE(sc, WMREG_GCR2, reg);
+			}
+			break;
+		case WM_T_80003:
+			/* TARC0 */
+			if (((sc->sc_wmp->wmp_flags & WMP_F_1000X) != 0)
+			    || ((sc->sc_wmp->wmp_flags & WMP_F_SERDES) != 0))
+				tarc0 &= ~__BIT(20); /* Clear bits 20 */
+
+			/* TARC1 bit 28 */
+			tarc1 = CSR_READ(sc, WMREG_TARC1);
+			if ((CSR_READ(sc, WMREG_TCTL) & TCTL_MULR) != 0)
+				tarc1 &= ~__BIT(28);
+			else
+				tarc1 |= __BIT(28);
+			CSR_WRITE(sc, WMREG_TARC1, tarc1);
+			break;
+		case WM_T_ICH8:
+		case WM_T_ICH9:
+		case WM_T_ICH10:
+		case WM_T_PCH:
+		case WM_T_PCH2:
+		case WM_T_PCH_LPT:
+			/* TARC 0 */
+			if (sc->sc_type == WM_T_ICH8) {
+				/* Set TARC0 bits 29 and 28 */
+				tarc0 |= __BITS(29, 28);
+			}
+			/* Set TARC0 bits 23,24,26,27 */
+			tarc0 |= __BITS(27, 26) | __BITS(24, 23);
+
+			/* CTRL_EXT */
+			reg = CSR_READ(sc, WMREG_CTRL_EXT);
+			reg |= __BIT(22);	/* Set bit 22 */
+			/*
+			 * Enable PHY low-power state when MAC is at D3
+			 * w/o WoL
+			 */
+			if (sc->sc_type >= WM_T_PCH)
+				reg |= CTRL_EXT_PHYPDEN;
+			CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+
+			/* TARC1 */
+			tarc1 = CSR_READ(sc, WMREG_TARC1);
+			/* bit 28 */
+			if ((CSR_READ(sc, WMREG_TCTL) & TCTL_MULR) != 0)
+				tarc1 &= ~__BIT(28);
+			else
+				tarc1 |= __BIT(28);
+			tarc1 |= __BIT(24) | __BIT(26) | __BIT(30);
+			CSR_WRITE(sc, WMREG_TARC1, tarc1);
+
+			/* Device Status */
+			if (sc->sc_type == WM_T_ICH8) {
+				reg = CSR_READ(sc, WMREG_STATUS);
+				reg &= ~__BIT(31);
+				CSR_WRITE(sc, WMREG_STATUS, reg);
+
+			}
+
+			/*
+			 * Work-around descriptor data corruption issue during
+			 * NFS v2 UDP traffic, just disable the NFS filtering
+			 * capability.
+			 */
+			reg = CSR_READ(sc, WMREG_RFCTL);
+			reg |= WMREG_RFCTL_NFSWDIS | WMREG_RFCTL_NFSRDIS;
+			CSR_WRITE(sc, WMREG_RFCTL, reg);
+			break;
+		default:
+			break;
+		}
+		CSR_WRITE(sc, WMREG_TARC0, tarc0);
+
+		/*
+		 * 8257[12] Errata No.52 and some others.
+		 * Avoid RSS Hash Value bug.
+		 */
+		switch (sc->sc_type) {
+		case WM_T_82571:
+		case WM_T_82572:
+		case WM_T_82573:
+		case WM_T_80003:
+		case WM_T_ICH8:
+			reg = CSR_READ(sc, WMREG_RFCTL);
+			reg |= WMREG_RFCTL_NEWIPV6EXDIS |WMREG_RFCTL_IPV6EXDIS;
+			CSR_WRITE(sc, WMREG_RFCTL, reg);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 /*
  * wm_reset:
  *
@@ -4049,8 +4377,8 @@ static void
 wm_reset(struct wm_softc *sc)
 {
 	int phy_reset = 0;
+	int error = 0;
 	uint32_t reg, mask;
-	int i;
 
 	/*
 	 * Allocate on-chip memory according to the MTU size.
@@ -4072,11 +4400,11 @@ 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;
 	case WM_T_82580:
-	case WM_T_82580ER:
 		sc->sc_pba = PBA_35K;
 		break;
 	case WM_T_I210:
@@ -4094,6 +4422,7 @@ wm_reset(struct wm_softc *sc)
 		sc->sc_pba = PBA_20K;
 		break;
 	case WM_T_ICH8:
+		/* Workaround for a bit corruption issue in FIFO memory */
 		sc->sc_pba = PBA_8K;
 		CSR_WRITE(sc, WMREG_PBS, PBA_16K);
 		break;
@@ -4130,7 +4459,9 @@ 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_82580)
+	    || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354)
+	    || (sc->sc_type == WM_T_I210) || (sc->sc_type == WM_T_I211))
 		wm_set_pcie_completion_timeout(sc);
 
 	/* Clear interrupt */
@@ -4138,8 +4469,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() */
 
@@ -4150,19 +4482,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82573:
 	case WM_T_82574:
 	case WM_T_82583:
-		i = 0;
-		reg = CSR_READ(sc, WMREG_EXTCNFCTR)
-		    | EXTCNFCTR_MDIO_SW_OWNERSHIP;
-		do {
-			CSR_WRITE(sc, WMREG_EXTCNFCTR,
-			    reg | EXTCNFCTR_MDIO_SW_OWNERSHIP);
-			reg = CSR_READ(sc, WMREG_EXTCNFCTR);
-			if ((reg & EXTCNFCTR_MDIO_SW_OWNERSHIP) != 0)
-				break;
-			reg |= EXTCNFCTR_MDIO_SW_OWNERSHIP;
-			delay(2*1000);
-			i++;
-		} while (i < WM_MDIO_OWNERSHIP_TIMEOUT);
+		error = wm_get_hw_semaphore_82573(sc);
 		break;
 	default:
 		break;
@@ -4176,6 +4496,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);
 	}
 
@@ -4236,9 +4557,20 @@ 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;
+	case WM_T_82580:
+	case WM_T_I350:
+	case WM_T_I354:
+	case WM_T_I210:
+	case WM_T_I211:
+		CSR_WRITE(sc, WMREG_CTRL, CSR_READ(sc, WMREG_CTRL) | CTRL_RST);
+		if (sc->sc_pcidevid != PCI_PRODUCT_INTEL_DH89XXCC_SGMII)
+			CSR_WRITE_FLUSH(sc);
+		delay(5000);
+		break;
 	case WM_T_82542_2_0:
 	case WM_T_82542_2_1:
 	case WM_T_82543:
@@ -4251,18 +4583,25 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82574:
 	case WM_T_82575:
 	case WM_T_82576:
-	case WM_T_82580:
-	case WM_T_82580ER:
 	case WM_T_82583:
-	case WM_T_I350:
-	case WM_T_I210:
-	case WM_T_I211:
 	default:
 		/* Everything else can safely use the documented method. */
 		CSR_WRITE(sc, WMREG_CTRL, CSR_READ(sc, WMREG_CTRL) | CTRL_RST);
 		break;
 	}
 
+	/* Must release the MDIO ownership after MAC reset */
+	switch (sc->sc_type) {
+	case WM_T_82573:
+	case WM_T_82574:
+	case WM_T_82583:
+		if (error == 0)
+			wm_put_hw_semaphore_82573(sc);
+		break;
+	default:
+		break;
+	}
+
 	if (phy_reset != 0)
 		wm_get_cfg_done(sc);
 
@@ -4275,6 +4614,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:
@@ -4301,6 +4641,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);
@@ -4315,8 +4656,8 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82575:
 	case WM_T_82576:
 	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:
@@ -4340,9 +4681,9 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82576:
 #if 0 /* XXX */
 	case WM_T_82580:
-	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) {
@@ -4351,8 +4692,8 @@ wm_reset(struct wm_softc *sc)
 			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_I350)
+			    || (sc->sc_type == WM_T_I354))
 				wm_reset_init_script_82575(sc);
 		}
 		break;
@@ -4360,8 +4701,8 @@ wm_reset(struct wm_softc *sc)
 		break;
 	}
 
-	if ((sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
-	    || (sc->sc_type == WM_T_I350)) {
+	if ((sc->sc_type == WM_T_82580)
+	    || (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);
 	}
@@ -4469,16 +4810,13 @@ wm_init(struct ifnet *ifp)
 		break;
 	}
 
+	/* Init hardware bits */
+	wm_initialize_hardware_bits(sc);
+
 	/* Reset the PHY. */
 	if (sc->sc_flags & WM_F_HAS_MII)
 		wm_gmii_reset(sc);
 
-	reg = CSR_READ(sc, WMREG_CTRL_EXT);
-	/* Enable PHY low-power state when MAC is at D3 w/o WoL */
-	if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)
-	    || (sc->sc_type == WM_T_PCH_LPT))
-		CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_PHYPDEN);
-
 	/* Initialize the transmit descriptor ring. */
 	memset(sc->sc_txdescs, 0, WM_TXDESCSIZE(sc));
 	WM_CDTXSYNC(sc, 0, WM_NTXDESC(sc),
@@ -4506,12 +4844,12 @@ wm_init(struct ifnet *ifp)
 			 * Don't write TDT before TCTL.EN is set.
 			 * See the document.
 			 */
-			CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_QUEUE_ENABLE
+			CSR_WRITE(sc, WMREG_TXDCTL(0), TXDCTL_QUEUE_ENABLE
 			    | TXDCTL_PTHRESH(0) | TXDCTL_HTHRESH(0)
 			    | TXDCTL_WTHRESH(0));
 		else {
 			CSR_WRITE(sc, WMREG_TDT, 0);
-			CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_PTHRESH(0) |
+			CSR_WRITE(sc, WMREG_TXDCTL(0), TXDCTL_PTHRESH(0) |
 			    TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0));
 			CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_PTHRESH(0) |
 			    RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1));
@@ -4597,7 +4935,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;
@@ -4695,17 +5033,12 @@ wm_init(struct ifnet *ifp)
 		reg |= RXCSUM_IPV6OFL | RXCSUM_TUOFL;
 	CSR_WRITE(sc, WMREG_RXCSUM, reg);
 
-	/* Reset TBI's RXCFG count */
-	sc->sc_tbi_nrxcfg = sc->sc_tbi_lastnrxcfg = 0;
-
 	/*
 	 * Set up the interrupt registers.
 	 */
 	CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
 	sc->sc_icr = ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 |
 	    ICR_RXO | ICR_RXT0;
-	if ((sc->sc_flags & WM_F_HAS_MII) == 0)
-		sc->sc_icr |= ICR_RXCFG;
 	CSR_WRITE(sc, WMREG_IMS, sc->sc_icr);
 
 	if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
@@ -4796,7 +5129,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)
@@ -4973,8 +5307,8 @@ wm_get_auto_rd_done(struct wm_softc *sc)
 	case WM_T_82575:
 	case WM_T_82576:
 	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:
@@ -5064,8 +5398,8 @@ wm_get_cfg_done(struct wm_softc *sc)
 	case WM_T_82575:
 	case WM_T_82576:
 	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) {
@@ -5216,10 +5550,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);
 	}
 }
@@ -5240,10 +5577,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;
@@ -5277,6 +5616,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 */
@@ -5284,13 +5624,14 @@ 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. */
 		wm_eeprom_sendbits(sc, UWIRE_OPC_READ, 3);
 
 		/* Shift in address. */
-		wm_eeprom_sendbits(sc, word + i, sc->sc_ee_addrbits);
+		wm_eeprom_sendbits(sc, word + i, sc->sc_nvm_addrbits);
 
 		/* Shift out the data. */
 		wm_eeprom_recvbits(sc, &val, 16);
@@ -5299,6 +5640,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);
 	}
 
@@ -5344,6 +5686,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))
@@ -5351,16 +5694,18 @@ 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;
-	if (sc->sc_ee_addrbits == 8 && word >= 128)
+	if (sc->sc_nvm_addrbits == 8 && word >= 128)
 		opc |= SPI_OPC_A8;
 
 	wm_eeprom_sendbits(sc, opc, 8);
-	wm_eeprom_sendbits(sc, word << 1, sc->sc_ee_addrbits);
+	wm_eeprom_sendbits(sc, word << 1, sc->sc_nvm_addrbits);
 
 	for (i = 0; i < wordcnt; i++) {
 		wm_eeprom_recvbits(sc, &val, 16);
@@ -5370,18 +5715,12 @@ 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;
 }
 
-#define NVM_CHECKSUM			0xBABA
-#define EEPROM_SIZE			0x0040
-#define NVM_COMPAT			0x0003
-#define NVM_COMPAT_VALID_CHECKSUM	0x0001
-#define NVM_FUTURE_INIT_WORD1			0x0019
-#define NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM	0x0040
-
 /*
  * wm_validate_eeprom_checksum
  *
@@ -5390,9 +5729,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;
@@ -5401,6 +5742,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;
@@ -5409,7 +5751,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)
@@ -5427,9 +5768,9 @@ wm_validate_eeprom_checksum(struct wm_so
 		printf("%s: NVM dump:\n", device_xname(sc->sc_dev));
 		for (i = 0; i < EEPROM_SIZE; i++) {
 			if (wm_read_eeprom(sc, i, 1, &eeprom_data))
-				printf("XX ");
+				printf("XXXX ");
 			else
-				printf("%04x ", eeprom_data);
+				printf("%04hx ", eeprom_data);
 			if (i % 8 == 7)
 				printf("\n");
 		}
@@ -5525,7 +5866,11 @@ wm_poll_eerd_eewr_done(struct wm_softc *
 	return done;
 }
 
-static int
+/*
+ * Get the offset of MAC address and return it.
+ * If error occured, use offset 0.
+ */
+static uint16_t
 wm_check_alt_mac_addr(struct wm_softc *sc)
 {
 	uint16_t myea[ETHER_ADDR_LEN / 2];
@@ -5533,12 +5878,13 @@ wm_check_alt_mac_addr(struct wm_softc *s
 
 	/* Try to read alternative MAC address pointer */
 	if (wm_read_eeprom(sc, EEPROM_ALT_MAC_ADDR_PTR, 1, &offset) != 0)
-		return -1;
+		return 0;
 
-	/* Check pointer */
-	if (offset == 0xffff)
-		return -1;
+	/* Check pointer if it's valid or not. */
+	if ((offset == 0x0000) || (offset == 0xffff))
+		return 0;
 
+	offset += NVM_OFF_MACADDR_82571(sc->sc_funcid);
 	/*
 	 * Check whether alternative MAC address is valid or not.
 	 * Some cards have non 0xffff pointer but those don't use
@@ -5548,10 +5894,10 @@ wm_check_alt_mac_addr(struct wm_softc *s
 	 */
 	if (wm_read_eeprom(sc, offset, 1, myea) == 0)
 		if (((myea[0] & 0xff) & 0x01) == 0)
-			return 0; /* found! */
+			return offset; /* Found */
 
-	/* not found */
-	return -1;
+	/* Not found */
+	return 0;
 }
 
 static int
@@ -5563,26 +5909,10 @@ wm_read_mac_addr(struct wm_softc *sc, ui
 
 	switch (sc->sc_type) {
 	case WM_T_82580:
-	case WM_T_82580ER:
 	case WM_T_I350:
-		switch (sc->sc_funcid) {
-		case 0:
-			/* default value (== EEPROM_OFF_MACADDR) */
-			break;
-		case 1:
-			offset = EEPROM_OFF_LAN1;
-			break;
-		case 2:
-			offset = EEPROM_OFF_LAN2;
-			break;
-		case 3:
-			offset = EEPROM_OFF_LAN3;
-			break;
-		default:
-			goto bad;
-			/* NOTREACHED */
-			break;
-		}
+	case WM_T_I354:
+		/* EEPROM Top Level Partitioning */
+		offset = NVM_OFF_LAN_FUNC_82580(sc->sc_funcid) + 0;
 		break;
 	case WM_T_82571:
 	case WM_T_82575:
@@ -5590,34 +5920,10 @@ wm_read_mac_addr(struct wm_softc *sc, ui
 	case WM_T_80003:
 	case WM_T_I210:
 	case WM_T_I211:
-		if (wm_check_alt_mac_addr(sc) != 0) {
-			/* reset the offset to LAN0 */
-			offset = EEPROM_OFF_MACADDR;
+		offset = wm_check_alt_mac_addr(sc);
+		if (offset == 0)
 			if ((sc->sc_funcid & 0x01) == 1)
 				do_invert = 1;
-			goto do_read;
-		}
-		switch (sc->sc_funcid) {
-		case 0:
-			/*
-			 * The offset is the value in EEPROM_ALT_MAC_ADDR_PTR
-			 * itself.
-			 */
-			break;
-		case 1:
-			offset += EEPROM_OFF_MACADDR_LAN1;
-			break;
-		case 2:
-			offset += EEPROM_OFF_MACADDR_LAN2;
-			break;
-		case 3:
-			offset += EEPROM_OFF_MACADDR_LAN3;
-			break;
-		default:
-			goto bad;
-			/* NOTREACHED */
-			break;
-		}
 		break;
 	default:
 		if ((sc->sc_funcid & 0x01) == 1)
@@ -5625,11 +5931,9 @@ wm_read_mac_addr(struct wm_softc *sc, ui
 		break;
 	}
 
- do_read:
 	if (wm_read_eeprom(sc, offset, sizeof(myea) / sizeof(myea[0]),
-		myea) != 0) {
+		myea) != 0)
 		goto bad;
-	}
 
 	enaddr[0] = myea[0] & 0xff;
 	enaddr[1] = myea[0] >> 8;
@@ -5648,8 +5952,6 @@ wm_read_mac_addr(struct wm_softc *sc, ui
 	return 0;
 
  bad:
-	aprint_error_dev(sc->sc_dev, "unable to read Ethernet address\n");
-
 	return -1;
 }
 
@@ -5806,7 +6108,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;
@@ -5919,8 +6221,15 @@ do {									\
 } while (/*CONSTCOND*/0)
 
 	aprint_normal_dev(sc->sc_dev, "");
-	ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD);
-	ADD("1000baseSX-FDX", IFM_1000_SX|IFM_FDX, ANAR_X_FD);
+
+	/* Only 82545 is LX */
+	if (sc->sc_type == WM_T_82545) {
+		ADD("1000baseLX", IFM_1000_LX, ANAR_X_HD);
+		ADD("1000baseLX-FDX", IFM_1000_LX|IFM_FDX, ANAR_X_FD);
+	} else {
+		ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD);
+		ADD("1000baseSX-FDX", IFM_1000_SX|IFM_FDX, ANAR_X_FD);
+	}
 	ADD("auto", IFM_AUTO, ANAR_X_FD|ANAR_X_HD);
 	aprint_normal("\n");
 
@@ -5950,7 +6259,11 @@ wm_tbi_mediastatus(struct ifnet *ifp, st
 	}
 
 	ifmr->ifm_status |= IFM_ACTIVE;
-	ifmr->ifm_active |= IFM_1000_SX;
+	/* Only 82545 is LX */
+	if (sc->sc_type == WM_T_82545)
+		ifmr->ifm_active |= IFM_1000_LX;
+	else
+		ifmr->ifm_active |= IFM_1000_SX;
 	if (CSR_READ(sc, WMREG_STATUS) & STATUS_FD)
 		ifmr->ifm_active |= IFM_FDX;
 	ctrl = CSR_READ(sc, WMREG_CTRL);
@@ -5973,28 +6286,30 @@ wm_tbi_mediachange(struct ifnet *ifp)
 	uint32_t status;
 	int i;
 
-	sc->sc_txcw = 0;
-	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO ||
-	    (sc->sc_mii.mii_media.ifm_media & IFM_FLOW) != 0)
+	if ((sc->sc_type == WM_T_82571) || (sc->sc_type == WM_T_82572)
+	    || (sc->sc_type >= WM_T_82575))
+		CSR_WRITE(sc, WMREG_SCTL, SCTL_DISABLE_SERDES_LOOPBACK);
+
+	/* XXX power_up_serdes_link_82575() */
+
+	sc->sc_ctrl &= ~CTRL_LRST;
+	sc->sc_txcw = TXCW_ANE;
+	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO)
+		sc->sc_txcw |= TXCW_FD | TXCW_HD;
+	else if (ife->ifm_media & IFM_FDX)
+		sc->sc_txcw |= TXCW_FD;
+	else
+		sc->sc_txcw |= TXCW_HD;
+
+	if ((sc->sc_mii.mii_media.ifm_media & IFM_FLOW) != 0)
 		sc->sc_txcw |= TXCW_SYM_PAUSE | TXCW_ASYM_PAUSE;
-	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
-		sc->sc_txcw |= TXCW_ANE;
-	} else {
-		/*
-		 * If autonegotiation is turned off, force link up and turn on
-		 * full duplex
-		 */
-		sc->sc_txcw &= ~TXCW_ANE;
-		sc->sc_ctrl |= CTRL_SLU | CTRL_FD;
-		sc->sc_ctrl &= ~(CTRL_TFCE | CTRL_RFCE);
-		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
-		delay(1000);
-	}
 
 	DPRINTF(WM_DEBUG_LINK,("%s: sc_txcw = 0x%x after autoneg check\n",
-		    device_xname(sc->sc_dev),sc->sc_txcw));
+		    device_xname(sc->sc_dev), sc->sc_txcw));
 	CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw);
-	delay(10000);
+	CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+	CSR_WRITE_FLUSH(sc);
+	delay(1000);
 
 	i = CSR_READ(sc, WMREG_CTRL) & CTRL_SWDPIN(1);
 	DPRINTF(WM_DEBUG_LINK,("%s: i = 0x%x\n", device_xname(sc->sc_dev),i));
@@ -6005,19 +6320,6 @@ wm_tbi_mediachange(struct ifnet *ifp)
 	 */
 	if (((i != 0) && (sc->sc_type > WM_T_82544)) || (i == 0)) {
 		/* Have signal; wait for the link to come up. */
-
-		if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
-			/*
-			 * Reset the link, and let autonegotiation do its thing
-			 */
-			sc->sc_ctrl |= CTRL_LRST;
-			CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
-			delay(1000);
-			sc->sc_ctrl &= ~CTRL_LRST;
-			CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
-			delay(1000);
-		}
-
 		for (i = 0; i < WM_LINKUP_TIMEOUT; i++) {
 			delay(10000);
 			if (CSR_READ(sc, WMREG_STATUS) & STATUS_LU)
@@ -6106,14 +6408,14 @@ wm_tbi_set_linkled(struct wm_softc *sc)
 static void
 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) {
@@ -6130,13 +6432,7 @@ wm_tbi_check_link(struct wm_softc *sc)
 	if ((sc->sc_ethercom.ec_if.if_flags & IFF_UP)
 	    && ((status & STATUS_LU) == 0)) {
 		sc->sc_tbi_linkup = 0;
-		if (sc->sc_tbi_nrxcfg - sc->sc_tbi_lastnrxcfg > 100) {
-			/* RXCFG storm! */
-			DPRINTF(WM_DEBUG_LINK, ("RXCFG storm! (%d)\n",
-				sc->sc_tbi_nrxcfg - sc->sc_tbi_lastnrxcfg));
-			wm_init(ifp);
-			ifp->if_start(ifp);
-		} else if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
+		if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
 			/* If the timer expired, retry autonegotiation */
 			if (++sc->sc_tbi_ticks >= sc->sc_tbi_anegticks) {
 				DPRINTF(WM_DEBUG_LINK, ("EXPIRE\n"));
@@ -6147,9 +6443,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);
@@ -6185,8 +6483,8 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82575:
 	case WM_T_82576:
 	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:
@@ -6233,9 +6531,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);
@@ -6259,16 +6559,18 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82575:
 	case WM_T_82576:
 	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)
@@ -6287,8 +6589,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:
@@ -6310,8 +6614,8 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82575:
 	case WM_T_82576:
 	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:
@@ -6354,8 +6658,8 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82575:
 	case WM_T_82576:
 	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:
@@ -6414,6 +6718,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.
@@ -6423,6 +6766,7 @@ wm_gmii_mediainit(struct wm_softc *sc, p
 {
 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 	struct mii_data *mii = &sc->sc_mii;
+	uint32_t reg;
 
 	/* We have MII. */
 	sc->sc_flags |= WM_F_HAS_MII;
@@ -6432,6 +6776,15 @@ wm_gmii_mediainit(struct wm_softc *sc, p
 	else
 		sc->sc_tipg = TIPG_1000T_DFLT;
 
+	/* XXX Not for I354? FreeBSD's e1000_82575.c doesn't include it */
+	if ((sc->sc_type == WM_T_82580)
+	    || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210)
+	    || (sc->sc_type == WM_T_I211)) {
+		reg = CSR_READ(sc, WMREG_PHPM);
+		reg &= ~PHPM_GO_LINK_D;
+		CSR_WRITE(sc, WMREG_PHPM, reg);
+	}
+
 	/*
 	 * Let the chip set speed/duplex on its own based on
 	 * signals from the PHY.
@@ -6452,8 +6805,9 @@ wm_gmii_mediainit(struct wm_softc *sc, p
 	 *  For some devices, we can determine the PHY access method
 	 * from sc_type.
 	 *
-	 *  For ICH8 variants, it's difficult to detemine the PHY access
-	 * method by sc_type, so use the PCI product ID for some devices.
+	 *  For ICH and PCH variants, it's difficult to determine the PHY
+	 * access  method by sc_type, so use the PCI product ID for some
+	 * devices.
 	 * For other ICH8 variants, try to use igp's method. If the PHY
 	 * can't detect, then use bm's method.
 	 */
@@ -6462,30 +6816,16 @@ wm_gmii_mediainit(struct wm_softc *sc, p
 	case PCI_PRODUCT_INTEL_PCH_M_LC:
 		/* 82577 */
 		sc->sc_phytype = WMPHY_82577;
-		mii->mii_readreg = wm_gmii_hv_readreg;
-		mii->mii_writereg = wm_gmii_hv_writereg;
 		break;
 	case PCI_PRODUCT_INTEL_PCH_D_DM:
 	case PCI_PRODUCT_INTEL_PCH_D_DC:
 		/* 82578 */
 		sc->sc_phytype = WMPHY_82578;
-		mii->mii_readreg = wm_gmii_hv_readreg;
-		mii->mii_writereg = wm_gmii_hv_writereg;
 		break;
 	case PCI_PRODUCT_INTEL_PCH2_LV_LM:
 	case PCI_PRODUCT_INTEL_PCH2_LV_V:
 		/* 82579 */
 		sc->sc_phytype = WMPHY_82579;
-		mii->mii_readreg = wm_gmii_hv_readreg;
-		mii->mii_writereg = wm_gmii_hv_writereg;
-		break;
-	case PCI_PRODUCT_INTEL_I217_LM:
-	case PCI_PRODUCT_INTEL_I217_V:
-	case PCI_PRODUCT_INTEL_I218_LM:
-	case PCI_PRODUCT_INTEL_I218_V:
-		/* I21[78] */
-		mii->mii_readreg = wm_gmii_hv_readreg;
-		mii->mii_writereg = wm_gmii_hv_writereg;
 		break;
 	case PCI_PRODUCT_INTEL_82801I_BM:
 	case PCI_PRODUCT_INTEL_82801J_R_BM_LM:
@@ -6499,7 +6839,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) {
@@ -6521,6 +6862,11 @@ wm_gmii_mediainit(struct wm_softc *sc, p
 		}
 		break;
 	}
+	if ((sc->sc_type >= WM_T_PCH) && (sc->sc_type <= WM_T_PCH_LPT)) {
+		/* All PCH* use _hv_ */
+		mii->mii_readreg = wm_gmii_hv_readreg;
+		mii->mii_writereg = wm_gmii_hv_writereg;
+	}
 	mii->mii_statchg = wm_gmii_statchg;
 
 	wm_gmii_reset(sc);
@@ -6530,31 +6876,40 @@ wm_gmii_mediainit(struct wm_softc *sc, p
 	    wm_gmii_mediastatus);
 
 	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_82580)
+	    || (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,
@@ -6694,10 +7049,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);
 	}
 }
@@ -6712,25 +7070,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;
@@ -7146,6 +7511,39 @@ 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_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
@@ -7201,16 +7599,18 @@ wm_sgmii_writereg(device_t self, int phy
 	struct wm_softc *sc = device_private(self);
 	uint32_t i2ccmd;
 	int i;
+	int val_swapped;
 
 	if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) {
 		aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
 		    __func__);
 		return;
 	}
-
+	/* Swap the data bytes for the I2C interface */
+	val_swapped = ((val >> 8) & 0x00FF) | ((val << 8) & 0xFF00);
 	i2ccmd = (reg << I2CCMD_REG_ADDR_SHIFT)
 	    | (phy << I2CCMD_PHY_ADDR_SHIFT)
-	    | I2CCMD_OPCODE_WRITE;
+	    | I2CCMD_OPCODE_WRITE | val_swapped;
 	CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd);
 
 	/* Poll the ready bit */
@@ -7371,6 +7771,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;
@@ -7441,8 +7842,28 @@ wm_get_swsm_semaphore(struct wm_softc *s
 	int32_t timeout;
 	uint32_t swsm;
 
+	if (sc->sc_flags & WM_F_EEPROM_SEMAPHORE) {
+		/* Get the SW semaphore. */
+		timeout = sc->sc_nvm_wordsize + 1;
+		while (timeout) {
+			swsm = CSR_READ(sc, WMREG_SWSM);
+
+			if ((swsm & SWSM_SMBI) == 0)
+				break;
+
+			delay(50);
+			timeout--;
+		}
+
+		if (timeout == 0) {
+			aprint_error_dev(sc->sc_dev,
+			    "could not acquire SWSM SMBI\n");
+			return 1;
+		}
+	}
+
 	/* Get the FW semaphore. */
-	timeout = 1000 + 1; /* XXX */
+	timeout = sc->sc_nvm_wordsize + 1;
 	while (timeout) {
 		swsm = CSR_READ(sc, WMREG_SWSM);
 		swsm |= SWSM_SWESMBI;
@@ -7457,7 +7878,7 @@ wm_get_swsm_semaphore(struct wm_softc *s
 	}
 
 	if (timeout == 0) {
-		aprint_error_dev(sc->sc_dev, "could not acquire EEPROM GNT\n");
+		aprint_error_dev(sc->sc_dev, "could not acquire SWSM SWESMBI\n");
 		/* Release semaphores */
 		wm_put_swsm_semaphore(sc);
 		return 1;
@@ -7471,7 +7892,7 @@ wm_put_swsm_semaphore(struct wm_softc *s
 	uint32_t swsm;
 
 	swsm = CSR_READ(sc, WMREG_SWSM);
-	swsm &= ~(SWSM_SWESMBI);
+	swsm &= ~(SWSM_SMBI | SWSM_SWESMBI);
 	CSR_WRITE(sc, WMREG_SWSM, swsm);
 }
 
@@ -7556,6 +7977,43 @@ wm_put_swfwhw_semaphore(struct wm_softc 
 }
 
 static int
+wm_get_hw_semaphore_82573(struct wm_softc *sc)
+{
+	int i = 0;
+	uint32_t reg;
+
+	reg = CSR_READ(sc, WMREG_EXTCNFCTR);
+	do {
+		CSR_WRITE(sc, WMREG_EXTCNFCTR,
+		    reg | EXTCNFCTR_MDIO_SW_OWNERSHIP);
+		reg = CSR_READ(sc, WMREG_EXTCNFCTR);
+		if ((reg & EXTCNFCTR_MDIO_SW_OWNERSHIP) != 0)
+			break;
+		delay(2*1000);
+		i++;
+	} while (i < WM_MDIO_OWNERSHIP_TIMEOUT);
+
+	if (i == WM_MDIO_OWNERSHIP_TIMEOUT) {
+		wm_put_hw_semaphore_82573(sc);
+		log(LOG_ERR, "%s: Driver can't access the PHY\n",
+		    device_xname(sc->sc_dev));
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+wm_put_hw_semaphore_82573(struct wm_softc *sc)
+{
+	uint32_t reg;
+
+	reg = CSR_READ(sc, WMREG_EXTCNFCTR);
+	reg &= ~EXTCNFCTR_MDIO_SW_OWNERSHIP;
+	CSR_WRITE(sc, WMREG_EXTCNFCTR, reg);
+}
+
+static int
 wm_valid_nvm_bank_detect_ich8lan(struct wm_softc *sc, unsigned int *bank)
 {
 	uint32_t eecd;
@@ -7592,7 +8050,8 @@ wm_valid_nvm_bank_detect_ich8lan(struct 
 		}
 	}
 
-	aprint_error_dev(sc->sc_dev, "EEPROM not present\n");
+	DPRINTF(WM_DEBUG_NVM, ("%s: No valid NVM bank present\n",
+		device_xname(sc->sc_dev)));
 	return -1;
 }
 
@@ -7622,9 +8081,9 @@ wm_read_eeprom_ich8(struct wm_softc *sc,
 	 */
 	error = wm_valid_nvm_bank_detect_ich8lan(sc, &flash_bank);
 	if (error) {
-		aprint_error_dev(sc->sc_dev, "%s: failed to detect NVM bank\n",
-		    __func__);
-		return error;
+		DPRINTF(WM_DEBUG_NVM, ("%s: failed to detect NVM bank\n",
+			device_xname(sc->sc_dev)));
+		flash_bank = 0;
 	}
 
 	/*
@@ -7964,8 +8423,7 @@ wm_enable_mng_pass_thru(struct wm_softc 
 
 	DPRINTF(WM_DEBUG_MANAGE, ("%s: MANC (%08x)\n",
 		device_xname(sc->sc_dev), manc));
-	if (((manc & MANC_RECV_TCO_EN) == 0)
-	    || ((manc & MANC_EN_MAC_ADDR_FILTER) == 0))
+	if ((manc & MANC_RECV_TCO_EN) == 0)
 		return 0;
 
 	if ((sc->sc_flags & WM_F_ARC_SUBSYS_VALID) != 0) {
@@ -7975,6 +8433,17 @@ wm_enable_mng_pass_thru(struct wm_softc 
 		    && ((fwsm & FWSM_MODE_MASK)
 			== (MNG_ICH_IAMT_MODE << FWSM_MODE_SHIFT)))
 			return 1;
+	} else if ((sc->sc_type == WM_T_82574) || (sc->sc_type == WM_T_82583)){
+		uint16_t data;
+
+		factps = CSR_READ(sc, WMREG_FACTPS);
+		wm_read_eeprom(sc, EEPROM_OFF_CFG2, 1, &data);
+		DPRINTF(WM_DEBUG_MANAGE, ("%s: FACTPS = %08x, CFG2=%04x\n",
+			device_xname(sc->sc_dev), factps, data));
+		if (((factps & FACTPS_MNGCG) == 0)
+		    && ((data & EEPROM_CFG2_MNGM_MASK)
+			== (EEPROM_CFG2_MNGM_PT << EEPROM_CFG2_MNGM_SHIFT)))
+			return 1;
 	} else if (((manc & MANC_SMBUS_EN) != 0)
 	    && ((manc & MANC_ASF_EN) == 0))
 		return 1;
@@ -8344,10 +8813,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);
 }
 
@@ -8362,9 +8833,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);
 
 		/*
@@ -8412,7 +8885,7 @@ wm_reset_init_script_82575(struct wm_sof
 {
 	/*
 	 * remark: this is untested code - we have no board without EEPROM
-	 *  same setup as mentioned int the freeBSD driver for the i82575
+	 *  same setup as mentioned int the FreeBSD driver for the i82575
 	 */
 
 	/* SerDes configuration via SERDESCTRL */
@@ -8467,6 +8940,7 @@ wm_release_manageability(struct wm_softc
 	if (sc->sc_flags & WM_F_HAS_MANAGE) {
 		uint32_t manc = CSR_READ(sc, WMREG_MANC);
 
+		manc |= MANC_ARP_EN;
 		if (sc->sc_type >= WM_T_82571)
 			manc &= ~MANC_EN_MNG2HOST;
 
@@ -8492,11 +8966,9 @@ wm_get_wakeup(struct wm_softc *sc)
 	case WM_T_82574:
 	case WM_T_82575:
 	case WM_T_82576:
-#if 0 /* XXX */
 	case WM_T_82580:
-	case WM_T_82580ER:
 	case WM_T_I350:
-#endif
+	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.24.20.8 src/sys/dev/pci/if_wmreg.h:1.24.20.9
--- src/sys/dev/pci/if_wmreg.h:1.24.20.8	Sat Sep  7 17:10:18 2013
+++ src/sys/dev/pci/if_wmreg.h	Thu Apr 30 20:00:27 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmreg.h,v 1.24.20.8 2013/09/07 17:10:18 bouyer Exp $	*/
+/*	$NetBSD: if_wmreg.h,v 1.24.20.9 2015/04/30 20:00:27 snj 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 */
@@ -286,6 +286,7 @@ struct livengood_tcpip_ctxdesc {
 #define	EECD_EE_AUTORD	(1U << 9)	/* auto read done */
 #define	EECD_EE_ABITS	(1U << 10)	/* EEPROM address bits
 					   (based on type) */
+#define	EECD_EE_SIZE_EX_MASK __BITS(14,11) /* EEPROM size for new devices */
 #define	EECD_EE_TYPE	(1U << 13)	/* EEPROM type
 					   (0 = Microwire, 1 = SPI) */
 #define EECD_SEC1VAL	(1U << 22)	/* Sector One Valid */
@@ -310,10 +311,17 @@ struct livengood_tcpip_ctxdesc {
 #define	SPI_SR_BP1	0x08
 #define	SPI_SR_WPEN	0x80
 
+#define NVM_CHECKSUM			0xBABA
+#define EEPROM_SIZE			0x0040
+#define NVM_COMPAT_VALID_CHECKSUM	0x0001
+
 #define	EEPROM_OFF_MACADDR	0x00	/* MAC address offset */
+#define NVM_COMPAT		0x03
 #define	EEPROM_OFF_CFG1		0x0a	/* config word 1 */
 #define	EEPROM_OFF_CFG2		0x0f	/* config word 2 */
+#define	NVM_OFF_EEPROM_SIZE	0x12	/* NVM SIZE */
 #define	EEPROM_OFF_CFG3_PORTB	0x14	/* config word 3 */
+#define NVM_FUTURE_INIT_WORD1	0x19
 #define	EEPROM_INIT_3GIO_3	0x1a	/* PCIe Initial Configuration Word 3 */
 #define	EEPROM_OFF_K1_CONFIG	0x1b	/* NVM K1 Config */
 #define	EEPROM_OFF_SWDPIN	0x20	/* SWD Pins (Cordova) */
@@ -350,7 +358,13 @@ struct livengood_tcpip_ctxdesc {
 #define	EEPROM_CFG2_APM_PME	(1U << 15)
 #define	EEPROM_CFG2_SWDPIO_SHIFT 4
 #define	EEPROM_CFG2_SWDPIO_MASK	(0xf << EEPROM_CFG2_SWDPIO_SHIFT)
-#define	EEPROM_CFG2_MNGM_MASK	(3U << 13) /* Manageability Operation mode */
+#define	EEPROM_CFG2_MNGM_SHIFT	13	/* Manageability Operation mode */
+#define	EEPROM_CFG2_MNGM_MASK	(3U << EEPROM_CFG2_MNGM_SHIFT)
+#define	EEPROM_CFG2_MNGM_DIS	0
+#define	EEPROM_CFG2_MNGM_NCSI	1
+#define	EEPROM_CFG2_MNGM_PT	2
+
+#define NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM	0x0040
 
 #define	EEPROM_K1_CONFIG_ENABLE	0x01
 
@@ -362,17 +376,13 @@ struct livengood_tcpip_ctxdesc {
 
 #define EEPROM_CFG3_APME	(1U << 10)	
 
-#define	EEPROM_OFF_MACADDR_LAN1	3	/* macaddr offset from PTR (port 1) */
-#define	EEPROM_OFF_MACADDR_LAN2	6	/* macaddr offset from PTR (port 2) */
-#define	EEPROM_OFF_MACADDR_LAN3	9	/* macaddr offset from PTR (port 3) */
+#define	NVM_OFF_MACADDR_82571(x)	(3 * (x))
 
 /*
  * EEPROM Partitioning. See Table 6-1, "EEPROM Top Level Partitioning"
  * in 82580's datasheet.
  */
-#define EEPROM_OFF_LAN1	0x0080	/* Offset for LAN1 (82580)*/
-#define EEPROM_OFF_LAN2	0x00c0	/* Offset for LAN2 (82580)*/
-#define EEPROM_OFF_LAN3	0x0100	/* Offset for LAN3 (82580)*/
+#define NVM_OFF_LAN_FUNC_82580(x)	((x) ? (0x40 + (0x40 * (x))) : 0)
 
 #define	WMREG_EERD	0x0014	/* EEPROM read */
 #define	EERD_DONE	0x02    /* done bit */
@@ -397,6 +407,7 @@ struct livengood_tcpip_ctxdesc {
 #define	CTRL_EXT_SPD_BYPS	(1U << 15) /* speed select bypass */
 #define	CTRL_EXT_IPS1		(1U << 16) /* invert power state bit 1 */
 #define	CTRL_EXT_RO_DIS		(1U << 17) /* relaxed ordering disabled */
+#define	CTRL_EXT_DMA_DYN_CLK	(1U << 19) /* DMA Dymamic Gating Enable */
 #define	CTRL_EXT_LINK_MODE_MASK		0x00C00000
 #define	CTRL_EXT_LINK_MODE_GMII		0x00000000
 #define	CTRL_EXT_LINK_MODE_KMRN		0x00000000
@@ -413,12 +424,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 */
 /*
@@ -429,6 +443,7 @@ struct livengood_tcpip_ctxdesc {
 #define SCTL_CTL_DATA_MASK 0x000000ff
 #define SCTL_CTL_ADDR_SHIFT 8
 #define SCTL_CTL_POLL_TIMEOUT 640
+#define SCTL_DISABLE_SERDES_LOOPBACK 0x0400
 
 #define	WMREG_FCAL	0x0028	/* Flow Control Address Low */
 #define	FCAL_CONST	0x00c28001	/* Flow Control MAC addr low */
@@ -592,6 +607,8 @@ struct livengood_tcpip_ctxdesc {
 
 #define	WMREG_TXCW	0x0178	/* Transmit Configuration Word (TBI mode) */
 	/* See MII ANAR_X bits. */
+#define	TXCW_FD		(1U << 5)	/* Full Duplex */
+#define	TXCW_HD		(1U << 6)	/* Half Duplex */
 #define	TXCW_SYM_PAUSE	(1U << 7)	/* sym pause request */
 #define	TXCW_ASYM_PAUSE	(1U << 8)	/* asym pause request */
 #define	TXCW_TxConfig	(1U << 30)	/* Tx Config */
@@ -686,11 +703,14 @@ struct livengood_tcpip_ctxdesc {
 #define	WMREG_OLD_TIDV	0x0440	/* Transmit Delay Interrupt Value */
 #define	WMREG_TIDV	0x3820
 
-#define	WMREG_TXDCTL	0x3828	/* Trandmit Descriptor Control */
+#define	WMREG_TXDCTL(n)		/* Trandmit Descriptor Control */ \
+	(((n) < 4) ? (0x3828 + ((n) * 0x100)) : (0xe028 + ((n) * 0x40)))
 #define	TXDCTL_PTHRESH(x) ((x) << 0)	/* prefetch threshold */
 #define	TXDCTL_HTHRESH(x) ((x) << 8)	/* host threshold */
 #define	TXDCTL_WTHRESH(x) ((x) << 16)	/* write back threshold */
 /* flags used starting with 82575 ... */
+#define TXDCTL_COUNT_DESC	__BIT(22) /* Enable the counting of desc.
+					   still to be processed. */
 #define TXDCTL_QUEUE_ENABLE  0x02000000 /* Enable specific Tx Queue */
 #define TXDCTL_SWFLSH        0x04000000 /* Tx Desc. write-back flushing */
 #define TXDCTL_PRIORITY      0x08000000
@@ -701,10 +721,19 @@ 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
 
+#define	WMREG_PHPM	0x0e14	/* PHY Power Management */
+#define	PHPM_GO_LINK_D		__BIT(5)	/* Go Link Disconnect */
+
 #define	WMREG_PBA	0x1000	/* Packet Buffer Allocation */
 #define	PBA_BYTE_SHIFT	10		/* KB -> bytes */
 #define	PBA_ADDR_SHIFT	7		/* KB -> quadwords */
@@ -787,11 +816,12 @@ struct livengood_tcpip_ctxdesc {
 #define	WMREG_TSPMT	0x3830	/* TCP Segmentation Pad and Minimum
 				   Threshold (Cordova) */
 
-#define	WMREG_TARC0	0x3840	/* Tx arbitration count */
-
 #define	TSPMT_TSMT(x)	(x)		/* TCP seg min transfer */
 #define	TSPMT_TSPBP(x)	((x) << 16)	/* TCP seg pkt buf padding */
 
+#define	WMREG_TARC0	0x3840	/* Tx arbitration count (0) */
+#define	WMREG_TARC1	0x3940	/* Tx arbitration count (1) */
+
 #define	WMREG_CRCERRS	0x4000	/* CRC Error Count */
 #define	WMREG_ALGNERRC	0x4004	/* Alignment Error Count */
 #define	WMREG_SYMERRC	0x4008	/* Symbol Error Count */
@@ -853,6 +883,13 @@ struct livengood_tcpip_ctxdesc {
 
 #define WMREG_RLPML	0x5004	/* Rx Long Packet Max Length */
 
+#define WMREG_RFCTL	0x5008	/* Receive Filter Control */
+#define WMREG_RFCTL_NFSWDIS	__BIT(6)  /* NFS Write Disable */
+#define WMREG_RFCTL_NFSRDIS	__BIT(7)  /* NFS Read Disable */
+#define WMREG_RFCTL_ACKDIS	__BIT(13) /* ACK Accelerate Disable */
+#define WMREG_RFCTL_IPV6EXDIS	__BIT(16) /* IPv6 Extension Header Disable */
+#define WMREG_RFCTL_NEWIPV6EXDIS __BIT(17) /* New IPv6 Extension Header */
+
 #define	WMREG_WUC	0x5800	/* Wakeup Control */
 #define	WUC_APME		0x00000001 /* APM Enable */
 #define	WUC_PME_EN		0x00000002 /* PME Enable */
@@ -870,8 +907,10 @@ struct livengood_tcpip_ctxdesc {
 #define	MANC_SMBUS_EN		0x00000001
 #define	MANC_ASF_EN		0x00000002
 #define	MANC_ARP_EN		0x00002000
+#define	MANC_RECV_TCO_RESET	0x00010000
 #define	MANC_RECV_TCO_EN	0x00020000
 #define	MANC_BLK_PHY_RST_ON_IDE	0x00040000
+#define	MANC_RECV_ALL		0x00080000
 #define	MANC_EN_MAC_ADDR_FILTER	0x00100000
 #define	MANC_EN_MNG2HOST	0x00200000
 
@@ -913,6 +952,9 @@ struct livengood_tcpip_ctxdesc {
 #define FWSM_RSPCIPHY		0x00000040	/* Reset PHY on PCI reset */
 #define FWSM_FW_VALID		0x00008000 /* FW established a valid mode */
 
+#define	WMREG_SWSM2	0x5b58	/* SW Semaphore 2 */
+#define SWSM2_LOCK		0x00000002 /* Secondary driver semaphore bit */
+
 #define	WMREG_SW_FW_SYNC 0x5b5c	/* software-firmware semaphore */
 #define	SWFW_EEP_SM		0x0001 /* eeprom access */
 #define	SWFW_PHY0_SM		0x0002 /* first ctrl phy access */
@@ -923,6 +965,8 @@ struct livengood_tcpip_ctxdesc {
 #define	SWFW_SOFT_SHIFT		0	/* software semaphores */
 #define	SWFW_FIRM_SHIFT		16	/* firmware semaphores */
 
+#define WMREG_GCR2	0x5b64	/* 3GPIO Control Register 2 */
+
 #define WMREG_CRC_OFFSET	0x5f50
 
 #define WMREG_EXTCNFCTR		0x0f00  /* Extended Configuration Control */
@@ -1009,6 +1053,8 @@ struct livengood_tcpip_ctxdesc {
 #define ICH_GFPREG_BASE_MASK       0x1FFF
 #define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
 
+#define NVM_WORD_SIZE_BASE_SHIFT 6
+
 #define ICH_NVM_SIG_WORD	0x13
 #define ICH_NVM_SIG_MASK	0xc000
 #define ICH_NVM_VALID_SIG_MASK	0xc0

Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.2.46.6 src/sys/dev/pci/if_wmvar.h:1.2.46.7
--- src/sys/dev/pci/if_wmvar.h:1.2.46.6	Sat Sep  7 17:10:18 2013
+++ src/sys/dev/pci/if_wmvar.h	Thu Apr 30 20:00:27 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmvar.h,v 1.2.46.6 2013/09/07 17:10:18 bouyer Exp $	*/
+/*	$NetBSD: if_wmvar.h,v 1.2.46.7 2015/04/30 20:00:27 snj Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -95,6 +95,7 @@
 #define WM_F_WOL		0x00100000
 #define WM_F_EEE		0x00200000  /* Energy Efficiency Ethernet */
 #define	WM_F_EEPROM_FLASH_HW	0x00400000	/* EEPROM is FLASH */
+#define WM_F_ATTACHED		0x00800000 /* attach() fininsed successfully */
 
 typedef enum {
 	WM_T_unknown		= 0,
@@ -119,8 +120,8 @@ typedef enum {
 	WM_T_82575,			/* i82575 */
 	WM_T_82576,			/* i82576 */
 	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.962.4.19 src/sys/dev/pci/pcidevs:1.962.4.20
--- src/sys/dev/pci/pcidevs:1.962.4.19	Sat Sep  7 17:10:18 2013
+++ src/sys/dev/pci/pcidevs	Thu Apr 30 20:00:27 2015
@@ -1,4 +1,4 @@
-$NetBSD: pcidevs,v 1.962.4.19 2013/09/07 17:10:18 bouyer Exp $
+$NetBSD: pcidevs,v 1.962.4.20 2015/04/30 20:00:27 snj Exp $
 
 /*
  * Copyright (c) 1995, 1996 Christopher G. Demetriou
@@ -2138,6 +2138,11 @@ product INTEL 6700PXH_PCIE1	0x032a	6700P
 product INTEL SRCZCRX		0x0407	RAID controller
 product INTEL SRCU42E		0x0408	SCSI RAID controller
 product INTEL SRCS28X		0x0409	SATA RAID controller
+product INTEL DH89XXCC_IQIA	0x0434	DH89xx CC PCIe Endpoint and QuiskAssit
+product INTEL DH89XXCC_SGMII	0x0438	DH89XXCC SGMII
+product INTEL DH89XXCC_SERDES	0x043a	DH89XXCC SerDes
+product INTEL DH89XXCC_BPLANE	0x043c	DH89XXCC backplane
+product INTEL DH89XXCC_SFP	0x0440	DH89XXCC SFP
 product INTEL PCEB		0x0482	82375EB/SB PCI-EISA Bridge
 product INTEL CDC		0x0483	82424ZX Cache and DRAM controller
 product INTEL SIO		0x0484	82378ZB System I/O
@@ -2324,6 +2329,10 @@ product INTEL I217_LM		0x153a	I217-LM Et
 product INTEL I217_V		0x153b	I217-V Ethernet Connection
 product INTEL I218_V		0x1559	I218-V Ethernet Connection
 product INTEL I218_LM		0x155a	I218-LM Ethernet Connection
+product INTEL I218_LM2		0x15a0	I218-LM Ethernet Connection
+product INTEL I218_V2		0x15a1	I218-V Ethernet Connection
+product INTEL I218_LM3		0x15a2	I218-LM Ethernet Connection
+product INTEL I218_V3		0x15a3	I218-V Ethernet Connection
 product INTEL 80960_RP		0x1960	ROB-in i960RP Microprocessor
 product INTEL 80960RM_2		0x1962	i960 RM PCI-PCI
 product INTEL 82840_HB		0x1a21	82840 Host
@@ -2356,6 +2365,56 @@ product INTEL 6SERIES_EHCI_1	0x1c26	6 Se
 product INTEL 6SERIES_EHCI_2	0x1c2d	6 Series USB
 product INTEL 6SERIES_MEI	0x1c3a	6 Series MEI
 product INTEL 6SERIES_KT	0x1c3d	6 Series KT
+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 DH89XX_LPC	0x2310	DH89xx LPC Controller
+product INTEL DH89XX_SATA_1	0x2323	DH89xx SATA Controller
+product INTEL DH89XX_SATA_2	0x2326	DH89xx SATA Controller
+product INTEL DH89XX_SMB	0x2330	DH89xx SMBus Host Controller
+product INTEL DH89XX_THERMAL	0x2332	DH89xx Thermal Subsystem
+product INTEL DH89XX_USB	0x2334	DH89xx USB EHCI
+product INTEL DH89XX_PCIE_1	0x2342	DH89xx PCIe Root Port
+product INTEL DH89XX_PCIE_2	0x2344	DH89xx PCIe Root Port
+product INTEL DH89XX_PCIE_3	0x2346	DH89xx PCIe Root Port
+product INTEL DH89XX_PCIE_4	0x2348	DH89xx PCIe Root Port
+product INTEL DH89XX_WDT	0x2360	DH89xx Watchdog Timer for Core Reset
+product INTEL DH89XX_MEI_1	0x2364	DH89xx MEI Controller
+product INTEL DH89XX_MEI_2	0x2365	DH89xx MEI Controller
 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