Module Name:    src
Committed By:   snj
Date:           Thu Dec  4 06:04:07 UTC 2014

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

Log Message:
Pull up following revision(s) (requested by msaitoh in ticket #1203):
        sys/dev/pci/if_wm.c: revisions 1.271, 1.273-1.274, 1.277-1.278,
                                       1.280, 1.282, 1.284-1.285, 1.287,
                                       1.293-1.294, 1.297-1.298,
                                       1.300-1.301, 1.305-1.307 via patch
        sys/dev/pci/if_wmreg.h: revisions 1.57-1.62, 1.64-1.65 via patch
        sys/dev/pci/if_wmvar.h: revisions 1.19, 1.21 via patch
- Acquire SW semaphore in wm_get_swsm_semaphore().
- Fix some bugs realted to semaphore. This change fixes a problem which
  was exposed in if_wm.c rev. 1.271. Tested by riastradh@.
  - Clear the SMBI bit in SWSM register before accessing NVM and PHY in
    wm_attach(). Same as FreeBSD.
  - Fix a bug that 82573 doesn't put the hardware semaphore. Same as
    FreeBSD r256200.
- 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). Tested with 82543GC, 82544EI,
  82545EM, 82546GB 82571EB and 82572EI fiber cards.
  - Don't use the RXCFG interrupt. It's not required and the interrupt is very
    heavy (a lot of interrupts). Same as {Free,Open}BSD.
  - Modify wm_tbi_mediachange() to be close to em_setup_fiber_serdes_link()
    of {Free,Open}BSD. At least, don't forget to set duplex setting.
  - WM_T_82545 is not 1000base-SX but 1000base-LX. Same as FreeBSD.
- Don't check SWSM_SMBI bit if WM_F_LOCK_SWSM isn't set. Fix a problem when
  using vmware with e1000"e". With e1000e which is regarded as 82574L,
  wm_gmii_init() fails with "could not acquire SWSM SMBI" message without
  this change. This problem doesn't occur with real 82574L card.
- Fix a bug that wm_get_swsm_semaphore() timed out when attaching device on
  some machines.
  - Calculate NVM word size correctly.
  - Determine timeout value based on the NVM word size.
- It's not required to print "failed to detect NVM bank" message.
  Only print while debugging. Same as {Free,Open}BSD.
- Add some new I218 devices.
- Delete 82580ER related code. It was from FreeBSD and was removed in r203049.
- 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.
- Move some NVM related macros from if_wm.c to if_wmreg.h.
- Sort definitions in if_wmreg.h
  - move NVM related values to the bottom.
  - sort in register's address' order.
- Simplify wm_read_mac_addr().
- Fix debug message.
- Add missing prototypes.
- Rename some functions for consistency and clarify.
- Rename some macros for consistency.
- Remove a duplicated error message.
- Fix typo in comment.
- Cleanup comments.
- KNF.


To generate a diff of this commit:
cvs rdiff -u -r1.227.2.13 -r1.227.2.14 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.46.2.6 -r1.46.2.7 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.12.10.4 -r1.12.10.5 src/sys/dev/pci/if_wmvar.h

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.227.2.13 src/sys/dev/pci/if_wm.c:1.227.2.14
--- src/sys/dev/pci/if_wm.c:1.227.2.13	Sun Nov  9 12:13:15 2014
+++ src/sys/dev/pci/if_wm.c	Thu Dec  4 06:04:07 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.227.2.13 2014/11/09 12:13:15 martin Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.227.2.14 2014/12/04 06:04:07 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.227.2.13 2014/11/09 12:13:15 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.227.2.14 2014/12/04 06:04:07 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -276,7 +276,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;
@@ -374,8 +375,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 */
 
@@ -494,43 +493,78 @@ do {									\
 	CSR_WRITE((sc), (sc)->sc_rdt_reg, (x));				\
 } while (/*CONSTCOND*/0)
 
-static void	wm_start(struct ifnet *);
-static void	wm_nq_start(struct ifnet *);
+/*
+ * Register read/write functions.
+ * Other than CSR_{READ|WRITE}().
+ */
+#if 0
+static inline uint32_t wm_io_read(struct wm_softc *, int);
+#endif
+static inline void wm_io_write(struct wm_softc *, int, uint32_t);
+static inline void wm_82575_write_8bit_ctlr_reg(struct wm_softc *, uint32_t,
+	uint32_t, uint32_t);
+static inline void wm_set_dma_addr(volatile wiseman_addr_t *, bus_addr_t);
+/*
+ * Device driver interface functions and commonly used functions.
+ * match, attach, detach, init, start, stop, ioctl, watchdog and so on.
+ */
+static const struct wm_product *wm_lookup(const struct pci_attach_args *);
+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);
+static bool	wm_suspend(device_t, const pmf_qual_t *);
+static bool	wm_resume(device_t, const pmf_qual_t *);
 static void	wm_watchdog(struct ifnet *);
+static void	wm_tick(void *);
 static int	wm_ifflags_cb(struct ethercom *);
 static int	wm_ioctl(struct ifnet *, u_long, void *);
-static int	wm_init(struct ifnet *);
-static void	wm_stop(struct ifnet *, int);
-static bool	wm_suspend(device_t, const pmf_qual_t *);
-static bool	wm_resume(device_t, const pmf_qual_t *);
-
-static void	wm_reset(struct wm_softc *);
-static void	wm_rxdrain(struct wm_softc *);
-static int	wm_add_rxbuf(struct wm_softc *, int);
-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 *);
+/* MAC address related */
+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 *);
-
+static void	wm_set_ral(struct wm_softc *, const uint8_t *, int);
+static uint32_t	wm_mchash(struct wm_softc *, const uint8_t *);
 static void	wm_set_filter(struct wm_softc *);
+/* Reset and init related */
 static void	wm_set_vlan(struct wm_softc *);
-
-static int	wm_intr(void *);
+static void	wm_set_pcie_completion_timeout(struct wm_softc *);
+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_reset(struct wm_softc *);
+static int	wm_add_rxbuf(struct wm_softc *, int);
+static void	wm_rxdrain(struct wm_softc *);
+static int	wm_init(struct ifnet *);
+static void	wm_stop(struct ifnet *, int);
+static int	wm_tx_offload(struct wm_softc *, struct wm_txsoft *,
+    uint32_t *, uint8_t *);
+static void	wm_dump_mbuf_chain(struct wm_softc *, struct mbuf *);
+static void	wm_82547_txfifo_stall(void *);
+static int	wm_82547_txfifo_bugchk(struct wm_softc *, struct mbuf *);
+/* Start */
+static void	wm_start(struct ifnet *);
+static int	wm_nq_tx_offload(struct wm_softc *, struct wm_txsoft *,
+    uint32_t *, uint32_t *, bool *);
+static void	wm_nq_start(struct ifnet *);
+/* Interrupt */
 static void	wm_txintr(struct wm_softc *);
 static void	wm_rxintr(struct wm_softc *);
+static void	wm_linkintr_gmii(struct wm_softc *, uint32_t);
+static void	wm_linkintr_tbi(struct wm_softc *, uint32_t);
 static void	wm_linkintr(struct wm_softc *, uint32_t);
+static int	wm_intr(void *);
 
-static void	wm_tbi_mediainit(struct wm_softc *);
-static int	wm_tbi_mediachange(struct ifnet *);
-static void	wm_tbi_mediastatus(struct ifnet *, struct ifmediareq *);
-
-static void	wm_tbi_set_linkled(struct wm_softc *);
-static void	wm_tbi_check_link(struct wm_softc *);
-
+/*
+ * Media related.
+ * GMII, SGMII, TBI (and SERDES)
+ */
+/* GMII related */
 static void	wm_gmii_reset(struct wm_softc *);
-
+static int	wm_get_phy_id_82575(struct wm_softc *);
+static void	wm_gmii_mediainit(struct wm_softc *, pci_product_id_t);
+static void	wm_gmii_mediastatus(struct ifnet *, struct ifmediareq *);
+static int	wm_gmii_mediachange(struct ifnet *);
+static void	wm_i82543_mii_sendbits(struct wm_softc *, uint32_t, int);
+static uint32_t	wm_i82543_mii_recvbits(struct wm_softc *);
 static int	wm_gmii_i82543_readreg(device_t, int, int);
 static void	wm_gmii_i82543_writereg(device_t, int, int, int);
 static int	wm_gmii_i82544_readreg(device_t, int, int);
@@ -539,35 +573,65 @@ static int	wm_gmii_i80003_readreg(device
 static void	wm_gmii_i80003_writereg(device_t, int, int, int);
 static int	wm_gmii_bm_readreg(device_t, int, int);
 static void	wm_gmii_bm_writereg(device_t, int, int, int);
+static void	wm_access_phy_wakeup_reg_bm(device_t, int, int16_t *, int);
 static int	wm_gmii_hv_readreg(device_t, int, int);
 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 void	wm_gmii_statchg(device_t);
+static int	wm_kmrn_readreg(struct wm_softc *, int);
+static void	wm_kmrn_writereg(struct wm_softc *, int, int);
+/* SGMII */
 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);
+/* TBI related */
+static int	wm_check_for_link(struct wm_softc *);
+static void	wm_tbi_mediainit(struct wm_softc *);
+static void	wm_tbi_mediastatus(struct ifnet *, struct ifmediareq *);
+static int	wm_tbi_mediachange(struct ifnet *);
+static void	wm_tbi_set_linkled(struct wm_softc *);
+static void	wm_tbi_check_link(struct wm_softc *);
 
