[BACK]Return to if_wm.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

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

Diff for /src/sys/dev/pci/if_wm.c between version 1.416 and 1.416.2.1

version 1.416, 2016/07/11 06:14:51 version 1.416.2.1, 2016/11/04 14:49:09
Line 144  __KERNEL_RCSID(0, "$NetBSD$");
Line 144  __KERNEL_RCSID(0, "$NetBSD$");
 #include <dev/pci/if_wmvar.h>  #include <dev/pci/if_wmvar.h>
   
 #ifdef WM_DEBUG  #ifdef WM_DEBUG
 #define WM_DEBUG_LINK           0x01  #define WM_DEBUG_LINK           __BIT(0)
 #define WM_DEBUG_TX             0x02  #define WM_DEBUG_TX             __BIT(1)
 #define WM_DEBUG_RX             0x04  #define WM_DEBUG_RX             __BIT(2)
 #define WM_DEBUG_GMII           0x08  #define WM_DEBUG_GMII           __BIT(3)
 #define WM_DEBUG_MANAGE         0x10  #define WM_DEBUG_MANAGE         __BIT(4)
 #define WM_DEBUG_NVM            0x20  #define WM_DEBUG_NVM            __BIT(5)
 #define WM_DEBUG_INIT           0x40  #define WM_DEBUG_INIT           __BIT(6)
   #define WM_DEBUG_LOCK           __BIT(7)
 int     wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | WM_DEBUG_GMII  int     wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | WM_DEBUG_GMII
     | WM_DEBUG_MANAGE | WM_DEBUG_NVM | WM_DEBUG_INIT;      | WM_DEBUG_MANAGE | WM_DEBUG_NVM | WM_DEBUG_INIT | WM_DEBUG_LOCK;
   
 #define DPRINTF(x, y)   if (wm_debug & (x)) printf y  #define DPRINTF(x, y)   if (wm_debug & (x)) printf y
 #else  #else