-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 *);
-
-static int	wm_kmrn_readreg(struct wm_softc *, int);
-static void	wm_kmrn_writereg(struct wm_softc *, int, int);
+/*
+ * NVM related.
+ * Microwire, SPI (w/wo EERD) and Flash.
+ */
+/* Misc functions */
+static void	wm_eeprom_sendbits(struct wm_softc *, uint32_t, int);
+static void	wm_eeprom_recvbits(struct wm_softc *, uint32_t *, int);
+static int	wm_nvm_set_addrbits_size_eecd(struct wm_softc *);
+/* Microwire */
+static int	wm_nvm_read_uwire(struct wm_softc *, int, int, uint16_t *);
+/* SPI */
+static int	wm_nvm_ready_spi(struct wm_softc *);
+static int	wm_nvm_read_spi(struct wm_softc *, int, int, uint16_t *);
+/* Using with EERD */
+static int	wm_poll_eerd_eewr_done(struct wm_softc *, int);
+static int	wm_nvm_read_eerd(struct wm_softc *, int, int, uint16_t *);
+/* Flash */
+static int	wm_nvm_valid_bank_detect_ich8lan(struct wm_softc *,
+    unsigned int *);
+static int32_t	wm_ich8_cycle_init(struct wm_softc *);
+static int32_t	wm_ich8_flash_cycle(struct wm_softc *, uint32_t);
+static int32_t	wm_read_ich8_data(struct wm_softc *, uint32_t, uint32_t,
+	uint16_t *);
+static int32_t	wm_read_ich8_byte(struct wm_softc *, uint32_t, uint8_t *);
+static int32_t	wm_read_ich8_word(struct wm_softc *, uint32_t, uint16_t *);
+static int	wm_nvm_read_ich8(struct wm_softc *, int, int, uint16_t *);
+/* Lock, detecting NVM type, validate checksum and read */
+static int	wm_nvm_acquire(struct wm_softc *);
+static void	wm_nvm_release(struct wm_softc *);
+static int	wm_nvm_is_onboard_eeprom(struct wm_softc *);
+static int	wm_nvm_validate_checksum(struct wm_softc *);
+static int	wm_nvm_read(struct wm_softc *, int, int, uint16_t *);
 
-static void	wm_set_spiaddrbits(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);
-static int	wm_is_onboard_nvm_eeprom(struct wm_softc *);
-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 *);
+/*
+ * Hardware semaphores.
+ * Very complexed...
+ */
 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);
 static int	wm_get_swfw_semaphore(struct wm_softc *, uint16_t);
 static void	wm_put_swfw_semaphore(struct wm_softc *, uint16_t);
 static int	wm_get_swfwhw_semaphore(struct wm_softc *);
@@ -575,15 +639,10 @@ static void	wm_put_swfwhw_semaphore(stru
 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 *);
-static int32_t	wm_ich8_flash_cycle(struct wm_softc *, uint32_t);
-static int32_t	wm_read_ich8_data(struct wm_softc *, uint32_t,
-		     uint32_t, uint16_t *);
-static int32_t	wm_read_ich8_byte(struct wm_softc *, uint32_t, uint8_t *);
-static int32_t	wm_read_ich8_word(struct wm_softc *, uint32_t, uint16_t *);
-static void	wm_82547_txfifo_stall(void *);
-static void	wm_gate_hw_phy_config_ich8lan(struct wm_softc *, int);
+/*
+ * Management mode and power management related subroutines.
+ * BMC, AMT, suspend/resume and EEE.
+ */
 static int	wm_check_mng_mode(struct wm_softc *);
 static int	wm_check_mng_mode_ich8lan(struct wm_softc *);
 static int	wm_check_mng_mode_82574(struct wm_softc *);
@@ -591,29 +650,32 @@ static int	wm_check_mng_mode_generic(str
 static int	wm_enable_mng_pass_thru(struct wm_softc *);
 static int	wm_check_reset_block(struct wm_softc *);
 static void	wm_get_hw_control(struct wm_softc *);
-static int	wm_check_for_link(struct wm_softc *);
-static void	wm_kmrn_lock_loss_workaround_ich8lan(struct wm_softc *);
-static void	wm_gig_downshift_workaround_ich8lan(struct wm_softc *);
+static void	wm_release_hw_control(struct wm_softc *);
+static void	wm_gate_hw_phy_config_ich8lan(struct wm_softc *, int);
+static void	wm_smbustopci(struct wm_softc *);
+static void	wm_init_manageability(struct wm_softc *);
+static void	wm_release_manageability(struct wm_softc *);
+static void	wm_get_wakeup(struct wm_softc *);
 #ifdef WM_WOL
+static void	wm_enable_phy_wakeup(struct wm_softc *);
 static void	wm_igp3_phy_powerdown_workaround_ich8lan(struct wm_softc *);
+static void	wm_enable_wakeup(struct wm_softc *);
 #endif
+/* EEE */
+static void	wm_set_eee_i350(struct wm_softc *);
+
+/*
+ * Workarounds (mainly PHY related).
+ * Basically, PHY's workarounds are in the PHY drivers.
+ */
+static void	wm_kmrn_lock_loss_workaround_ich8lan(struct wm_softc *);
+static void	wm_gig_downshift_workaround_ich8lan(struct wm_softc *);
 static void	wm_hv_phy_workaround_ich8lan(struct wm_softc *);
 static void	wm_lv_phy_workaround_ich8lan(struct wm_softc *);
 static void	wm_k1_gig_workaround_hv(struct wm_softc *, int);
 static void	wm_set_mdio_slow_mode_hv(struct wm_softc *);
 static void	wm_configure_k1_ich8lan(struct wm_softc *, int);
-static void	wm_smbustopci(struct wm_softc *);
-static void	wm_set_pcie_completion_timeout(struct wm_softc *);
 static void	wm_reset_init_script_82575(struct wm_softc *);
-static void	wm_release_manageability(struct wm_softc *);
-static void	wm_release_hw_control(struct wm_softc *);
-static void	wm_get_wakeup(struct wm_softc *);
-#ifdef WM_WOL
-static void	wm_enable_phy_wakeup(struct wm_softc *);
-static void	wm_enable_wakeup(struct wm_softc *);
-#endif
-static void	wm_init_manageability(struct wm_softc *);
-static void	wm_set_eee_i350(struct wm_softc *);
 
 CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc),
     wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