Line 302  struct wm_txqueue {
Line 303  struct wm_txqueue {
         int txq_flags;                  /* flags for H/W queue, see below */          int txq_flags;                  /* flags for H/W queue, see below */
 #define WM_TXQ_NO_SPACE 0x1  #define WM_TXQ_NO_SPACE 0x1
   
         /* XXX which event counter is required? */          bool txq_stopping;
   
   #ifdef WM_EVENT_COUNTERS
           WM_Q_EVCNT_DEFINE(txq, txsstall)        /* Tx stalled due to no txs */
           WM_Q_EVCNT_DEFINE(txq, txdstall)        /* Tx stalled due to no txd */
           WM_Q_EVCNT_DEFINE(txq, txfifo_stall)    /* Tx FIFO stalls (82547) */
           WM_Q_EVCNT_DEFINE(txq, txdw)            /* Tx descriptor interrupts */
           WM_Q_EVCNT_DEFINE(txq, txqe)            /* Tx queue empty interrupts */
                                                   /* XXX not used? */
   
           WM_Q_EVCNT_DEFINE(txq, txipsum)         /* IP checksums comp. out-bound */
           WM_Q_EVCNT_DEFINE(txq,txtusum)          /* TCP/UDP cksums comp. out-bound */
           WM_Q_EVCNT_DEFINE(txq, txtusum6)        /* TCP/UDP v6 cksums comp. out-bound */
           WM_Q_EVCNT_DEFINE(txq, txtso)           /* TCP seg offload out-bound (IPv4) */
           WM_Q_EVCNT_DEFINE(txq, txtso6)          /* TCP seg offload out-bound (IPv6) */
           WM_Q_EVCNT_DEFINE(txq, txtsopain)       /* painful header manip. for TSO */
   
           WM_Q_EVCNT_DEFINE(txq, txdrop)          /* Tx packets dropped(too many segs) */
   
           WM_Q_EVCNT_DEFINE(txq, tu)              /* Tx underrun */
   
           char txq_txseg_evcnt_names[WM_NTXSEGS][sizeof("txqXXtxsegXXX")];
           struct evcnt txq_ev_txseg[WM_NTXSEGS]; /* Tx packets w/ N segments */
   #endif /* WM_EVENT_COUNTERS */
 };  };
   
 struct wm_rxqueue {  struct wm_rxqueue {
Line 330  struct wm_rxqueue {
Line 354  struct wm_rxqueue {
         struct mbuf *rxq_tail;          struct mbuf *rxq_tail;
         struct mbuf **rxq_tailp;          struct mbuf **rxq_tailp;
   
         /* XXX which event counter is required? */          bool rxq_stopping;
   
   #ifdef WM_EVENT_COUNTERS
           WM_Q_EVCNT_DEFINE(rxq, rxintr);         /* Rx interrupts */
   
           WM_Q_EVCNT_DEFINE(rxq, rxipsum);        /* IP checksums checked in-bound */
           WM_Q_EVCNT_DEFINE(rxq, rxtusum);        /* TCP/UDP cksums checked in-bound */
   #endif
 };  };
   
 struct wm_queue {  struct wm_queue {
Line 341  struct wm_queue {
Line 372  struct wm_queue {
         struct wm_rxqueue wmq_rxq;          struct wm_rxqueue wmq_rxq;
 };  };
   
   struct wm_phyop {
           int (*acquire)(struct wm_softc *);
           void (*release)(struct wm_softc *);
   };
   
 /*  /*
  * Software state per device.   * Software state per device.
  */   */
Line 394  struct wm_softc {
Line 430  struct wm_softc {
         int sc_link_intr_idx;           /* index of MSI-X tables */          int sc_link_intr_idx;           /* index of MSI-X tables */
   
         callout_t sc_tick_ch;           /* tick callout */          callout_t sc_tick_ch;           /* tick callout */
         bool sc_stopping;          bool sc_core_stopping;
   
         int sc_nvm_ver_major;          int sc_nvm_ver_major;
         int sc_nvm_ver_minor;          int sc_nvm_ver_minor;
Line 465  struct wm_softc {
Line 501  struct wm_softc {
   
         krndsource_t rnd_source;        /* random source */          krndsource_t rnd_source;        /* random source */
   
           struct if_percpuq *sc_ipq;      /* softint-based input queues */
   
         kmutex_t *sc_core_lock;         /* lock for softc operations */          kmutex_t *sc_core_lock;         /* lock for softc operations */
           kmutex_t *sc_ich_phymtx;        /*
                                            * 82574/82583/ICH/PCH specific PHY
                                            * mutex. For 82574/82583, the mutex
                                            * is used for both PHY and NVM.
                                            */
           kmutex_t *sc_ich_nvmmtx;        /* ICH/PCH specific NVM mutex */
   
         struct if_percpuq *sc_ipq;      /* softint-based input queues */          struct wm_phyop phy;
 };  };
   
 #define WM_CORE_LOCK(_sc)       if ((_sc)->sc_core_lock) mutex_enter((_sc)->sc_core_lock)  #define WM_CORE_LOCK(_sc)       if ((_sc)->sc_core_lock) mutex_enter((_sc)->sc_core_lock)
Line 593  static int wm_setup_legacy(struct wm_sof
Line 637  static int wm_setup_legacy(struct wm_sof
 static int      wm_setup_msix(struct wm_softc *);  static int      wm_setup_msix(struct wm_softc *);
 static int      wm_init(struct ifnet *);  static int      wm_init(struct ifnet *);
 static int      wm_init_locked(struct ifnet *);  static int      wm_init_locked(struct ifnet *);
   static void     wm_turnon(struct wm_softc *);
   static void     wm_turnoff(struct wm_softc *);
 static void     wm_stop(struct ifnet *, int);  static void     wm_stop(struct ifnet *, int);
 static void     wm_stop_locked(struct ifnet *, int);  static void     wm_stop_locked(struct ifnet *, int);
 static void     wm_dump_mbuf_chain(struct wm_softc *, struct mbuf *);  static void     wm_dump_mbuf_chain(struct wm_softc *, struct mbuf *);
Line 661  static void wm_i82543_mii_sendbits(struc
Line 707  static void wm_i82543_mii_sendbits(struc
 static uint32_t wm_i82543_mii_recvbits(struct wm_softc *);  static uint32_t wm_i82543_mii_recvbits(struct wm_softc *);
 static int      wm_gmii_i82543_readreg(device_t, int, int);  static int      wm_gmii_i82543_readreg(device_t, int, int);
 static void     wm_gmii_i82543_writereg(device_t, int, int, int);  static void     wm_gmii_i82543_writereg(device_t, int, int, int);
   static int      wm_gmii_mdic_readreg(device_t, int, int);
   static void     wm_gmii_mdic_writereg(device_t, int, int, int);
 static int      wm_gmii_i82544_readreg(device_t, int, int);  static int      wm_gmii_i82544_readreg(device_t, int, int);
 static void     wm_gmii_i82544_writereg(device_t, int, int, int);  static void     wm_gmii_i82544_writereg(device_t, int, int, int);
 static int      wm_gmii_i80003_readreg(device_t, int, int);  static int      wm_gmii_i80003_readreg(device_t, int, int);
Line 669  static int wm_gmii_bm_readreg(device_t, 
Line 717  static int wm_gmii_bm_readreg(device_t, 
 static void     wm_gmii_bm_writereg(device_t, int, 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 void     wm_access_phy_wakeup_reg_bm(device_t, int, int16_t *, int);
 static int      wm_gmii_hv_readreg(device_t, int, int);  static int      wm_gmii_hv_readreg(device_t, int, int);
   static int      wm_gmii_hv_readreg_locked(device_t, int, int);
 static void     wm_gmii_hv_writereg(device_t, int, int, int);  static void     wm_gmii_hv_writereg(device_t, int, int, int);
   static void     wm_gmii_hv_writereg_locked(device_t, int, int, int);
 static int      wm_gmii_82580_readreg(device_t, 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_82580_writereg(device_t, int, int, int);
 static int      wm_gmii_gs40g_readreg(device_t, int, int);  static int      wm_gmii_gs40g_readreg(device_t, int, int);
 static void     wm_gmii_gs40g_writereg(device_t, int, int, int);  static void     wm_gmii_gs40g_writereg(device_t, int, int, int);
 static void     wm_gmii_statchg(struct ifnet *);  static void     wm_gmii_statchg(struct ifnet *);
 static int      wm_kmrn_readreg(struct wm_softc *, int);  static int      wm_kmrn_readreg(struct wm_softc *, int);
   static int      wm_kmrn_readreg_locked(struct wm_softc *, int);
 static void     wm_kmrn_writereg(struct wm_softc *, int, int);  static void     wm_kmrn_writereg(struct wm_softc *, int, int);
   static void     wm_kmrn_writereg_locked(struct wm_softc *, int, int);
 /* SGMII */  /* SGMII */
 static bool     wm_sgmii_uses_mdio(struct wm_softc *);  static bool     wm_sgmii_uses_mdio(struct wm_softc *);
 static int      wm_sgmii_readreg(device_t, int, int);  static int      wm_sgmii_readreg(device_t, int, int);
Line 741  static int wm_nvm_read(struct wm_softc *
Line 793  static int wm_nvm_read(struct wm_softc *
  * Hardware semaphores.   * Hardware semaphores.
  * Very complexed...   * Very complexed...
  */   */
 static int      wm_get_swsm_semaphore(struct wm_softc *);  static int      wm_get_null(struct wm_softc *);
   static void     wm_put_null(struct wm_softc *);
   static int      wm_get_swsm_semaphore(struct wm_softc *); /* 8257[123] */
 static void     wm_put_swsm_semaphore(struct wm_softc *);  static void     wm_put_swsm_semaphore(struct wm_softc *);
 static int      wm_get_swfw_semaphore(struct wm_softc *, uint16_t);  static int      wm_get_swfw_semaphore(struct wm_softc *, uint16_t);
 static void     wm_put_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 *);  static int      wm_get_phy_82575(struct wm_softc *);
   static void     wm_put_phy_82575(struct wm_softc *);
   static int      wm_get_swfwhw_semaphore(struct wm_softc *); /* For 574/583 */
 static void     wm_put_swfwhw_semaphore(struct wm_softc *);  static void     wm_put_swfwhw_semaphore(struct wm_softc *);
   static int      wm_get_swflag_ich8lan(struct wm_softc *);       /* For PHY */
   static void     wm_put_swflag_ich8lan(struct wm_softc *);
   static int      wm_get_nvm_ich8lan(struct wm_softc *);          /* For NVM */
   static void     wm_put_nvm_ich8lan(struct wm_softc *);
 static int      wm_get_hw_semaphore_82573(struct wm_softc *);  static int      wm_get_hw_semaphore_82573(struct wm_softc *);
 static void     wm_put_hw_semaphore_82573(struct wm_softc *);  static void     wm_put_hw_semaphore_82573(struct wm_softc *);
   
Line 788  static void wm_kmrn_lock_loss_workaround
Line 848  static void wm_kmrn_lock_loss_workaround
 static void     wm_gig_downshift_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_hv_phy_workaround_ich8lan(struct wm_softc *);
 static void     wm_lv_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 int      wm_k1_gig_workaround_hv(struct wm_softc *, int);
 static void     wm_set_mdio_slow_mode_hv(struct wm_softc *);  static void     wm_set_mdio_slow_mode_hv(struct wm_softc *);
 static void     wm_configure_k1_ich8lan(struct wm_softc *, int);  static void     wm_configure_k1_ich8lan(struct wm_softc *, int);
 static void     wm_reset_init_script_82575(struct wm_softc *);  static void     wm_reset_init_script_82575(struct wm_softc *);
Line 1074  static const struct wm_product {
Line 1134  static const struct wm_product {
         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801H_IFE_G,          { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801H_IFE_G,
           "Intel i82801H IFE (G) LAN Controller",            "Intel i82801H IFE (G) LAN Controller",
           WM_T_ICH8,            WMP_F_COPPER },            WM_T_ICH8,            WMP_F_COPPER },
           { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801H_82567V_3,
             "82567V-3 LAN Controller",
             WM_T_ICH8,            WMP_F_COPPER },
         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_IGP_AMT,          { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_IGP_AMT,
           "82801I (AMT) LAN Controller",            "82801I (AMT) LAN Controller",
           WM_T_ICH9,            WMP_F_COPPER },            WM_T_ICH9,            WMP_F_COPPER },
Line 1101  static const struct wm_product {
Line 1164  static const struct wm_product {
         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_BM,          { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_BM,
           "82567LM-4 LAN Controller",            "82567LM-4 LAN Controller",
           WM_T_ICH9,            WMP_F_COPPER },            WM_T_ICH9,            WMP_F_COPPER },
         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_82567V_3,  
           "82567V-3 LAN Controller",  
           WM_T_ICH9,            WMP_F_COPPER },  
         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801J_R_BM_LM,          { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801J_R_BM_LM,
           "82567LM-2 LAN Controller",            "82567LM-2 LAN Controller",
           WM_T_ICH10,           WMP_F_COPPER },            WM_T_ICH10,           WMP_F_COPPER },
Line 1321  static const struct wm_product {
Line 1381  static const struct wm_product {
         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_V2,          { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_V2,
           "I219 V Ethernet Connection",            "I219 V Ethernet Connection",
           WM_T_PCH_SPT,         WMP_F_COPPER },            WM_T_PCH_SPT,         WMP_F_COPPER },
           { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_V4,
             "I219 V Ethernet Connection",
             WM_T_PCH_SPT,         WMP_F_COPPER },
           { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_V5,
             "I219 V Ethernet Connection",
             WM_T_PCH_SPT,         WMP_F_COPPER },
         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_LM,          { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_LM,
           "I219 LM Ethernet Connection",            "I219 LM Ethernet Connection",
           WM_T_PCH_SPT,         WMP_F_COPPER },            WM_T_PCH_SPT,         WMP_F_COPPER },
         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_LM2,          { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_LM2,
           "I219 LM Ethernet Connection",            "I219 LM Ethernet Connection",
           WM_T_PCH_SPT,         WMP_F_COPPER },            WM_T_PCH_SPT,         WMP_F_COPPER },
           { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_LM3,
             "I219 LM Ethernet Connection",
             WM_T_PCH_SPT,         WMP_F_COPPER },
           { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_LM4,
             "I219 LM Ethernet Connection",
             WM_T_PCH_SPT,         WMP_F_COPPER },
           { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_I219_LM5,
             "I219 LM Ethernet Connection",
             WM_T_PCH_SPT,         WMP_F_COPPER },
 #endif  #endif
         { 0,                    0,          { 0,                    0,
           NULL,            NULL,
Line 1522  wm_attach(device_t parent, device_t self
Line 1597  wm_attach(device_t parent, device_t self
   
         sc->sc_dev = self;          sc->sc_dev = self;
         callout_init(&sc->sc_tick_ch, CALLOUT_FLAGS);          callout_init(&sc->sc_tick_ch, CALLOUT_FLAGS);
         sc->sc_stopping = false;          sc->sc_core_stopping = false;
   
         wmp = wm_lookup(pa);          wmp = wm_lookup(pa);
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
Line 1546  wm_attach(device_t parent, device_t self
Line 1621  wm_attach(device_t parent, device_t self
         pci_aprint_devinfo_fancy(pa, "Ethernet controller", wmp->wmp_name, 1);          pci_aprint_devinfo_fancy(pa, "Ethernet controller", wmp->wmp_name, 1);
   
         sc->sc_type = wmp->wmp_type;          sc->sc_type = wmp->wmp_type;
   
           /* Set default function pointers */
           sc->phy.acquire = wm_get_null;
           sc->phy.release = wm_put_null;
   
         if (sc->sc_type < WM_T_82543) {          if (sc->sc_type < WM_T_82543) {
                 if (sc->sc_rev < 2) {                  if (sc->sc_rev < 2) {
                         aprint_error_dev(sc->sc_dev,                          aprint_error_dev(sc->sc_dev,
Line 1849  alloc_retry:
Line 1929  alloc_retry:
             || (sc->sc_type == WM_T_PCH_LPT) || (sc->sc_type == WM_T_PCH_SPT))              || (sc->sc_type == WM_T_PCH_LPT) || (sc->sc_type == WM_T_PCH_SPT))
                 wm_smbustopci(sc);                  wm_smbustopci(sc);
   
         /* Reset the chip to a known state. */          if ((sc->sc_type == WM_T_82574) || (sc->sc_type == WM_T_82583)
         wm_reset(sc);              || (sc->sc_type >= WM_T_ICH8))
                   sc->sc_ich_phymtx = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
           if (sc->sc_type >= WM_T_ICH8)
                   sc->sc_ich_nvmmtx = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
   
         /* Get some information about the EEPROM. */          /* Set PHY, NVM mutex related stuff */
         switch (sc->sc_type) {          switch (sc->sc_type) {
         case WM_T_82542_2_0:          case WM_T_82542_2_0:
         case WM_T_82542_2_1:          case WM_T_82542_2_1:
Line 1905  alloc_retry:
Line 1988  alloc_retry:
                 sc->sc_flags |= WM_F_EEPROM_SPI;                  sc->sc_flags |= WM_F_EEPROM_SPI;
                 wm_nvm_set_addrbits_size_eecd(sc);                  wm_nvm_set_addrbits_size_eecd(sc);
                 sc->sc_flags |= WM_F_LOCK_EECD | WM_F_LOCK_SWSM;                  sc->sc_flags |= WM_F_LOCK_EECD | WM_F_LOCK_SWSM;
                   sc->phy.acquire = wm_get_swsm_semaphore;
                   sc->phy.release = wm_put_swsm_semaphore;
                 break;                  break;
         case WM_T_82573:          case WM_T_82573:
                 sc->sc_flags |= WM_F_LOCK_SWSM;  
                 /* FALLTHROUGH */  
         case WM_T_82574:          case WM_T_82574:
         case WM_T_82583:          case WM_T_82583:
                   if (sc->sc_type == WM_T_82573) {
                           sc->sc_flags |= WM_F_LOCK_SWSM;
                           sc->phy.acquire = wm_get_swsm_semaphore;
                           sc->phy.release = wm_put_swsm_semaphore;
                   } else {
                           sc->sc_flags |= WM_F_LOCK_EXTCNF;
                           /* Both PHY and NVM use the same semaphore. */
                           sc->phy.acquire
                               = wm_get_swfwhw_semaphore;
                           sc->phy.release
                               = wm_put_swfwhw_semaphore;
                   }
                 if (wm_nvm_is_onboard_eeprom(sc) == 0) {                  if (wm_nvm_is_onboard_eeprom(sc) == 0) {
                         sc->sc_flags |= WM_F_EEPROM_FLASH;                          sc->sc_flags |= WM_F_EEPROM_FLASH;
                         sc->sc_nvm_wordsize = 2048;                          sc->sc_nvm_wordsize = 2048;
Line 1932  alloc_retry:
Line 2027  alloc_retry:
                 wm_nvm_set_addrbits_size_eecd(sc);                  wm_nvm_set_addrbits_size_eecd(sc);
                 sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW                  sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW
                     | WM_F_LOCK_SWSM;                      | WM_F_LOCK_SWSM;
                   sc->phy.acquire = wm_get_phy_82575;
                   sc->phy.release = wm_put_phy_82575;
                 break;                  break;
         case WM_T_ICH8:          case WM_T_ICH8:
         case WM_T_ICH9:          case WM_T_ICH9:
Line 1958  alloc_retry:
Line 2055  alloc_retry:
                 sc->sc_ich8_flash_bank_size *= ICH_FLASH_SECTOR_SIZE;                  sc->sc_ich8_flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
                 sc->sc_ich8_flash_bank_size /= 2 * sizeof(uint16_t);                  sc->sc_ich8_flash_bank_size /= 2 * sizeof(uint16_t);
                 sc->sc_flashreg_offset = 0;                  sc->sc_flashreg_offset = 0;
                   sc->phy.acquire = wm_get_swflag_ich8lan;
                   sc->phy.release = wm_put_swflag_ich8lan;
                 break;                  break;
         case WM_T_PCH_SPT:          case WM_T_PCH_SPT:
                 /* SPT has no GFPREG; flash registers mapped through BAR0 */                  /* SPT has no GFPREG; flash registers mapped through BAR0 */
Line 1973  alloc_retry:
Line 2072  alloc_retry:
                 /* assume 2 banks */                  /* assume 2 banks */
                 sc->sc_ich8_flash_bank_size = sc->sc_nvm_wordsize / 2;                  sc->sc_ich8_flash_bank_size = sc->sc_nvm_wordsize / 2;
                 sc->sc_flashreg_offset = WM_PCH_SPT_FLASHOFFSET;                  sc->sc_flashreg_offset = WM_PCH_SPT_FLASHOFFSET;
                   sc->phy.acquire = wm_get_swflag_ich8lan;
                   sc->phy.release = wm_put_swflag_ich8lan;
                 break;                  break;
         case WM_T_I210:          case WM_T_I210:
         case WM_T_I211:          case WM_T_I211:
                 if (wm_nvm_get_flash_presence_i210(sc)) {                  if (wm_nvm_get_flash_presence_i210(sc)) {
                         wm_nvm_set_addrbits_size_eecd(sc);                          wm_nvm_set_addrbits_size_eecd(sc);
                         sc->sc_flags |= WM_F_EEPROM_FLASH_HW;                          sc->sc_flags |= WM_F_EEPROM_FLASH_HW;
                         sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW;                          sc->sc_flags |= WM_F_EEPROM_EERDEEWR;
                 } else {                  } else {
                         sc->sc_nvm_wordsize = INVM_SIZE;                          sc->sc_nvm_wordsize = INVM_SIZE;
                         sc->sc_flags |= WM_F_EEPROM_INVM;                          sc->sc_flags |= WM_F_EEPROM_INVM;
                         sc->sc_flags |= WM_F_LOCK_SWFW;  
                 }                  }
                   sc->sc_flags |= WM_F_LOCK_SWFW | WM_F_LOCK_SWSM;
                   sc->phy.acquire = wm_get_phy_82575;
                   sc->phy.release = wm_put_phy_82575;
                 break;                  break;
         default:          default:
                 break;                  break;
         }          }
   
           /* Reset the chip to a known state. */
           wm_reset(sc);
   
         /* Ensure the SMBI bit is clear before first NVM or PHY access */          /* Ensure the SMBI bit is clear before first NVM or PHY access */
         switch (sc->sc_type) {          switch (sc->sc_type) {
         case WM_T_82571:          case WM_T_82571:
Line 2657  wm_detach(device_t self, int flags __unu
Line 2763  wm_detach(device_t self, int flags __unu
   
         if (sc->sc_core_lock)          if (sc->sc_core_lock)
                 mutex_obj_free(sc->sc_core_lock);                  mutex_obj_free(sc->sc_core_lock);
           if (sc->sc_ich_phymtx)
                   mutex_obj_free(sc->sc_ich_phymtx);
           if (sc->sc_ich_nvmmtx)
                   mutex_obj_free(sc->sc_ich_nvmmtx);
   
         return 0;          return 0;
 }  }
Line 2774  wm_tick(void *arg)
Line 2884  wm_tick(void *arg)
   
         WM_CORE_LOCK(sc);          WM_CORE_LOCK(sc);
   
         if (sc->sc_stopping)          if (sc->sc_core_stopping)
                 goto out;                  goto out;
   
         if (sc->sc_type >= WM_T_82542_2_1) {          if (sc->sc_type >= WM_T_82542_2_1) {
Line 2794  wm_tick(void *arg)
Line 2904  wm_tick(void *arg)
             + CSR_READ(sc, WMREG_SEC)              + CSR_READ(sc, WMREG_SEC)
             + CSR_READ(sc, WMREG_CEXTERR)              + CSR_READ(sc, WMREG_CEXTERR)
             + CSR_READ(sc, WMREG_RLEC);              + CSR_READ(sc, WMREG_RLEC);
         ifp->if_iqdrops += CSR_READ(sc, WMREG_MPC) + CSR_READ(sc, WMREG_RNBC);          /*
            * WMREG_RNBC is incremented when there is no available buffers in host
            * memory. It does not mean the number of dropped packet. Because
            * ethernet controller can receive packets in such case if there is
            * space in phy's FIFO.
            *
            * If you want to know the nubmer of WMREG_RMBC, you should use such as
            * own EVCNT instead of if_iqdrops.
            */
           ifp->if_iqdrops += CSR_READ(sc, WMREG_MPC);
   
         if (sc->sc_flags & WM_F_HAS_MII)          if (sc->sc_flags & WM_F_HAS_MII)
                 mii_tick(&sc->sc_mii);                  mii_tick(&sc->sc_mii);
Line 2810  out:
Line 2929  out:
         splx(s);          splx(s);
 #endif  #endif
   
         if (!sc->sc_stopping)          if (!sc->sc_core_stopping)
                 callout_reset(&sc->sc_tick_ch, hz, wm_tick, sc);                  callout_reset(&sc->sc_tick_ch, hz, wm_tick, sc);
 }  }
   
Line 2819  wm_ifflags_cb(struct ethercom *ec)
Line 2938  wm_ifflags_cb(struct ethercom *ec)
 {  {
         struct ifnet *ifp = &ec->ec_if;          struct ifnet *ifp = &ec->ec_if;
         struct wm_softc *sc = ifp->if_softc;          struct wm_softc *sc = ifp->if_softc;
         int change = ifp->if_flags ^ sc->sc_if_flags;  
         int rc = 0;          int rc = 0;
   
         WM_CORE_LOCK(sc);          WM_CORE_LOCK(sc);
   
         if (change != 0)          int change = ifp->if_flags ^ sc->sc_if_flags;
                 sc->sc_if_flags = ifp->if_flags;          sc->sc_if_flags = ifp->if_flags;
   
         if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {          if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
                 rc = ENETRESET;                  rc = ENETRESET;
Line 2859  wm_ioctl(struct ifnet *ifp, u_long cmd, 
Line 2977  wm_ioctl(struct ifnet *ifp, u_long cmd, 
   
         DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                 device_xname(sc->sc_dev), __func__));                  device_xname(sc->sc_dev), __func__));
   
 #ifndef WM_MPSAFE  #ifndef WM_MPSAFE
         s = splnet();          s = splnet();
 #endif  #endif
Line 3004  wm_read_mac_addr(struct wm_softc *sc, ui
Line 3123  wm_read_mac_addr(struct wm_softc *sc, ui
                 break;                  break;
         }          }
   
         if (wm_nvm_read(sc, offset, sizeof(myea) / sizeof(myea[0]),          if (wm_nvm_read(sc, offset, sizeof(myea) / sizeof(myea[0]), myea) != 0)
                 myea) != 0)  
                 goto bad;                  goto bad;
   
         enaddr[0] = myea[0] & 0xff;          enaddr[0] = myea[0] & 0xff;
Line 3106  wm_set_filter(struct wm_softc *sc)
Line 3224  wm_set_filter(struct wm_softc *sc)
   
         DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                 device_xname(sc->sc_dev), __func__));                  device_xname(sc->sc_dev), __func__));
   
         if (sc->sc_type >= WM_T_82544)          if (sc->sc_type >= WM_T_82544)
                 mta_reg = WMREG_CORDOVA_MTA;                  mta_reg = WMREG_CORDOVA_MTA;
         else          else
Line 3240  wm_set_vlan(struct wm_softc *sc)
Line 3359  wm_set_vlan(struct wm_softc *sc)
   
         DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                 device_xname(sc->sc_dev), __func__));                  device_xname(sc->sc_dev), __func__));
   
         /* Deal with VLAN enables. */          /* Deal with VLAN enables. */
         if (VLAN_ATTACHED(&sc->sc_ethercom))          if (VLAN_ATTACHED(&sc->sc_ethercom))
                 sc->sc_ctrl |= CTRL_VME;                  sc->sc_ctrl |= CTRL_VME;
Line 3323  wm_lan_init_done(struct wm_softc *sc)
Line 3443  wm_lan_init_done(struct wm_softc *sc)
         uint32_t reg = 0;          uint32_t reg = 0;
         int i;          int i;
   
         /* wait for eeprom to reload */          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
           /* Wait for eeprom to reload */
         switch (sc->sc_type) {          switch (sc->sc_type) {
         case WM_T_ICH10:          case WM_T_ICH10:
         case WM_T_PCH:          case WM_T_PCH:
Line 3358  wm_get_cfg_done(struct wm_softc *sc)
Line 3481  wm_get_cfg_done(struct wm_softc *sc)
         uint32_t reg;          uint32_t reg;
         int i;          int i;
   
         /* wait for eeprom to reload */          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
           /* Wait for eeprom to reload */
         switch (sc->sc_type) {          switch (sc->sc_type) {
         case WM_T_82542_2_0:          case WM_T_82542_2_0:
         case WM_T_82542_2_1:          case WM_T_82542_2_1:
Line 3438  wm_initialize_hardware_bits(struct wm_so
Line 3564  wm_initialize_hardware_bits(struct wm_so
   
         DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                 device_xname(sc->sc_dev), __func__));                  device_xname(sc->sc_dev), __func__));
   
         /* For 82571 variant, 80003 and ICHs */          /* For 82571 variant, 80003 and ICHs */
         if (((sc->sc_type >= WM_T_82571) && (sc->sc_type <= WM_T_82583))          if (((sc->sc_type >= WM_T_82571) && (sc->sc_type <= WM_T_82583))
             || (sc->sc_type >= WM_T_80003)) {              || (sc->sc_type >= WM_T_80003)) {
Line 3666  wm_reset(struct wm_softc *sc)
Line 3793  wm_reset(struct wm_softc *sc)
 {  {
         int phy_reset = 0;          int phy_reset = 0;
         int i, error = 0;          int i, error = 0;
         uint32_t reg, mask;          uint32_t reg;
   
         DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                 device_xname(sc->sc_dev), __func__));                  device_xname(sc->sc_dev), __func__));
           KASSERT(sc->sc_type != 0);
   
         /*          /*
          * Allocate on-chip memory according to the MTU size.           * Allocate on-chip memory according to the MTU size.
          * The Packet Buffer Allocation register must be written           * The Packet Buffer Allocation register must be written
Line 3838  wm_reset(struct wm_softc *sc)
Line 3967  wm_reset(struct wm_softc *sc)
                 CSR_WRITE(sc, WMREG_CTRL_SHADOW, CTRL_RST);                  CSR_WRITE(sc, WMREG_CTRL_SHADOW, CTRL_RST);
                 break;                  break;
         case WM_T_80003:          case WM_T_80003:
                 mask = swfwphysem[sc->sc_funcid];  
                 reg = CSR_READ(sc, WMREG_CTRL) | CTRL_RST;                  reg = CSR_READ(sc, WMREG_CTRL) | CTRL_RST;
                 wm_get_swfw_semaphore(sc, mask);                  sc->phy.acquire(sc);
                 CSR_WRITE(sc, WMREG_CTRL, reg);                  CSR_WRITE(sc, WMREG_CTRL, reg);
                 wm_put_swfw_semaphore(sc, mask);                  sc->phy.release(sc);
                 break;                  break;
         case WM_T_ICH8:          case WM_T_ICH8:
         case WM_T_ICH9:          case WM_T_ICH9:
Line 3866  wm_reset(struct wm_softc *sc)
Line 3994  wm_reset(struct wm_softc *sc)
                         phy_reset = 1;                          phy_reset = 1;
                 } else                  } else
                         printf("XXX reset is blocked!!!\n");                          printf("XXX reset is blocked!!!\n");
                 wm_get_swfwhw_semaphore(sc);                  sc->phy.acquire(sc);
                 CSR_WRITE(sc, WMREG_CTRL, reg);                  CSR_WRITE(sc, WMREG_CTRL, reg);
                 /* Don't insert a completion barrier when reset */                  /* Don't insert a completion barrier when reset */
                 delay(20*1000);                  delay(20*1000);
                 wm_put_swfwhw_semaphore(sc);                  mutex_exit(sc->sc_ich_phymtx);
                 break;                  break;
         case WM_T_82580:          case WM_T_82580:
         case WM_T_I350:          case WM_T_I350:
Line 4030  wm_reset(struct wm_softc *sc)
Line 4158  wm_reset(struct wm_softc *sc)
         if ((sc->sc_type >= WM_T_I350) && (sc->sc_type <= WM_T_I211))          if ((sc->sc_type >= WM_T_I350) && (sc->sc_type <= WM_T_I211))
                 wm_set_eee_i350(sc);                  wm_set_eee_i350(sc);
   
         /* dummy read from WUC */          /* Clear the host wakeup bit after lcd reset */
         if (sc->sc_type == WM_T_PCH)          if (sc->sc_type >= WM_T_PCH) {
                 reg = wm_gmii_hv_readreg(sc->sc_dev, 1, BM_WUC);                  reg = wm_gmii_hv_readreg(sc->sc_dev, 2,
                       BM_PORT_GEN_CFG);
                   reg &= ~BM_WUC_HOST_WU_BIT;
                   wm_gmii_hv_writereg(sc->sc_dev, 2,
                       BM_PORT_GEN_CFG, reg);
           }
   
         /*          /*
          * For PCH, this write will make sure that any noise will be detected           * For PCH, this write will make sure that any noise will be detected
          * as a CRC error and be dropped rather than show up as a bad packet           * as a CRC error and be dropped rather than show up as a bad packet
Line 4468  wm_setup_msix(struct wm_softc *sc)
Line 4602  wm_setup_msix(struct wm_softc *sc)
         return ENOMEM;          return ENOMEM;
 }  }
   
   static void
   wm_turnon(struct wm_softc *sc)
   {
           int i;
   
           KASSERT(WM_CORE_LOCKED(sc));
   
           for(i = 0; i < sc->sc_nqueues; i++) {
                   struct wm_txqueue *txq = &sc->sc_queue[i].wmq_txq;
                   struct wm_rxqueue *rxq = &sc->sc_queue[i].wmq_rxq;
   
                   mutex_enter(txq->txq_lock);
                   txq->txq_stopping = false;
                   mutex_exit(txq->txq_lock);
   
                   mutex_enter(rxq->rxq_lock);
                   rxq->rxq_stopping = false;
                   mutex_exit(rxq->rxq_lock);
           }
   
           sc->sc_core_stopping = false;
   }
   
   static void
   wm_turnoff(struct wm_softc *sc)
   {
           int i;
   
           KASSERT(WM_CORE_LOCKED(sc));
   
           sc->sc_core_stopping = true;
   
           for(i = 0; i < sc->sc_nqueues; i++) {
                   struct wm_rxqueue *rxq = &sc->sc_queue[i].wmq_rxq;
                   struct wm_txqueue *txq = &sc->sc_queue[i].wmq_txq;
   
                   mutex_enter(rxq->rxq_lock);
                   rxq->rxq_stopping = true;
                   mutex_exit(rxq->rxq_lock);
   
                   mutex_enter(txq->txq_lock);
                   txq->txq_stopping = true;
                   mutex_exit(txq->txq_lock);
           }
   }
   
 /*  /*
  * wm_init:             [ifnet interface function]   * wm_init:             [ifnet interface function]
  *   *
Line 4496  wm_init_locked(struct ifnet *ifp)
Line 4676  wm_init_locked(struct ifnet *ifp)
         DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                 device_xname(sc->sc_dev), __func__));                  device_xname(sc->sc_dev), __func__));
         KASSERT(WM_CORE_LOCKED(sc));          KASSERT(WM_CORE_LOCKED(sc));
   
         /*          /*
          * *_HDR_ALIGNED_P is constant 1 if __NO_STRICT_ALIGMENT is set.           * *_HDR_ALIGNED_P is constant 1 if __NO_STRICT_ALIGMENT is set.
          * There is a small but measurable benefit to avoiding the adjusment           * There is a small but measurable benefit to avoiding the adjusment
Line 5001  wm_init_locked(struct ifnet *ifp)
Line 5182  wm_init_locked(struct ifnet *ifp)
                 }                  }
         }          }
   
         sc->sc_stopping = false;          wm_turnon(sc);
   
         /* Start the one second link check clock. */          /* Start the one second link check clock. */
         callout_reset(&sc->sc_tick_ch, hz, wm_tick, sc);          callout_reset(&sc->sc_tick_ch, hz, wm_tick, sc);
Line 5044  wm_stop_locked(struct ifnet *ifp, int di
Line 5225  wm_stop_locked(struct ifnet *ifp, int di
                 device_xname(sc->sc_dev), __func__));                  device_xname(sc->sc_dev), __func__));
         KASSERT(WM_CORE_LOCKED(sc));          KASSERT(WM_CORE_LOCKED(sc));
   
         sc->sc_stopping = true;          wm_turnoff(sc);
   
         /* Stop the one second clock. */          /* Stop the one second clock. */
         callout_stop(&sc->sc_tick_ch);          callout_stop(&sc->sc_tick_ch);
Line 5191  wm_82547_txfifo_stall(void *arg)
Line 5372  wm_82547_txfifo_stall(void *arg)
   
         mutex_enter(txq->txq_lock);          mutex_enter(txq->txq_lock);
   
         if (sc->sc_stopping)          if (txq->txq_stopping)
                 goto out;                  goto out;
   
         if (txq->txq_fifo_stall) {          if (txq->txq_fifo_stall) {
Line 5653  wm_init_tx_regs(struct wm_softc *sc, str
Line 5834  wm_init_tx_regs(struct wm_softc *sc, str
     struct wm_txqueue *txq)      struct wm_txqueue *txq)
 {  {
   
           DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
         KASSERT(mutex_owned(txq->txq_lock));          KASSERT(mutex_owned(txq->txq_lock));
   
         if (sc->sc_type < WM_T_82543) {          if (sc->sc_type < WM_T_82543) {
Line 5855  wm_init_txrx_queues(struct wm_softc *sc)
Line 6038  wm_init_txrx_queues(struct wm_softc *sc)
   
         DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                 device_xname(sc->sc_dev), __func__));                  device_xname(sc->sc_dev), __func__));
   
         for (i = 0; i < sc->sc_nqueues; i++) {          for (i = 0; i < sc->sc_nqueues; i++) {
                 struct wm_queue *wmq = &sc->sc_queue[i];                  struct wm_queue *wmq = &sc->sc_queue[i];
                 struct wm_txqueue *txq = &wmq->wmq_txq;                  struct wm_txqueue *txq = &wmq->wmq_txq;
Line 6084  wm_start(struct ifnet *ifp)
Line 6268  wm_start(struct ifnet *ifp)
         KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);          KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);
   
         mutex_enter(txq->txq_lock);          mutex_enter(txq->txq_lock);
         if (!sc->sc_stopping)          if (!txq->txq_stopping)
                 wm_start_locked(ifp);                  wm_start_locked(ifp);
         mutex_exit(txq->txq_lock);          mutex_exit(txq->txq_lock);
 }  }
Line 6603  wm_nq_start(struct ifnet *ifp)
Line 6787  wm_nq_start(struct ifnet *ifp)
         KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);          KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);
   
         mutex_enter(txq->txq_lock);          mutex_enter(txq->txq_lock);
         if (!sc->sc_stopping)          if (!txq->txq_stopping)
                 wm_nq_start_locked(ifp);                  wm_nq_start_locked(ifp);
         mutex_exit(txq->txq_lock);          mutex_exit(txq->txq_lock);
 }  }
Line 6653  wm_nq_transmit(struct ifnet *ifp, struct
Line 6837  wm_nq_transmit(struct ifnet *ifp, struct
                 if (m->m_flags & M_MCAST)                  if (m->m_flags & M_MCAST)
                         ifp->if_omcasts++;                          ifp->if_omcasts++;
   
                 if (!sc->sc_stopping)                  if (!txq->txq_stopping)
                         wm_nq_transmit_locked(ifp, txq);                          wm_nq_transmit_locked(ifp, txq);
                 mutex_exit(txq->txq_lock);                  mutex_exit(txq->txq_lock);
         }          }
Line 6966  wm_txeof(struct wm_softc *sc, struct wm_
Line 7150  wm_txeof(struct wm_softc *sc, struct wm_
   
         KASSERT(mutex_owned(txq->txq_lock));          KASSERT(mutex_owned(txq->txq_lock));
   
         if (sc->sc_stopping)          if (txq->txq_stopping)
                 return 0;                  return 0;
   
         if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)          if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
Line 7254  wm_rxeof(struct wm_rxqueue *rxq)
Line 7438  wm_rxeof(struct wm_rxqueue *rxq)
   
                 mutex_enter(rxq->rxq_lock);                  mutex_enter(rxq->rxq_lock);
   
                 if (sc->sc_stopping)                  if (rxq->rxq_stopping)
                         break;                          break;
         }          }
   
Line 7526  wm_intr_legacy(void *arg)
Line 7710  wm_intr_legacy(void *arg)
   
                 mutex_enter(rxq->rxq_lock);                  mutex_enter(rxq->rxq_lock);
   
                 if (sc->sc_stopping) {                  if (rxq->rxq_stopping) {
                         mutex_exit(rxq->rxq_lock);                          mutex_exit(rxq->rxq_lock);
                         break;                          break;
                 }                  }
Line 7547  wm_intr_legacy(void *arg)
Line 7731  wm_intr_legacy(void *arg)
                 mutex_exit(rxq->rxq_lock);                  mutex_exit(rxq->rxq_lock);
                 mutex_enter(txq->txq_lock);                  mutex_enter(txq->txq_lock);
   
                   if (txq->txq_stopping) {
                           mutex_exit(txq->txq_lock);
                           break;
                   }
   
 #if defined(WM_DEBUG) || defined(WM_EVENT_COUNTERS)  #if defined(WM_DEBUG) || defined(WM_EVENT_COUNTERS)
                 if (icr & ICR_TXDW) {                  if (icr & ICR_TXDW) {
                         DPRINTF(WM_DEBUG_TX,                          DPRINTF(WM_DEBUG_TX,
Line 7560  wm_intr_legacy(void *arg)
Line 7749  wm_intr_legacy(void *arg)
                 mutex_exit(txq->txq_lock);                  mutex_exit(txq->txq_lock);
                 WM_CORE_LOCK(sc);                  WM_CORE_LOCK(sc);
   
                   if (sc->sc_core_stopping) {
                           WM_CORE_UNLOCK(sc);
                           break;
                   }
   
                 if (icr & (ICR_LSC | ICR_RXSEQ)) {                  if (icr & (ICR_LSC | ICR_RXSEQ)) {
                         WM_EVCNT_INCR(&sc->sc_ev_linkintr);                          WM_EVCNT_INCR(&sc->sc_ev_linkintr);
                         wm_linkintr(sc, icr);                          wm_linkintr(sc, icr);
Line 7606  wm_txrxintr_msix(void *arg)
Line 7800  wm_txrxintr_msix(void *arg)
         else          else
                 CSR_WRITE(sc, WMREG_EIMC, 1 << wmq->wmq_intr_idx);                  CSR_WRITE(sc, WMREG_EIMC, 1 << wmq->wmq_intr_idx);
   
         if (!sc->sc_stopping) {          mutex_enter(txq->txq_lock);
                 mutex_enter(txq->txq_lock);  
   
                 WM_EVCNT_INCR(&sc->sc_ev_txdw);  
                 wm_txeof(sc, txq);  
   
                 /* Try to get more packets going. */          if (txq->txq_stopping) {
                 if (pcq_peek(txq->txq_interq) != NULL)  
                         wm_nq_transmit_locked(ifp, txq);  
                 /*  
                  * There are still some upper layer processing which call  
                  * ifp->if_start(). e.g. ALTQ  
                  */  
                 if (wmq->wmq_id == 0) {  
                         if (!IFQ_IS_EMPTY(&ifp->if_snd))  
                                 wm_nq_start_locked(ifp);  
                 }  
                 mutex_exit(txq->txq_lock);                  mutex_exit(txq->txq_lock);
                   return 0;
           }
   
           WM_Q_EVCNT_INCR(txq, txdw);
           wm_txeof(sc, txq);
   
           /* Try to get more packets going. */
           if (pcq_peek(txq->txq_interq) != NULL)
                   wm_nq_transmit_locked(ifp, txq);
           /*
            * There are still some upper layer processing which call
            * ifp->if_start(). e.g. ALTQ
            */
           if (wmq->wmq_id == 0) {
                   if (!IFQ_IS_EMPTY(&ifp->if_snd))
                           wm_nq_start_locked(ifp);
         }          }
   
           mutex_exit(txq->txq_lock);
   
         DPRINTF(WM_DEBUG_RX,          DPRINTF(WM_DEBUG_RX,
             ("%s: RX: got Rx intr\n", device_xname(sc->sc_dev)));              ("%s: RX: got Rx intr\n", device_xname(sc->sc_dev)));
           mutex_enter(rxq->rxq_lock);
   
         if (!sc->sc_stopping) {          if (rxq->rxq_stopping) {
                 mutex_enter(rxq->rxq_lock);  
                 WM_EVCNT_INCR(&sc->sc_ev_rxintr);  
                 wm_rxeof(rxq);  
                 mutex_exit(rxq->rxq_lock);                  mutex_exit(rxq->rxq_lock);
                   return 0;
         }          }
   
           WM_Q_EVCNT_INCR(rxq, rxintr);
           wm_rxeof(rxq);
           mutex_exit(rxq->rxq_lock);
   
         if (sc->sc_type == WM_T_82574)          if (sc->sc_type == WM_T_82574)
                 CSR_WRITE(sc, WMREG_IMS, ICR_TXQ(wmq->wmq_id) | ICR_RXQ(wmq->wmq_id));                  CSR_WRITE(sc, WMREG_IMS, ICR_TXQ(wmq->wmq_id) | ICR_RXQ(wmq->wmq_id));
         else if (sc->sc_type == WM_T_82575)          else if (sc->sc_type == WM_T_82575)
Line 7662  wm_linkintr_msix(void *arg)
Line 7863  wm_linkintr_msix(void *arg)
   
         reg = CSR_READ(sc, WMREG_ICR);          reg = CSR_READ(sc, WMREG_ICR);
         WM_CORE_LOCK(sc);          WM_CORE_LOCK(sc);
         if ((sc->sc_stopping) || ((reg & ICR_LSC) == 0))          if ((sc->sc_core_stopping) || ((reg & ICR_LSC) == 0))
                 goto out;                  goto out;
   
         WM_EVCNT_INCR(&sc->sc_ev_linkintr);          WM_EVCNT_INCR(&sc->sc_ev_linkintr);
Line 7723  wm_gmii_reset(struct wm_softc *sc)
Line 7924  wm_gmii_reset(struct wm_softc *sc)
   
         DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                 device_xname(sc->sc_dev), __func__));                  device_xname(sc->sc_dev), __func__));
         /* get phy semaphore */  
         switch (sc->sc_type) {          rv = sc->phy.acquire(sc);
         case WM_T_82571:  
         case WM_T_82572:  
         case WM_T_82573:  
         case WM_T_82574:  
         case WM_T_82583:  
                  /* XXX should get sw semaphore, too */  
                 rv = wm_get_swsm_semaphore(sc);  
                 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:  
         case WM_T_80003:  
                 rv = wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);  
                 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:  
         case WM_T_PCH_SPT:  
                 rv = wm_get_swfwhw_semaphore(sc);  
                 break;  
         default:  
                 /* nothing to do*/  
                 rv = 0;  
                 break;  
         }  
         if (rv != 0) {          if (rv != 0) {
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
Line 7856  wm_gmii_reset(struct wm_softc *sc)
Line 8025  wm_gmii_reset(struct wm_softc *sc)
                 break;                  break;
         }          }
   
         /* release PHY semaphore */          sc->phy.release(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:  
                  /* XXX should put sw semaphore, too */  
                 wm_put_swsm_semaphore(sc);  
                 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:  
         case WM_T_80003:  
                 wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);  
                 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:  
         case WM_T_PCH_SPT:  
                 wm_put_swfwhw_semaphore(sc);  
                 break;  
         default:  
                 /* nothing to do */  
                 rv = 0;  
                 break;  
         }  
   
         /* get_cfg_done */          /* get_cfg_done */
         wm_get_cfg_done(sc);          wm_get_cfg_done(sc);
Line 7944  wm_gmii_reset(struct wm_softc *sc)
Line 8080  wm_gmii_reset(struct wm_softc *sc)
                 if (sc->sc_type == WM_T_PCH2)                  if (sc->sc_type == WM_T_PCH2)
                         wm_lv_phy_workaround_ich8lan(sc);                          wm_lv_phy_workaround_ich8lan(sc);
   
                 if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)) {                  /* Clear the host wakeup bit after lcd reset */
                         /*                  if (sc->sc_type >= WM_T_PCH) {
                          * dummy read to clear the phy wakeup bit after lcd                          reg = wm_gmii_hv_readreg(sc->sc_dev, 2,
                          * reset                              BM_PORT_GEN_CFG);
                          */                          reg &= ~BM_WUC_HOST_WU_BIT;
                         reg = wm_gmii_hv_readreg(sc->sc_dev, 1, BM_WUC);                          wm_gmii_hv_writereg(sc->sc_dev, 2,
                               BM_PORT_GEN_CFG, reg);
                 }                  }
   
                 /*                  /*
Line 8020  wm_gmii_mediainit(struct wm_softc *sc, p
Line 8157  wm_gmii_mediainit(struct wm_softc *sc, p
         struct mii_data *mii = &sc->sc_mii;          struct mii_data *mii = &sc->sc_mii;
         uint32_t reg;          uint32_t reg;
   
           DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         /* We have GMII. */          /* We have GMII. */
         sc->sc_flags |= WM_F_HAS_MII;          sc->sc_flags |= WM_F_HAS_MII;
   
Line 8079  wm_gmii_mediainit(struct wm_softc *sc, p
Line 8219  wm_gmii_mediainit(struct wm_softc *sc, p
                 /* 82579 */                  /* 82579 */
                 sc->sc_phytype = WMPHY_82579;                  sc->sc_phytype = WMPHY_82579;
                 break;                  break;
           case PCI_PRODUCT_INTEL_82801H_82567V_3:
         case PCI_PRODUCT_INTEL_82801I_BM:          case PCI_PRODUCT_INTEL_82801I_BM:
         case PCI_PRODUCT_INTEL_82801J_R_BM_LM:          case PCI_PRODUCT_INTEL_82801J_R_BM_LM:
         case PCI_PRODUCT_INTEL_82801J_R_BM_LF:          case PCI_PRODUCT_INTEL_82801J_R_BM_LF:
         case PCI_PRODUCT_INTEL_82801J_D_BM_LM:          case PCI_PRODUCT_INTEL_82801J_D_BM_LM:
         case PCI_PRODUCT_INTEL_82801J_D_BM_LF:          case PCI_PRODUCT_INTEL_82801J_D_BM_LF:
         case PCI_PRODUCT_INTEL_82801J_R_BM_V:          case PCI_PRODUCT_INTEL_82801J_R_BM_V:
                 /* 82567 */                  /* ICH8, 9, 10 with 82567 */
                 sc->sc_phytype = WMPHY_BM;                  sc->sc_phytype = WMPHY_BM;
                 mii->mii_readreg = wm_gmii_bm_readreg;                  mii->mii_readreg = wm_gmii_bm_readreg;
                 mii->mii_writereg = wm_gmii_bm_writereg;                  mii->mii_writereg = wm_gmii_bm_writereg;
Line 8096  wm_gmii_mediainit(struct wm_softc *sc, p
Line 8237  wm_gmii_mediainit(struct wm_softc *sc, p
                         /* SGMII */                          /* SGMII */
                         mii->mii_readreg = wm_sgmii_readreg;                          mii->mii_readreg = wm_sgmii_readreg;
                         mii->mii_writereg = wm_sgmii_writereg;                          mii->mii_writereg = wm_sgmii_writereg;
                   } else if ((sc->sc_type == WM_T_82574)
                       || (sc->sc_type == WM_T_82583)) {
                           /* BM2 (phyaddr == 1) */
                           sc->sc_phytype = WMPHY_BM;
                           mii->mii_readreg = wm_gmii_bm_readreg;
                           mii->mii_writereg = wm_gmii_bm_writereg;
                   } else if (sc->sc_type >= WM_T_ICH8) {
                           /* non-82567 ICH8, 9 and 10 */
                           mii->mii_readreg = wm_gmii_i82544_readreg;
                           mii->mii_writereg = wm_gmii_i82544_writereg;
                 } else if (sc->sc_type >= WM_T_80003) {                  } else if (sc->sc_type >= WM_T_80003) {
                         /* 80003 */                          /* 80003 */
                           sc->sc_phytype = WMPHY_GG82563;
                         mii->mii_readreg = wm_gmii_i80003_readreg;                          mii->mii_readreg = wm_gmii_i80003_readreg;
                         mii->mii_writereg = wm_gmii_i80003_writereg;                          mii->mii_writereg = wm_gmii_i80003_writereg;
                 } else if (sc->sc_type >= WM_T_I210) {                  } else if (sc->sc_type >= WM_T_I210) {
                         /* I210 and I211 */                          /* I210 and I211 */
                           sc->sc_phytype = WMPHY_210;
                         mii->mii_readreg = wm_gmii_gs40g_readreg;                          mii->mii_readreg = wm_gmii_gs40g_readreg;
                         mii->mii_writereg = wm_gmii_gs40g_writereg;                          mii->mii_writereg = wm_gmii_gs40g_writereg;
                 } else if (sc->sc_type >= WM_T_82580) {                  } else if (sc->sc_type >= WM_T_82580) {
Line 8216  wm_gmii_mediainit(struct wm_softc *sc, p
Line 8369  wm_gmii_mediainit(struct wm_softc *sc, p
                         sc->sc_phytype = WMPHY_IGP_3;                          sc->sc_phytype = WMPHY_IGP_3;
   
                 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);                  ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
   
                   printf("XXX OUI = %08x, model = %04x, rev = %04x\n",
                       child->mii_mpd_oui, child->mii_mpd_model, child->mii_mpd_rev);
         }          }
 }  }
   
Line 8231  wm_gmii_mediachange(struct ifnet *ifp)
Line 8387  wm_gmii_mediachange(struct ifnet *ifp)
         struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur;          struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur;
         int rc;          int rc;
   
           DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
         if ((ifp->if_flags & IFF_UP) == 0)          if ((ifp->if_flags & IFF_UP) == 0)
                 return 0;                  return 0;
   
Line 8397  wm_gmii_i82543_writereg(device_t self, i
Line 8555  wm_gmii_i82543_writereg(device_t self, i
 }  }
   
 /*  /*
  * wm_gmii_i82544_readreg:      [mii interface function]   * wm_gmii_mdic_readreg:        [mii interface function]
  *   *
  *      Read a PHY register on the GMII.   *      Read a PHY register on the GMII.
  */   */
 static int  static int
 wm_gmii_i82544_readreg(device_t self, int phy, int reg)  wm_gmii_mdic_readreg(device_t self, int phy, int reg)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         uint32_t mdic = 0;          uint32_t mdic = 0;
Line 8438  wm_gmii_i82544_readreg(device_t self, in
Line 8596  wm_gmii_i82544_readreg(device_t self, in
 }  }
   
 /*  /*
  * wm_gmii_i82544_writereg:     [mii interface function]   * wm_gmii_mdic_writereg:       [mii interface function]
  *   *
  *      Write a PHY register on the GMII.   *      Write a PHY register on the GMII.
  */   */
 static void  static void
 wm_gmii_i82544_writereg(device_t self, int phy, int reg, int val)  wm_gmii_mdic_writereg(device_t self, int phy, int reg, int val)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         uint32_t mdic = 0;          uint32_t mdic = 0;
Line 8468  wm_gmii_i82544_writereg(device_t self, i
Line 8626  wm_gmii_i82544_writereg(device_t self, i
 }  }
   
 /*  /*
    * wm_gmii_i82544_readreg:      [mii interface function]
    *
    *      Read a PHY register on the GMII.
    */
   static int
   wm_gmii_i82544_readreg(device_t self, int phy, int reg)
   {
           struct wm_softc *sc = device_private(self);
           int rv;
   
           if (sc->phy.acquire(sc)) {
                   aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                       __func__);
                   return 0;
           }
           rv = wm_gmii_mdic_readreg(self, phy, reg);
           sc->phy.release(sc);
   
           return rv;
   }
   
   /*
    * wm_gmii_i82544_writereg:     [mii interface function]
    *
    *      Write a PHY register on the GMII.
    */
   static void
   wm_gmii_i82544_writereg(device_t self, int phy, int reg, int val)
   {
           struct wm_softc *sc = device_private(self);
   
           if (sc->phy.acquire(sc)) {
                   aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                       __func__);
           }
           wm_gmii_mdic_writereg(self, phy, reg, val);
           sc->phy.release(sc);
   }
   
   /*
  * wm_gmii_i80003_readreg:      [mii interface function]   * wm_gmii_i80003_readreg:      [mii interface function]
  *   *
  *      Read a PHY register on the kumeran   *      Read a PHY register on the kumeran
Line 8478  static int
Line 8676  static int
 wm_gmii_i80003_readreg(device_t self, int phy, int reg)  wm_gmii_i80003_readreg(device_t self, int phy, int reg)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         int sem;  
         int rv;          int rv;
   
         if (phy != 1) /* only one PHY on kumeran bus */          if (phy != 1) /* only one PHY on kumeran bus */
                 return 0;                  return 0;
   
         sem = swfwphysem[sc->sc_funcid];          if (sc->phy.acquire(sc)) {
         if (wm_get_swfw_semaphore(sc, sem)) {  
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return 0;                  return 0;
         }          }
   
         if ((reg & GG82563_MAX_REG_ADDRESS) < GG82563_MIN_ALT_REG) {          if ((reg & MII_ADDRMASK) < GG82563_MIN_ALT_REG) {
                 wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT,                  wm_gmii_mdic_writereg(self, phy, GG82563_PHY_PAGE_SELECT,
                     reg >> GG82563_PAGE_SHIFT);                      reg >> GG82563_PAGE_SHIFT);
         } else {          } else {
                 wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT_ALT,                  wm_gmii_mdic_writereg(self, phy, GG82563_PHY_PAGE_SELECT_ALT,
                     reg >> GG82563_PAGE_SHIFT);                      reg >> GG82563_PAGE_SHIFT);
         }          }
         /* Wait more 200us for a bug of the ready bit in the MDIC register */          /* Wait more 200us for a bug of the ready bit in the MDIC register */
         delay(200);          delay(200);
         rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS);          rv = wm_gmii_mdic_readreg(self, phy, reg & MII_ADDRMASK);
         delay(200);          delay(200);
           sc->phy.release(sc);
   
         wm_put_swfw_semaphore(sc, sem);  
         return rv;          return rv;
 }  }
   
Line 8518  static void
Line 8714  static void
 wm_gmii_i80003_writereg(device_t self, int phy, int reg, int val)  wm_gmii_i80003_writereg(device_t self, int phy, int reg, int val)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         int sem;  
   
         if (phy != 1) /* only one PHY on kumeran bus */          if (phy != 1) /* only one PHY on kumeran bus */
                 return;                  return;
   
         sem = swfwphysem[sc->sc_funcid];          if (sc->phy.acquire(sc)) {
         if (wm_get_swfw_semaphore(sc, sem)) {  
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return;                  return;
         }          }
   
         if ((reg & GG82563_MAX_REG_ADDRESS) < GG82563_MIN_ALT_REG) {          if ((reg & MII_ADDRMASK) < GG82563_MIN_ALT_REG) {
                 wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT,                  wm_gmii_mdic_writereg(self, phy, GG82563_PHY_PAGE_SELECT,
                     reg >> GG82563_PAGE_SHIFT);                      reg >> GG82563_PAGE_SHIFT);
         } else {          } else {
                 wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT_ALT,                  wm_gmii_mdic_writereg(self, phy, GG82563_PHY_PAGE_SELECT_ALT,
                     reg >> GG82563_PAGE_SHIFT);                      reg >> GG82563_PAGE_SHIFT);
         }          }
         /* Wait more 200us for a bug of the ready bit in the MDIC register */          /* Wait more 200us for a bug of the ready bit in the MDIC register */
         delay(200);          delay(200);
         wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val);          wm_gmii_mdic_writereg(self, phy, reg & MII_ADDRMASK, val);
         delay(200);          delay(200);
   
         wm_put_swfw_semaphore(sc, sem);          sc->phy.release(sc);
 }  }
   
 /*  /*
Line 8556  static int
Line 8750  static int
 wm_gmii_bm_readreg(device_t self, int phy, int reg)  wm_gmii_bm_readreg(device_t self, int phy, int reg)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         int sem;          uint16_t page = reg >> BME1000_PAGE_SHIFT;
           uint16_t val;
         int rv;          int rv;
   
         sem = swfwphysem[sc->sc_funcid];          if (sc->phy.acquire(sc)) {
         if (wm_get_swfw_semaphore(sc, sem)) {  
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return 0;                  return 0;
         }          }
   
           if ((sc->sc_type != WM_T_82574) && (sc->sc_type != WM_T_82583))
                   phy = ((page >= 768) || ((page == 0) && (reg == 25))
                       || (reg == 31)) ? 1 : phy;
           /* Page 800 works differently than the rest so it has its own func */
           if (page == BM_WUC_PAGE) {
                   wm_access_phy_wakeup_reg_bm(self, reg, &val, 1);
                   rv = val;
                   goto release;
           }
   
         if (reg > BME1000_MAX_MULTI_PAGE_REG) {          if (reg > BME1000_MAX_MULTI_PAGE_REG) {
                 if (phy == 1)                  if ((phy == 1) && (sc->sc_type != WM_T_82574)
                         wm_gmii_i82544_writereg(self, phy,                      && (sc->sc_type != WM_T_82583))
                             MII_IGPHY_PAGE_SELECT, reg);                          wm_gmii_mdic_writereg(self, phy,
                               MII_IGPHY_PAGE_SELECT, page << BME1000_PAGE_SHIFT);
                 else                  else
                         wm_gmii_i82544_writereg(self, phy,                          wm_gmii_mdic_writereg(self, phy,
                             GG82563_PHY_PAGE_SELECT,                              BME1000_PHY_PAGE_SELECT, page);
                             reg >> GG82563_PAGE_SHIFT);  
         }          }
   
         rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS);          rv = wm_gmii_mdic_readreg(self, phy, reg & MII_ADDRMASK);
         wm_put_swfw_semaphore(sc, sem);  
   release:
           sc->phy.release(sc);
         return rv;          return rv;
 }  }
   
Line 8592  static void
Line 8798  static void
 wm_gmii_bm_writereg(device_t self, int phy, int reg, int val)  wm_gmii_bm_writereg(device_t self, int phy, int reg, int val)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         int sem;          uint16_t page = reg >> BME1000_PAGE_SHIFT;
   
         sem = swfwphysem[sc->sc_funcid];          if (sc->phy.acquire(sc)) {
         if (wm_get_swfw_semaphore(sc, sem)) {  
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return;                  return;
         }          }
   
           if ((sc->sc_type != WM_T_82574) && (sc->sc_type != WM_T_82583))
                   phy = ((page >= 768) || ((page == 0) && (reg == 25))
                       || (reg == 31)) ? 1 : phy;
           /* Page 800 works differently than the rest so it has its own func */
           if (page == BM_WUC_PAGE) {
                   uint16_t tmp;
   
                   tmp = val;
                   wm_access_phy_wakeup_reg_bm(self, reg, &tmp, 0);
                   goto release;
           }
   
         if (reg > BME1000_MAX_MULTI_PAGE_REG) {          if (reg > BME1000_MAX_MULTI_PAGE_REG) {
                 if (phy == 1)                  if ((phy == 1) && (sc->sc_type != WM_T_82574)
                         wm_gmii_i82544_writereg(self, phy,                      && (sc->sc_type != WM_T_82583))
                             MII_IGPHY_PAGE_SELECT, reg);                          wm_gmii_mdic_writereg(self, phy,
                               MII_IGPHY_PAGE_SELECT, page << BME1000_PAGE_SHIFT);
                 else                  else
                         wm_gmii_i82544_writereg(self, phy,                          wm_gmii_mdic_writereg(self, phy,
                             GG82563_PHY_PAGE_SELECT,                              BME1000_PHY_PAGE_SELECT, page);
                             reg >> GG82563_PAGE_SHIFT);  
         }          }
   
         wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val);          wm_gmii_mdic_writereg(self, phy, reg & MII_ADDRMASK, val);
         wm_put_swfw_semaphore(sc, sem);  
   release:
           sc->phy.release(sc);
 }  }
   
 static void  static void