@@ -1003,12 +1065,6 @@ 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 },
@@ -1061,9 +1117,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 },
@@ -1073,6 +1141,12 @@ static const struct wm_product {
 static char wm_txseg_evcnt_names[WM_NTXSEGS][sizeof("txsegXXX")];
 #endif /* WM_EVENT_COUNTERS */
 
+
+/*
+ * Register read/write functions.
+ * Other than CSR_{READ|WRITE}().
+ */
+
 #if 0 /* Not currently used */
 static inline uint32_t
 wm_io_read(struct wm_softc *sc, int reg)
@@ -1108,7 +1182,8 @@ wm_82575_write_8bit_ctlr_reg(struct wm_s
 			break;
 	}
 	if (i == SCTL_CTL_POLL_TIMEOUT) {
-		aprint_error("%s: WARNING: i82575 reg 0x%08x setup did not indicate ready\n",
+		aprint_error("%s: WARNING:"
+		    " i82575 reg 0x%08x setup did not indicate ready\n",
 		    device_xname(sc->sc_dev), reg);
 	}
 }
@@ -1123,16 +1198,76 @@ 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_nvm_read(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;
 }
 
+/*
+ * Device driver interface functions and commonly used functions.
+ * match, attach, detach, init, start, stop, ioctl, watchdog and so on.
+ */
+
+/* Lookup supported device table */
 static const struct wm_product *
 wm_lookup(const struct pci_attach_args *pa)
 {
@@ -1146,6 +1281,7 @@ wm_lookup(const struct pci_attach_args *
 	return NULL;
 }
 
+/* The match function (ca_match) */
 static int
 wm_match(device_t parent, cfdata_t cf, void *aux)
 {
@@ -1157,6 +1293,7 @@ wm_match(device_t parent, cfdata_t cf, v
 	return 0;
 }
 
+/* The attach function (ca_attach) */
 static void
 wm_attach(device_t parent, device_t self, void *aux)
 {
@@ -1180,6 +1317,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;
@@ -1214,7 +1352,7 @@ 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_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;
@@ -1330,7 +1468,7 @@ 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_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;
@@ -1366,7 +1504,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,
@@ -1552,7 +1689,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:
@@ -1561,10 +1699,13 @@ 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:
@@ -1574,39 +1715,54 @@ wm_attach(device_t parent, device_t self
 		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;
+			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;
+			}
+		}
 		sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
 		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_nvm_is_onboard_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: /* XXXX ok? */
+	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:
@@ -1616,6 +1772,7 @@ 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)) {
@@ -1635,6 +1792,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;
@@ -1642,6 +1800,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
@@ -1651,12 +1837,12 @@ wm_attach(device_t parent, device_t self
 	 * Validate the EEPROM checksum. If the checksum fails, flag
 	 * this for later, so we can fail future reads from the EEPROM.
 	 */
-	if (wm_validate_eeprom_checksum(sc)) {
+	if (wm_nvm_validate_checksum(sc)) {
 		/*
 		 * Read twice again because some PCI-e parts fail the
 		 * first check due to the link being in sleep state.
 		 */
-		if (wm_validate_eeprom_checksum(sc))
+		if (wm_nvm_validate_checksum(sc))
 			sc->sc_flags |= WM_F_EEPROM_INVALID;
 	}
 
@@ -1665,19 +1851,21 @@ 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) {
@@ -1729,7 +1917,7 @@ wm_attach(device_t parent, device_t self
 		KASSERT(prop_object_type(pn) == PROP_TYPE_NUMBER);
 		cfg1 = (uint16_t) prop_number_integer_value(pn);
 	} else {
-		if (wm_read_eeprom(sc, EEPROM_OFF_CFG1, 1, &cfg1)) {
+		if (wm_nvm_read(sc, NVM_OFF_CFG1, 1, &cfg1)) {
 			aprint_error_dev(sc->sc_dev, "unable to read CFG1\n");
 			return;
 		}
@@ -1740,7 +1928,7 @@ wm_attach(device_t parent, device_t self
 		KASSERT(prop_object_type(pn) == PROP_TYPE_NUMBER);
 		cfg2 = (uint16_t) prop_number_integer_value(pn);
 	} else {
-		if (wm_read_eeprom(sc, EEPROM_OFF_CFG2, 1, &cfg2)) {
+		if (wm_nvm_read(sc, NVM_OFF_CFG2, 1, &cfg2)) {
 			aprint_error_dev(sc->sc_dev, "unable to read CFG2\n");
 			return;
 		}
@@ -1753,10 +1941,10 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82543:
 		/* dummy? */
 		eeprom_data = 0;
-		apme_mask = EEPROM_CFG3_APME;
+		apme_mask = NVM_CFG3_APME;
 		break;
 	case WM_T_82544:
-		apme_mask = EEPROM_CFG2_82544_APM_EN;
+		apme_mask = NVM_CFG2_82544_APM_EN;
 		eeprom_data = cfg2;
 		break;
 	case WM_T_82546:
@@ -1768,14 +1956,13 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82583:
 	case WM_T_80003:
 	default:
-		apme_mask = EEPROM_CFG3_APME;
-		wm_read_eeprom(sc, (sc->sc_funcid == 1) ? EEPROM_OFF_CFG3_PORTB
-		    : EEPROM_OFF_CFG3_PORTA, 1, &eeprom_data);
+		apme_mask = NVM_CFG3_APME;
+		wm_nvm_read(sc, (sc->sc_funcid == 1) ? NVM_OFF_CFG3_PORTB
+		    : NVM_OFF_CFG3_PORTA, 1, &eeprom_data);
 		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: /* XXX ok? */
 	case WM_T_ICH8:
@@ -1809,7 +1996,7 @@ wm_attach(device_t parent, device_t self
 			KASSERT(prop_object_type(pn) == PROP_TYPE_NUMBER);
 			swdpin = (uint16_t) prop_number_integer_value(pn);
 		} else {
-			if (wm_read_eeprom(sc, EEPROM_OFF_SWDPIN, 1, &swdpin)) {
+			if (wm_nvm_read(sc, NVM_OFF_SWDPIN, 1, &swdpin)) {
 				aprint_error_dev(sc->sc_dev,
 				    "unable to read SWDPIN\n");
 				return;
@@ -1817,36 +2004,36 @@ wm_attach(device_t parent, device_t self
 		}
 	}
 
-	if (cfg1 & EEPROM_CFG1_ILOS)
+	if (cfg1 & NVM_CFG1_ILOS)
 		sc->sc_ctrl |= CTRL_ILOS;
 	if (sc->sc_type >= WM_T_82544) {
 		sc->sc_ctrl |=
-		    ((swdpin >> EEPROM_SWDPIN_SWDPIO_SHIFT) & 0xf) <<
+		    ((swdpin >> NVM_SWDPIN_SWDPIO_SHIFT) & 0xf) <<
 		    CTRL_SWDPIO_SHIFT;
 		sc->sc_ctrl |=
-		    ((swdpin >> EEPROM_SWDPIN_SWDPIN_SHIFT) & 0xf) <<
+		    ((swdpin >> NVM_SWDPIN_SWDPIN_SHIFT) & 0xf) <<
 		    CTRL_SWDPINS_SHIFT;
 	} else {
 		sc->sc_ctrl |=
-		    ((cfg1 >> EEPROM_CFG1_SWDPIO_SHIFT) & 0xf) <<
+		    ((cfg1 >> NVM_CFG1_SWDPIO_SHIFT) & 0xf) <<
 		    CTRL_SWDPIO_SHIFT;
 	}
 
 #if 0
 	if (sc->sc_type >= WM_T_82544) {
-		if (cfg1 & EEPROM_CFG1_IPS0)
+		if (cfg1 & NVM_CFG1_IPS0)
 			sc->sc_ctrl_ext |= CTRL_EXT_IPS;
-		if (cfg1 & EEPROM_CFG1_IPS1)
+		if (cfg1 & NVM_CFG1_IPS1)
 			sc->sc_ctrl_ext |= CTRL_EXT_IPS1;
 		sc->sc_ctrl_ext |=
-		    ((swdpin >> (EEPROM_SWDPIN_SWDPIO_SHIFT + 4)) & 0xd) <<
+		    ((swdpin >> (NVM_SWDPIN_SWDPIO_SHIFT + 4)) & 0xd) <<
 		    CTRL_EXT_SWDPIO_SHIFT;
 		sc->sc_ctrl_ext |=
-		    ((swdpin >> (EEPROM_SWDPIN_SWDPIN_SHIFT + 4)) & 0xd) <<
+		    ((swdpin >> (NVM_SWDPIN_SWDPIN_SHIFT + 4)) & 0xd) <<
 		    CTRL_EXT_SWDPINS_SHIFT;
 	} else {
 		sc->sc_ctrl_ext |=
-		    ((cfg2 >> EEPROM_CFG2_SWDPIO_SHIFT) & 0xf) <<
+		    ((cfg2 >> NVM_CFG2_SWDPIO_SHIFT) & 0xf) <<
 		    CTRL_EXT_SWDPIO_SHIFT;
 	}
 #endif
@@ -1872,9 +2059,9 @@ wm_attach(device_t parent, device_t self
 		uint16_t val;
 
 		/* Save the NVM K1 bit setting */
-		wm_read_eeprom(sc, EEPROM_OFF_K1_CONFIG, 1, &val);
+		wm_nvm_read(sc, NVM_OFF_K1_CONFIG, 1, &val);
 
-		if ((val & EEPROM_K1_CONFIG_ENABLE) != 0)
+		if ((val & NVM_K1_CONFIG_ENABLE) != 0)
 			sc->sc_nvm_k1_enabled = 1;
 		else
 			sc->sc_nvm_k1_enabled = 0;
@@ -1902,7 +2089,6 @@ 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:
@@ -1968,8 +2154,8 @@ wm_attach(device_t parent, device_t self
 	switch (sc->sc_type) {
 	case WM_T_82573:
 		/* XXX limited to 9234 if ASPM is disabled */
-		wm_read_eeprom(sc, EEPROM_INIT_3GIO_3, 1, &io3);
-		if ((io3 & EEPROM_3GIO_3_ASPM_MASK) != 0)
+		wm_nvm_read(sc, NVM_OFF_INIT_3GIO_3, 1, &io3);
+		if ((io3 & NVM_3GIO_3_ASPM_MASK) != 0)
 			sc->sc_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU;
 		break;
 	case WM_T_82571:
@@ -1978,7 +2164,6 @@ 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:
@@ -2152,6 +2337,7 @@ wm_attach(device_t parent, device_t self
 	return;
 }
 
+/* The detach function (ca_detach) */
 static int
 wm_detach(device_t self, int flags __unused)
 {
@@ -3505,7 +3691,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);
 		}
@@ -3957,11 +4143,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",
@@ -4037,6 +4218,7 @@ static void
 wm_reset(struct wm_softc *sc)
 {
 	int phy_reset = 0;
+	int error = 0;
 	uint32_t reg, mask;
 
 	/*
@@ -4064,7 +4246,6 @@ wm_reset(struct wm_softc *sc)
 		sc->sc_pba = PBA_32K;
 		break;
 	case WM_T_82580:
-	case WM_T_82580ER:
 		sc->sc_pba = PBA_35K;
 		break;
 	case WM_T_I210:
@@ -4118,7 +4299,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_I354))
+	    || (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 */
@@ -4139,7 +4322,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82573:
 	case WM_T_82574:
 	case WM_T_82583:
-		wm_get_hw_semaphore_82573(sc);
+		error = wm_get_hw_semaphore_82573(sc);
 		break;
 	default:
 		break;
@@ -4231,7 +4414,6 @@ 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_82583:
 	case WM_T_I350:
 	case WM_T_I354:
@@ -4245,9 +4427,11 @@ wm_reset(struct wm_softc *sc)
 
 	/* Must release the MDIO ownership after MAC reset */
 	switch (sc->sc_type) {
+	case WM_T_82573:
 	case WM_T_82574:
 	case WM_T_82583:
-		wm_put_hw_semaphore_82573(sc);
+		if (error == 0)
+			wm_put_hw_semaphore_82573(sc);
 		break;
 	default:
 		break;
@@ -4307,7 +4491,6 @@ 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:
@@ -4333,7 +4516,6 @@ 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:
@@ -4345,7 +4527,6 @@ 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_I354))
 				wm_reset_init_script_82575(sc);
@@ -4355,7 +4536,7 @@ wm_reset(struct wm_softc *sc)
 		break;
 	}
 
-	if ((sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
+	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);
@@ -4690,17 +4871,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)
@@ -4969,7 +5145,6 @@ 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:
@@ -5061,7 +5236,6 @@ 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:
@@ -5105,12 +5279,12 @@ wm_get_cfg_done(struct wm_softc *sc)
 }
 
 /*
- * wm_acquire_eeprom:
+ * wm_nvm_acquire:
  *
  *	Perform the EEPROM handshake required on some chips.
  */
 static int
-wm_acquire_eeprom(struct wm_softc *sc)
+wm_nvm_acquire(struct wm_softc *sc)
 {
 	uint32_t reg;
 	int x;
@@ -5168,12 +5342,12 @@ wm_acquire_eeprom(struct wm_softc *sc)
 }
 
 /*
- * wm_release_eeprom:
+ * wm_nvm_release:
  *
  *	Release the EEPROM mutex.
  */
 static void
-wm_release_eeprom(struct wm_softc *sc)
+wm_nvm_release(struct wm_softc *sc)
 {
 	uint32_t reg;
 
@@ -5253,12 +5427,12 @@ wm_eeprom_recvbits(struct wm_softc *sc, 
 }
 
 /*
- * wm_read_eeprom_uwire:
+ * wm_nvm_read_uwire:
  *
  *	Read a word from the EEPROM using the MicroWire protocol.
  */
 static int
-wm_read_eeprom_uwire(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
+wm_nvm_read_uwire(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
 {
 	uint32_t reg, val;
 	int i;
@@ -5295,7 +5469,7 @@ wm_read_eeprom_uwire(struct wm_softc *sc
 		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);
@@ -5312,12 +5486,12 @@ wm_read_eeprom_uwire(struct wm_softc *sc
 }
 
 /*
- * wm_spi_eeprom_ready:
+ * wm_nvm_ready_spi:
  *
  *	Wait for a SPI EEPROM to be ready for commands.
  */
 static int
-wm_spi_eeprom_ready(struct wm_softc *sc)
+wm_nvm_ready_spi(struct wm_softc *sc)
 {
 	uint32_t val;
 	int usec;
@@ -5336,12 +5510,12 @@ wm_spi_eeprom_ready(struct wm_softc *sc)
 }
 
 /*
- * wm_read_eeprom_spi:
+ * wm_nvm_read_spi:
  *
  *	Read a work from the EEPROM using the SPI protocol.
  */
 static int
-wm_read_eeprom_spi(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
+wm_nvm_read_spi(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
 {
 	uint32_t reg, val;
 	int i;
@@ -5353,7 +5527,7 @@ wm_read_eeprom_spi(struct wm_softc *sc, 
 	CSR_WRITE_FLUSH(sc);
 	delay(2);
 
-	if (wm_spi_eeprom_ready(sc))
+	if (wm_nvm_ready_spi(sc))
 		return 1;
 
 	/* Toggle CS to flush commands. */
@@ -5365,11 +5539,11 @@ wm_read_eeprom_spi(struct wm_softc *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);
@@ -5385,20 +5559,13 @@ wm_read_eeprom_spi(struct wm_softc *sc, 
 	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
+ * wm_nvm_validate_checksum
  *
  * The checksum is defined as the sum of the first 64 (16 bit) words.
  */
 static int
-wm_validate_eeprom_checksum(struct wm_softc *sc)
+wm_nvm_validate_checksum(struct wm_softc *sc)
 {
 	uint16_t checksum;
 	uint16_t eeprom_data;
@@ -5415,10 +5582,10 @@ wm_validate_eeprom_checksum(struct wm_so
 
 #ifdef WM_DEBUG
 	if (sc->sc_type == WM_T_PCH_LPT) {
-		csum_wordaddr = NVM_COMPAT;
+		csum_wordaddr = NVM_OFF_COMPAT;
 		valid_checksum = NVM_COMPAT_VALID_CHECKSUM;
 	} else {
-		csum_wordaddr = NVM_FUTURE_INIT_WORD1;
+		csum_wordaddr = NVM_OFF_FUTURE_INIT_WORD1;
 		valid_checksum = NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM;
 	}
 
@@ -5426,7 +5593,7 @@ wm_validate_eeprom_checksum(struct wm_so
 	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)
 	    || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) {
-		wm_read_eeprom(sc, csum_wordaddr, 1, &eeprom_data);
+		wm_nvm_read(sc, csum_wordaddr, 1, &eeprom_data);
 		if ((eeprom_data & valid_checksum) == 0) {
 			DPRINTF(WM_DEBUG_NVM,
 			    ("%s: NVM need to be updated (%04x != %04x)\n",
@@ -5437,11 +5604,11 @@ wm_validate_eeprom_checksum(struct wm_so
 
 	if ((wm_debug & WM_DEBUG_NVM) != 0) {
 		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 ");
+		for (i = 0; i < NVM_SIZE; i++) {
+			if (wm_nvm_read(sc, i, 1, &eeprom_data))
+				printf("XXXX ");
 			else
-				printf("%04x ", eeprom_data);
+				printf("%04hx ", eeprom_data);
 			if (i % 8 == 7)
 				printf("\n");
 		}
@@ -5449,8 +5616,8 @@ wm_validate_eeprom_checksum(struct wm_so
 
 #endif /* WM_DEBUG */
 
-	for (i = 0; i < EEPROM_SIZE; i++) {
-		if (wm_read_eeprom(sc, i, 1, &eeprom_data))
+	for (i = 0; i < NVM_SIZE; i++) {
+		if (wm_nvm_read(sc, i, 1, &eeprom_data))
 			return 1;
 		checksum += eeprom_data;
 	}
@@ -5465,39 +5632,8 @@ wm_validate_eeprom_checksum(struct wm_so
 	return 0;
 }
 
-/*
- * wm_read_eeprom:
- *
- *	Read data from the serial EEPROM.
- */
 static int
-wm_read_eeprom(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
-{
-	int rv;
-
-	if (sc->sc_flags & WM_F_EEPROM_INVALID)
-		return 1;
-
-	if (wm_acquire_eeprom(sc))
-		return 1;
-
-	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)
-	    || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT))
-		rv = wm_read_eeprom_ich8(sc, word, wordcnt, data);
-	else if (sc->sc_flags & WM_F_EEPROM_EERDEEWR)
-		rv = wm_read_eeprom_eerd(sc, word, wordcnt, data);
-	else if (sc->sc_flags & WM_F_EEPROM_SPI)
-		rv = wm_read_eeprom_spi(sc, word, wordcnt, data);
-	else
-		rv = wm_read_eeprom_uwire(sc, word, wordcnt, data);
-
-	wm_release_eeprom(sc);
-	return rv;
-}
-
-static int
-wm_read_eeprom_eerd(struct wm_softc *sc, int offset, int wordcnt,
+wm_nvm_read_eerd(struct wm_softc *sc, int offset, int wordcnt,
     uint16_t *data)
 {
 	int i, eerd = 0;
@@ -5537,20 +5673,58 @@ wm_poll_eerd_eewr_done(struct wm_softc *
 	return done;
 }
 
+/*
+ * wm_nvm_read:
+ *
+ *	Read data from the serial EEPROM.
+ */
 static int
+wm_nvm_read(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
+{
+	int rv;
+
+	if (sc->sc_flags & WM_F_EEPROM_INVALID)
+		return 1;
+
+	if (wm_nvm_acquire(sc))
+		return 1;
+
+	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)
+	    || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT))
+		rv = wm_nvm_read_ich8(sc, word, wordcnt, data);
+	else if (sc->sc_flags & WM_F_EEPROM_EERDEEWR)
+		rv = wm_nvm_read_eerd(sc, word, wordcnt, data);
+	else if (sc->sc_flags & WM_F_EEPROM_SPI)
+		rv = wm_nvm_read_spi(sc, word, wordcnt, data);
+	else
+		rv = wm_nvm_read_uwire(sc, word, wordcnt, data);
+
+	wm_nvm_release(sc);
+	return rv;
+}
+
+/* MAC address related */
+
+/*
+ * 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];
-	uint16_t offset = EEPROM_OFF_MACADDR;
+	uint16_t offset = NVM_OFF_MACADDR;
 
 	/* Try to read alternative MAC address pointer */
-	if (wm_read_eeprom(sc, EEPROM_ALT_MAC_ADDR_PTR, 1, &offset) != 0)
-		return -1;
+	if (wm_nvm_read(sc, NVM_OFF_ALT_MAC_ADDR_PTR, 1, &offset) != 0)
+		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
@@ -5558,44 +5732,27 @@ wm_check_alt_mac_addr(struct wm_softc *s
 	 *
 	 * Check whether the broadcast bit is set or not.
 	 */
-	if (wm_read_eeprom(sc, offset, 1, myea) == 0)
+	if (wm_nvm_read(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
 wm_read_mac_addr(struct wm_softc *sc, uint8_t *enaddr)
 {
 	uint16_t myea[ETHER_ADDR_LEN / 2];
-	uint16_t offset = EEPROM_OFF_MACADDR;
+	uint16_t offset = NVM_OFF_MACADDR;
 	int do_invert = 0;
 
 	switch (sc->sc_type) {
 	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) */
-			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;
-		}
+		/* EEPROM Top Level Partitioning */
+		offset = NVM_OFF_LAN_FUNC_82580(sc->sc_funcid) + 0;
 		break;
 	case WM_T_82571:
 	case WM_T_82575:
@@ -5603,34 +5760,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)
@@ -5638,11 +5771,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) {
+	if (wm_nvm_read(sc, offset, sizeof(myea) / sizeof(myea[0]),
+		myea) != 0)
 		goto bad;
-	}
 
 	enaddr[0] = myea[0] & 0xff;
 	enaddr[1] = myea[0] >> 8;
@@ -5661,8 +5792,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;
 }
 
@@ -5932,8 +6061,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");
 
@@ -5963,7 +6099,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;
 	else
@@ -5988,30 +6128,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);
-		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));
+		    device_xname(sc->sc_dev), sc->sc_txcw));
 	CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw);
+	CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
 	CSR_WRITE_FLUSH(sc);
-	delay(10000);
+	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));
@@ -6022,21 +6162,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);
-			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);
-		}
-
 		for (i = 0; i < WM_LINKUP_TIMEOUT; i++) {
 			delay(10000);
 			if (CSR_READ(sc, WMREG_STATUS) & STATUS_LU)
@@ -6125,7 +6250,6 @@ 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 status;
 
@@ -6138,25 +6262,21 @@ wm_tbi_check_link(struct wm_softc *sc)
 	/* set link status */
 	if ((status & STATUS_LU) == 0) {
 		DPRINTF(WM_DEBUG_LINK,
-		    ("%s: LINK: checklink -> down\n", device_xname(sc->sc_dev)));
+		    ("%s: LINK: checklink -> down\n",
+			device_xname(sc->sc_dev)));
 		sc->sc_tbi_linkup = 0;
 	} else if (sc->sc_tbi_linkup == 0) {
 		DPRINTF(WM_DEBUG_LINK,
-		    ("%s: LINK: checklink -> up %s\n", device_xname(sc->sc_dev),
-		    (status & STATUS_FD) ? "FDX" : "HDX"));
+		    ("%s: LINK: checklink -> up %s\n",
+			device_xname(sc->sc_dev),
+			(status & STATUS_FD) ? "FDX" : "HDX"));
 		sc->sc_tbi_linkup = 1;
 	}
 
 	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"));
@@ -6207,7 +6327,6 @@ 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:
@@ -6284,7 +6403,6 @@ 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:
@@ -6340,7 +6458,6 @@ 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:
@@ -6385,7 +6502,6 @@ 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:
@@ -6494,6 +6610,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;
@@ -6503,6 +6620,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.
@@ -6523,7 +6649,7 @@ 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
+	 *  For ICH8 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.
@@ -6602,7 +6728,7 @@ 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_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) {
@@ -6761,7 +6887,7 @@ wm_gmii_mediachange(struct ifnet *ifp)
 #define	MDI_CLK		CTRL_SWDPIN(3)
 
 static void
-i82543_mii_sendbits(struct wm_softc *sc, uint32_t data, int nbits)
+wm_i82543_mii_sendbits(struct wm_softc *sc, uint32_t data, int nbits)
 {
 	uint32_t i, v;
 
@@ -6787,7 +6913,7 @@ i82543_mii_sendbits(struct wm_softc *sc,
 }
 
 static uint32_t
-i82543_mii_recvbits(struct wm_softc *sc)
+wm_i82543_mii_recvbits(struct wm_softc *sc)
 {
 	uint32_t v, i, data = 0;
 
@@ -6842,10 +6968,10 @@ wm_gmii_i82543_readreg(device_t self, in
 	struct wm_softc *sc = device_private(self);
 	int rv;
 
-	i82543_mii_sendbits(sc, 0xffffffffU, 32);
-	i82543_mii_sendbits(sc, reg | (phy << 5) |
+	wm_i82543_mii_sendbits(sc, 0xffffffffU, 32);
+	wm_i82543_mii_sendbits(sc, reg | (phy << 5) |
 	    (MII_COMMAND_READ << 10) | (MII_COMMAND_START << 12), 14);
-	rv = i82543_mii_recvbits(sc) & 0xffff;
+	rv = wm_i82543_mii_recvbits(sc) & 0xffff;
 
 	DPRINTF(WM_DEBUG_GMII,
 	    ("%s: GMII: read phy %d reg %d -> 0x%04x\n",
@@ -6864,8 +6990,8 @@ wm_gmii_i82543_writereg(device_t self, i
 {
 	struct wm_softc *sc = device_private(self);
 
-	i82543_mii_sendbits(sc, 0xffffffffU, 32);
-	i82543_mii_sendbits(sc, val | (MII_COMMAND_ACK << 16) |
+	wm_i82543_mii_sendbits(sc, 0xffffffffU, 32);
+	wm_i82543_mii_sendbits(sc, val | (MII_COMMAND_ACK << 16) |
 	    (reg << 18) | (phy << 23) | (MII_COMMAND_WRITE << 28) |
 	    (MII_COMMAND_START << 30), 32);
 }
@@ -7255,7 +7381,6 @@ wm_sgmii_uses_mdio(struct wm_softc *sc)
 		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:
@@ -7543,7 +7668,7 @@ wm_kmrn_writereg(struct wm_softc *sc, in
 }
 
 static int
-wm_is_onboard_nvm_eeprom(struct wm_softc *sc)
+wm_nvm_is_onboard_eeprom(struct wm_softc *sc)
 {
 	uint32_t eecd = 0;
 
@@ -7567,8 +7692,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;
@@ -7583,7 +7728,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;
@@ -7597,7 +7742,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);
 }
 
@@ -7719,7 +7864,7 @@ wm_put_hw_semaphore_82573(struct wm_soft
 }
 
 static int
-wm_valid_nvm_bank_detect_ich8lan(struct wm_softc *sc, unsigned int *bank)
+wm_nvm_valid_bank_detect_ich8lan(struct wm_softc *sc, unsigned int *bank)
 {
 	uint32_t eecd;
 	uint32_t act_offset = ICH_NVM_SIG_WORD * 2 + 1;
@@ -7770,7 +7915,7 @@ wm_valid_nvm_bank_detect_ich8lan(struct 
  * words - number of words to read
  *****************************************************************************/
 static int
-wm_read_eeprom_ich8(struct wm_softc *sc, int offset, int words, uint16_t *data)
+wm_nvm_read_ich8(struct wm_softc *sc, int offset, int words, uint16_t *data)
 {
 	int32_t  error = 0;
 	uint32_t flash_bank = 0;
@@ -7784,10 +7929,10 @@ wm_read_eeprom_ich8(struct wm_softc *sc,
 	 * managing flash_bank.  So it cannot be trusted and needs
 	 * to be updated with each read.
 	 */
-	error = wm_valid_nvm_bank_detect_ich8lan(sc, &flash_bank);
+	error = wm_nvm_valid_bank_detect_ich8lan(sc, &flash_bank);
 	if (error) {
-		aprint_error_dev(sc->sc_dev, "%s: failed to detect NVM bank\n",
-		    __func__);
+		DPRINTF(WM_DEBUG_NVM, ("%s: failed to detect NVM bank\n",
+			device_xname(sc->sc_dev)));
 		flash_bank = 0;
 	}
 
@@ -8095,9 +8240,9 @@ wm_check_mng_mode_82574(struct wm_softc 
 {
 	uint16_t data;
 
-	wm_read_eeprom(sc, EEPROM_OFF_CFG2, 1, &data);
+	wm_nvm_read(sc, NVM_OFF_CFG2, 1, &data);
 
-	if ((data & EEPROM_CFG2_MNGM_MASK) != 0)
+	if ((data & NVM_CFG2_MNGM_MASK) != 0)
 		return 1;
 
 	return 0;
@@ -8142,12 +8287,12 @@ wm_enable_mng_pass_thru(struct wm_softc 
 		uint16_t data;
 
 		factps = CSR_READ(sc, WMREG_FACTPS);
-		wm_read_eeprom(sc, EEPROM_OFF_CFG2, 1, &data);
+		wm_nvm_read(sc, NVM_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)))
+		    && ((data & NVM_CFG2_MNGM_MASK)
+			== (NVM_CFG2_MNGM_PT << NVM_CFG2_MNGM_SHIFT)))
 			return 1;
 	} else if (((manc & MANC_SMBUS_EN) != 0)
 	    && ((manc & MANC_ASF_EN) == 0))
@@ -8672,7 +8817,6 @@ wm_get_wakeup(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:
 		if ((CSR_READ(sc, WMREG_FWSM) & FWSM_MODE_MASK) != 0)

Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.46.2.6 src/sys/dev/pci/if_wmreg.h:1.46.2.7
--- src/sys/dev/pci/if_wmreg.h:1.46.2.6	Sun Nov  9 12:03:18 2014
+++ src/sys/dev/pci/if_wmreg.h	Thu Dec  4 06:04:07 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmreg.h,v 1.46.2.6 2014/11/09 12:03:18 martin Exp $	*/
+/*	$NetBSD: if_wmreg.h,v 1.46.2.7 2014/12/04 06:04:07 snj Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -286,98 +286,12 @@ 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 */
 #define EECD_SEC1VAL_VALMASK (EECD_EE_AUTORD | EECD_EE_PRES) /* Valid Mask */
 
-#define	UWIRE_OPC_ERASE	0x04		/* MicroWire "erase" opcode */
-#define	UWIRE_OPC_WRITE	0x05		/* MicroWire "write" opcode */
-#define	UWIRE_OPC_READ	0x06		/* MicroWire "read" opcode */
-
-#define	SPI_OPC_WRITE	0x02		/* SPI "write" opcode */
-#define	SPI_OPC_READ	0x03		/* SPI "read" opcode */
-#define	SPI_OPC_A8	0x08		/* opcode bit 3 == address bit 8 */
-#define	SPI_OPC_WREN	0x06		/* SPI "set write enable" opcode */
-#define	SPI_OPC_WRDI	0x04		/* SPI "clear write enable" opcode */
-#define	SPI_OPC_RDSR	0x05		/* SPI "read status" opcode */
-#define	SPI_OPC_WRSR	0x01		/* SPI "write status" opcode */
-#define	SPI_MAX_RETRIES	5000		/* max wait of 5ms for RDY signal */
-
-#define	SPI_SR_RDY	0x01
-#define	SPI_SR_WEN	0x02
-#define	SPI_SR_BP0	0x04
-#define	SPI_SR_BP1	0x08
-#define	SPI_SR_WPEN	0x80
-
-#define	EEPROM_OFF_MACADDR	0x00	/* MAC address offset */
-#define	EEPROM_OFF_CFG1		0x0a	/* config word 1 */
-#define	EEPROM_OFF_CFG2		0x0f	/* config word 2 */
-#define	EEPROM_OFF_CFG3_PORTB	0x14	/* config word 3 */
-#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) */
-#define	EEPROM_OFF_CFG3_PORTA	0x24	/* config word 3 */
-#define EEPROM_ALT_MAC_ADDR_PTR	0x37	/* to the alternative MAC addresses */
-
-#define	EEPROM_CFG1_LVDID	(1U << 0)
-#define	EEPROM_CFG1_LSSID	(1U << 1)
-#define	EEPROM_CFG1_PME_CLOCK	(1U << 2)
-#define	EEPROM_CFG1_PM		(1U << 3)
-#define	EEPROM_CFG1_ILOS	(1U << 4)
-#define	EEPROM_CFG1_SWDPIO_SHIFT 5
-#define	EEPROM_CFG1_SWDPIO_MASK	(0xf << EEPROM_CFG1_SWDPIO_SHIFT)
-#define	EEPROM_CFG1_IPS1	(1U << 8)
-#define	EEPROM_CFG1_LRST	(1U << 9)
-#define	EEPROM_CFG1_FD		(1U << 10)
-#define	EEPROM_CFG1_FRCSPD	(1U << 11)
-#define	EEPROM_CFG1_IPS0	(1U << 12)
-#define	EEPROM_CFG1_64_32_BAR	(1U << 13)
-
-#define	EEPROM_CFG2_CSR_RD_SPLIT (1U << 1)
-#define	EEPROM_CFG2_82544_APM_EN (1U << 2)
-#define	EEPROM_CFG2_64_BIT	(1U << 3)
-#define	EEPROM_CFG2_MAX_READ	(1U << 4)
-#define	EEPROM_CFG2_DMCR_MAP	(1U << 5)
-#define	EEPROM_CFG2_133_CAP	(1U << 6)
-#define	EEPROM_CFG2_MSI_DIS	(1U << 7)
-#define	EEPROM_CFG2_FLASH_DIS	(1U << 8)
-#define	EEPROM_CFG2_FLASH_SIZE(x) (((x) & 3) >> 9)
-#define	EEPROM_CFG2_APM_EN (1U << 10)
-#define	EEPROM_CFG2_ANE		(1U << 11)
-#define	EEPROM_CFG2_PAUSE(x)	(((x) & 3) >> 12)
-#define	EEPROM_CFG2_ASDE	(1U << 14)
-#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_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	EEPROM_K1_CONFIG_ENABLE	0x01
-
-#define	EEPROM_SWDPIN_MASK	0xdf
-#define	EEPROM_SWDPIN_SWDPIN_SHIFT 0
-#define	EEPROM_SWDPIN_SWDPIO_SHIFT 8
-
-#define EEPROM_3GIO_3_ASPM_MASK	(0x3 << 2)	/* Active State PM Support */
-
-#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) */
-
-/*
- * 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	WMREG_EERD	0x0014	/* EEPROM read */
 #define	EERD_DONE	0x02    /* done bit */
 #define	EERD_START	0x01	/* First bit for telling part to start operation */
@@ -413,7 +327,6 @@ struct livengood_tcpip_ctxdesc {
 #define CTRL_EXT_I2C_ENA	0x02000000  /* I2C enable */
 #define	CTRL_EXT_DRV_LOAD	0x10000000
 
-
 #define	WMREG_MDIC	0x0020	/* MDI Control Register */
 #define	MDIC_DATA(x)	((x) & 0xffff)
 #define	MDIC_REGADD(x)	((x) << 16)
@@ -436,6 +349,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 */
@@ -445,8 +359,43 @@ struct livengood_tcpip_ctxdesc {
 
 #define	WMREG_FCT	0x0030	/* Flow Control Type */
 
-#define	WMREG_VET	0x0038	/* VLAN Ethertype */
+#define	WMREG_KUMCTRLSTA 0x0034	/* MAC-PHY interface - RW */
+#define	KUMCTRLSTA_MASK			0x0000FFFF
+#define	KUMCTRLSTA_OFFSET		0x001F0000
+#define	KUMCTRLSTA_OFFSET_SHIFT		16
+#define	KUMCTRLSTA_REN			0x00200000
 
+#define	KUMCTRLSTA_OFFSET_FIFO_CTRL	0x00000000
+#define	KUMCTRLSTA_OFFSET_CTRL		0x00000001
+#define	KUMCTRLSTA_OFFSET_INB_CTRL	0x00000002
+#define	KUMCTRLSTA_OFFSET_DIAG		0x00000003
+#define	KUMCTRLSTA_OFFSET_TIMEOUTS	0x00000004
+#define	KUMCTRLSTA_OFFSET_K1_CONFIG	0x00000007
+#define	KUMCTRLSTA_OFFSET_INB_PARAM	0x00000009
+#define	KUMCTRLSTA_OFFSET_HD_CTRL	0x00000010
+#define	KUMCTRLSTA_OFFSET_M2P_SERDES	0x0000001E
+#define	KUMCTRLSTA_OFFSET_M2P_MODES	0x0000001F
+
+/* FIFO Control */
+#define	KUMCTRLSTA_FIFO_CTRL_RX_BYPASS	0x00000008
+#define	KUMCTRLSTA_FIFO_CTRL_TX_BYPASS	0x00000800
+
+/* In-Band Control */
+#define	KUMCTRLSTA_INB_CTRL_LINK_TMOUT_DFLT 0x00000500
+#define	KUMCTRLSTA_INB_CTRL_DIS_PADDING	0x00000010
+
+/* Diag */
+#define	KUMCTRLSTA_DIAG_NELPBK	0x1000
+
+/* K1 Config */
+#define	KUMCTRLSTA_K1_ENABLE	0x0002
+
+/* Half-Duplex Control */
+#define	KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
+#define	KUMCTRLSTA_HD_CTRL_1000_DEFAULT	0x00000000
+
+#define	WMREG_VET	0x0038	/* VLAN Ethertype */
+#define	WMREG_MDPHYA	0x003C	/* PHY address - RW */
 #define	WMREG_RAL_BASE	0x0040	/* Receive Address List */
 #define	WMREG_CORDOVA_RAL_BASE 0x5400
 #define	WMREG_RAL_LO(b, x) ((b) + ((x) << 3))
@@ -526,7 +475,7 @@ struct livengood_tcpip_ctxdesc {
 #define	WMREG_RDTR	0x2820
 #define	RDTR_FPD	(1U << 31)	/* flush partial descriptor */
 
-#define	WMREG_RADV	0x282c	/* Receive Interrupt Absolute Delay Timer */
+#define WMREG_LTRC	0x01a0	/* Latency Tolerance Reportiong Control */
 
 #define	WMREG_OLD_RDBAL0 0x0110	/* Receive Descriptor Base Low (ring 0) */
 #define	WMREG_RDBAL	0x2800
@@ -540,20 +489,20 @@ struct livengood_tcpip_ctxdesc {
 #define	WMREG_RDLEN	0x2808
 #define	WMREG_RDLEN_2	0x0c08	/* for 82576 ... */
 
-#define WMREG_SRRCTL	0x280c	/* additional recieve control used in 82575 ... */
+#define WMREG_SRRCTL	0x280c	/* additional recv control used in 82575 ... */
 #define WMREG_SRRCTL_2	0x0c0c	/* for 82576 ... */
-#define SRRCTL_BSIZEPKT_MASK				0x0000007f
+#define SRRCTL_BSIZEPKT_MASK		0x0000007f
 #define SRRCTL_BSIZEPKT_SHIFT		10	/* Shift _right_ */
-#define SRRCTL_BSIZEHDRSIZE_MASK			0x00000f00
+#define SRRCTL_BSIZEHDRSIZE_MASK	0x00000f00
 #define SRRCTL_BSIZEHDRSIZE_SHIFT	2	/* Shift _left_ */
-#define SRRCTL_DESCTYPE_LEGACY				0x00000000
-#define SRRCTL_DESCTYPE_ADV_ONEBUF			(1U << 25)
-#define SRRCTL_DESCTYPE_HDR_SPLIT			(2U << 25)
-#define SRRCTL_DESCTYPE_HDR_REPLICATION			(3U << 25)
-#define SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT	(4U << 25)
-#define SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS		(5U << 25) /* 82575 only */
-#define SRRCTL_DESCTYPE_MASK				(7U << 25)
-#define SRRCTL_DROP_EN					0x80000000
+#define SRRCTL_DESCTYPE_LEGACY		0x00000000
+#define SRRCTL_DESCTYPE_ADV_ONEBUF	(1U << 25)
+#define SRRCTL_DESCTYPE_HDR_SPLIT	(2U << 25)
+#define SRRCTL_DESCTYPE_HDR_REPLICATION	(3U << 25)
+#define SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT (4U << 25)
+#define SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS (5U << 25) /* 82575 only */
+#define SRRCTL_DESCTYPE_MASK		(7U << 25)
+#define SRRCTL_DROP_EN			0x80000000
 
 #define	WMREG_OLD_RDH0	0x0120	/* Receive Descriptor Head (ring 0) */
 #define	WMREG_RDH	0x2810
@@ -574,17 +523,11 @@ struct livengood_tcpip_ctxdesc {
 #define RXDCTL_SWFLSH        0x04000000 /* Rx Desc. write-back flushing */
 
 #define	WMREG_OLD_RDTR1	0x0130	/* Receive Delay Timer (ring 1) */
-
 #define	WMREG_OLD_RDBA1_LO 0x0138 /* Receive Descriptor Base Low (ring 1) */
-
 #define	WMREG_OLD_RDBA1_HI 0x013c /* Receive Descriptor Base High (ring 1) */
-
 #define	WMREG_OLD_RDLEN1 0x0140	/* Receive Drscriptor Length (ring 1) */
-
 #define	WMREG_OLD_RDH1	0x0148
-
 #define	WMREG_OLD_RDT1	0x0150
-
 #define	WMREG_OLD_FCRTH 0x0160	/* Flow Control Rx Threshold Hi (OLD) */
 #define	WMREG_FCRTL	0x2160	/* Flow Control Rx Threshold Lo */
 #define	FCRTH_DFLT	0x00008000
@@ -599,6 +542,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 */
@@ -637,14 +582,12 @@ struct livengood_tcpip_ctxdesc {
 #define	DEFAULT_80003ES2LAN_TCTL_EXT_GCEX 0x00010000
 
 #define	WMREG_TQSA_LO	0x0408
-
 #define	WMREG_TQSA_HI	0x040c
 
 #define	WMREG_TIPG	0x0410	/* Transmit IPG Register */
 #define	TIPG_IPGT(x)	(x)		/* IPG transmit time */
 #define	TIPG_IPGR1(x)	((x) << 10)	/* IPG receive time 1 */
 #define	TIPG_IPGR2(x)	((x) << 20)	/* IPG receive time 2 */
-
 #define	TIPG_WM_DFLT	(TIPG_IPGT(0x0a) | TIPG_IPGR1(0x02) | TIPG_IPGR2(0x0a))
 #define	TIPG_LG_DFLT	(TIPG_IPGT(0x06) | TIPG_IPGR1(0x08) | TIPG_IPGR2(0x06))
 #define	TIPG_1000T_DFLT	(TIPG_IPGT(0x08) | TIPG_IPGR1(0x08) | TIPG_IPGR2(0x06))
@@ -655,26 +598,6 @@ struct livengood_tcpip_ctxdesc {
 
 #define	WMREG_TQC	0x0418
 
-#define	WMREG_EEWR	0x102c	/* EEPROM write */
-
-#define	WMREG_RDFH	0x2410	/* Receive Data FIFO Head */
-
-#define	WMREG_RDFT	0x2418	/* Receive Data FIFO Tail */
-
-#define	WMREG_RDFHS	0x2420	/* Receive Data FIFO Head Saved */
-
-#define	WMREG_RDFTS	0x2428	/* Receive Data FIFO Tail Saved */
-
-#define	WMREG_TDFH	0x3410	/* Transmit Data FIFO Head */
-
-#define	WMREG_TDFT	0x3418	/* Transmit Data FIFO Tail */
-
-#define	WMREG_TDFHS	0x3420	/* Transmit Data FIFO Head Saved */
-
-#define	WMREG_TDFTS	0x3428	/* Transmit Data FIFO Tail Saved */
-
-#define	WMREG_TDFPC	0x3430	/* Transmit Data FIFO Packet Count */
-
 #define	WMREG_OLD_TDBAL	0x0420	/* Transmit Descriptor Base Lo */
 #define	WMREG_TDBAL	0x3800
 
@@ -693,19 +616,7 @@ 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	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_QUEUE_ENABLE  0x02000000 /* Enable specific Tx Queue */
-#define TXDCTL_SWFLSH        0x04000000 /* Tx Desc. write-back flushing */
-#define TXDCTL_PRIORITY      0x08000000
-
-#define	WMREG_TADV	0x382c	/* Transmit Absolute Interrupt Delay Timer */
-
 #define	WMREG_AIT	0x0458	/* Adaptive IFS Throttle */
-
 #define	WMREG_VFTA	0x0600
 
 #define	WMREG_MDICNFG	0x0e04	/* MDC/MDIO Configuration Register */
@@ -718,6 +629,40 @@ struct livengood_tcpip_ctxdesc {
 #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_EEER	0x0e30	/* Energy Efficiency Ethernet "EEE" */
+#define EEER_TX_LPI_EN		0x00010000 /* EEER Tx LPI Enable */
+#define EEER_RX_LPI_EN		0x00020000 /* EEER Rx LPI Enable */
+#define EEER_LPI_FC		0x00040000 /* EEER Ena on Flow Cntrl */
+#define EEER_EEER_NEG		0x20000000 /* EEER capability nego */
+#define EEER_EEER_RX_LPI_STATUS	0x40000000 /* EEER Rx in LPI state */
+#define EEER_EEER_TX_LPI_STATUS	0x80000000 /* EEER Tx in LPI state */
+#define WMREG_EEE_SU	0x0e34	/* EEE Setup */
+#define WMREG_IPCNFG	0x0e38	/* Internal PHY Configuration */
+#define IPCNFG_EEE_100M_AN	0x00000004 /* IPCNFG EEE Ena 100M AN */
+#define IPCNFG_EEE_1G_AN	0x00000008 /* IPCNFG EEE Ena 1G AN */
+
+#define WMREG_EXTCNFCTR	0x0f00  /* Extended Configuration Control */
+#define EXTCNFCTR_PCIE_WRITE_ENABLE	0x00000001
+#define EXTCNFCTR_PHY_WRITE_ENABLE	0x00000002
+#define EXTCNFCTR_D_UD_ENABLE		0x00000004
+#define EXTCNFCTR_D_UD_LATENCY		0x00000008
+#define EXTCNFCTR_D_UD_OWNER		0x00000010
+#define EXTCNFCTR_MDIO_SW_OWNERSHIP	0x00000020
+#define EXTCNFCTR_MDIO_HW_OWNERSHIP	0x00000040
+#define EXTCNFCTR_GATE_PHY_CFG		0x00000080
+#define EXTCNFCTR_EXT_CNF_POINTER	0x0FFF0000
+#define E1000_EXTCNF_CTRL_SWFLAG	EXTCNFCTR_MDIO_SW_OWNERSHIP
+
+#define	WMREG_PHY_CTRL	0x0f10	/* PHY control */
+#define	PHY_CTRL_SPD_EN		(1 << 0)
+#define	PHY_CTRL_D0A_LPLU	(1 << 1)
+#define	PHY_CTRL_NOND0A_LPLU	(1 << 2)
+#define	PHY_CTRL_NOND0A_GBE_DIS	(1 << 3)
+#define	PHY_CTRL_GBE_DIS	(1 << 4)
+
 #define	WMREG_PBA	0x1000	/* Packet Buffer Allocation */
 #define	PBA_BYTE_SHIFT	10		/* KB -> bytes */
 #define	PBA_ADDR_SHIFT	7		/* KB -> quadwords */
@@ -762,6 +707,8 @@ struct livengood_tcpip_ctxdesc {
 #define MAX_SGMII_PHY_REG_ADDR	255
 #define I2CCMD_PHY_TIMEOUT	200
 
+#define	WMREG_EEWR	0x102c	/* EEPROM write */
+
 #define WMREG_PBA_ECC	0x01100	/* PBA ECC */
 #define PBA_ECC_COUNTER_MASK	0xfff00000 /* ECC counter mask */
 #define PBA_ECC_COUNTER_SHIFT	20	   /* ECC counter shift value */
@@ -791,15 +738,36 @@ struct livengood_tcpip_ctxdesc {
 #define WMREG_EITR(x)	(0x01680 + (0x4 * (x)))
 #define EITR_ITR_INT_MASK	0x0000ffff
 
+#define	WMREG_RDFH	0x2410	/* Receive Data FIFO Head */
+#define	WMREG_RDFT	0x2418	/* Receive Data FIFO Tail */
+#define	WMREG_RDFHS	0x2420	/* Receive Data FIFO Head Saved */
+#define	WMREG_RDFTS	0x2428	/* Receive Data FIFO Tail Saved */
+#define	WMREG_RADV	0x282c	/* Receive Interrupt Absolute Delay Timer */
+
 #define	WMREG_TXDMAC	0x3000	/* Transfer DMA Control */
 #define	TXDMAC_DPP	(1U << 0)	/* disable packet prefetch */
 
 #define WMREG_KABGTXD	0x3004	/* AFE and Gap Transmit Ref Data */
 #define	KABGTXD_BGSQLBIAS 0x00050000
 
+#define	WMREG_TDFH	0x3410	/* Transmit Data FIFO Head */
+#define	WMREG_TDFT	0x3418	/* Transmit Data FIFO Tail */
+#define	WMREG_TDFHS	0x3420	/* Transmit Data FIFO Head Saved */
+#define	WMREG_TDFTS	0x3428	/* Transmit Data FIFO Tail Saved */
+#define	WMREG_TDFPC	0x3430	/* Transmit Data FIFO Packet Count */
+
+#define	WMREG_TXDCTL	0x3828	/* Trandmit Descriptor Control */
+#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_QUEUE_ENABLE  0x02000000 /* Enable specific Tx Queue */
+#define TXDCTL_SWFLSH        0x04000000 /* Tx Desc. write-back flushing */
+#define TXDCTL_PRIORITY      0x08000000
+
+#define	WMREG_TADV	0x382c	/* Transmit Absolute Interrupt Delay Timer */
 #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 */
@@ -820,43 +788,8 @@ struct livengood_tcpip_ctxdesc {
 #define	WMREG_XOFFTXC	0x4054	/* XOFF Tx Count - R/clr */
 #define	WMREG_FCRUC	0x4058	/* Flow Control Rx Unsupported Count - R/clr */
 #define WMREG_RNBC	0x40a0	/* Receive No Buffers Count */
-
-#define	WMREG_KUMCTRLSTA 0x0034	/* MAC-PHY interface - RW */
-#define	KUMCTRLSTA_MASK			0x0000FFFF
-#define	KUMCTRLSTA_OFFSET		0x001F0000
-#define	KUMCTRLSTA_OFFSET_SHIFT		16
-#define	KUMCTRLSTA_REN			0x00200000
-
-#define	KUMCTRLSTA_OFFSET_FIFO_CTRL	0x00000000
-#define	KUMCTRLSTA_OFFSET_CTRL		0x00000001
-#define	KUMCTRLSTA_OFFSET_INB_CTRL	0x00000002
-#define	KUMCTRLSTA_OFFSET_DIAG		0x00000003
-#define	KUMCTRLSTA_OFFSET_TIMEOUTS	0x00000004
-#define	KUMCTRLSTA_OFFSET_K1_CONFIG	0x00000007
-#define	KUMCTRLSTA_OFFSET_INB_PARAM	0x00000009
-#define	KUMCTRLSTA_OFFSET_HD_CTRL	0x00000010
-#define	KUMCTRLSTA_OFFSET_M2P_SERDES	0x0000001E
-#define	KUMCTRLSTA_OFFSET_M2P_MODES	0x0000001F
-
-/* FIFO Control */
-#define	KUMCTRLSTA_FIFO_CTRL_RX_BYPASS	0x00000008
-#define	KUMCTRLSTA_FIFO_CTRL_TX_BYPASS	0x00000800
-
-/* In-Band Control */
-#define	KUMCTRLSTA_INB_CTRL_LINK_TMOUT_DFLT 0x00000500
-#define	KUMCTRLSTA_INB_CTRL_DIS_PADDING	0x00000010
-
-/* Diag */
-#define	KUMCTRLSTA_DIAG_NELPBK	0x1000
-
-/* K1 Config */
-#define	KUMCTRLSTA_K1_ENABLE	0x0002
-
-/* Half-Duplex Control */
-#define	KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
-#define	KUMCTRLSTA_HD_CTRL_1000_DEFAULT	0x00000000
-
-#define	WMREG_MDPHYA	0x003C	/* PHY address - RW */
+#define WMREG_TLPIC	0x4148	/* EEE Tx LPI Count */
+#define WMREG_RLPIC	0x414c	/* EEE Rx LPI Count */
 
 #define	WMREG_RXCSUM	0x5000	/* Receive Checksum register */
 #define	RXCSUM_PCSS	0x000000ff	/* Packet Checksum Start */
@@ -928,6 +861,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 */
@@ -938,42 +874,105 @@ struct livengood_tcpip_ctxdesc {
 #define	SWFW_SOFT_SHIFT		0	/* software semaphores */
 #define	SWFW_FIRM_SHIFT		16	/* firmware semaphores */
 
-#define WMREG_CRC_OFFSET	0x5f50
+#define WMREG_CRC_OFFSET 0x5f50
 
-#define WMREG_EXTCNFCTR		0x0f00  /* Extended Configuration Control */
-#define EXTCNFCTR_PCIE_WRITE_ENABLE	0x00000001
-#define EXTCNFCTR_PHY_WRITE_ENABLE	0x00000002
-#define EXTCNFCTR_D_UD_ENABLE		0x00000004
-#define EXTCNFCTR_D_UD_LATENCY		0x00000008
-#define EXTCNFCTR_D_UD_OWNER		0x00000010
-#define EXTCNFCTR_MDIO_SW_OWNERSHIP	0x00000020
-#define EXTCNFCTR_MDIO_HW_OWNERSHIP	0x00000040
-#define EXTCNFCTR_GATE_PHY_CFG		0x00000080
-#define EXTCNFCTR_EXT_CNF_POINTER	0x0FFF0000
-#define E1000_EXTCNF_CTRL_SWFLAG	EXTCNFCTR_MDIO_SW_OWNERSHIP
+/*
+ * NVM related values.
+ *  Microwire, SPI, and flash
+ */
+#define	UWIRE_OPC_ERASE	0x04		/* MicroWire "erase" opcode */
+#define	UWIRE_OPC_WRITE	0x05		/* MicroWire "write" opcode */
+#define	UWIRE_OPC_READ	0x06		/* MicroWire "read" opcode */
 
-#define	WMREG_PHY_CTRL	0x0f10	/* PHY control */
-#define	PHY_CTRL_SPD_EN		(1 << 0)
-#define	PHY_CTRL_D0A_LPLU	(1 << 1)
-#define	PHY_CTRL_NOND0A_LPLU	(1 << 2)
-#define	PHY_CTRL_NOND0A_GBE_DIS	(1 << 3)
-#define	PHY_CTRL_GBE_DIS	(1 << 4)
+#define	SPI_OPC_WRITE	0x02		/* SPI "write" opcode */
+#define	SPI_OPC_READ	0x03		/* SPI "read" opcode */
+#define	SPI_OPC_A8	0x08		/* opcode bit 3 == address bit 8 */
+#define	SPI_OPC_WREN	0x06		/* SPI "set write enable" opcode */
+#define	SPI_OPC_WRDI	0x04		/* SPI "clear write enable" opcode */
+#define	SPI_OPC_RDSR	0x05		/* SPI "read status" opcode */
+#define	SPI_OPC_WRSR	0x01		/* SPI "write status" opcode */
+#define	SPI_MAX_RETRIES	5000		/* max wait of 5ms for RDY signal */
 
-/* Energy Efficient Ethernet "EEE" registers */
-#define WMREG_LTRC	0x01a0	/* Latency Tolerance Reportiong Control */
-#define WMREG_EEER	0x0e30	/* Energy Efficiency Ethernet "EEE" */
-#define EEER_TX_LPI_EN		0x00010000 /* EEER Tx LPI Enable */
-#define EEER_RX_LPI_EN		0x00020000 /* EEER Rx LPI Enable */
-#define EEER_LPI_FC		0x00040000 /* EEER Ena on Flow Cntrl */
-#define EEER_EEER_NEG		0x20000000 /* EEER capability nego */
-#define EEER_EEER_RX_LPI_STATUS	0x40000000 /* EEER Rx in LPI state */
-#define EEER_EEER_TX_LPI_STATUS	0x80000000 /* EEER Tx in LPI state */
-#define WMREG_EEE_SU	0x0e34	/* EEE Setup */
-#define WMREG_IPCNFG	0x0e38	/* Internal PHY Configuration */
-#define IPCNFG_EEE_100M_AN	0x00000004 /* IPCNFG EEE Ena 100M AN */
-#define IPCNFG_EEE_1G_AN	0x00000008 /* IPCNFG EEE Ena 1G AN */
-#define WMREG_TLPIC	0x4148	/* EEE Tx LPI Count */
-#define WMREG_RLPIC	0x414c	/* EEE Rx LPI Count */
+#define	SPI_SR_RDY	0x01
+#define	SPI_SR_WEN	0x02
+#define	SPI_SR_BP0	0x04
+#define	SPI_SR_BP1	0x08
+#define	SPI_SR_WPEN	0x80
+
+#define NVM_CHECKSUM		0xBABA
+#define NVM_SIZE		0x0040
+#define NVM_WORD_SIZE_BASE_SHIFT 6
+
+#define	NVM_OFF_MACADDR		0x0000	/* MAC address offset */
+#define NVM_OFF_COMPAT		0x0003
+#define	NVM_OFF_CFG1		0x000a	/* config word 1 */
+#define	NVM_OFF_CFG2		0x000f	/* config word 2 */
+#define	NVM_OFF_EEPROM_SIZE	0x0012	/* NVM SIZE */
+#define	NVM_OFF_CFG3_PORTB	0x0014	/* config word 3 */
+#define NVM_OFF_FUTURE_INIT_WORD1 0x0019
+#define	NVM_OFF_INIT_3GIO_3	0x001a	/* PCIe Initial Configuration Word 3 */
+#define	NVM_OFF_K1_CONFIG	0x001b	/* NVM K1 Config */
+#define	NVM_OFF_SWDPIN		0x0020	/* SWD Pins (Cordova) */
+#define	NVM_OFF_CFG3_PORTA	0x0024	/* config word 3 */
+#define NVM_OFF_ALT_MAC_ADDR_PTR 0x0037	/* to the alternative MAC addresses */
+
+#define NVM_COMPAT_VALID_CHECKSUM	0x0001
+
+#define	NVM_CFG1_LVDID		(1U << 0)
+#define	NVM_CFG1_LSSID		(1U << 1)
+#define	NVM_CFG1_PME_CLOCK	(1U << 2)
+#define	NVM_CFG1_PM		(1U << 3)
+#define	NVM_CFG1_ILOS		(1U << 4)
+#define	NVM_CFG1_SWDPIO_SHIFT	5
+#define	NVM_CFG1_SWDPIO_MASK	(0xf << NVM_CFG1_SWDPIO_SHIFT)
+#define	NVM_CFG1_IPS1		(1U << 8)
+#define	NVM_CFG1_LRST		(1U << 9)
+#define	NVM_CFG1_FD		(1U << 10)
+#define	NVM_CFG1_FRCSPD		(1U << 11)
+#define	NVM_CFG1_IPS0		(1U << 12)
+#define	NVM_CFG1_64_32_BAR	(1U << 13)
+
+#define	NVM_CFG2_CSR_RD_SPLIT	(1U << 1)
+#define	NVM_CFG2_82544_APM_EN	(1U << 2)
+#define	NVM_CFG2_64_BIT		(1U << 3)
+#define	NVM_CFG2_MAX_READ	(1U << 4)
+#define	NVM_CFG2_DMCR_MAP	(1U << 5)
+#define	NVM_CFG2_133_CAP	(1U << 6)
+#define	NVM_CFG2_MSI_DIS	(1U << 7)
+#define	NVM_CFG2_FLASH_DIS	(1U << 8)
+#define	NVM_CFG2_FLASH_SIZE(x)	(((x) & 3) >> 9)
+#define	NVM_CFG2_APM_EN		(1U << 10)
+#define	NVM_CFG2_ANE		(1U << 11)
+#define	NVM_CFG2_PAUSE(x)	(((x) & 3) >> 12)
+#define	NVM_CFG2_ASDE		(1U << 14)
+#define	NVM_CFG2_APM_PME	(1U << 15)
+#define	NVM_CFG2_SWDPIO_SHIFT	4
+#define	NVM_CFG2_SWDPIO_MASK	(0xf << NVM_CFG2_SWDPIO_SHIFT)
+#define	NVM_CFG2_MNGM_SHIFT	13	/* Manageability Operation mode */
+#define	NVM_CFG2_MNGM_MASK	(3U << NVM_CFG2_MNGM_SHIFT)
+#define	NVM_CFG2_MNGM_DIS	0
+#define	NVM_CFG2_MNGM_NCSI	1
+#define	NVM_CFG2_MNGM_PT	2
+
+#define NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM	0x0040
+
+#define	NVM_K1_CONFIG_ENABLE	0x01
+
+#define	NVM_SWDPIN_MASK		0xdf
+#define	NVM_SWDPIN_SWDPIN_SHIFT 0
+#define	NVM_SWDPIN_SWDPIO_SHIFT 8
+
+#define NVM_3GIO_3_ASPM_MASK	(0x3 << 2)	/* Active State PM Support */
+
+#define NVM_CFG3_APME		(1U << 10)	
+
+#define	NVM_OFF_MACADDR_82571(x)	(3 * (x))
+
+/*
+ * EEPROM Partitioning. See Table 6-1, "EEPROM Top Level Partitioning"
+ * in 82580's datasheet.
+ */
+#define NVM_OFF_LAN_FUNC_82580(x)	((x) ? (0x40 + (0x40 * (x))) : 0)
 
 /* ich8 flash control */
 #define ICH_FLASH_COMMAND_TIMEOUT            5000    /* 5000 uSecs - adjusted */

Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.12.10.4 src/sys/dev/pci/if_wmvar.h:1.12.10.5
--- src/sys/dev/pci/if_wmvar.h:1.12.10.4	Sun Nov  9 12:03:18 2014
+++ src/sys/dev/pci/if_wmvar.h	Thu Dec  4 06:04:07 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmvar.h,v 1.12.10.4 2014/11/09 12:03:18 martin Exp $	*/
+/*	$NetBSD: if_wmvar.h,v 1.12.10.5 2014/12/04 06:04:07 snj Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -72,29 +72,29 @@
 #define _DEV_PCI_IF_WMVAR_H_
 
 /* sc_flags */
-#define	WM_F_HAS_MII		0x00000001	/* has MII */
-#define	WM_F_EEPROM_HANDSHAKE	0x00000002	/* requires EEPROM handshake */
-#define	WM_F_EEPROM_SEMAPHORE	0x00000004	/* EEPROM with semaphore */
-#define	WM_F_EEPROM_EERDEEWR	0x00000008	/* EEPROM access via EERD/EEWR */
-#define	WM_F_EEPROM_SPI		0x00000010	/* EEPROM is SPI */
-#define	WM_F_EEPROM_FLASH	0x00000020	/* EEPROM is FLASH */
-#define	WM_F_EEPROM_INVALID	0x00000040	/* EEPROM not present (bad checksum) */
-#define	WM_F_IOH_VALID		0x00000080	/* I/O handle is valid */
-#define	WM_F_BUS64		0x00000100	/* bus is 64-bit */
-#define	WM_F_PCIX		0x00000200	/* bus is PCI-X */
-#define	WM_F_CSA		0x00000400	/* bus is CSA */
-#define	WM_F_PCIE		0x00000800	/* bus is PCI-Express */
-#define WM_F_SWFW_SYNC		0x00001000  /* Software-Firmware synchronisation */
-#define WM_F_SWFWHW_SYNC	0x00002000  /* Software-Firmware synchronisation */
-#define WM_F_SGMII		0x00004000  /* use SGMII */
-#define WM_F_NEWQUEUE		0x00008000  /* chips which has the new queue system */
+#define	WM_F_HAS_MII		0x00000001 /* has MII */
+#define	WM_F_EEPROM_HANDSHAKE	0x00000002 /* requires EEPROM handshake */
+#define	WM_F_EEPROM_SEMAPHORE	0x00000004 /* EEPROM with semaphore */
+#define	WM_F_EEPROM_EERDEEWR	0x00000008 /* EEPROM access via EERD/EEWR */
+#define	WM_F_EEPROM_SPI		0x00000010 /* EEPROM is SPI */
+#define	WM_F_EEPROM_FLASH	0x00000020 /* EEPROM is FLASH */
+#define	WM_F_EEPROM_INVALID	0x00000040 /* EEPROM not present (bad checksum) */
+#define	WM_F_IOH_VALID		0x00000080 /* I/O handle is valid */
+#define	WM_F_BUS64		0x00000100 /* bus is 64-bit */
+#define	WM_F_PCIX		0x00000200 /* bus is PCI-X */
+#define	WM_F_CSA		0x00000400 /* bus is CSA */
+#define	WM_F_PCIE		0x00000800 /* bus is PCI-Express */
+#define WM_F_SWFW_SYNC		0x00001000 /* Software-Firmware synchronisation */
+#define WM_F_SWFWHW_SYNC	0x00002000 /* Software-Firmware synchronisation */
+#define WM_F_SGMII		0x00004000 /* use SGMII */
+#define WM_F_NEWQUEUE		0x00008000 /* chips which has the new queue system */
 #define WM_F_ASF_FIRMWARE_PRES	0x00010000
 #define WM_F_ARC_SUBSYS_VALID	0x00020000
 #define WM_F_HAS_AMT		0x00040000
 #define WM_F_HAS_MANAGE		0x00080000
 #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_EEE		0x00200000 /* Energy Efficiency Ethernet */
+#define	WM_F_EEPROM_FLASH_HW	0x00400000 /* EEPROM is FLASH */
 
 typedef enum {
 	WM_T_unknown		= 0,
@@ -119,7 +119,6 @@ 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 */

Reply via email to