Line 8622  wm_access_phy_wakeup_reg_bm(device_t sel
Line 8841  wm_access_phy_wakeup_reg_bm(device_t sel
         uint16_t regnum = BM_PHY_REG_NUM(offset);          uint16_t regnum = BM_PHY_REG_NUM(offset);
         uint16_t wuce;          uint16_t wuce;
   
           DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
         /* XXX Gig must be disabled for MDIO accesses to page 800 */          /* XXX Gig must be disabled for MDIO accesses to page 800 */
         if (sc->sc_type == WM_T_PCH) {          if (sc->sc_type == WM_T_PCH) {
                 /* XXX e1000 driver do nothing... why? */                  /* XXX e1000 driver do nothing... why? */
         }          }
   
         /* Set page 769 */          /* Set page 769 */
         wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,          wm_gmii_mdic_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
             BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT);              BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT);
   
         wuce = wm_gmii_i82544_readreg(self, 1, BM_WUC_ENABLE_REG);          wuce = wm_gmii_mdic_readreg(self, 1, BM_WUC_ENABLE_REG);
   
         wuce &= ~BM_WUC_HOST_WU_BIT;          wuce &= ~BM_WUC_HOST_WU_BIT;
         wm_gmii_i82544_writereg(self, 1, BM_WUC_ENABLE_REG,          wm_gmii_mdic_writereg(self, 1, BM_WUC_ENABLE_REG,
             wuce | BM_WUC_ENABLE_BIT);              wuce | BM_WUC_ENABLE_BIT);
   
         /* Select page 800 */          /* Select page 800 */
         wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,          wm_gmii_mdic_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
             BM_WUC_PAGE << BME1000_PAGE_SHIFT);              BM_WUC_PAGE << BME1000_PAGE_SHIFT);
   
         /* Write page 800 */          /* Write page 800 */
         wm_gmii_i82544_writereg(self, 1, BM_WUC_ADDRESS_OPCODE, regnum);          wm_gmii_mdic_writereg(self, 1, BM_WUC_ADDRESS_OPCODE, regnum);
   
         if (rd)          if (rd)
                 *val = wm_gmii_i82544_readreg(self, 1, BM_WUC_DATA_OPCODE);                  *val = wm_gmii_mdic_readreg(self, 1, BM_WUC_DATA_OPCODE);
         else          else
                 wm_gmii_i82544_writereg(self, 1, BM_WUC_DATA_OPCODE, *val);                  wm_gmii_mdic_writereg(self, 1, BM_WUC_DATA_OPCODE, *val);
   
         /* Set page 769 */          /* Set page 769 */
         wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,          wm_gmii_mdic_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
             BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT);              BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT);
   
         wm_gmii_i82544_writereg(self, 1, BM_WUC_ENABLE_REG, wuce);          wm_gmii_mdic_writereg(self, 1, BM_WUC_ENABLE_REG, wuce);
 }  }
   
 /*  /*
Line 8667  static int
Line 8888  static int
 wm_gmii_hv_readreg(device_t self, int phy, int reg)  wm_gmii_hv_readreg(device_t self, int phy, int reg)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         uint16_t page = BM_PHY_REG_PAGE(reg);  
         uint16_t regnum = BM_PHY_REG_NUM(reg);  
         uint16_t val;  
         int rv;          int rv;
   
         if (wm_get_swfwhw_semaphore(sc)) {          DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           if (sc->phy.acquire(sc)) {
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return 0;                  return 0;
         }          }
   
         /* XXX Workaround failure in MDIO access while cable is disconnected */          rv = wm_gmii_hv_readreg_locked(self, phy, reg);
         if (sc->sc_phytype == WMPHY_82577) {          sc->phy.release(sc);
                 /* XXX must write */          return rv;
         }  }
   
   static int
   wm_gmii_hv_readreg_locked(device_t self, int phy, int reg)
   {
           uint16_t page = BM_PHY_REG_PAGE(reg);
           uint16_t regnum = BM_PHY_REG_NUM(reg);
           uint16_t val;
           int rv;
   
           phy = (page >= HV_INTC_FC_PAGE_START) ? 1 : phy;
   
         /* Page 800 works differently than the rest so it has its own func */          /* Page 800 works differently than the rest so it has its own func */
         if (page == BM_WUC_PAGE) {          if (page == BM_WUC_PAGE) {
Line 8699  wm_gmii_hv_readreg(device_t self, int ph
Line 8929  wm_gmii_hv_readreg(device_t self, int ph
         }          }
   
         if (regnum > BME1000_MAX_MULTI_PAGE_REG) {          if (regnum > BME1000_MAX_MULTI_PAGE_REG) {
                 wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,                  wm_gmii_mdic_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
                     page << BME1000_PAGE_SHIFT);                      page << BME1000_PAGE_SHIFT);
         }          }
   
         rv = wm_gmii_i82544_readreg(self, phy, regnum & IGPHY_MAXREGADDR);          rv = wm_gmii_mdic_readreg(self, phy, regnum & MII_ADDRMASK);
         wm_put_swfwhw_semaphore(sc);  
         return rv;          return rv;
 }  }
   
Line 8719  static void
Line 8948  static void
 wm_gmii_hv_writereg(device_t self, int phy, int reg, int val)  wm_gmii_hv_writereg(device_t self, int phy, int reg, int val)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         uint16_t page = BM_PHY_REG_PAGE(reg);  
         uint16_t regnum = BM_PHY_REG_NUM(reg);  
   
         if (wm_get_swfwhw_semaphore(sc)) {          DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
           if (sc->phy.acquire(sc)) {
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return;                  return;
         }          }
   
         /* XXX Workaround failure in MDIO access while cable is disconnected */          wm_gmii_hv_writereg_locked(self, phy, reg, val);
           sc->phy.release(sc);
   }
   
   static void
   wm_gmii_hv_writereg_locked(device_t self, int phy, int reg, int val)
   {
           struct wm_softc *sc = device_private(self);
           uint16_t page = BM_PHY_REG_PAGE(reg);
           uint16_t regnum = BM_PHY_REG_NUM(reg);
   
           phy = (page >= HV_INTC_FC_PAGE_START) ? 1 : phy;
   
         /* Page 800 works differently than the rest so it has its own func */          /* Page 800 works differently than the rest so it has its own func */
         if (page == BM_WUC_PAGE) {          if (page == BM_WUC_PAGE) {
Line 8748  wm_gmii_hv_writereg(device_t self, int p
Line 8989  wm_gmii_hv_writereg(device_t self, int p
                 return;                  return;
         }          }
   
         /*          {
          * XXX Workaround MDIO accesses being disabled after entering IEEE                  /*
          * Power Down (whenever bit 11 of the PHY control register is set)                   * XXX Workaround MDIO accesses being disabled after entering
          */                   * IEEE Power Down (whenever bit 11 of the PHY control
                    * register is set)
                    */
                   if (sc->sc_phytype == WMPHY_82578) {
                           struct mii_softc *child;
   
         if (regnum > BME1000_MAX_MULTI_PAGE_REG) {                          child = LIST_FIRST(&sc->sc_mii.mii_phys);
                 wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,                          if ((child != NULL) && (child->mii_mpd_rev >= 1)
                     page << BME1000_PAGE_SHIFT);                              && (phy == 2) && ((regnum & MII_ADDRMASK) == 0)
                               && ((val & (1 << 11)) != 0)) {
                                   printf("XXX need workaround\n");
                           }
                   }
   
                   if (regnum > BME1000_MAX_MULTI_PAGE_REG) {
                           wm_gmii_mdic_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
                               page << BME1000_PAGE_SHIFT);
                   }
         }          }
   
         wm_gmii_i82544_writereg(self, phy, regnum & IGPHY_MAXREGADDR, val);          wm_gmii_mdic_writereg(self, phy, regnum & MII_ADDRMASK, val);
         wm_put_swfwhw_semaphore(sc);  
 }  }
   
 /*  /*
Line 8773  static int
Line 9026  static int
 wm_gmii_82580_readreg(device_t self, int phy, int reg)  wm_gmii_82580_readreg(device_t self, int phy, int reg)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         int sem;  
         int rv;          int rv;
   
         sem = swfwphysem[sc->sc_funcid];          if (sc->phy.acquire(sc) != 0) {
         if (wm_get_swfw_semaphore(sc, sem)) {  
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return 0;                  return 0;
         }          }
   
         rv = wm_gmii_i82544_readreg(self, phy, reg);          rv = wm_gmii_mdic_readreg(self, phy, reg);
   
         wm_put_swfw_semaphore(sc, sem);          sc->phy.release(sc);
         return rv;          return rv;
 }  }
   
Line 8800  static void
Line 9051  static void
 wm_gmii_82580_writereg(device_t self, int phy, int reg, int val)  wm_gmii_82580_writereg(device_t self, int phy, int reg, int val)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         int sem;  
   
         sem = swfwphysem[sc->sc_funcid];          if (sc->phy.acquire(sc) != 0) {
         if (wm_get_swfw_semaphore(sc, sem)) {  
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return;                  return;
         }          }
   
         wm_gmii_i82544_writereg(self, phy, reg, val);          wm_gmii_mdic_writereg(self, phy, reg, val);
   
         wm_put_swfw_semaphore(sc, sem);          sc->phy.release(sc);
 }  }
   
 /*  /*
Line 8825  static int
Line 9074  static int
 wm_gmii_gs40g_readreg(device_t self, int phy, int reg)  wm_gmii_gs40g_readreg(device_t self, int phy, int reg)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         int sem;  
         int page, offset;          int page, offset;
         int rv;          int rv;
   
         /* Acquire semaphore */          /* Acquire semaphore */
         sem = swfwphysem[sc->sc_funcid];          if (sc->phy.acquire(sc)) {
         if (wm_get_swfw_semaphore(sc, sem)) {  
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return 0;                  return 0;
Line 8839  wm_gmii_gs40g_readreg(device_t self, int
Line 9086  wm_gmii_gs40g_readreg(device_t self, int
   
         /* Page select */          /* Page select */
         page = reg >> GS40G_PAGE_SHIFT;          page = reg >> GS40G_PAGE_SHIFT;
         wm_gmii_i82544_writereg(self, phy, GS40G_PAGE_SELECT, page);          wm_gmii_mdic_writereg(self, phy, GS40G_PAGE_SELECT, page);
   
         /* Read reg */          /* Read reg */
         offset = reg & GS40G_OFFSET_MASK;          offset = reg & GS40G_OFFSET_MASK;
         rv = wm_gmii_i82544_readreg(self, phy, offset);          rv = wm_gmii_mdic_readreg(self, phy, offset);
   
         wm_put_swfw_semaphore(sc, sem);          sc->phy.release(sc);
         return rv;          return rv;
 }  }
   
Line 8860  static void
Line 9107  static void
 wm_gmii_gs40g_writereg(device_t self, int phy, int reg, int val)  wm_gmii_gs40g_writereg(device_t self, int phy, int reg, int val)
 {  {
         struct wm_softc *sc = device_private(self);          struct wm_softc *sc = device_private(self);
         int sem;  
         int page, offset;          int page, offset;
   
         /* Acquire semaphore */          /* Acquire semaphore */
         sem = swfwphysem[sc->sc_funcid];          if (sc->phy.acquire(sc)) {
         if (wm_get_swfw_semaphore(sc, sem)) {  
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return;                  return;
Line 8873  wm_gmii_gs40g_writereg(device_t self, in
Line 9118  wm_gmii_gs40g_writereg(device_t self, in
   
         /* Page select */          /* Page select */
         page = reg >> GS40G_PAGE_SHIFT;          page = reg >> GS40G_PAGE_SHIFT;
         wm_gmii_i82544_writereg(self, phy, GS40G_PAGE_SELECT, page);          wm_gmii_mdic_writereg(self, phy, GS40G_PAGE_SELECT, page);
   
         /* Write reg */          /* Write reg */
         offset = reg & GS40G_OFFSET_MASK;          offset = reg & GS40G_OFFSET_MASK;
         wm_gmii_i82544_writereg(self, phy, offset, val);          wm_gmii_mdic_writereg(self, phy, offset, val);
   
         /* Release semaphore */          /* Release semaphore */
         wm_put_swfw_semaphore(sc, sem);          sc->phy.release(sc);
 }  }
   
 /*  /*
Line 8957  wm_kmrn_readreg(struct wm_softc *sc, int
Line 9202  wm_kmrn_readreg(struct wm_softc *sc, int
 {  {
         int rv;          int rv;
   
         if (sc->sc_flags & WM_F_LOCK_SWFW) {          if (sc->sc_type == WM_T_80003)
                 if (wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM)) {                  rv = wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM);
                         aprint_error_dev(sc->sc_dev,          else
                             "%s: failed to get semaphore\n", __func__);                  rv = sc->phy.acquire(sc);
                         return 0;          if (rv != 0) {
                 }                  aprint_error_dev(sc->sc_dev,
         } else if (sc->sc_flags & WM_F_LOCK_EXTCNF) {                      "%s: failed to get semaphore\n", __func__);
                 if (wm_get_swfwhw_semaphore(sc)) {                  return 0;
                         aprint_error_dev(sc->sc_dev,  
                             "%s: failed to get semaphore\n", __func__);  
                         return 0;  
                 }  
         }          }
   
           rv = wm_kmrn_readreg_locked(sc, reg);
   
           if (sc->sc_type == WM_T_80003)
                   wm_put_swfw_semaphore(sc, SWFW_MAC_CSR_SM);
           else
                   sc->phy.release(sc);
   
           return rv;
   }
   
   static int
   wm_kmrn_readreg_locked(struct wm_softc *sc, int reg)
   {
           int rv;
   
         CSR_WRITE(sc, WMREG_KUMCTRLSTA,          CSR_WRITE(sc, WMREG_KUMCTRLSTA,
             ((reg << KUMCTRLSTA_OFFSET_SHIFT) & KUMCTRLSTA_OFFSET) |              ((reg << KUMCTRLSTA_OFFSET_SHIFT) & KUMCTRLSTA_OFFSET) |
             KUMCTRLSTA_REN);              KUMCTRLSTA_REN);
Line 8979  wm_kmrn_readreg(struct wm_softc *sc, int
Line 9235  wm_kmrn_readreg(struct wm_softc *sc, int
   
         rv = CSR_READ(sc, WMREG_KUMCTRLSTA) & KUMCTRLSTA_MASK;          rv = CSR_READ(sc, WMREG_KUMCTRLSTA) & KUMCTRLSTA_MASK;
   
         if (sc->sc_flags & WM_F_LOCK_SWFW)  
                 wm_put_swfw_semaphore(sc, SWFW_MAC_CSR_SM);  
         else if (sc->sc_flags & WM_F_LOCK_EXTCNF)  
                 wm_put_swfwhw_semaphore(sc);  
   
         return rv;          return rv;
 }  }
   
Line 8995  wm_kmrn_readreg(struct wm_softc *sc, int
Line 9246  wm_kmrn_readreg(struct wm_softc *sc, int
 static void  static void
 wm_kmrn_writereg(struct wm_softc *sc, int reg, int val)  wm_kmrn_writereg(struct wm_softc *sc, int reg, int val)
 {  {
           int rv;
   
         if (sc->sc_flags & WM_F_LOCK_SWFW) {          if (sc->sc_type == WM_T_80003)
                 if (wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM)) {                  rv = wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM);
                         aprint_error_dev(sc->sc_dev,          else
                             "%s: failed to get semaphore\n", __func__);                  rv = sc->phy.acquire(sc);
                         return;          if (rv != 0) {
                 }                  aprint_error_dev(sc->sc_dev,
         } else if (sc->sc_flags & WM_F_LOCK_EXTCNF) {                      "%s: failed to get semaphore\n", __func__);
                 if (wm_get_swfwhw_semaphore(sc)) {                  return;
                         aprint_error_dev(sc->sc_dev,  
                             "%s: failed to get semaphore\n", __func__);  
                         return;  
                 }  
         }          }
   
           wm_kmrn_writereg_locked(sc, reg, val);
   
           if (sc->sc_type == WM_T_80003)
                   wm_put_swfw_semaphore(sc, SWFW_MAC_CSR_SM);
           else
                   sc->phy.release(sc);
   }
   
   static void
   wm_kmrn_writereg_locked(struct wm_softc *sc, int reg, int val)
   {
   
         CSR_WRITE(sc, WMREG_KUMCTRLSTA,          CSR_WRITE(sc, WMREG_KUMCTRLSTA,
             ((reg << KUMCTRLSTA_OFFSET_SHIFT) & KUMCTRLSTA_OFFSET) |              ((reg << KUMCTRLSTA_OFFSET_SHIFT) & KUMCTRLSTA_OFFSET) |
             (val & KUMCTRLSTA_MASK));              (val & KUMCTRLSTA_MASK));
   
         if (sc->sc_flags & WM_F_LOCK_SWFW)  
                 wm_put_swfw_semaphore(sc, SWFW_MAC_CSR_SM);  
         else if (sc->sc_flags & WM_F_LOCK_EXTCNF)  
                 wm_put_swfwhw_semaphore(sc);  
 }  }
   
 /* SGMII related */  /* SGMII related */
Line 9069  wm_sgmii_readreg(device_t self, int phy,
Line 9324  wm_sgmii_readreg(device_t self, int phy,
         uint32_t i2ccmd;          uint32_t i2ccmd;
         int i, rv;          int i, rv;
   
         if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) {          if (sc->phy.acquire(sc)) {
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return 0;                  return 0;
Line 9094  wm_sgmii_readreg(device_t self, int phy,
Line 9349  wm_sgmii_readreg(device_t self, int phy,
   
         rv = ((i2ccmd >> 8) & 0x00ff) | ((i2ccmd << 8) & 0xff00);          rv = ((i2ccmd >> 8) & 0x00ff) | ((i2ccmd << 8) & 0xff00);
   
         wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);          sc->phy.release(sc);
         return rv;          return rv;
 }  }
   
Line 9113  wm_sgmii_writereg(device_t self, int phy
Line 9368  wm_sgmii_writereg(device_t self, int phy
         int i;          int i;
         int val_swapped;          int val_swapped;
   
         if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) {          if (sc->phy.acquire(sc) != 0) {
                 aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",                  aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                     __func__);                      __func__);
                 return;                  return;
Line 9137  wm_sgmii_writereg(device_t self, int phy
Line 9392  wm_sgmii_writereg(device_t self, int phy
         if ((i2ccmd & I2CCMD_ERROR) != 0)          if ((i2ccmd & I2CCMD_ERROR) != 0)
                 aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n");                  aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n");
   
         wm_put_swfw_semaphore(sc, SWFW_PHY0_SM);          sc->phy.release(sc);
 }  }
   
 /* TBI related */  /* TBI related */
Line 9860  wm_nvm_read_uwire(struct wm_softc *sc, i
Line 10115  wm_nvm_read_uwire(struct wm_softc *sc, i
         uint32_t reg, val;          uint32_t reg, val;
         int i;          int i;
   
           DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         for (i = 0; i < wordcnt; i++) {          for (i = 0; i < wordcnt; i++) {
                 /* Clear SK and DI. */                  /* Clear SK and DI. */
                 reg = CSR_READ(sc, WMREG_EECD) & ~(EECD_SK | EECD_DI);                  reg = CSR_READ(sc, WMREG_EECD) & ~(EECD_SK | EECD_DI);
Line 9985  wm_nvm_ready_spi(struct wm_softc *sc)
Line 10243  wm_nvm_ready_spi(struct wm_softc *sc)
         uint32_t val;          uint32_t val;
         int usec;          int usec;
   
           DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         for (usec = 0; usec < SPI_MAX_RETRIES; delay(5), usec += 5) {          for (usec = 0; usec < SPI_MAX_RETRIES; delay(5), usec += 5) {
                 wm_eeprom_sendbits(sc, SPI_OPC_RDSR, 8);                  wm_eeprom_sendbits(sc, SPI_OPC_RDSR, 8);
                 wm_eeprom_recvbits(sc, &val, 8);                  wm_eeprom_recvbits(sc, &val, 8);
Line 10010  wm_nvm_read_spi(struct wm_softc *sc, int
Line 10271  wm_nvm_read_spi(struct wm_softc *sc, int
         int i;          int i;
         uint8_t opc;          uint8_t opc;
   
           DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         /* Clear SK and CS. */          /* Clear SK and CS. */
         reg = CSR_READ(sc, WMREG_EECD) & ~(EECD_SK | EECD_CS);          reg = CSR_READ(sc, WMREG_EECD) & ~(EECD_SK | EECD_CS);
         CSR_WRITE(sc, WMREG_EECD, reg);          CSR_WRITE(sc, WMREG_EECD, reg);
Line 10077  wm_nvm_read_eerd(struct wm_softc *sc, in
Line 10341  wm_nvm_read_eerd(struct wm_softc *sc, in
         int i, eerd = 0;          int i, eerd = 0;
         int error = 0;          int error = 0;
   
           DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         for (i = 0; i < wordcnt; i++) {          for (i = 0; i < wordcnt; i++) {
                 eerd = ((offset + i) << EERD_ADDR_SHIFT) | EERD_START;                  eerd = ((offset + i) << EERD_ADDR_SHIFT) | EERD_START;
   
Line 10110  wm_nvm_valid_bank_detect_ich8lan(struct 
Line 10377  wm_nvm_valid_bank_detect_ich8lan(struct 
                 *bank = CSR_READ(sc, WMREG_CTRL_EXT) & CTRL_EXT_NVMVS;                  *bank = CSR_READ(sc, WMREG_CTRL_EXT) & CTRL_EXT_NVMVS;
                 if ((*bank == 0) || (*bank == 1)) {                  if ((*bank == 0) || (*bank == 1)) {
                         aprint_error_dev(sc->sc_dev,                          aprint_error_dev(sc->sc_dev,
                                          "%s: no valid NVM bank present\n",                              "%s: no valid NVM bank present (%u)\n", __func__,
                                 __func__);                                  *bank);
                         return -1;                          return -1;
                 } else {                  } else {
                         *bank = *bank - 2;                          *bank = *bank - 2;
Line 10425  wm_nvm_read_ich8(struct wm_softc *sc, in
Line 10692  wm_nvm_read_ich8(struct wm_softc *sc, in
         uint16_t word = 0;          uint16_t word = 0;
         uint16_t i = 0;          uint16_t i = 0;
   
           DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         /*          /*
          * We need to know which is the valid flash bank.  In the event           * We need to know which is the valid flash bank.  In the event
          * that we didn't allocate eeprom_shadow_ram, we may not be           * that we didn't allocate eeprom_shadow_ram, we may not be
Line 10486  wm_nvm_read_spt(struct wm_softc *sc, int
Line 10756  wm_nvm_read_spt(struct wm_softc *sc, int
         uint32_t dword = 0;          uint32_t dword = 0;
         uint16_t i = 0;          uint16_t i = 0;
   
           DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         /*          /*
          * We need to know which is the valid flash bank.  In the event           * We need to know which is the valid flash bank.  In the event
          * that we didn't allocate eeprom_shadow_ram, we may not be           * that we didn't allocate eeprom_shadow_ram, we may not be
Line 10543  wm_nvm_read_word_invm(struct wm_softc *s
Line 10816  wm_nvm_read_word_invm(struct wm_softc *s
         uint16_t i;          uint16_t i;
         uint8_t record_type, word_address;          uint8_t record_type, word_address;
   
           DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         for (i = 0; i < INVM_SIZE; i++) {          for (i = 0; i < INVM_SIZE; i++) {
                 invm_dword = CSR_READ(sc, WM_INVM_DATA_REG(i));                  invm_dword = CSR_READ(sc, WM_INVM_DATA_REG(i));
                 /* Get record type */                  /* Get record type */
Line 10571  wm_nvm_read_invm(struct wm_softc *sc, in
Line 10847  wm_nvm_read_invm(struct wm_softc *sc, in
 {  {
         int rv = 0;          int rv = 0;
         int i;          int i;
   
           DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         for (i = 0; i < words; i++) {          for (i = 0; i < words; i++) {
                 switch (offset + i) {                  switch (offset + i) {
Line 10643  wm_nvm_acquire(struct wm_softc *sc)
Line 10922  wm_nvm_acquire(struct wm_softc *sc)
         int x;          int x;
         int ret = 0;          int ret = 0;
   
         /* always success */          DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
         if ((sc->sc_flags & WM_F_EEPROM_FLASH) != 0)                  device_xname(sc->sc_dev), __func__));
                 return 0;  
   
         if (sc->sc_flags & WM_F_LOCK_EXTCNF) {          if (sc->sc_type >= WM_T_ICH8) {
                   ret = wm_get_nvm_ich8lan(sc);
           } else if (sc->sc_flags & WM_F_LOCK_EXTCNF) {
                 ret = wm_get_swfwhw_semaphore(sc);                  ret = wm_get_swfwhw_semaphore(sc);
         } else if (sc->sc_flags & WM_F_LOCK_SWFW) {          } else if (sc->sc_flags & WM_F_LOCK_SWFW) {
                 /* This will also do wm_get_swsm_semaphore() if needed */                  /* This will also do wm_get_swsm_semaphore() if needed */
Line 10704  wm_nvm_release(struct wm_softc *sc)
Line 10984  wm_nvm_release(struct wm_softc *sc)
 {  {
         uint32_t reg;          uint32_t reg;
   
         /* always success */          DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
         if ((sc->sc_flags & WM_F_EEPROM_FLASH) != 0)                  device_xname(sc->sc_dev), __func__));
                 return;  
   
         if (sc->sc_flags & WM_F_LOCK_EECD) {          if (sc->sc_flags & WM_F_LOCK_EECD) {
                 reg = CSR_READ(sc, WMREG_EECD);                  reg = CSR_READ(sc, WMREG_EECD);
Line 10714  wm_nvm_release(struct wm_softc *sc)
Line 10993  wm_nvm_release(struct wm_softc *sc)
                 CSR_WRITE(sc, WMREG_EECD, reg);                  CSR_WRITE(sc, WMREG_EECD, reg);
         }          }
   
         if (sc->sc_flags & WM_F_LOCK_EXTCNF)          if (sc->sc_type >= WM_T_ICH8) {
                   wm_put_nvm_ich8lan(sc);
           } else if (sc->sc_flags & WM_F_LOCK_EXTCNF)
                 wm_put_swfwhw_semaphore(sc);                  wm_put_swfwhw_semaphore(sc);
         if (sc->sc_flags & WM_F_LOCK_SWFW)          if (sc->sc_flags & WM_F_LOCK_SWFW)
                 wm_put_swfw_semaphore(sc, SWFW_EEP_SM);                  wm_put_swfw_semaphore(sc, SWFW_EEP_SM);
Line 10964  wm_nvm_read(struct wm_softc *sc, int wor
Line 11245  wm_nvm_read(struct wm_softc *sc, int wor
 {  {
         int rv;          int rv;
   
           DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         if (sc->sc_flags & WM_F_EEPROM_INVALID)          if (sc->sc_flags & WM_F_EEPROM_INVALID)
                 return 1;                  return 1;
   
Line 10995  wm_nvm_read(struct wm_softc *sc, int wor
Line 11279  wm_nvm_read(struct wm_softc *sc, int wor
  */   */
   
 static int  static int
   wm_get_null(struct wm_softc *sc)
   {
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           return 0;
   }
   
   static void
   wm_put_null(struct wm_softc *sc)
   {
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           return;
   }
   
   /*
    * Get hardware semaphore.
    * Same as e1000_get_hw_semaphore_generic()
    */
   static int
 wm_get_swsm_semaphore(struct wm_softc *sc)  wm_get_swsm_semaphore(struct wm_softc *sc)
 {  {
         int32_t timeout;          int32_t timeout;
         uint32_t swsm;          uint32_t swsm;
   
         if (sc->sc_flags & WM_F_LOCK_SWSM) {          DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                 /* Get the SW semaphore. */                  device_xname(sc->sc_dev), __func__));
                 timeout = sc->sc_nvm_wordsize + 1;          KASSERT(sc->sc_nvm_wordsize > 0);
                 while (timeout) {  
                         swsm = CSR_READ(sc, WMREG_SWSM);  
   
                         if ((swsm & SWSM_SMBI) == 0)          /* Get the SW semaphore. */
                                 break;          timeout = sc->sc_nvm_wordsize + 1;
           while (timeout) {
                   swsm = CSR_READ(sc, WMREG_SWSM);
   
                         delay(50);                  if ((swsm & SWSM_SMBI) == 0)
                         timeout--;                          break;
                 }  
   
                 if (timeout == 0) {                  delay(50);
                         aprint_error_dev(sc->sc_dev,                  timeout--;
                             "could not acquire SWSM SMBI\n");          }
                         return 1;  
                 }          if (timeout == 0) {
                   aprint_error_dev(sc->sc_dev,
                       "could not acquire SWSM SMBI\n");
                   return 1;
         }          }
   
         /* Get the FW semaphore. */          /* Get the FW semaphore. */
Line 11045  wm_get_swsm_semaphore(struct wm_softc *s
Line 11353  wm_get_swsm_semaphore(struct wm_softc *s
         return 0;          return 0;
 }  }
   
   /*
    * Put hardware semaphore.
    * Same as e1000_put_hw_semaphore_generic()
    */
 static void  static void
 wm_put_swsm_semaphore(struct wm_softc *sc)  wm_put_swsm_semaphore(struct wm_softc *sc)
 {  {
         uint32_t swsm;          uint32_t swsm;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         swsm = CSR_READ(sc, WMREG_SWSM);          swsm = CSR_READ(sc, WMREG_SWSM);
         swsm &= ~(SWSM_SMBI | SWSM_SWESMBI);          swsm &= ~(SWSM_SMBI | SWSM_SWESMBI);
         CSR_WRITE(sc, WMREG_SWSM, swsm);          CSR_WRITE(sc, WMREG_SWSM, swsm);
 }  }
   
   /*
    * Get SW/FW semaphore.
    * Same as e1000_acquire_swfw_sync_82575().
    */
 static int  static int
 wm_get_swfw_semaphore(struct wm_softc *sc, uint16_t mask)  wm_get_swfw_semaphore(struct wm_softc *sc, uint16_t mask)
 {  {
Line 11063  wm_get_swfw_semaphore(struct wm_softc *s
Line 11382  wm_get_swfw_semaphore(struct wm_softc *s
         uint32_t fwmask = mask << SWFW_FIRM_SHIFT;          uint32_t fwmask = mask << SWFW_FIRM_SHIFT;
         int timeout = 200;          int timeout = 200;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           KASSERT((sc->sc_flags & WM_F_LOCK_SWSM) != 0);
   
         for (timeout = 0; timeout < 200; timeout++) {          for (timeout = 0; timeout < 200; timeout++) {
                 if (sc->sc_flags & WM_F_LOCK_SWSM) {                  if (sc->sc_flags & WM_F_LOCK_SWSM) {
                         if (wm_get_swsm_semaphore(sc)) {                          if (wm_get_swsm_semaphore(sc)) {
Line 11094  wm_put_swfw_semaphore(struct wm_softc *s
Line 11417  wm_put_swfw_semaphore(struct wm_softc *s
 {  {
         uint32_t swfw_sync;          uint32_t swfw_sync;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           KASSERT((sc->sc_flags & WM_F_LOCK_SWSM) != 0);
   
         if (sc->sc_flags & WM_F_LOCK_SWSM) {          if (sc->sc_flags & WM_F_LOCK_SWSM) {
                 while (wm_get_swsm_semaphore(sc) != 0)                  while (wm_get_swsm_semaphore(sc) != 0)
                         continue;                          continue;
Line 11106  wm_put_swfw_semaphore(struct wm_softc *s
Line 11433  wm_put_swfw_semaphore(struct wm_softc *s
 }  }
   
 static int  static int
   wm_get_phy_82575(struct wm_softc *sc)
   {
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           return wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
   }
   
   static void
   wm_put_phy_82575(struct wm_softc *sc)
   {
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           return wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
   }
   
   static int
 wm_get_swfwhw_semaphore(struct wm_softc *sc)  wm_get_swfwhw_semaphore(struct wm_softc *sc)
 {  {
         uint32_t ext_ctrl;          uint32_t ext_ctrl;
         int timeout = 200;          int timeout = 200;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
           mutex_enter(sc->sc_ich_phymtx); /* Use PHY mtx for both PHY and NVM */
         for (timeout = 0; timeout < 200; timeout++) {          for (timeout = 0; timeout < 200; timeout++) {
                 ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR);                  ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR);
                 ext_ctrl |= EXTCNFCTR_MDIO_SW_OWNERSHIP;                  ext_ctrl |= EXTCNFCTR_MDIO_SW_OWNERSHIP;
Line 11123  wm_get_swfwhw_semaphore(struct wm_softc 
Line 11472  wm_get_swfwhw_semaphore(struct wm_softc 
         }          }
         printf("%s: failed to get swfwhw semaphore ext_ctrl 0x%x\n",          printf("%s: failed to get swfwhw semaphore ext_ctrl 0x%x\n",
             device_xname(sc->sc_dev), ext_ctrl);              device_xname(sc->sc_dev), ext_ctrl);
           mutex_exit(sc->sc_ich_phymtx); /* Use PHY mtx for both PHY and NVM */
         return 1;          return 1;
 }  }
   
Line 11131  wm_put_swfwhw_semaphore(struct wm_softc 
Line 11481  wm_put_swfwhw_semaphore(struct wm_softc 
 {  {
         uint32_t ext_ctrl;          uint32_t ext_ctrl;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR);          ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR);
         ext_ctrl &= ~EXTCNFCTR_MDIO_SW_OWNERSHIP;          ext_ctrl &= ~EXTCNFCTR_MDIO_SW_OWNERSHIP;
         CSR_WRITE(sc, WMREG_EXTCNFCTR, ext_ctrl);          CSR_WRITE(sc, WMREG_EXTCNFCTR, ext_ctrl);
   
           mutex_exit(sc->sc_ich_phymtx); /* Use PHY mtx for both PHY and NVM */
   }
   
   static int
   wm_get_swflag_ich8lan(struct wm_softc *sc)
   {
           uint32_t ext_ctrl;
           int timeout;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           mutex_enter(sc->sc_ich_phymtx);
           for (timeout = 0; timeout < WM_PHY_CFG_TIMEOUT; timeout++) {
                   ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR);
                   if ((ext_ctrl & EXTCNFCTR_MDIO_SW_OWNERSHIP) == 0)
                           break;
                   delay(1000);
           }
           if (timeout >= WM_PHY_CFG_TIMEOUT) {
                   printf("%s: SW has already locked the resource\n",
                       device_xname(sc->sc_dev));
                   goto out;
           }
   
           ext_ctrl |= EXTCNFCTR_MDIO_SW_OWNERSHIP;
           CSR_WRITE(sc, WMREG_EXTCNFCTR, ext_ctrl);
           for (timeout = 0; timeout < 1000; timeout++) {
                   ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR);
                   if (ext_ctrl & EXTCNFCTR_MDIO_SW_OWNERSHIP)
                           break;
                   delay(1000);
           }
           if (timeout >= 1000) {
                   printf("%s: failed to acquire semaphore\n",
                       device_xname(sc->sc_dev));
                   ext_ctrl &= ~EXTCNFCTR_MDIO_SW_OWNERSHIP;
                   CSR_WRITE(sc, WMREG_EXTCNFCTR, ext_ctrl);
                   goto out;
           }
           return 0;
   
   out:
           mutex_exit(sc->sc_ich_phymtx);
           return 1;
   }
   
   static void
   wm_put_swflag_ich8lan(struct wm_softc *sc)
   {
           uint32_t ext_ctrl;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR);
           if (ext_ctrl & EXTCNFCTR_MDIO_SW_OWNERSHIP) {
                   ext_ctrl &= ~EXTCNFCTR_MDIO_SW_OWNERSHIP;
                   CSR_WRITE(sc, WMREG_EXTCNFCTR, ext_ctrl);
           } else {
                   printf("%s: Semaphore unexpectedly released\n",
                       device_xname(sc->sc_dev));
           }
   
           mutex_exit(sc->sc_ich_phymtx);
   }
   
   static int
   wm_get_nvm_ich8lan(struct wm_softc *sc)
   {
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           mutex_enter(sc->sc_ich_nvmmtx);
   
           return 0;
   }
   
   static void
   wm_put_nvm_ich8lan(struct wm_softc *sc)
   {
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           mutex_exit(sc->sc_ich_nvmmtx);
 }  }
   
 static int  static int
Line 11142  wm_get_hw_semaphore_82573(struct wm_soft
Line 11579  wm_get_hw_semaphore_82573(struct wm_soft
         int i = 0;          int i = 0;
         uint32_t reg;          uint32_t reg;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         reg = CSR_READ(sc, WMREG_EXTCNFCTR);          reg = CSR_READ(sc, WMREG_EXTCNFCTR);
         do {          do {
                 CSR_WRITE(sc, WMREG_EXTCNFCTR,                  CSR_WRITE(sc, WMREG_EXTCNFCTR,
Line 11168  wm_put_hw_semaphore_82573(struct wm_soft
Line 11608  wm_put_hw_semaphore_82573(struct wm_soft
 {  {
         uint32_t reg;          uint32_t reg;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         reg = CSR_READ(sc, WMREG_EXTCNFCTR);          reg = CSR_READ(sc, WMREG_EXTCNFCTR);
         reg &= ~EXTCNFCTR_MDIO_SW_OWNERSHIP;          reg &= ~EXTCNFCTR_MDIO_SW_OWNERSHIP;
         CSR_WRITE(sc, WMREG_EXTCNFCTR, reg);          CSR_WRITE(sc, WMREG_EXTCNFCTR, reg);
Line 11300  wm_phy_resetisblocked(struct wm_softc *s
Line 11743  wm_phy_resetisblocked(struct wm_softc *s
         uint32_t reg;          uint32_t reg;
         int i = 0;          int i = 0;
   
           DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         switch (sc->sc_type) {          switch (sc->sc_type) {
         case WM_T_ICH8:          case WM_T_ICH8:
         case WM_T_ICH9:          case WM_T_ICH9:
Line 11316  wm_phy_resetisblocked(struct wm_softc *s
Line 11762  wm_phy_resetisblocked(struct wm_softc *s
                                 continue;                                  continue;
                         }                          }
                         blocked = false;                          blocked = false;
                 } while (blocked && (i++ < 10));                  } while (blocked && (i++ < 30));
                 return blocked;                  return blocked;
                 break;                  break;
         case WM_T_82571:          case WM_T_82571:
Line 11344  wm_get_hw_control(struct wm_softc *sc)
Line 11790  wm_get_hw_control(struct wm_softc *sc)
 {  {
         uint32_t reg;          uint32_t reg;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         switch (sc->sc_type) {          switch (sc->sc_type) {
         case WM_T_82573:          case WM_T_82573:
                 reg = CSR_READ(sc, WMREG_SWSM);                  reg = CSR_READ(sc, WMREG_SWSM);
Line 11374  wm_release_hw_control(struct wm_softc *s
Line 11823  wm_release_hw_control(struct wm_softc *s
 {  {
         uint32_t reg;          uint32_t reg;
   
           DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         if ((sc->sc_flags & WM_F_HAS_MANAGE) == 0)          if ((sc->sc_flags & WM_F_HAS_MANAGE) == 0)
                 return;                  return;
   
         if (sc->sc_type == WM_T_82573) {          if (sc->sc_type == WM_T_82573) {
                 reg = CSR_READ(sc, WMREG_SWSM);                  reg = CSR_READ(sc, WMREG_SWSM);
                 reg &= ~SWSM_DRV_LOAD;  
                 CSR_WRITE(sc, WMREG_SWSM, reg & ~SWSM_DRV_LOAD);                  CSR_WRITE(sc, WMREG_SWSM, reg & ~SWSM_DRV_LOAD);
         } else {          } else {
                 reg = CSR_READ(sc, WMREG_CTRL_EXT);                  reg = CSR_READ(sc, WMREG_CTRL_EXT);
Line 11392  wm_gate_hw_phy_config_ich8lan(struct wm_
Line 11843  wm_gate_hw_phy_config_ich8lan(struct wm_
 {  {
         uint32_t reg;          uint32_t reg;
   
           DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         if (sc->sc_type < WM_T_PCH2)          if (sc->sc_type < WM_T_PCH2)
                 return;                  return;
   
Line 11410  wm_smbustopci(struct wm_softc *sc)
Line 11864  wm_smbustopci(struct wm_softc *sc)
 {  {
         uint32_t fwsm, reg;          uint32_t fwsm, reg;
   
           DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         /* Gate automatic PHY configuration by hardware on non-managed 82579 */          /* Gate automatic PHY configuration by hardware on non-managed 82579 */
         wm_gate_hw_phy_config_ich8lan(sc, true);          wm_gate_hw_phy_config_ich8lan(sc, true);
   
         /* Acquire semaphore */          /* Acquire PHY semaphore */
         wm_get_swfwhw_semaphore(sc);          sc->phy.acquire(sc);
   
         fwsm = CSR_READ(sc, WMREG_FWSM);          fwsm = CSR_READ(sc, WMREG_FWSM);
         if (((fwsm & FWSM_FW_VALID) == 0)          if (((fwsm & FWSM_FW_VALID) == 0)
Line 11432  wm_smbustopci(struct wm_softc *sc)
Line 11889  wm_smbustopci(struct wm_softc *sc)
                 sc->sc_ctrl &= ~CTRL_LANPHYPC_VALUE;                  sc->sc_ctrl &= ~CTRL_LANPHYPC_VALUE;
                 CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);                  CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
                 CSR_WRITE_FLUSH(sc);                  CSR_WRITE_FLUSH(sc);
                 delay(10);                  delay(1000);
                 sc->sc_ctrl &= ~CTRL_LANPHYPC_OVERRIDE;                  sc->sc_ctrl &= ~CTRL_LANPHYPC_OVERRIDE;
                 CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);                  CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
                 CSR_WRITE_FLUSH(sc);                  CSR_WRITE_FLUSH(sc);
Line 11446  wm_smbustopci(struct wm_softc *sc)
Line 11903  wm_smbustopci(struct wm_softc *sc)
         }          }
   
         /* Release semaphore */          /* Release semaphore */
         wm_put_swfwhw_semaphore(sc);          sc->phy.release(sc);
   
         /*          /*
          * Ungate automatic PHY configuration by hardware on non-managed 82579           * Ungate automatic PHY configuration by hardware on non-managed 82579
Line 11622  wm_enable_wakeup(struct wm_softc *sc)
Line 12079  wm_enable_wakeup(struct wm_softc *sc)
         uint32_t reg, pmreg;          uint32_t reg, pmreg;
         pcireg_t pmode;          pcireg_t pmode;
   
           DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_PWRMGMT,          if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_PWRMGMT,
                 &pmreg, NULL) == 0)                  &pmreg, NULL) == 0)
                 return;                  return;
Line 11709  wm_lplu_d0_disable(struct wm_softc *sc)
Line 12169  wm_lplu_d0_disable(struct wm_softc *sc)
 {  {
         uint32_t reg;          uint32_t reg;
   
           DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         reg = CSR_READ(sc, WMREG_PHY_CTRL);          reg = CSR_READ(sc, WMREG_PHY_CTRL);
         reg &= ~(PHY_CTRL_GBE_DIS | PHY_CTRL_D0A_LPLU);          reg &= ~(PHY_CTRL_GBE_DIS | PHY_CTRL_D0A_LPLU);
         CSR_WRITE(sc, WMREG_PHY_CTRL, reg);          CSR_WRITE(sc, WMREG_PHY_CTRL, reg);
Line 11719  wm_lplu_d0_disable_pch(struct wm_softc *
Line 12182  wm_lplu_d0_disable_pch(struct wm_softc *
 {  {
         uint32_t reg;          uint32_t reg;
   
           DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
         reg = wm_gmii_hv_readreg(sc->sc_dev, 1, HV_OEM_BITS);          reg = wm_gmii_hv_readreg(sc->sc_dev, 1, HV_OEM_BITS);
         reg &= ~(HV_OEM_BITS_A1KDIS | HV_OEM_BITS_LPLU);          reg &= ~(HV_OEM_BITS_A1KDIS | HV_OEM_BITS_LPLU);
         reg |= HV_OEM_BITS_ANEGNOW;          reg |= HV_OEM_BITS_ANEGNOW;
Line 11828  wm_gig_downshift_workaround_ich8lan(stru
Line 12294  wm_gig_downshift_workaround_ich8lan(stru
 static void  static void
 wm_hv_phy_workaround_ich8lan(struct wm_softc *sc)  wm_hv_phy_workaround_ich8lan(struct wm_softc *sc)
 {  {
   
           DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           KASSERT(sc->sc_type == WM_T_PCH);
   
         if (sc->sc_phytype == WMPHY_82577)          if (sc->sc_phytype == WMPHY_82577)
                 wm_set_mdio_slow_mode_hv(sc);                  wm_set_mdio_slow_mode_hv(sc);
   
Line 11837  wm_hv_phy_workaround_ich8lan(struct wm_s
Line 12308  wm_hv_phy_workaround_ich8lan(struct wm_s
   
         /* 82578 */          /* 82578 */
         if (sc->sc_phytype == WMPHY_82578) {          if (sc->sc_phytype == WMPHY_82578) {
                 /* PCH rev. < 3 */                  struct mii_softc *child;
                 if (sc->sc_rev < 3) {  
                         /* XXX 6 bit shift? Why? Is it page2? */  
                         wm_gmii_hv_writereg(sc->sc_dev, 1, ((1 << 6) | 0x29),  
                             0x66c0);  
                         wm_gmii_hv_writereg(sc->sc_dev, 1, ((1 << 6) | 0x1e),  
                             0xffff);  
                 }  
   
                 /* XXX phy rev. < 2 */                  /*
                    * Return registers to default by doing a soft reset then
                    * writing 0x3140 to the control register
                    * 0x3140 == BMCR_SPEED0 | BMCR_AUTOEN | BMCR_FDX | BMCR_SPEED1
                    */
                   child = LIST_FIRST(&sc->sc_mii.mii_phys);
                   if ((child != NULL) && (child->mii_mpd_rev < 2)) {
                           PHY_RESET(child);
                           sc->sc_mii.mii_writereg(sc->sc_dev, 2, MII_BMCR,
                               0x3140);
                   }
         }          }
   
         /* Select page 0 */          /* Select page 0 */
           sc->phy.acquire(sc);
         /* XXX acquire semaphore */          wm_gmii_mdic_writereg(sc->sc_dev, 1, MII_IGPHY_PAGE_SELECT, 0);
         wm_gmii_i82544_writereg(sc->sc_dev, 1, MII_IGPHY_PAGE_SELECT, 0);          sc->phy.release(sc);
         /* XXX release semaphore */  
   
         /*          /*
          * Configure the K1 Si workaround during phy reset assuming there is           * Configure the K1 Si workaround during phy reset assuming there is
Line 11866  static void
Line 12339  static void
 wm_lv_phy_workaround_ich8lan(struct wm_softc *sc)  wm_lv_phy_workaround_ich8lan(struct wm_softc *sc)
 {  {
   
           DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
           KASSERT(sc->sc_type == WM_T_PCH2);
   
         wm_set_mdio_slow_mode_hv(sc);          wm_set_mdio_slow_mode_hv(sc);
 }  }
   
 static void  static int
 wm_k1_gig_workaround_hv(struct wm_softc *sc, int link)  wm_k1_gig_workaround_hv(struct wm_softc *sc, int link)
 {  {
         int k1_enable = sc->sc_nvm_k1_enabled;          int k1_enable = sc->sc_nvm_k1_enabled;
   
         /* XXX acquire semaphore */          DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                   device_xname(sc->sc_dev), __func__));
   
           if (sc->phy.acquire(sc) != 0)
                   return -1;
   
         if (link) {          if (link) {
                 k1_enable = 0;                  k1_enable = 0;
   
                 /* Link stall fix for link up */                  /* Link stall fix for link up */
                 wm_gmii_hv_writereg(sc->sc_dev, 1, IGP3_KMRN_DIAG, 0x0100);                  wm_gmii_hv_writereg_locked(sc->sc_dev, 1, IGP3_KMRN_DIAG, 0x0100);
         } else {          } else {
                 /* Link stall fix for link down */                  /* Link stall fix for link down */
                 wm_gmii_hv_writereg(sc->sc_dev, 1, IGP3_KMRN_DIAG, 0x4100);                  wm_gmii_hv_writereg_locked(sc->sc_dev, 1, IGP3_KMRN_DIAG, 0x4100);
         }          }
   
         wm_configure_k1_ich8lan(sc, k1_enable);          wm_configure_k1_ich8lan(sc, k1_enable);
           sc->phy.release(sc);
   
         /* XXX release semaphore */          return 0;
 }  }
   
 static void  static void
Line 11907  wm_configure_k1_ich8lan(struct wm_softc 
Line 12389  wm_configure_k1_ich8lan(struct wm_softc 
         uint32_t ctrl, ctrl_ext, tmp;          uint32_t ctrl, ctrl_ext, tmp;
         uint16_t kmrn_reg;          uint16_t kmrn_reg;
   
         kmrn_reg = wm_kmrn_readreg(sc, KUMCTRLSTA_OFFSET_K1_CONFIG);          kmrn_reg = wm_kmrn_readreg_locked(sc, KUMCTRLSTA_OFFSET_K1_CONFIG);
   
         if (k1_enable)          if (k1_enable)
                 kmrn_reg |= KUMCTRLSTA_K1_ENABLE;                  kmrn_reg |= KUMCTRLSTA_K1_ENABLE;
         else          else
                 kmrn_reg &= ~KUMCTRLSTA_K1_ENABLE;                  kmrn_reg &= ~KUMCTRLSTA_K1_ENABLE;
   
         wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_K1_CONFIG, kmrn_reg);          wm_kmrn_writereg_locked(sc, KUMCTRLSTA_OFFSET_K1_CONFIG, kmrn_reg);
   
         delay(20);          delay(20);
   

Legend:
Removed from v.1.416  
changed lines
  Added in v.1.416.2.1

CVSweb <webmaster@jp.NetBSD.org>