e1000: update base driver
authorIntel <intel.com>
Wed, 19 Dec 2012 23:00:00 +0000 (00:00 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Thu, 25 Jul 2013 13:23:28 +0000 (15:23 +0200)
Signed-off-by: Intel
22 files changed:
lib/librte_eal/common/include/rte_pci_dev_ids.h
lib/librte_pmd_e1000/e1000/README
lib/librte_pmd_e1000/e1000/e1000_82575.c
lib/librte_pmd_e1000/e1000/e1000_82575.h
lib/librte_pmd_e1000/e1000/e1000_api.c
lib/librte_pmd_e1000/e1000/e1000_api.h
lib/librte_pmd_e1000/e1000/e1000_defines.h
lib/librte_pmd_e1000/e1000/e1000_hw.h
lib/librte_pmd_e1000/e1000/e1000_mac.c
lib/librte_pmd_e1000/e1000/e1000_mac.h
lib/librte_pmd_e1000/e1000/e1000_manage.c
lib/librte_pmd_e1000/e1000/e1000_manage.h
lib/librte_pmd_e1000/e1000/e1000_nvm.c
lib/librte_pmd_e1000/e1000/e1000_nvm.h
lib/librte_pmd_e1000/e1000/e1000_osdep.c
lib/librte_pmd_e1000/e1000/e1000_osdep.h
lib/librte_pmd_e1000/e1000/e1000_phy.c
lib/librte_pmd_e1000/e1000/e1000_phy.h
lib/librte_pmd_e1000/e1000/e1000_regs.h
lib/librte_pmd_e1000/e1000/e1000_vf.c
lib/librte_pmd_e1000/e1000/if_igb.c [deleted file]
lib/librte_pmd_e1000/e1000/if_igb.h [deleted file]

index 65e152b..2ee6d16 100644 (file)
  * This file contains a list of the PCI device IDs recognised by DPDK, which
  * can be used to fill out an array of structures describing the devices.
  *
- * Currently two families of devices are recognised: those supported by the
- * IGB driver, and those supported by the IXGBE driver. The inclusion of these
- * in an array built using this file depends on the definition of
- * RTE_LIBRTE_IGB_PMD and RTE_LIBRTE_IXGBE_PMD at the time when this file is
- * included.
+ * Currently three families of devices are recognised: those supported by the
+ * IGB driver, by EM driver, and those supported by the IXGBE driver.
+ * The inclusion of these in an array built using this file depends on the
+ * definition of
+ * RTE_PCI_DEV_ID_DECL_EM
+ * RTE_PCI_DEV_ID_DECL_IGB
+ * RTE_PCI_DEV_ID_DECL_IGBVF
+ * RTE_PCI_DEV_ID_DECL_IXGBE
+ * RTE_PCI_DEV_ID_DECL_IXGBEVF
+ * at the time when this file is included.
  *
  * In order to populate an array, the user of this file must define this macro:
- * RTE_PCI_DEV_ID_DECL(vendorID, deviceID). For example:
+ * RTE_PCI_DEV_ID_DECL_IXGBE(vendorID, deviceID). For example:
  *
  * @code
  * struct device {
  * Note that this file can be included multiple times within the same file.
  */
 
-#ifndef RTE_PCI_DEV_ID_DECL
-#error "You must define RTE_PCI_DEV_ID_DECL before including rte_pci_dev_ids.h"
+#ifndef RTE_PCI_DEV_ID_DECL_EM
+#define RTE_PCI_DEV_ID_DECL_EM(vend, dev)
+#endif
+
+#ifndef RTE_PCI_DEV_ID_DECL_IGB
+#define RTE_PCI_DEV_ID_DECL_IGB(vend, dev)
+#endif
+
+#ifndef RTE_PCI_DEV_ID_DECL_IGBVF
+#define RTE_PCI_DEV_ID_DECL_IGBVF(vend, dev)
 #endif
 
 #ifndef PCI_VENDOR_ID_INTEL
 #define PCI_VENDOR_ID_INTEL 0x8086
 #endif
 
+/******************** Physical EM devices from e1000_hw.h ********************/
+
+#define E1000_DEV_ID_82542                    0x1000
+#define E1000_DEV_ID_82543GC_FIBER            0x1001
+#define E1000_DEV_ID_82543GC_COPPER           0x1004
+#define E1000_DEV_ID_82544EI_COPPER           0x1008
+#define E1000_DEV_ID_82544EI_FIBER            0x1009
+#define E1000_DEV_ID_82544GC_COPPER           0x100C
+#define E1000_DEV_ID_82544GC_LOM              0x100D
+#define E1000_DEV_ID_82540EM                  0x100E
+#define E1000_DEV_ID_82540EM_LOM              0x1015
+#define E1000_DEV_ID_82540EP_LOM              0x1016
+#define E1000_DEV_ID_82540EP                  0x1017
+#define E1000_DEV_ID_82540EP_LP               0x101E
+#define E1000_DEV_ID_82545EM_COPPER           0x100F
+#define E1000_DEV_ID_82545EM_FIBER            0x1011
+#define E1000_DEV_ID_82545GM_COPPER           0x1026
+#define E1000_DEV_ID_82545GM_FIBER            0x1027
+#define E1000_DEV_ID_82545GM_SERDES           0x1028
+#define E1000_DEV_ID_82546EB_COPPER           0x1010
+#define E1000_DEV_ID_82546EB_FIBER            0x1012
+#define E1000_DEV_ID_82546EB_QUAD_COPPER      0x101D
+#define E1000_DEV_ID_82546GB_COPPER           0x1079
+#define E1000_DEV_ID_82546GB_FIBER            0x107A
+#define E1000_DEV_ID_82546GB_SERDES           0x107B
+#define E1000_DEV_ID_82546GB_PCIE             0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER      0x1099
+#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
+#define E1000_DEV_ID_82541EI                  0x1013
+#define E1000_DEV_ID_82541EI_MOBILE           0x1018
+#define E1000_DEV_ID_82541ER_LOM              0x1014
+#define E1000_DEV_ID_82541ER                  0x1078
+#define E1000_DEV_ID_82541GI                  0x1076
+#define E1000_DEV_ID_82541GI_LF               0x107C
+#define E1000_DEV_ID_82541GI_MOBILE           0x1077
+#define E1000_DEV_ID_82547EI                  0x1019
+#define E1000_DEV_ID_82547EI_MOBILE           0x101A
+#define E1000_DEV_ID_82547GI                  0x1075
+#define E1000_DEV_ID_82571EB_COPPER           0x105E
+#define E1000_DEV_ID_82571EB_FIBER            0x105F
+#define E1000_DEV_ID_82571EB_SERDES           0x1060
+#define E1000_DEV_ID_82571EB_SERDES_DUAL      0x10D9
+#define E1000_DEV_ID_82571EB_SERDES_QUAD      0x10DA
+#define E1000_DEV_ID_82571EB_QUAD_COPPER      0x10A4
+#define E1000_DEV_ID_82571PT_QUAD_COPPER      0x10D5
+#define E1000_DEV_ID_82571EB_QUAD_FIBER       0x10A5
+#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP   0x10BC
+#define E1000_DEV_ID_82572EI_COPPER           0x107D
+#define E1000_DEV_ID_82572EI_FIBER            0x107E
+#define E1000_DEV_ID_82572EI_SERDES           0x107F
+#define E1000_DEV_ID_82572EI                  0x10B9
+#define E1000_DEV_ID_82573E                   0x108B
+#define E1000_DEV_ID_82573E_IAMT              0x108C
+#define E1000_DEV_ID_82573L                   0x109A
+#define E1000_DEV_ID_82574L                   0x10D3
+#define E1000_DEV_ID_82574LA                  0x10F6
+#define E1000_DEV_ID_82583V                   0x150C
+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT   0x1096
+#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT   0x1098
+#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT   0x10BA
+#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT   0x10BB
+#define E1000_DEV_ID_ICH8_82567V_3            0x1501
+#define E1000_DEV_ID_ICH8_IGP_M_AMT           0x1049
+#define E1000_DEV_ID_ICH8_IGP_AMT             0x104A
+#define E1000_DEV_ID_ICH8_IGP_C               0x104B
+#define E1000_DEV_ID_ICH8_IFE                 0x104C
+#define E1000_DEV_ID_ICH8_IFE_GT              0x10C4
+#define E1000_DEV_ID_ICH8_IFE_G               0x10C5
+#define E1000_DEV_ID_ICH8_IGP_M               0x104D
+#define E1000_DEV_ID_ICH9_IGP_M               0x10BF
+#define E1000_DEV_ID_ICH9_IGP_M_AMT           0x10F5
+#define E1000_DEV_ID_ICH9_IGP_M_V             0x10CB
+#define E1000_DEV_ID_ICH9_IGP_AMT             0x10BD
+#define E1000_DEV_ID_ICH9_BM                  0x10E5
+#define E1000_DEV_ID_ICH9_IGP_C               0x294C
+#define E1000_DEV_ID_ICH9_IFE                 0x10C0
+#define E1000_DEV_ID_ICH9_IFE_GT              0x10C3
+#define E1000_DEV_ID_ICH9_IFE_G               0x10C2
+#define E1000_DEV_ID_ICH10_R_BM_LM            0x10CC
+#define E1000_DEV_ID_ICH10_R_BM_LF            0x10CD
+#define E1000_DEV_ID_ICH10_R_BM_V             0x10CE
+#define E1000_DEV_ID_ICH10_D_BM_LM            0x10DE
+#define E1000_DEV_ID_ICH10_D_BM_LF            0x10DF
+#define E1000_DEV_ID_ICH10_D_BM_V             0x1525
+
+#define E1000_DEV_ID_PCH_M_HV_LM              0x10EA
+#define E1000_DEV_ID_PCH_M_HV_LC              0x10EB
+#define E1000_DEV_ID_PCH_D_HV_DM              0x10EF
+#define E1000_DEV_ID_PCH_D_HV_DC              0x10F0
+#define E1000_DEV_ID_PCH2_LV_LM               0x1502
+#define E1000_DEV_ID_PCH2_LV_V                0x1503
+
+/*
+ * Tested (supported) on VM emulated HW.
+ */
+
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82540EM)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82545EM_COPPER)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82545EM_FIBER)
+
+/*
+ * Tested (supported) on real HW.
+ */
+
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_COPPER)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_FIBER)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_SERDES)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82572EI_COPPER)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82572EI_FIBER)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82572EI_SERDES)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82572EI)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82573L)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82574L)
+RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82574LA)
+
 /******************** Physical IGB devices from e1000_hw.h ********************/
-#ifdef RTE_LIBRTE_IGB_PMD
 
 #define E1000_DEV_ID_82576                      0x10C9
 #define E1000_DEV_ID_82576_FIBER                0x10E6
 #define E1000_DEV_ID_I350_SERDES                0x1523
 #define E1000_DEV_ID_I350_SGMII                 0x1524
 #define E1000_DEV_ID_I350_DA4                   0x1546
+#define E1000_DEV_ID_I210_COPPER                0x1533
+#define E1000_DEV_ID_I210_COPPER_OEM1           0x1534
+#define E1000_DEV_ID_I210_COPPER_IT             0x1535
+#define E1000_DEV_ID_I210_FIBER                 0x1536
+#define E1000_DEV_ID_I210_SERDES                0x1537
+#define E1000_DEV_ID_I210_SGMII                 0x1538
+#define E1000_DEV_ID_I211_COPPER                0x1539
 #define E1000_DEV_ID_DH89XXCC_SGMII             0x0438
 #define E1000_DEV_ID_DH89XXCC_SERDES            0x043A
 #define E1000_DEV_ID_DH89XXCC_BACKPLANE         0x043C
 #define E1000_DEV_ID_DH89XXCC_SFP               0x0440
 
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_FIBER)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_SERDES)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_QUAD_COPPER)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_QUAD_COPPER_ET2)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_NS)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_NS_SERDES)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_SERDES_QUAD)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_FIBER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_SERDES)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_QUAD_COPPER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_QUAD_COPPER_ET2)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_NS)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_NS_SERDES)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_SERDES_QUAD)
 
 /* This device is the on-board NIC on some development boards. */
 #ifdef RTE_PCI_DEV_USE_82575EB_COPPER
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82575EB_COPPER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82575EB_COPPER)
 #endif
 
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER)
 
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_COPPER)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_FIBER)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_SERDES)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_SGMII)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_COPPER_DUAL)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_QUAD_FIBER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_COPPER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_FIBER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_SERDES)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_SGMII)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_COPPER_DUAL)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_QUAD_FIBER)
 
 /* This device is the on-board NIC on some development boards. */
 #ifndef RTE_PCI_DEV_NO_USE_I350_COPPER
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_COPPER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_COPPER)
 #endif
 
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_FIBER)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_SERDES)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_SGMII)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_DA4)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SGMII)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SERDES)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE)
-RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SFP)
-
-#endif /* RTE_LIBRTE_IGB_PMD */
-
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_FIBER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_SERDES)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_SGMII)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_DA4)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_COPPER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_COPPER_OEM1)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_COPPER_IT)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_FIBER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_SERDES)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_SGMII)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I211_COPPER)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SGMII)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SERDES)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE)
+RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SFP)
 
 /****************** Physical IXGBE devices from ixgbe_type.h ******************/
 #ifdef RTE_LIBRTE_IXGBE_PMD
@@ -228,3 +372,10 @@ RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_T3_LOM)
 RTE_PCI_DEV_ID_DECL(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X540T)
 
 #endif /* RTE_LIBRTE_IXGBE_PMD */
+
+/*
+ * Undef all RTE_PCI_DEV_ID_DECL_* here.
+ */
+#undef RTE_PCI_DEV_ID_DECL_EM
+#undef RTE_PCI_DEV_ID_DECL_IGB
+#undef RTE_PCI_DEV_ID_DECL_IGBVF
index c511b6e..6564011 100644 (file)
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-Intel® IGB driver
-=================
-
-This directory contains code from the Intel® Network Adapter Driver for 82575/6
-and 82580-based Gigabit Network Connections under FreeBSD, version 2.2.3,
-dated 04/25/2011. This code is available from
-`http://downloadmirror.intel.com/15815/eng/igb-2.2.3.tar.gz`
-
-This driver is valid for the product(s) listed below
-
-* Intel® 82575EB Gigabit Ethernet Controller
-* Intel® 82576 Gigabit Ethernet Controller
-* Intel® 82580EB Gigabit Ethernet Controller
-* Intel® Ethernet Controller I350
-* Intel® Ethernet Server Adapter I340-F4
-* Intel® Ethernet Server Adapter I340-T4
-* Intel® Ethernet Server Adapter I350-F2
-* Intel® Ethernet Server Adapter I350-F4
-* Intel® Ethernet Server Adapter I350-T2
-* Intel® Ethernet Server Adapter I350-T4
-* Intel® Gigabit EF Dual Port Server Adapter
-* Intel® Gigabit ET Dual Port Server Adapter
-* Intel® Gigabit ET Quad Port Server Adapter
-* Intel® Gigabit ET2 Quad Port Server Adapter
-* Intel® Gigabit VT Quad Port Server Adapter
-
-
-Updating driver
-===============
-
-The following modifications have been made to this code to integrate it with the
-Intel® DPDK:
-
-
-e1000_osdep.h and e1000_osdep.c
--------------------------------
-
-The OS dependency layer has been extensively modified to support the drivers in
-the Intel® DPDK environment. It is expected that these files will not need to be
-changed on updating the driver.
+This directory contains source code of FreeBSD em & igb drivers of version
+cid-shared-code.2012.11.09 released by LAD. The sub-directory of lad/
+contains the original source package.
+Few changes to the original FreeBSD sources were made to:
+- Adopt it for PMD usage mode:
+       e1000_osdep.c
+       e1000_osdep.h
index 60e870d..a6187db 100644 (file)
@@ -37,9 +37,12 @@ POSSIBILITY OF SUCH DAMAGE.
  * 82575GB Gigabit Network Connection
  * 82576 Gigabit Network Connection
  * 82576 Quad Port Gigabit Mezzanine Adapter
+ * 82580 Gigabit Network Connection
+ * I350 Gigabit Network Connection
  */
 
 #include "e1000_api.h"
+#include "e1000_i210.h"
 
 STATIC s32  e1000_init_phy_params_82575(struct e1000_hw *hw);
 STATIC s32  e1000_init_mac_params_82575(struct e1000_hw *hw);
@@ -69,6 +72,8 @@ STATIC s32  e1000_set_d0_lplu_state_82575(struct e1000_hw *hw,
                                           bool active);
 STATIC s32  e1000_setup_copper_link_82575(struct e1000_hw *hw);
 STATIC s32  e1000_setup_serdes_link_82575(struct e1000_hw *hw);
+STATIC s32  e1000_get_media_type_82575(struct e1000_hw *hw);
+STATIC s32  e1000_set_sfp_media_type_82575(struct e1000_hw *hw);
 STATIC s32  e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data);
 STATIC s32  e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw,
                                             u32 offset, u16 data);
@@ -95,10 +100,23 @@ STATIC s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
                                                u16 offset);
 STATIC s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw);
 STATIC s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw);
-
-static const u16 e1000_82580_rxpbs_table[] =
-       { 36, 72, 144, 1, 2, 4, 8, 16,
-         35, 70, 140 };
+STATIC void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value);
+STATIC void e1000_clear_vfta_i350(struct e1000_hw *hw);
+
+STATIC void e1000_i2c_start(struct e1000_hw *hw);
+STATIC void e1000_i2c_stop(struct e1000_hw *hw);
+STATIC s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data);
+STATIC s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data);
+STATIC s32 e1000_get_i2c_ack(struct e1000_hw *hw);
+STATIC s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data);
+STATIC s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data);
+STATIC void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl);
+STATIC void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl);
+STATIC s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data);
+STATIC bool e1000_get_i2c_data(u32 *i2cctl);
+
+static const u16 e1000_82580_rxpbs_table[] = {
+       36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 };
 #define E1000_82580_RXPBS_TABLE_SIZE \
        (sizeof(e1000_82580_rxpbs_table)/sizeof(u16))
 
@@ -125,6 +143,8 @@ STATIC bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw)
                break;
        case e1000_82580:
        case e1000_i350:
+       case e1000_i210:
+       case e1000_i211:
                reg = E1000_READ_REG(hw, E1000_MDICNFG);
                ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
                break;
@@ -146,6 +166,9 @@ STATIC s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_init_phy_params_82575");
 
+       phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic;
+       phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic;
+
        if (hw->phy.media_type != e1000_media_type_copper) {
                phy->type = e1000_phy_none;
                goto out;
@@ -179,13 +202,23 @@ STATIC s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
        if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) {
                phy->ops.read_reg   = e1000_read_phy_reg_sgmii_82575;
                phy->ops.write_reg  = e1000_write_phy_reg_sgmii_82575;
-       } else if (hw->mac.type >= e1000_82580) {
+       } else {
+               switch (hw->mac.type) {
+               case e1000_82580:
+               case e1000_i350:
                phy->ops.read_reg   = e1000_read_phy_reg_82580;
                phy->ops.write_reg  = e1000_write_phy_reg_82580;
-       } else {
+                       break;
+               case e1000_i210:
+               case e1000_i211:
+                       phy->ops.read_reg = e1000_read_phy_reg_gs40g;
+                       phy->ops.write_reg = e1000_write_phy_reg_gs40g;
+                       break;
+               default:
                phy->ops.read_reg   = e1000_read_phy_reg_igp;
                phy->ops.write_reg  = e1000_write_phy_reg_igp;
        }
+       }
 
        /* Set phy->phy_addr and phy->id. */
        ret_val = e1000_get_phy_id_82575(hw);
@@ -229,6 +262,15 @@ STATIC s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
                phy->ops.set_d0_lplu_state  = e1000_set_d0_lplu_state_82580;
                phy->ops.set_d3_lplu_state  = e1000_set_d3_lplu_state_82580;
                break;
+       case I210_I_PHY_ID:
+               phy->type               = e1000_phy_i210;
+               phy->ops.check_polarity = e1000_check_polarity_m88;
+               phy->ops.get_info       = e1000_get_phy_info_m88;
+               phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2;
+               phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
+               phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
+               phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
+               break;
        default:
                ret_val = -E1000_ERR_PHY;
                goto out;
@@ -258,9 +300,17 @@ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
         */
        size += NVM_WORD_SIZE_BASE_SHIFT;
 
+       /* Just in case size is out of range, cap it to the largest
+        * EEPROM size supported
+        */
+       if (size > 15)
+               size = 15;
+
        nvm->word_size = 1 << size;
+       if (hw->mac.type < e1000_i210) {
        nvm->opcode_bits        = 8;
        nvm->delay_usec         = 1;
+
        switch (nvm->override) {
        case e1000_nvm_override_spi_large:
                nvm->page_size    = 32;
@@ -276,12 +326,13 @@ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
                                            16 : 8;
                break;
        }
-
-       nvm->type = e1000_nvm_eeprom_spi;
-
        if (nvm->word_size == (1 << 15))
                nvm->page_size = 128;
 
+               nvm->type = e1000_nvm_eeprom_spi;
+       } else {
+               nvm->type = e1000_nvm_flash_hw;
+       }
        /* Function Pointers */
        nvm->ops.acquire    = e1000_acquire_nvm_82575;
        nvm->ops.release    = e1000_release_nvm_82575;
@@ -320,34 +371,11 @@ STATIC s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
-       u32 ctrl_ext = 0;
 
        DEBUGFUNC("e1000_init_mac_params_82575");
 
-       /* Set media type */
-        /*
-        * The 82575 uses bits 22:23 for link mode. The mode can be changed
-         * based on the EEPROM. We cannot rely upon device ID. There
-         * is no distinguishable difference between fiber and internal
-         * SerDes mode on the 82575. There can be an external PHY attached
-         * on the SGMII interface. For this, we'll set sgmii_active to TRUE.
-         */
-       hw->phy.media_type = e1000_media_type_copper;
-       dev_spec->sgmii_active = FALSE;
-
-       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
-       switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
-       case E1000_CTRL_EXT_LINK_MODE_SGMII:
-               dev_spec->sgmii_active = TRUE;
-               break;
-       case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
-       case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
-               hw->phy.media_type = e1000_media_type_internal_serdes;
-               break;
-       default:
-               break;
-       }
-
+       /* Derives media type */
+       e1000_get_media_type_82575(hw);
        /* Set mta register count */
        mac->mta_reg_count = 128;
        /* Set uta register count */
@@ -395,18 +423,26 @@ STATIC s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
        mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575;
        /* check for link */
        mac->ops.check_for_link = e1000_check_for_link_82575;
-       /* receive address register setting */
-       mac->ops.rar_set = e1000_rar_set_generic;
        /* read mac address */
        mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
        /* configure collision distance */
        mac->ops.config_collision_dist = e1000_config_collision_dist_82575;
        /* multicast address update */
        mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
+       if (mac->type == e1000_i350) {
+               /* writing VFTA */
+               mac->ops.write_vfta = e1000_write_vfta_i350;
+               /* clearing VFTA */
+               mac->ops.clear_vfta = e1000_clear_vfta_i350;
+       } else {
        /* writing VFTA */
        mac->ops.write_vfta = e1000_write_vfta_generic;
        /* clearing VFTA */
        mac->ops.clear_vfta = e1000_clear_vfta_generic;
+       }
+       if (hw->mac.type >= e1000_82580)
+               mac->ops.validate_mdi_setting =
+                               e1000_validate_mdi_setting_crossover_generic;
        /* ID LED init */
        mac->ops.id_led_init = e1000_id_led_init_generic;
        /* blink LED */
@@ -422,6 +458,13 @@ STATIC s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
        mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575;
        /* link info */
        mac->ops.get_link_up_info = e1000_get_link_up_info_82575;
+       /* acquire SW_FW sync */
+       mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575;
+       mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575;
+       if (mac->type >= e1000_i210) {
+               mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210;
+               mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210;
+       }
 
        /* set lan id for port to determine which phy lock to use */
        hw->mac.ops.set_lan_id(hw);
@@ -464,7 +507,7 @@ STATIC s32 e1000_acquire_phy_82575(struct e1000_hw *hw)
        else if (hw->bus.func == E1000_FUNC_3)
                mask = E1000_SWFW_PHY3_SM;
 
-       return e1000_acquire_swfw_sync_82575(hw, mask);
+       return hw->mac.ops.acquire_swfw_sync(hw, mask);
 }
 
 /**
@@ -486,7 +529,7 @@ STATIC void e1000_release_phy_82575(struct e1000_hw *hw)
        else if (hw->bus.func == E1000_FUNC_3)
                mask = E1000_SWFW_PHY3_SM;
 
-       e1000_release_swfw_sync_82575(hw, mask);
+       hw->mac.ops.release_swfw_sync(hw, mask);
 }
 
 /**
@@ -595,6 +638,8 @@ STATIC s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
                        break;
                case e1000_82580:
                case e1000_i350:
+               case e1000_i210:
+               case e1000_i211:
                        mdic = E1000_READ_REG(hw, E1000_MDICNFG);
                        mdic &= E1000_MDICNFG_PHY_MASK;
                        phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
@@ -790,7 +835,7 @@ STATIC s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val = E1000_SUCCESS;
-       u16 data;
+       u32 data;
 
        DEBUGFUNC("e1000_set_d0_lplu_state_82580");
 
@@ -838,7 +883,7 @@ s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val = E1000_SUCCESS;
-       u16 data;
+       u32 data;
 
        DEBUGFUNC("e1000_set_d3_lplu_state_82580");
 
@@ -931,6 +976,8 @@ STATIC void e1000_release_nvm_82575(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_release_nvm_82575");
 
+       e1000_release_nvm_generic(hw);
+
        e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
 }
 
@@ -1101,6 +1148,16 @@ STATIC s32 e1000_check_for_link_82575(struct e1000_hw *hw)
                 * continue to check for link.
                 */
                hw->mac.get_link_status = !hw->mac.serdes_has_link;
+
+               /*
+                * Configure Flow Control now that Auto-Neg has completed.
+                * First, we need to restore the desired flow control
+                * settings because we may have had to re-autoneg with a
+                * different link partner.
+                */
+               ret_val = e1000_config_fc_after_link_up_generic(hw);
+               if (ret_val)
+                       DEBUGOUT("Error configuring flow control\n");
        } else {
                ret_val = e1000_check_for_copper_link_generic(hw);
        }
@@ -1154,11 +1211,6 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
 
        DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575");
 
-       /* Set up defaults for the return values of this function */
-       mac->serdes_has_link = FALSE;
-       *speed = 0;
-       *duplex = 0;
-
        /*
         * Read the PCS Status register for link state. For non-copper mode,
         * the status register is not accurate. The PCS status register is
@@ -1167,12 +1219,10 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
        pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT);
 
        /*
-        * The link up bit determines when link is up on autoneg. The sync ok
-        * gets set once both sides sync up and agree upon link. Stable link
-        * can be determined by checking for both link up and link sync ok
+        * The link up bit determines when link is up on autoneg.
         */
-       if ((pcs & E1000_PCS_LSTS_LINK_OK) && (pcs & E1000_PCS_LSTS_SYNK_OK)) {
-               mac->serdes_has_link = TRUE;
+       if (pcs & E1000_PCS_LSTS_LINK_OK) {
+               mac->serdes_has_link = true;
 
                /* Detect and store PCS speed */
                if (pcs & E1000_PCS_LSTS_SPEED_1000)
@@ -1187,6 +1237,11 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
                        *duplex = FULL_DUPLEX;
                else
                        *duplex = HALF_DUPLEX;
+
+       } else {
+               mac->serdes_has_link = false;
+               *speed = 0;
+               *duplex = 0;
                }
 
        return E1000_SUCCESS;
@@ -1333,6 +1388,9 @@ STATIC s32 e1000_init_hw_82575(struct e1000_hw *hw)
        /* Setup link and flow control */
        ret_val = mac->ops.setup_link(hw);
 
+       /* Set the default MTU size */
+       hw->dev_spec._82575.mtu = 1500;
+
        /*
         * Clear all of the statistics registers (clear on read).  It is
         * important that we do this after we have tried to establish link
@@ -1356,6 +1414,7 @@ STATIC s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32  ret_val;
+       u32 phpm_reg;
 
        DEBUGFUNC("e1000_setup_copper_link_82575");
 
@@ -1364,11 +1423,18 @@ STATIC s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
        ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
 
+       /* Clear Go Link Disconnect bit */
+       if (hw->mac.type >= e1000_82580) {
+               phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+               phpm_reg &= ~E1000_82580_PM_GO_LINKD;
+               E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg);
+       }
+
        ret_val = e1000_setup_serdes_link_82575(hw);
        if (ret_val)
                goto out;
 
-       if (e1000_sgmii_active_82575(hw) && !hw->phy.reset_disable) {
+       if (e1000_sgmii_active_82575(hw)) {
                /* allow time for SFP cage time to power up phy */
                msec_delay(300);
 
@@ -1379,6 +1445,7 @@ STATIC s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
                }
        }
        switch (hw->phy.type) {
+       case e1000_phy_i210:
        case e1000_phy_m88:
                if (hw->phy.id == I347AT4_E_PHY_ID ||
                    hw->phy.id == M88E1112_E_PHY_ID ||
@@ -1417,14 +1484,16 @@ out:
  **/
 STATIC s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
 {
-       u32 ctrl_ext, ctrl_reg, reg;
+       u32 ctrl_ext, ctrl_reg, reg, anadv_reg;
        bool pcs_autoneg;
+       s32 ret_val = E1000_SUCCESS;
+       u16 data;
 
        DEBUGFUNC("e1000_setup_serdes_link_82575");
 
        if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
            !e1000_sgmii_active_82575(hw))
-               return E1000_SUCCESS;
+               return ret_val;
 
        /*
         * On the 82575, SerDes loopback mode persists until it is
@@ -1463,6 +1532,18 @@ STATIC s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
                pcs_autoneg = false;
                /* fall through to default case */
        default:
+               if (hw->mac.type == e1000_82575 ||
+                   hw->mac.type == e1000_82576) {
+                       ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data);
+                       if (ret_val) {
+                               DEBUGOUT("NVM Read Error\n");
+                               return ret_val;
+                       }
+
+                       if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT)
+                               pcs_autoneg = false;
+               }
+
                /*
                 * non-SGMII modes only supports a speed of 1000/Full for the
                 * link so it is best to just force the MAC and let the pcs
@@ -1487,29 +1568,272 @@ STATIC s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
        reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
                 E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
 
-       /*
-        * We force flow control to prevent the CTRL register values from being
-        * overwritten by the autonegotiated flow control values
-        */
-       reg |= E1000_PCS_LCTL_FORCE_FCTRL;
-
        if (pcs_autoneg) {
                /* Set PCS register for autoneg */
                reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
                       E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */
+
+               /* Disable force flow control for autoneg */
+               reg &= ~E1000_PCS_LCTL_FORCE_FCTRL;
+
+               /* Configure flow control advertisement for autoneg */
+               anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV);
+               anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE);
+
+               switch (hw->fc.requested_mode) {
+               case e1000_fc_full:
+               case e1000_fc_rx_pause:
+                       anadv_reg |= E1000_TXCW_ASM_DIR;
+                       anadv_reg |= E1000_TXCW_PAUSE;
+                       break;
+               case e1000_fc_tx_pause:
+                       anadv_reg |= E1000_TXCW_ASM_DIR;
+                       break;
+               default:
+                       break;
+               }
+
+               E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg);
+
                DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
        } else {
                /* Set PCS register for forced link */
                reg |= E1000_PCS_LCTL_FSD;        /* Force Speed */
+
+               /* Force flow control for forced link */
+               reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+
                DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
        }
 
        E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg);
 
-       if (!e1000_sgmii_active_82575(hw))
+       if (!pcs_autoneg && !e1000_sgmii_active_82575(hw))
                e1000_force_mac_fc_generic(hw);
 
-       return E1000_SUCCESS;
+       return ret_val;
+}
+
+/**
+ *  e1000_get_media_type_82575 - derives current media type.
+ *  @hw: pointer to the HW structure
+ *
+ *  The media type is chosen reflecting few settings.
+ *  The following are taken into account:
+ *  - link mode set in the current port Init Control Word #3
+ *  - current link mode settings in CSR register
+ *  - MDIO vs. I2C PHY control interface chosen
+ *  - SFP module media type
+ **/
+STATIC s32 e1000_get_media_type_82575(struct e1000_hw *hw)
+{
+       u32 lan_id = 0;
+       s32 ret_val = E1000_ERR_CONFIG;
+       struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+       u32 ctrl_ext = 0;
+       u32 current_link_mode = 0;
+       u16 init_ctrl_wd_3 = 0;
+       u8 init_ctrl_wd_3_offset = 0;
+       u8 init_ctrl_wd_3_bit_offset = 0;
+
+       /* Set internal phy as default */
+       dev_spec->sgmii_active = false;
+       dev_spec->module_plugged = false;
+
+       /*
+        * Check if NVM access method is attached already.
+        * If it is then Init Control Word #3 is considered
+        * otherwise runtime CSR register content is taken.
+        */
+
+       /* Get CSR setting */
+       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+
+       /* Get link mode setting */
+       if ((hw->nvm.ops.read) && (hw->nvm.ops.read != e1000_null_read_nvm)) {
+               /* Take link mode from EEPROM */
+
+               /*
+                * Get LAN port ID to derive its
+                * adequate Init Control Word #3
+                */
+               lan_id = ((E1000_READ_REG(hw, E1000_STATUS) &
+                     E1000_STATUS_LAN_ID_MASK) >> E1000_STATUS_LAN_ID_OFFSET);
+               /*
+                * Derive Init Control Word #3 offset
+                * and mask to pick up link mode setting.
+                */
+               if (hw->mac.type < e1000_82580) {
+                       init_ctrl_wd_3_offset = lan_id ?
+                          NVM_INIT_CONTROL3_PORT_A : NVM_INIT_CONTROL3_PORT_B;
+                       init_ctrl_wd_3_bit_offset = NVM_WORD24_LNK_MODE_OFFSET;
+               } else {
+                       init_ctrl_wd_3_offset =
+                                           NVM_82580_LAN_FUNC_OFFSET(lan_id) +
+                                           NVM_INIT_CONTROL3_PORT_A;
+                       init_ctrl_wd_3_bit_offset =
+                                             NVM_WORD24_82580_LNK_MODE_OFFSET;
+               }
+               /* Read Init Control Word #3*/
+               hw->nvm.ops.read(hw, init_ctrl_wd_3_offset, 1, &init_ctrl_wd_3);
+
+               /*
+                * Align link mode bits to
+                * their CTRL_EXT location.
+                */
+               current_link_mode = init_ctrl_wd_3;
+               current_link_mode <<= (E1000_CTRL_EXT_LINK_MODE_OFFSET -
+                                      init_ctrl_wd_3_bit_offset);
+               current_link_mode &= E1000_CTRL_EXT_LINK_MODE_MASK;
+
+               /*
+                * Switch to CSR for all but internal PHY.
+                */
+               if (current_link_mode != E1000_CTRL_EXT_LINK_MODE_GMII)
+                       /* Take link mode from CSR */
+                       current_link_mode = ctrl_ext &
+                                           E1000_CTRL_EXT_LINK_MODE_MASK;
+       } else {
+               /* Take link mode from CSR */
+               current_link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK;
+       }
+
+       switch (current_link_mode) {
+
+       case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
+               hw->phy.media_type = e1000_media_type_internal_serdes;
+               current_link_mode = E1000_CTRL_EXT_LINK_MODE_1000BASE_KX;
+               break;
+       case E1000_CTRL_EXT_LINK_MODE_GMII:
+               hw->phy.media_type = e1000_media_type_copper;
+               current_link_mode = E1000_CTRL_EXT_LINK_MODE_GMII;
+               break;
+       case E1000_CTRL_EXT_LINK_MODE_SGMII:
+       case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
+               /* Get phy control interface type set (MDIO vs. I2C)*/
+               if (e1000_sgmii_uses_mdio_82575(hw)) {
+                       hw->phy.media_type = e1000_media_type_copper;
+                       dev_spec->sgmii_active = true;
+                       current_link_mode = E1000_CTRL_EXT_LINK_MODE_SGMII;
+               } else {
+                       ret_val = e1000_set_sfp_media_type_82575(hw);
+                       if (ret_val != E1000_SUCCESS)
+                               goto out;
+                       if (hw->phy.media_type ==
+                               e1000_media_type_internal_serdes) {
+                               /* Keep Link Mode as SGMII for 100BaseFX */
+                               if (!dev_spec->eth_flags.e100_base_fx) {
+                                       current_link_mode =
+                                        E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
+                               }
+                       } else if (hw->phy.media_type ==
+                               e1000_media_type_copper) {
+                               current_link_mode =
+                                              E1000_CTRL_EXT_LINK_MODE_SGMII;
+                       }
+               }
+               break;
+       default:
+               DEBUGOUT("Link mode mask doesn't fit bit field size\n");
+               goto out;
+       }
+       /*
+        * Do not change current link mode setting
+        * if media type is fibre or has not been
+        * recognized.
+        */
+       if ((hw->phy.media_type != e1000_media_type_unknown) &&
+           (hw->phy.media_type != e1000_media_type_fiber)) {
+               /* Update link mode */
+               ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
+               E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext |
+                               current_link_mode);
+       }
+
+       ret_val = E1000_SUCCESS;
+out:
+       /*
+        * If media type was not identified then return media type
+        * defined by the CTRL_EXT settings.
+        */
+       if (hw->phy.media_type == e1000_media_type_unknown) {
+               if (current_link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII)
+                       hw->phy.media_type = e1000_media_type_copper;
+               else
+                       hw->phy.media_type = e1000_media_type_internal_serdes;
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_set_sfp_media_type_82575 - derives SFP module media type.
+ *  @hw: pointer to the HW structure
+ *
+ *  The media type is chosen based on SFP module.
+ *  compatibility flags retrieved from SFP ID EEPROM.
+ **/
+STATIC s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_ERR_CONFIG;
+       u32 ctrl_ext = 0;
+       struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+       struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags;
+       u8 tranceiver_type = 0;
+       s32 timeout = 3;
+
+       /* Turn I2C interface ON and power on sfp cage */
+       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+       ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA);
+
+       E1000_WRITE_FLUSH(hw);
+
+       /* Read SFP module data */
+       while (timeout) {
+               ret_val = e1000_read_sfp_data_byte(hw,
+                       E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET),
+                       &tranceiver_type);
+               if (ret_val == E1000_SUCCESS)
+                       break;
+               msec_delay(100);
+               timeout--;
+       }
+       if (ret_val != E1000_SUCCESS)
+               goto out;
+       ret_val = e1000_read_sfp_data_byte(hw,
+                       E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET),
+                       (u8 *)eth_flags);
+       if (ret_val != E1000_SUCCESS)
+               goto out;
+       /*
+        * Check if there is some SFP
+        * module plugged and powered
+        */
+       if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) ||
+           (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) {
+               dev_spec->module_plugged = true;
+               if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) {
+                       hw->phy.media_type = e1000_media_type_internal_serdes;
+               } else if (eth_flags->e100_base_fx) {
+                       dev_spec->sgmii_active = true;
+                       hw->phy.media_type = e1000_media_type_internal_serdes;
+               } else if (eth_flags->e1000_base_t) {
+                       dev_spec->sgmii_active = true;
+                       hw->phy.media_type = e1000_media_type_copper;
+               } else {
+                               hw->phy.media_type = e1000_media_type_unknown;
+                               DEBUGOUT("PHY module has not been recognized\n");
+                               goto out;
+               }
+       } else {
+               hw->phy.media_type = e1000_media_type_unknown;
+       }
+       ret_val = E1000_SUCCESS;
+out:
+       /* Restore I2C interface setting */
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       return ret_val;
 }
 
 /**
@@ -1877,7 +2201,8 @@ void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
                                   E1000_DTXSWC_VLAN_SPOOF_MASK);
                        /* The PF can spoof - it has to in order to
                         * support emulation mode NICs */
-                       dtxswc ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
+                       dtxswc ^= (1 << pf | 1 << (pf +
+                                  E1000_DTXSWC_VLAN_SPOOF_SHIFT));
                } else {
                        dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
                                    E1000_DTXSWC_VLAN_SPOOF_MASK);
@@ -1892,7 +2217,8 @@ void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
                        /* The PF can spoof - it has to in order to
                         * support emulation mode NICs
                         */
-                       dtxswc ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
+                       dtxswc ^= (1 << pf | 1 << (pf +
+                                  E1000_DTXSWC_VLAN_SPOOF_SHIFT));
                } else {
                        dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
                                    E1000_DTXSWC_VLAN_SPOOF_MASK);
@@ -2089,17 +2415,18 @@ STATIC s32 e1000_reset_hw_82580(struct e1000_hw *hw)
        msec_delay(10);
 
        /* Determine whether or not a global dev reset is requested */
-       if (global_device_reset &&
-               e1000_acquire_swfw_sync_82575(hw, swmbsw_mask))
-                       global_device_reset = FALSE;
+       if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw,
+           swmbsw_mask))
+                       global_device_reset = false;
 
-       if (global_device_reset &&
-               !(E1000_READ_REG(hw, E1000_STATUS) & E1000_STAT_DEV_RST_SET))
+       if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) &
+           E1000_STAT_DEV_RST_SET))
                ctrl |= E1000_CTRL_DEV_RST;
        else
                ctrl |= E1000_CTRL_RST;
 
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       E1000_WRITE_FLUSH(hw);
 
        /* Add delay to insure DEV_RST has time to complete */
        if (global_device_reset)
@@ -2135,7 +2462,7 @@ STATIC s32 e1000_reset_hw_82580(struct e1000_hw *hw)
 
        /* Release semaphore */
        if (global_device_reset)
-               e1000_release_swfw_sync_82575(hw, swmbsw_mask);
+               hw->mac.ops.release_swfw_sync(hw, swmbsw_mask);
 
        return ret_val;
 }
@@ -2382,23 +2709,27 @@ out:
 s32 e1000_set_eee_i350(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
-       u32 ipcnfg, eeer, ctrl_ext;
+       u32 ipcnfg, eeer;
 
        DEBUGFUNC("e1000_set_eee_i350");
 
-       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
-       if ((hw->mac.type != e1000_i350) ||
-           (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK))
+       if ((hw->mac.type < e1000_i350) ||
+           (hw->phy.media_type != e1000_media_type_copper))
                goto out;
        ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG);
        eeer = E1000_READ_REG(hw, E1000_EEER);
 
        /* enable or disable per user setting */
        if (!(hw->dev_spec._82575.eee_disable)) {
+               u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU);
+
                ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
                eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
                         E1000_EEER_LPI_FC);
 
+               /* This bit should not be set in normal operation. */
+               if (eee_su & E1000_EEE_SU_LPI_CLK_STP)
+                       DEBUGOUT("LPI Clock Stop Bit should not be set!\n");
        } else {
                ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
                eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
@@ -2412,3 +2743,601 @@ out:
 
        return ret_val;
 }
+
+/* Due to a hw errata, if the host tries to  configure the VFTA register
+ * while performing queries from the BMC or DMA, then the VFTA in some
+ * cases won't be written.
+ */
+
+/**
+ *  e1000_clear_vfta_i350 - Clear VLAN filter table
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the register array which contains the VLAN filter table by
+ *  setting all the values to 0.
+ **/
+void e1000_clear_vfta_i350(struct e1000_hw *hw)
+{
+       u32 offset;
+       int i;
+
+       DEBUGFUNC("e1000_clear_vfta_350");
+
+       for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+               for (i = 0; i < 10; i++)
+                       E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
+
+               E1000_WRITE_FLUSH(hw);
+       }
+}
+
+/**
+ *  e1000_write_vfta_i350 - Write value to VLAN filter table
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset in VLAN filter table
+ *  @value: register value written to VLAN filter table
+ *
+ *  Writes value at the given offset in the register array which stores
+ *  the VLAN filter table.
+ **/
+void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
+{
+       int i;
+
+       DEBUGFUNC("e1000_write_vfta_350");
+
+       for (i = 0; i < 10; i++)
+               E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
+
+       E1000_WRITE_FLUSH(hw);
+}
+
+
+/**
+ *  e1000_set_i2c_bb - Enable I2C bit-bang
+ *  @hw: pointer to the HW structure
+ *
+ *  Enable I2C bit-bang interface
+ *
+ **/
+s32 e1000_set_i2c_bb(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u32 ctrl_ext, i2cparams;
+
+       DEBUGFUNC("e1000_set_i2c_bb");
+
+       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+       ctrl_ext |= E1000_CTRL_I2C_ENA;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       E1000_WRITE_FLUSH(hw);
+
+       i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS);
+       i2cparams |= E1000_I2CBB_EN;
+       i2cparams |= E1000_I2C_DATA_OE_N;
+       i2cparams |= E1000_I2C_CLK_OE_N;
+       E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams);
+       E1000_WRITE_FLUSH(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_read_i2c_byte_generic - Reads 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @dev_addr: device address
+ *  @data: value read
+ *
+ *  Performs byte read operation over I2C interface at
+ *  a specified device address.
+ **/
+s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+                               u8 dev_addr, u8 *data)
+{
+       s32 status = E1000_SUCCESS;
+       u32 max_retry = 10;
+       u32 retry = 1;
+       u16 swfw_mask = 0;
+
+       bool nack = true;
+
+       DEBUGFUNC("e1000_read_i2c_byte_generic");
+
+       swfw_mask = E1000_SWFW_PHY0_SM;
+
+       do {
+               if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)
+                   != E1000_SUCCESS) {
+                       status = E1000_ERR_SWFW_SYNC;
+                       goto read_byte_out;
+               }
+
+               e1000_i2c_start(hw);
+
+               /* Device Address and write indication */
+               status = e1000_clock_out_i2c_byte(hw, dev_addr);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_get_i2c_ack(hw);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_clock_out_i2c_byte(hw, byte_offset);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_get_i2c_ack(hw);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               e1000_i2c_start(hw);
+
+               /* Device Address and read indication */
+               status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1));
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_get_i2c_ack(hw);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_clock_in_i2c_byte(hw, data);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_clock_out_i2c_bit(hw, nack);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               e1000_i2c_stop(hw);
+               break;
+
+fail:
+               hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+               msec_delay(100);
+               e1000_i2c_bus_clear(hw);
+               retry++;
+               if (retry < max_retry)
+                       DEBUGOUT("I2C byte read error - Retrying.\n");
+               else
+                       DEBUGOUT("I2C byte read error.\n");
+
+       } while (retry < max_retry);
+
+       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+
+read_byte_out:
+
+       return status;
+}
+
+/**
+ *  e1000_write_i2c_byte_generic - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @dev_addr: device address
+ *  @data: value to write
+ *
+ *  Performs byte write operation over I2C interface at
+ *  a specified device address.
+ **/
+s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+                                u8 dev_addr, u8 data)
+{
+       s32 status = E1000_SUCCESS;
+       u32 max_retry = 1;
+       u32 retry = 0;
+       u16 swfw_mask = 0;
+
+       DEBUGFUNC("e1000_write_i2c_byte_generic");
+
+       swfw_mask = E1000_SWFW_PHY0_SM;
+
+       if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) {
+               status = E1000_ERR_SWFW_SYNC;
+               goto write_byte_out;
+       }
+
+       do {
+               e1000_i2c_start(hw);
+
+               status = e1000_clock_out_i2c_byte(hw, dev_addr);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_get_i2c_ack(hw);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_clock_out_i2c_byte(hw, byte_offset);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_get_i2c_ack(hw);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_clock_out_i2c_byte(hw, data);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               status = e1000_get_i2c_ack(hw);
+               if (status != E1000_SUCCESS)
+                       goto fail;
+
+               e1000_i2c_stop(hw);
+               break;
+
+fail:
+               e1000_i2c_bus_clear(hw);
+               retry++;
+               if (retry < max_retry)
+                       DEBUGOUT("I2C byte write error - Retrying.\n");
+               else
+                       DEBUGOUT("I2C byte write error.\n");
+       } while (retry < max_retry);
+
+       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+
+write_byte_out:
+
+       return status;
+}
+
+/**
+ *  e1000_i2c_start - Sets I2C start condition
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets I2C start condition (High -> Low on SDA while SCL is High)
+ **/
+STATIC void e1000_i2c_start(struct e1000_hw *hw)
+{
+       u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+       DEBUGFUNC("e1000_i2c_start");
+
+       /* Start condition must begin with data and clock high */
+       e1000_set_i2c_data(hw, &i2cctl, 1);
+       e1000_raise_i2c_clk(hw, &i2cctl);
+
+       /* Setup time for start condition (4.7us) */
+       usec_delay(E1000_I2C_T_SU_STA);
+
+       e1000_set_i2c_data(hw, &i2cctl, 0);
+
+       /* Hold time for start condition (4us) */
+       usec_delay(E1000_I2C_T_HD_STA);
+
+       e1000_lower_i2c_clk(hw, &i2cctl);
+
+       /* Minimum low period of clock is 4.7 us */
+       usec_delay(E1000_I2C_T_LOW);
+
+}
+
+/**
+ *  e1000_i2c_stop - Sets I2C stop condition
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
+ **/
+STATIC void e1000_i2c_stop(struct e1000_hw *hw)
+{
+       u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+       DEBUGFUNC("e1000_i2c_stop");
+
+       /* Stop condition must begin with data low and clock high */
+       e1000_set_i2c_data(hw, &i2cctl, 0);
+       e1000_raise_i2c_clk(hw, &i2cctl);
+
+       /* Setup time for stop condition (4us) */
+       usec_delay(E1000_I2C_T_SU_STO);
+
+       e1000_set_i2c_data(hw, &i2cctl, 1);
+
+       /* bus free time between stop and start (4.7us)*/
+       usec_delay(E1000_I2C_T_BUF);
+}
+
+/**
+ *  e1000_clock_in_i2c_byte - Clocks in one byte via I2C
+ *  @hw: pointer to hardware structure
+ *  @data: data byte to clock in
+ *
+ *  Clocks in one byte data via I2C data/clock
+ **/
+STATIC s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data)
+{
+       s32 i;
+       bool bit = 0;
+
+       DEBUGFUNC("e1000_clock_in_i2c_byte");
+
+       *data = 0;
+       for (i = 7; i >= 0; i--) {
+               e1000_clock_in_i2c_bit(hw, &bit);
+               *data |= bit << i;
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_clock_out_i2c_byte - Clocks out one byte via I2C
+ *  @hw: pointer to hardware structure
+ *  @data: data byte clocked out
+ *
+ *  Clocks out one byte data via I2C data/clock
+ **/
+STATIC s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data)
+{
+       s32 status = E1000_SUCCESS;
+       s32 i;
+       u32 i2cctl;
+       bool bit = 0;
+
+       DEBUGFUNC("e1000_clock_out_i2c_byte");
+
+       for (i = 7; i >= 0; i--) {
+               bit = (data >> i) & 0x1;
+               status = e1000_clock_out_i2c_bit(hw, bit);
+
+               if (status != E1000_SUCCESS)
+                       break;
+       }
+
+       /* Release SDA line (set high) */
+       i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+       i2cctl |= E1000_I2C_DATA_OE_N;
+       E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl);
+       E1000_WRITE_FLUSH(hw);
+
+       return status;
+}
+
+/**
+ *  e1000_get_i2c_ack - Polls for I2C ACK
+ *  @hw: pointer to hardware structure
+ *
+ *  Clocks in/out one bit via I2C data/clock
+ **/
+STATIC s32 e1000_get_i2c_ack(struct e1000_hw *hw)
+{
+       s32 status = E1000_SUCCESS;
+       u32 i = 0;
+       u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+       u32 timeout = 10;
+       bool ack = true;
+
+       DEBUGFUNC("e1000_get_i2c_ack");
+
+       e1000_raise_i2c_clk(hw, &i2cctl);
+
+       /* Minimum high period of clock is 4us */
+       usec_delay(E1000_I2C_T_HIGH);
+
+       /* Wait until SCL returns high */
+       for (i = 0; i < timeout; i++) {
+               usec_delay(1);
+               i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+               if (i2cctl & E1000_I2C_CLK_IN)
+                       break;
+       }
+       if (!(i2cctl & E1000_I2C_CLK_IN))
+               return E1000_ERR_I2C;
+
+       ack = e1000_get_i2c_data(&i2cctl);
+       if (ack) {
+               DEBUGOUT("I2C ack was not received.\n");
+               status = E1000_ERR_I2C;
+       }
+
+       e1000_lower_i2c_clk(hw, &i2cctl);
+
+       /* Minimum low period of clock is 4.7 us */
+       usec_delay(E1000_I2C_T_LOW);
+
+       return status;
+}
+
+/**
+ *  e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
+ *  @hw: pointer to hardware structure
+ *  @data: read data value
+ *
+ *  Clocks in one bit via I2C data/clock
+ **/
+STATIC s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data)
+{
+       u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+       DEBUGFUNC("e1000_clock_in_i2c_bit");
+
+       e1000_raise_i2c_clk(hw, &i2cctl);
+
+       /* Minimum high period of clock is 4us */
+       usec_delay(E1000_I2C_T_HIGH);
+
+       i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+       *data = e1000_get_i2c_data(&i2cctl);
+
+       e1000_lower_i2c_clk(hw, &i2cctl);
+
+       /* Minimum low period of clock is 4.7 us */
+       usec_delay(E1000_I2C_T_LOW);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
+ *  @hw: pointer to hardware structure
+ *  @data: data value to write
+ *
+ *  Clocks out one bit via I2C data/clock
+ **/
+STATIC s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data)
+{
+       s32 status;
+       u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+       DEBUGFUNC("e1000_clock_out_i2c_bit");
+
+       status = e1000_set_i2c_data(hw, &i2cctl, data);
+       if (status == E1000_SUCCESS) {
+               e1000_raise_i2c_clk(hw, &i2cctl);
+
+               /* Minimum high period of clock is 4us */
+               usec_delay(E1000_I2C_T_HIGH);
+
+               e1000_lower_i2c_clk(hw, &i2cctl);
+
+               /* Minimum low period of clock is 4.7 us.
+                * This also takes care of the data hold time.
+                */
+               usec_delay(E1000_I2C_T_LOW);
+       } else {
+               status = E1000_ERR_I2C;
+               DEBUGOUT1("I2C data was not set to %X\n", data);
+       }
+
+       return status;
+}
+/**
+ *  e1000_raise_i2c_clk - Raises the I2C SCL clock
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *
+ *  Raises the I2C clock line '0'->'1'
+ **/
+STATIC void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
+{
+       DEBUGFUNC("e1000_raise_i2c_clk");
+
+       *i2cctl |= E1000_I2C_CLK_OUT;
+       *i2cctl &= ~E1000_I2C_CLK_OE_N;
+       E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
+       E1000_WRITE_FLUSH(hw);
+
+       /* SCL rise time (1000ns) */
+       usec_delay(E1000_I2C_T_RISE);
+}
+
+/**
+ *  e1000_lower_i2c_clk - Lowers the I2C SCL clock
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *
+ *  Lowers the I2C clock line '1'->'0'
+ **/
+STATIC void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
+{
+
+       DEBUGFUNC("e1000_lower_i2c_clk");
+
+       *i2cctl &= ~E1000_I2C_CLK_OUT;
+       *i2cctl &= ~E1000_I2C_CLK_OE_N;
+       E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
+       E1000_WRITE_FLUSH(hw);
+
+       /* SCL fall time (300ns) */
+       usec_delay(E1000_I2C_T_FALL);
+}
+
+/**
+ *  e1000_set_i2c_data - Sets the I2C data bit
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *  @data: I2C data value (0 or 1) to set
+ *
+ *  Sets the I2C data bit
+ **/
+STATIC s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data)
+{
+       s32 status = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_set_i2c_data");
+
+       if (data)
+               *i2cctl |= E1000_I2C_DATA_OUT;
+       else
+               *i2cctl &= ~E1000_I2C_DATA_OUT;
+
+       *i2cctl &= ~E1000_I2C_DATA_OE_N;
+       *i2cctl |= E1000_I2C_CLK_OE_N;
+       E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
+       E1000_WRITE_FLUSH(hw);
+
+       /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
+       usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA);
+
+       *i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+       if (data != e1000_get_i2c_data(i2cctl)) {
+               status = E1000_ERR_I2C;
+               DEBUGOUT1("Error - I2C data was not set to %X.\n", data);
+       }
+
+       return status;
+}
+
+/**
+ *  e1000_get_i2c_data - Reads the I2C SDA data bit
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *
+ *  Returns the I2C data bit value
+ **/
+STATIC bool e1000_get_i2c_data(u32 *i2cctl)
+{
+       bool data;
+
+       DEBUGFUNC("e1000_get_i2c_data");
+
+       if (*i2cctl & E1000_I2C_DATA_IN)
+               data = 1;
+       else
+               data = 0;
+
+       return data;
+}
+
+/**
+ *  e1000_i2c_bus_clear - Clears the I2C bus
+ *  @hw: pointer to hardware structure
+ *
+ *  Clears the I2C bus by sending nine clock pulses.
+ *  Used when data line is stuck low.
+ **/
+void e1000_i2c_bus_clear(struct e1000_hw *hw)
+{
+       u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+       u32 i;
+
+       DEBUGFUNC("e1000_i2c_bus_clear");
+
+       e1000_i2c_start(hw);
+
+       e1000_set_i2c_data(hw, &i2cctl, 1);
+
+       for (i = 0; i < 9; i++) {
+               e1000_raise_i2c_clk(hw, &i2cctl);
+
+               /* Min high period of clock is 4us */
+               usec_delay(E1000_I2C_T_HIGH);
+
+               e1000_lower_i2c_clk(hw, &i2cctl);
+
+               /* Min low period of clock is 4.7us*/
+               usec_delay(E1000_I2C_T_LOW);
+       }
+
+       e1000_i2c_start(hw);
+
+       /* Put the i2c bus back to default state */
+       e1000_i2c_stop(hw);
+}
+
index f0857d4..0a144d7 100644 (file)
@@ -488,4 +488,23 @@ void e1000_rlpml_set_vf(struct e1000_hw *, u16);
 s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type);
 u16 e1000_rxpbs_adjust_82580(u32 data);
 s32 e1000_set_eee_i350(struct e1000_hw *);
+
+/* I2C SDA and SCL timing parameters for standard mode */
+#define E1000_I2C_T_HD_STA     4
+#define E1000_I2C_T_LOW                5
+#define E1000_I2C_T_HIGH       4
+#define E1000_I2C_T_SU_STA     5
+#define E1000_I2C_T_HD_DATA    5
+#define E1000_I2C_T_SU_DATA    1
+#define E1000_I2C_T_RISE       1
+#define E1000_I2C_T_FALL       1
+#define E1000_I2C_T_SU_STO     4
+#define E1000_I2C_T_BUF                5
+
+s32 e1000_set_i2c_bb(struct e1000_hw *hw);
+s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+                               u8 dev_addr, u8 *data);
+s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+                                u8 dev_addr, u8 data);
+void e1000_i2c_bus_clear(struct e1000_hw *hw);
 #endif /* _E1000_82575_H_ */
index 3b18f1f..b2125e2 100644 (file)
@@ -154,6 +154,140 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
        DEBUGFUNC("e1000_set_mac_type");
 
        switch (hw->device_id) {
+       case E1000_DEV_ID_82542:
+               mac->type = e1000_82542;
+               break;
+       case E1000_DEV_ID_82543GC_FIBER:
+       case E1000_DEV_ID_82543GC_COPPER:
+               mac->type = e1000_82543;
+               break;
+       case E1000_DEV_ID_82544EI_COPPER:
+       case E1000_DEV_ID_82544EI_FIBER:
+       case E1000_DEV_ID_82544GC_COPPER:
+       case E1000_DEV_ID_82544GC_LOM:
+               mac->type = e1000_82544;
+               break;
+       case E1000_DEV_ID_82540EM:
+       case E1000_DEV_ID_82540EM_LOM:
+       case E1000_DEV_ID_82540EP:
+       case E1000_DEV_ID_82540EP_LOM:
+       case E1000_DEV_ID_82540EP_LP:
+               mac->type = e1000_82540;
+               break;
+       case E1000_DEV_ID_82545EM_COPPER:
+       case E1000_DEV_ID_82545EM_FIBER:
+               mac->type = e1000_82545;
+               break;
+       case E1000_DEV_ID_82545GM_COPPER:
+       case E1000_DEV_ID_82545GM_FIBER:
+       case E1000_DEV_ID_82545GM_SERDES:
+               mac->type = e1000_82545_rev_3;
+               break;
+       case E1000_DEV_ID_82546EB_COPPER:
+       case E1000_DEV_ID_82546EB_FIBER:
+       case E1000_DEV_ID_82546EB_QUAD_COPPER:
+               mac->type = e1000_82546;
+               break;
+       case E1000_DEV_ID_82546GB_COPPER:
+       case E1000_DEV_ID_82546GB_FIBER:
+       case E1000_DEV_ID_82546GB_SERDES:
+       case E1000_DEV_ID_82546GB_PCIE:
+       case E1000_DEV_ID_82546GB_QUAD_COPPER:
+       case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
+               mac->type = e1000_82546_rev_3;
+               break;
+       case E1000_DEV_ID_82541EI:
+       case E1000_DEV_ID_82541EI_MOBILE:
+       case E1000_DEV_ID_82541ER_LOM:
+               mac->type = e1000_82541;
+               break;
+       case E1000_DEV_ID_82541ER:
+       case E1000_DEV_ID_82541GI:
+       case E1000_DEV_ID_82541GI_LF:
+       case E1000_DEV_ID_82541GI_MOBILE:
+               mac->type = e1000_82541_rev_2;
+               break;
+       case E1000_DEV_ID_82547EI:
+       case E1000_DEV_ID_82547EI_MOBILE:
+               mac->type = e1000_82547;
+               break;
+       case E1000_DEV_ID_82547GI:
+               mac->type = e1000_82547_rev_2;
+               break;
+       case E1000_DEV_ID_82571EB_COPPER:
+       case E1000_DEV_ID_82571EB_FIBER:
+       case E1000_DEV_ID_82571EB_SERDES:
+       case E1000_DEV_ID_82571EB_SERDES_DUAL:
+       case E1000_DEV_ID_82571EB_SERDES_QUAD:
+       case E1000_DEV_ID_82571EB_QUAD_COPPER:
+       case E1000_DEV_ID_82571PT_QUAD_COPPER:
+       case E1000_DEV_ID_82571EB_QUAD_FIBER:
+       case E1000_DEV_ID_82571EB_QUAD_COPPER_LP:
+               mac->type = e1000_82571;
+               break;
+       case E1000_DEV_ID_82572EI:
+       case E1000_DEV_ID_82572EI_COPPER:
+       case E1000_DEV_ID_82572EI_FIBER:
+       case E1000_DEV_ID_82572EI_SERDES:
+               mac->type = e1000_82572;
+               break;
+       case E1000_DEV_ID_82573E:
+       case E1000_DEV_ID_82573E_IAMT:
+       case E1000_DEV_ID_82573L:
+               mac->type = e1000_82573;
+               break;
+       case E1000_DEV_ID_82574L:
+       case E1000_DEV_ID_82574LA:
+               mac->type = e1000_82574;
+               break;
+       case E1000_DEV_ID_82583V:
+               mac->type = e1000_82583;
+               break;
+       case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
+       case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
+       case E1000_DEV_ID_80003ES2LAN_COPPER_SPT:
+       case E1000_DEV_ID_80003ES2LAN_SERDES_SPT:
+               mac->type = e1000_80003es2lan;
+               break;
+       case E1000_DEV_ID_ICH8_IFE:
+       case E1000_DEV_ID_ICH8_IFE_GT:
+       case E1000_DEV_ID_ICH8_IFE_G:
+       case E1000_DEV_ID_ICH8_IGP_M:
+       case E1000_DEV_ID_ICH8_IGP_M_AMT:
+       case E1000_DEV_ID_ICH8_IGP_AMT:
+       case E1000_DEV_ID_ICH8_IGP_C:
+       case E1000_DEV_ID_ICH8_82567V_3:
+               mac->type = e1000_ich8lan;
+               break;
+       case E1000_DEV_ID_ICH9_IFE:
+       case E1000_DEV_ID_ICH9_IFE_GT:
+       case E1000_DEV_ID_ICH9_IFE_G:
+       case E1000_DEV_ID_ICH9_IGP_M:
+       case E1000_DEV_ID_ICH9_IGP_M_AMT:
+       case E1000_DEV_ID_ICH9_IGP_M_V:
+       case E1000_DEV_ID_ICH9_IGP_AMT:
+       case E1000_DEV_ID_ICH9_BM:
+       case E1000_DEV_ID_ICH9_IGP_C:
+       case E1000_DEV_ID_ICH10_R_BM_LM:
+       case E1000_DEV_ID_ICH10_R_BM_LF:
+       case E1000_DEV_ID_ICH10_R_BM_V:
+               mac->type = e1000_ich9lan;
+               break;
+       case E1000_DEV_ID_ICH10_D_BM_LM:
+       case E1000_DEV_ID_ICH10_D_BM_LF:
+       case E1000_DEV_ID_ICH10_D_BM_V:
+               mac->type = e1000_ich10lan;
+               break;
+       case E1000_DEV_ID_PCH_D_HV_DM:
+       case E1000_DEV_ID_PCH_D_HV_DC:
+       case E1000_DEV_ID_PCH_M_HV_LM:
+       case E1000_DEV_ID_PCH_M_HV_LC:
+               mac->type = e1000_pchlan;
+               break;
+       case E1000_DEV_ID_PCH2_LV_LM:
+       case E1000_DEV_ID_PCH2_LV_V:
+               mac->type = e1000_pch2lan;
+               break;
        case E1000_DEV_ID_82575EB_COPPER:
        case E1000_DEV_ID_82575EB_FIBER_SERDES:
        case E1000_DEV_ID_82575GB_QUAD_COPPER:
@@ -188,12 +322,26 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
        case E1000_DEV_ID_I350_DA4:
                mac->type = e1000_i350;
                break;
+       case E1000_DEV_ID_I210_COPPER:
+       case E1000_DEV_ID_I210_COPPER_OEM1:
+       case E1000_DEV_ID_I210_COPPER_IT:
+       case E1000_DEV_ID_I210_FIBER:
+       case E1000_DEV_ID_I210_SERDES:
+       case E1000_DEV_ID_I210_SGMII:
+               mac->type = e1000_i210;
+               break;
+       case E1000_DEV_ID_I211_COPPER:
+       mac->type = e1000_i211;
+       break;
        case E1000_DEV_ID_82576_VF:
+       case E1000_DEV_ID_82576_VF_HV:
                mac->type = e1000_vfadapt;
                break;
        case E1000_DEV_ID_I350_VF:
+       case E1000_DEV_ID_I350_VF_HV:
                mac->type = e1000_vfadapt_i350;
                break;
+
        default:
                /* Should never have loaded on this device */
                ret_val = -E1000_ERR_MAC_INIT;
@@ -247,12 +395,53 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
         * the functions in that family.
         */
        switch (hw->mac.type) {
+       case e1000_82542:
+               e1000_init_function_pointers_82542(hw);
+               break;
+       case e1000_82543:
+       case e1000_82544:
+               e1000_init_function_pointers_82543(hw);
+               break;
+       case e1000_82540:
+       case e1000_82545:
+       case e1000_82545_rev_3:
+       case e1000_82546:
+       case e1000_82546_rev_3:
+               e1000_init_function_pointers_82540(hw);
+               break;
+       case e1000_82541:
+       case e1000_82541_rev_2:
+       case e1000_82547:
+       case e1000_82547_rev_2:
+               e1000_init_function_pointers_82541(hw);
+               break;
+       case e1000_82571:
+       case e1000_82572:
+       case e1000_82573:
+       case e1000_82574:
+       case e1000_82583:
+               e1000_init_function_pointers_82571(hw);
+               break;
+       case e1000_80003es2lan:
+               e1000_init_function_pointers_80003es2lan(hw);
+               break;
+       case e1000_ich8lan:
+       case e1000_ich9lan:
+       case e1000_ich10lan:
+       case e1000_pchlan:
+       case e1000_pch2lan:
+               e1000_init_function_pointers_ich8lan(hw);
+               break;
        case e1000_82575:
        case e1000_82576:
        case e1000_82580:
        case e1000_i350:
                e1000_init_function_pointers_82575(hw);
                break;
+       case e1000_i210:
+       case e1000_i211:
+               e1000_init_function_pointers_i210(hw);
+               break;
        case e1000_vfadapt:
                e1000_init_function_pointers_vf(hw);
                break;
@@ -819,6 +1008,18 @@ s32 e1000_acquire_phy(struct e1000_hw *hw)
        return E1000_SUCCESS;
 }
 
+/**
+ *  e1000_cfg_on_link_up - Configure PHY upon link up
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_cfg_on_link_up(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.cfg_on_link_up)
+               return hw->phy.ops.cfg_on_link_up(hw);
+
+       return E1000_SUCCESS;
+}
+
 /**
  *  e1000_read_kmrn_reg - Reads register using Kumeran interface
  *  @hw: pointer to the HW structure
index 9a1e5c7..4cbbdd8 100644 (file)
@@ -36,12 +36,21 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include "e1000_hw.h"
 
+extern void e1000_init_function_pointers_82542(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82543(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82540(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82571(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82541(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw);
 extern void    e1000_init_function_pointers_82575(struct e1000_hw *hw);
 extern void    e1000_rx_fifo_flush_82575(struct e1000_hw *hw);
 extern void    e1000_init_function_pointers_vf(struct e1000_hw *hw);
 extern void    e1000_power_up_fiber_serdes_link(struct e1000_hw *hw);
 extern void    e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_i210(struct e1000_hw *hw);
 
+s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr);
 s32  e1000_set_mac_type(struct e1000_hw *hw);
 s32  e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device);
 s32  e1000_init_mac_params(struct e1000_hw *hw);
@@ -81,6 +90,7 @@ s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset,
 s32  e1000_get_phy_info(struct e1000_hw *hw);
 void e1000_release_phy(struct e1000_hw *hw);
 s32  e1000_acquire_phy(struct e1000_hw *hw);
+s32  e1000_cfg_on_link_up(struct e1000_hw *hw);
 s32  e1000_phy_hw_reset(struct e1000_hw *hw);
 s32  e1000_phy_commit(struct e1000_hw *hw);
 void e1000_power_up_phy(struct e1000_hw *hw);
@@ -106,6 +116,9 @@ s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
 s32  e1000_mng_write_cmd_header(struct e1000_hw *hw,
                                 struct e1000_host_mng_command_header *hdr);
 s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length);
+u32  e1000_translate_register_82542(u32 reg);
+
+
 
 /*
  * TBI_ACCEPT macro definition:
@@ -149,3 +162,6 @@ s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length);
           (((length) > min_frame_size) && \
            ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1)))))
 
+#define E1000_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define E1000_DIVIDE_ROUND_UP(a, b)    (((a) + (b) - 1) / (b)) /* ceil(a/b) */
+#endif /* _E1000_API_H_ */
index 1cc0fcb..6339370 100644 (file)
@@ -49,6 +49,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_WUC_LSCWO      0x00000020 /* Link Status wake up override */
 #define E1000_WUC_SPM        0x80000000 /* Enable SPM */
 #define E1000_WUC_PHY_WAKE   0x00000100 /* if PHY supports wakeup */
+#define E1000_WUC_FLX6_PHY     0x4000 /* Flexible Filter 6 Enable */
+#define E1000_WUC_FLX7_PHY     0x8000 /* Flexible Filter 7 Enable */
 
 /* Wake Up Filter Control */
 #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
@@ -59,15 +61,35 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_WUFC_ARP  0x00000020 /* ARP Request Packet Wakeup Enable */
 #define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
 #define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
+#define E1000_WUFC_IGNORE_TCO_PHY 0x00000800 /* Ignore WakeOn TCO packets */
+#define E1000_WUFC_FLX0_PHY    0x00001000 /* Flexible Filter 0 Enable */
+#define E1000_WUFC_FLX1_PHY    0x00002000 /* Flexible Filter 1 Enable */
+#define E1000_WUFC_FLX2_PHY    0x00004000 /* Flexible Filter 2 Enable */
+#define E1000_WUFC_FLX3_PHY    0x00008000 /* Flexible Filter 3 Enable */
+#define E1000_WUFC_FLX4_PHY    0x00000200 /* Flexible Filter 4 Enable */
+#define E1000_WUFC_FLX5_PHY    0x00000400 /* Flexible Filter 5 Enable */
 #define E1000_WUFC_IGNORE_TCO   0x00008000 /* Ignore WakeOn TCO packets */
 #define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
 #define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
 #define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
 #define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
+#define E1000_WUFC_FLX4                0x00100000 /* Flexible Filter 4 Enable */
+#define E1000_WUFC_FLX5                0x00200000 /* Flexible Filter 5 Enable */
+#define E1000_WUFC_FLX6                0x00400000 /* Flexible Filter 6 Enable */
+#define E1000_WUFC_FLX7                0x00800000 /* Flexible Filter 7 Enable */
 #define E1000_WUFC_FW_RST 0x80000000 /* Wake on FW Reset Enable */
-#define E1000_WUFC_ALL_FILTERS  0x000F00FF /* Mask for all wakeup filters */
-#define E1000_WUFC_FLX_OFFSET   16 /* Offset to the Flexible Filters bits */
-#define E1000_WUFC_FLX_FILTERS  0x000F0000 /*Mask for the 4 flexible filters */
+#define E1000_WUFC_ALL_FILTERS_PHY_4   0x0000F0FF /* wakeup filters mask */
+#define E1000_WUFC_FLX_OFFSET_PHY      12 /* Flexible Filters bits offset */
+#define E1000_WUFC_FLX_FILTERS_PHY_4   0x0000F000 /* 4 flexible filters mask */
+#define E1000_WUFC_ALL_FILTERS_PHY_6   0x0000F6FF /* 6 wakeup filters mask */
+#define E1000_WUFC_FLX_FILTERS_PHY_6   0x0000F600 /* 6 flexible filters mask */
+#define E1000_WUFC_ALL_FILTERS         0x000F00FF /* all wakeup filters mask */
+#define E1000_WUFC_ALL_FILTERS_6       0x003F00FF /* Mask all 6 wu filters */
+#define E1000_WUFC_ALL_FILTERS_8       0x00FF00FF /* Mask all 8 wu filters */
+#define E1000_WUFC_FLX_OFFSET          16 /* Flexible Filters bits offset */
+#define E1000_WUFC_FLX_FILTERS         0x000F0000 /* 4 flexible filters mask */
+#define E1000_WUFC_FLX_FILTERS_6       0x003F0000 /* 6 flexible filters mask */
+#define E1000_WUFC_FLX_FILTERS_8       0x00FF0000 /* 8 flexible filters mask */
 /*
  * For 82576 to utilize Extended filter masks in addition to
  * existing (filter) masks
@@ -83,17 +105,37 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_WUS_ARP          E1000_WUFC_ARP
 #define E1000_WUS_IPV4         E1000_WUFC_IPV4
 #define E1000_WUS_IPV6         E1000_WUFC_IPV6
+#define E1000_WUS_FLX0_PHY     E1000_WUFC_FLX0_PHY
+#define E1000_WUS_FLX1_PHY     E1000_WUFC_FLX1_PHY
+#define E1000_WUS_FLX2_PHY     E1000_WUFC_FLX2_PHY
+#define E1000_WUS_FLX3_PHY     E1000_WUFC_FLX3_PHY
+#define E1000_WUS_FLX_FILTERS_PHY_4    E1000_WUFC_FLX_FILTERS_PHY_4
 #define E1000_WUS_FLX0         E1000_WUFC_FLX0
 #define E1000_WUS_FLX1         E1000_WUFC_FLX1
 #define E1000_WUS_FLX2         E1000_WUFC_FLX2
 #define E1000_WUS_FLX3         E1000_WUFC_FLX3
+#define E1000_WUS_FLX4         E1000_WUFC_FLX4
+#define E1000_WUS_FLX5         E1000_WUFC_FLX5
+#define E1000_WUS_FLX6         E1000_WUFC_FLX6
+#define E1000_WUS_FLX7         E1000_WUFC_FLX7
+#define E1000_WUS_FLX4_PHY     E1000_WUFC_FLX4_PHY
+#define E1000_WUS_FLX5_PHY     E1000_WUFC_FLX5_PHY
+#define E1000_WUS_FLX6_PHY     0x0400
+#define E1000_WUS_FLX7_PHY     0x0800
 #define E1000_WUS_FLX_FILTERS  E1000_WUFC_FLX_FILTERS
+#define E1000_WUS_FLX_FILTERS_6                E1000_WUFC_FLX_FILTERS_6
+#define E1000_WUS_FLX_FILTERS_8                E1000_WUFC_FLX_FILTERS_8
+#define E1000_WUS_FLX_FILTERS_PHY_6    E1000_WUFC_FLX_FILTERS_PHY_6
 
 /* Wake Up Packet Length */
 #define E1000_WUPL_LENGTH_MASK 0x0FFF   /* Only the lower 12 bits are valid */
 
 /* Four Flexible Filters are supported */
 #define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
+/* Six Flexible Filters are supported */
+#define E1000_FLEXIBLE_FILTER_COUNT_MAX_6      6
+/* Eight Flexible Filters are supported */
+#define E1000_FLEXIBLE_FILTER_COUNT_MAX_8      8
 /* Two Extended Flexible Filters are supported (82576) */
 #define E1000_EXT_FLEXIBLE_FILTER_COUNT_MAX     2
 #define E1000_FHFT_LENGTH_OFFSET        0xFC /* Length byte in FHFT */
@@ -103,6 +145,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_FLEXIBLE_FILTER_SIZE_MAX  128
 
 #define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX
+#define E1000_FFLT_SIZE_6      E1000_FLEXIBLE_FILTER_COUNT_MAX_6
+#define E1000_FFLT_SIZE_8      E1000_FLEXIBLE_FILTER_COUNT_MAX_8
 #define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
 #define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
 
@@ -132,6 +176,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
 #define E1000_CTRL_EXT_DMA_DYN_CLK_EN  0x00080000 /* DMA Dynamic Clk Gating */
 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
+/* Offset of the link mode field in Ctrl Ext register */
+#define E1000_CTRL_EXT_LINK_MODE_OFFSET        22
 #define E1000_CTRL_EXT_LINK_MODE_82580_MASK 0x01C00000 /*82580 bit 24:22*/
 #define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX  0x00400000
 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
@@ -157,6 +203,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_CTRL_EXT_DF_PAREN                0x02000000
 #define E1000_CTRL_EXT_GHOST_PAREN    0x40000000
 #define E1000_CTRL_EXT_PBA_CLR        0x80000000 /* PBA Clear */
+#define E1000_CTRL_EXT_LSECCK          0x00001000
+#define E1000_CTRL_EXT_PHYPDEN         0x00100000
 #define E1000_I2CCMD_REG_ADDR_SHIFT   16
 #define E1000_I2CCMD_REG_ADDR         0x00FF0000
 #define E1000_I2CCMD_PHY_ADDR_SHIFT   24
@@ -167,6 +215,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_I2CCMD_READY            0x20000000
 #define E1000_I2CCMD_INTERRUPT_ENA    0x40000000
 #define E1000_I2CCMD_ERROR            0x80000000
+#define E1000_I2CCMD_SFP_DATA_ADDR(a)  (0x0000 + (a))
+#define E1000_I2CCMD_SFP_DIAG_ADDR(a)  (0x0100 + (a))
 #define E1000_MAX_SGMII_PHY_REG_ADDR  255
 #define E1000_I2CCMD_PHY_TIMEOUT      200
 #define E1000_IVAR_VALID        0x80
@@ -202,6 +252,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_RXD_SPC_CFI_MASK  0x1000  /* CFI is bit 12 */
 #define E1000_RXD_SPC_CFI_SHIFT 12
 
+#define E1000_RXDEXT_STATERR_TST       0x00000100 /* Time Stamp taken */
 #define E1000_RXDEXT_STATERR_LB    0x00040000
 #define E1000_RXDEXT_STATERR_CE    0x01000000
 #define E1000_RXDEXT_STATERR_SE    0x02000000
@@ -211,6 +262,13 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_RXDEXT_STATERR_IPE   0x40000000
 #define E1000_RXDEXT_STATERR_RXE   0x80000000
 
+#define E1000_RXDEXT_LSECH             0x01000000
+#define E1000_RXDEXT_LSECE_MASK                0x60000000
+#define E1000_RXDEXT_LSECE_NO_ERROR    0x00000000
+#define E1000_RXDEXT_LSECE_NO_SA_MATCH 0x20000000
+#define E1000_RXDEXT_LSECE_REPLAY_DETECT 0x40000000
+#define E1000_RXDEXT_LSECE_BAD_SIG     0x60000000
+
 /* mask to determine if packets should be dropped due to frame errors */
 #define E1000_RXD_ERR_FRAME_ERR_MASK ( \
     E1000_RXD_ERR_CE  |                \
@@ -227,6 +285,10 @@ POSSIBILITY OF SUCH DAMAGE.
     E1000_RXDEXT_STATERR_CXE |            \
     E1000_RXDEXT_STATERR_RXE)
 
+/* Packet Types as indicated in the Adv/Ext receive descriptor. */
+#define E1000_RXD_PKTTYPE_MASK                 0x000F0000
+#define E1000_RXD_PKTTYPE_PTP                  0x000E0000
+
 #define E1000_MRQC_ENABLE_MASK                 0x00000007
 #define E1000_MRQC_ENABLE_RSS_2Q               0x00000001
 #define E1000_MRQC_ENABLE_RSS_INT              0x00000004
@@ -389,6 +451,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_CTRL_FORCE_PHY_RESET     0x00008000
 /* enable link status from external LINK_0 and LINK_1 pins */
 #define E1000_CTRL_EXT_LINK_EN         0x00010000
+#define E1000_CTRL_LANPHYPC_OVERRIDE   0x00010000 /* SW control of LANPHYPC */
+#define E1000_CTRL_LANPHYPC_VALUE      0x00020000 /* SW value of LANPHYPC */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
 #define E1000_CTRL_SWDPIN2  0x00100000  /* SWDPIN 2 value */
@@ -525,6 +589,11 @@ POSSIBILITY OF SUCH DAMAGE.
 #define AUTONEG_ADVERTISE_SPEED_DEFAULT   E1000_ALL_SPEED_DUPLEX
 
 /* LED Control */
+#define E1000_PHY_LED0_MODE_MASK       0x00000007
+#define E1000_PHY_LED0_IVRT            0x00000008
+#define E1000_PHY_LED0_BLINK           0x00000010
+#define E1000_PHY_LED0_MASK            0x0000001F
+
 #define E1000_LEDCTL_LED0_MODE_MASK       0x0000000F
 #define E1000_LEDCTL_LED0_MODE_SHIFT      0
 #define E1000_LEDCTL_LED0_BLINK_RATE      0x00000020
@@ -586,6 +655,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_TXD_CMD_TSE    0x04000000 /* TCP Seg enable */
 #define E1000_TXD_STAT_TC    0x00000004 /* Tx Underrun */
 /* Extended desc bits for Linksec and timesync */
+#define E1000_TXD_CMD_LINKSEC  0x10000000 /* Apply LinkSec on packet */
+#define E1000_TXD_EXTCMD_TSTAMP        0x00000010 /* IEEE1588 Timestamp packet */
 
 /* Transmit Control */
 #define E1000_TCTL_RST    0x00000001    /* software reset */
@@ -640,6 +711,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_COLD_SHIFT                12
 
 /* Default values for the transmit IPG register */
+#define DEFAULT_82542_TIPG_IPGT                10
 #define DEFAULT_82543_TIPG_IPGT_FIBER  9
 #define DEFAULT_82543_TIPG_IPGT_COPPER 8
 
@@ -647,9 +719,11 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_TIPG_IPGR1_MASK 0x000FFC00
 #define E1000_TIPG_IPGR2_MASK 0x3FF00000
 
+#define DEFAULT_82542_TIPG_IPGR1       2
 #define DEFAULT_82543_TIPG_IPGR1 8
 #define E1000_TIPG_IPGR1_SHIFT  10
 
+#define DEFAULT_82542_TIPG_IPGR2       10
 #define DEFAULT_82543_TIPG_IPGR2 6
 #define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
 #define E1000_TIPG_IPGR2_SHIFT  20
@@ -679,6 +753,11 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #define E1000_KABGTXD_BGSQLBIAS           0x00050000
 
+/* Low Power IDLE Control */
+#define E1000_LPIC_1000ENABLE          0x00010000
+#define E1000_LPIC_100ENABLE           0x00020000
+#define E1000_LPIC_LPIET_SHIFT         24      /* Low Power Idle Entry Time */
+
 /* PBA constants */
 #define E1000_PBA_6K  0x0006    /* 6KB */
 #define E1000_PBA_8K  0x0008    /* 8KB */
@@ -700,6 +779,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_PBA_48K 0x0030    /* 48KB */
 #define E1000_PBA_64K 0x0040    /* 64KB */
 
+#define E1000_PBA_RXA_MASK     0xFFFF
+
 #define E1000_PBS_16K E1000_PBA_16K
 #define E1000_PBS_24K E1000_PBA_24K
 
@@ -737,6 +818,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_ICR_ACK           0x00020000 /* Receive Ack frame */
 #define E1000_ICR_MNG           0x00040000 /* Manageability event */
 #define E1000_ICR_DOCK          0x00080000 /* Dock/Undock */
+#define E1000_ICR_TS           0x00080000 /* Time Sync Interrupt */
 #define E1000_ICR_DRSTA         0x40000000 /* Device Reset Asserted */
 /* If this bit asserted, the driver should claim the interrupt */
 #define E1000_ICR_INT_ASSERTED 0x80000000
@@ -753,11 +835,26 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_ICR_PHYINT       0x00001000
 #define E1000_ICR_DOUTSYNC      0x10000000 /* NIC DMA out of sync */
 #define E1000_ICR_EPRST         0x00100000 /* ME hardware reset occurs */
+#define E1000_ICR_RXQ0         0x00100000 /* Rx Queue 0 Interrupt */
+#define E1000_ICR_RXQ1         0x00200000 /* Rx Queue 1 Interrupt */
+#define E1000_ICR_TXQ0         0x00400000 /* Tx Queue 0 Interrupt */
+#define E1000_ICR_TXQ1         0x00800000 /* Tx Queue 1 Interrupt */
+#define E1000_ICR_OTHER                0x01000000 /* Other Interrupts */
 #define E1000_ICR_FER           0x00400000 /* Fatal Error */
 
 #define E1000_ICR_THS           0x00800000 /* ICR.THS: Thermal Sensor Event*/
 #define E1000_ICR_MDDET         0x10000000 /* Malicious Driver Detect */
 
+#define E1000_ITR_MASK         0x000FFFFF /* ITR value bitfield */
+#define E1000_ITR_MULT         256 /* ITR mulitplier in nsec */
+
+/* PBA ECC Register */
+#define E1000_PBA_ECC_COUNTER_MASK     0xFFF00000 /* ECC counter mask */
+#define E1000_PBA_ECC_COUNTER_SHIFT    20 /* ECC counter shift value */
+#define E1000_PBA_ECC_CORR_EN  0x00000001 /* Enable ECC error correction */
+#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */
+#define E1000_PBA_ECC_INT_EN   0x00000004 /* Enable ICR bit 5 on ECC error */
+
 /* Extended Interrupt Cause Read */
 #define E1000_EICR_RX_QUEUE0    0x00000001 /* Rx Queue 0 Interrupt */
 #define E1000_EICR_RX_QUEUE1    0x00000002 /* Rx Queue 1 Interrupt */
@@ -821,6 +918,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_IMS_ACK       E1000_ICR_ACK       /* Receive Ack frame */
 #define E1000_IMS_MNG       E1000_ICR_MNG       /* Manageability event */
 #define E1000_IMS_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
+#define E1000_IMS_TS           E1000_ICR_TS      /* Time Sync Interrupt */
 #define E1000_IMS_DRSTA     E1000_ICR_DRSTA     /* Device Reset Asserted */
 /* Q0 Rx desc FIFO parity error */
 #define E1000_IMS_RXD_FIFO_PAR0        E1000_ICR_RXD_FIFO_PAR0
@@ -838,6 +936,11 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_IMS_PHYINT    E1000_ICR_PHYINT
 #define E1000_IMS_DOUTSYNC  E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
 #define E1000_IMS_EPRST     E1000_ICR_EPRST
+#define E1000_IMS_RXQ0         E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */
+#define E1000_IMS_RXQ1         E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */
+#define E1000_IMS_TXQ0         E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */
+#define E1000_IMS_TXQ1         E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */
+#define E1000_IMS_OTHER                E1000_ICR_OTHER /* Other Interrupts */
 #define E1000_IMS_FER           E1000_ICR_FER /* Fatal Error */
 
 #define E1000_IMS_THS           E1000_ICR_THS /* ICR.TS: Thermal Sensor Event*/
@@ -962,6 +1065,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_ERR_INVALID_ARGUMENT  16
 #define E1000_ERR_NO_SPACE          17
 #define E1000_ERR_NVM_PBA_SECTION   18
+#define E1000_ERR_I2C                  19
+#define E1000_ERR_INVM_VALUE_NOT_FOUND 20
 
 /* Loop limit on how long we wait for auto-negotiation to complete */
 #define FIBER_LINK_UP_LIMIT               50
@@ -1015,6 +1120,13 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_TSYNCRXCTL_TYPE_ALL         0x08
 #define E1000_TSYNCRXCTL_TYPE_EVENT_V2    0x0A
 #define E1000_TSYNCRXCTL_ENABLED    0x00000010 /* enable Rx timestamping */
+#define E1000_TSYNCRXCTL_SYSCFI                0x00000020 /* Sys clock frequency */
+
+#define E1000_RXMTRL_PTP_V1_SYNC_MESSAGE       0x00000000
+#define E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE  0x00010000
+
+#define E1000_RXMTRL_PTP_V2_SYNC_MESSAGE       0x00000000
+#define E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE  0x01000000
 
 #define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK   0x000000FF
 #define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE       0x00
@@ -1036,6 +1148,11 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE           0x0D00
 
 #define E1000_TIMINCA_16NS_SHIFT 24
+#define E1000_TIMINCA_INCPERIOD_SHIFT  24
+#define E1000_TIMINCA_INCVALUE_MASK    0x00FFFFFF
+
+#define E1000_TSICR_TXTS               0x00000002
+#define E1000_TSIM_TXTS                        0x00000002
 /* TUPLE Filtering Configuration */
 #define E1000_TTQF_DISABLE_MASK   0xF0008000     /* TTQF Disable Mask */
 #define E1000_TTQF_QUEUE_ENABLE   0x100          /* TTQF Queue Enable Bit */
@@ -1076,7 +1193,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_EEER_EEE_NEG             0x20000000 /* EEE capability nego */
 #define E1000_EEER_RX_LPI_STATUS    0x40000000  /* Rx in LPI state */
 #define E1000_EEER_TX_LPI_STATUS    0x80000000  /* Tx in LPI state */
-
+#define E1000_EEE_SU_LPI_CLK_STP       0x00800000 /* EEE LPI Clock Stop */
 /* PCI Express Control */
 #define E1000_GCR_RXD_NO_SNOOP          0x00000001
 #define E1000_GCR_RXDSCW_NO_SNOOP       0x00000002
@@ -1096,6 +1213,16 @@ POSSIBILITY OF SUCH DAMAGE.
                            E1000_GCR_TXDSCW_NO_SNOOP      | \
                            E1000_GCR_TXDSCR_NO_SNOOP)
 
+/* mPHY address control and data registers */
+#define E1000_MPHY_ADDR_CTL            0x0024 /* Address Control Reg */
+#define E1000_MPHY_ADDR_CTL_OFFSET_MASK        0xFFFF0000
+#define E1000_MPHY_DATA                        0x0E10 /* Data Register */
+
+/* AFE CSR Offset for PCS CLK */
+#define E1000_MPHY_PCS_CLK_REG_OFFSET  0x0004
+/* Override for near end digital loopback. */
+#define E1000_MPHY_PCS_CLK_REG_DIGINELBEN      0x10
+
 /* PHY Control Register */
 #define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
 #define MII_CR_COLL_TEST_ENABLE 0x0080  /* Collision test enable */
@@ -1240,6 +1367,17 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_EECD_SEC1VAL   0x00400000 /* Sector One Valid */
 #define E1000_EECD_SECVAL_SHIFT      22
 #define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES)
+#define E1000_EECD_FLUPD_I210          0x00800000 /* Update FLASH */
+#define E1000_EECD_FLUDONE_I210                0x04000000 /* Update FLASH done */
+#define E1000_EECD_FLASH_DETECTED_I210 0x00080000 /* FLASH detected */
+#define E1000_EECD_SEC1VAL_I210                0x02000000 /* Sector One Valid */
+#define E1000_FLUDONE_ATTEMPTS         20000
+#define E1000_EERD_EEWR_MAX_COUNT      512 /* buffered EEPROM words rw */
+#define E1000_I210_FIFO_SEL_RX         0x00
+#define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i))
+#define E1000_I210_FIFO_SEL_TX_LEGACY  E1000_I210_FIFO_SEL_TX_QAV(0)
+#define E1000_I210_FIFO_SEL_BMC2OS_TX  0x06
+#define E1000_I210_FIFO_SEL_BMC2OS_RX  0x01
 
 #define E1000_NVM_SWDPIN0   0x0001   /* SWDPIN 0 NVM Value */
 #define E1000_NVM_LED_LOGIC 0x0020   /* Led Logic Word */
@@ -1257,6 +1395,34 @@ POSSIBILITY OF SUCH DAMAGE.
 #define NVM_VERSION                0x0005
 #define NVM_SERDES_AMPLITUDE       0x0006 /* SERDES output amplitude */
 #define NVM_PHY_CLASS_WORD         0x0007
+#define NVM_FUTURE_INIT_WORD1          0x0019
+#define NVM_FUTURE_INIT_WORD2          0x001A
+#define NVM_ETRACK_WORD                        0x0042
+#define NVM_COMB_VER_OFF               0x0083
+#define NVM_COMB_VER_PTR               0x003d
+
+/* NVM version defines */
+#define NVM_MAJOR_MASK                 0xF000
+#define NVM_MINOR_MASK                 0x000F
+#define NVM_COMB_VER_MASK              0x00FF
+#define NVM_MAJOR_SHIFT                        12
+#define NVM_COMB_VER_SHFT              8
+#define NVM_VER_INVALID                        0xFFFF
+#define NVM_ETRACK_SHIFT               16
+
+#define NVM_MAC_ADDR                   0x0000
+#define NVM_SUB_DEV_ID                 0x000B
+#define NVM_SUB_VEN_ID                 0x000C
+#define NVM_DEV_ID                     0x000D
+#define NVM_VEN_ID                     0x000E
+#define NVM_INIT_CTRL_2                        0x000F
+#define NVM_INIT_CTRL_4                        0x0013
+#define NVM_LED_1_CFG                  0x001C
+#define NVM_LED_0_2_CFG                        0x001F
+
+#define NVM_COMPAT_VALID_CSUM          0x0001
+#define NVM_FUTURE_INIT_WORD1_VALID_CSUM       0x0040
+
 #define NVM_INIT_CONTROL1_REG      0x000A
 #define NVM_INIT_CONTROL2_REG      0x000F
 #define NVM_SWDEF_PINS_CTRL_PORT_1 0x0010
@@ -1276,11 +1442,16 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_NVM_CFG_DONE_PORT_2  0x100000 /* ...for third port */
 #define E1000_NVM_CFG_DONE_PORT_3  0x200000 /* ...for fourth port */
 
-#define NVM_82580_LAN_FUNC_OFFSET(a) (a ? (0x40 + (0x40 * a)) : 0)
+#define NVM_82580_LAN_FUNC_OFFSET(a)   ((a) ? (0x40 + (0x40 * (a))) : 0)
 
 /* Mask bits for fields in Word 0x24 of the NVM */
 #define NVM_WORD24_COM_MDIO         0x0008 /* MDIO interface shared */
 #define NVM_WORD24_EXT_MDIO            0x0004 /* MDIO accesses routed extrnl */
+/* Offset of Link Mode bits for 82575/82576 */
+#define NVM_WORD24_LNK_MODE_OFFSET     8
+/* Offset of Link Mode bits for 82580 up */
+#define NVM_WORD24_82580_LNK_MODE_OFFSET       4
+
 
 /* Mask bits for fields in Word 0x0f of the NVM */
 #define NVM_WORD0F_PAUSE_MASK       0x3000
@@ -1382,9 +1553,6 @@ POSSIBILITY OF SUCH DAMAGE.
 #define PCIE_LINK_SPEED_5000         0x02
 #define PCIE_DEVICE_CONTROL2_16ms    0x0005
 
-#ifndef ETH_ADDR_LEN
-#define ETH_ADDR_LEN                 6
-#endif
 
 #define PHY_REVISION_MASK      0xFFFFFFF0
 #define MAX_PHY_REG_ADDRESS    0x1F  /* 5 bit address bus (0-0x1F) */
@@ -1409,8 +1577,15 @@ POSSIBILITY OF SUCH DAMAGE.
 #define IFE_E_PHY_ID         0x02A80330
 #define IFE_PLUS_E_PHY_ID    0x02A80320
 #define IFE_C_E_PHY_ID       0x02A80310
+#define BME1000_E_PHY_ID       0x01410CB0
+#define BME1000_E_PHY_ID_R2    0x01410CB1
+#define I82577_E_PHY_ID                0x01540050
+#define I82578_E_PHY_ID                0x004DD040
+#define I82579_E_PHY_ID                0x01540090
+#define I217_E_PHY_ID          0x015400A0
 #define I82580_I_PHY_ID      0x015403A0
 #define I350_I_PHY_ID        0x015403B0
+#define I210_I_PHY_ID          0x01410C00
 #define IGP04E1000_E_PHY_ID  0x02A80391
 #define M88_VENDOR           0x0141
 
@@ -1554,6 +1729,12 @@ POSSIBILITY OF SUCH DAMAGE.
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X    0x0C00
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X    0x0E00
 
+#define I82578_EPSCR_DOWNSHIFT_ENABLE          0x0020
+#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK    0x001C
+
+/* BME1000 PHY Specific Control Register */
+#define BME1000_PSCR_ENABLE_DOWNSHIFT  0x0800 /* 1 = enable downshift */
+
 /*
  * Bits...
  * 15-5: page
@@ -1666,6 +1847,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_DMACR_DMAC_LX_MASK       0x30000000
 #define E1000_DMACR_DMAC_LX_SHIFT       28
 #define E1000_DMACR_DMAC_EN             0x80000000 /* Enable DMA Coalescing */
+/* DMA Coalescing BMC-to-OS Watchdog Enable */
+#define E1000_DMACR_DC_BMC2OSW_EN      0x00008000
 
 /* DMA Coalescing Transmit Threshold */
 #define E1000_DMCTXTH_DMCTTHR_MASK     0x00000FFF
@@ -1686,6 +1869,10 @@ POSSIBILITY OF SUCH DAMAGE.
 /* Lx power decision based on DMA coal */
 #define E1000_PCIEMISC_LX_DECISION     0x00000080
 
+#define E1000_RXPBS_CFG_TS_EN          0x80000000 /* Timestamp in Rx buffer */
+#define E1000_RXPBS_SIZE_I210_MASK     0x0000003F /* Rx packet buffer size */
+#define E1000_TXPB0S_SIZE_I210_MASK    0x0000003F /* Tx packet buffer 0 size */
+
 /* Proxy Filter Control */
 #define E1000_PROXYFC_D0               0x00000001  /* Enable offload in D0 */
 #define E1000_PROXYFC_EX               0x00000004  /* Directed exact proxy */
@@ -1701,4 +1888,11 @@ POSSIBILITY OF SUCH DAMAGE.
 
 /* Firmware Status */
 #define E1000_FWSTS_FWRI               0x80000000 /* FW Reset Indication */
+/* VF Control */
+#define E1000_VTCTRL_RST               0x04000000 /* Reset VF */
+
+#define E1000_STATUS_LAN_ID_MASK       0x00000000C /* Mask for Lan ID field */
+/* Lan ID bit field offset in status register */
+#define E1000_STATUS_LAN_ID_OFFSET     2
+#define E1000_VFTA_ENTRIES             128
 #endif /* _E1000_DEFINES_H_ */
index 5110121..64e7dc2 100644 (file)
@@ -40,6 +40,95 @@ POSSIBILITY OF SUCH DAMAGE.
 
 struct e1000_hw;
 
+#define E1000_DEV_ID_82542                     0x1000
+#define E1000_DEV_ID_82543GC_FIBER             0x1001
+#define E1000_DEV_ID_82543GC_COPPER            0x1004
+#define E1000_DEV_ID_82544EI_COPPER            0x1008
+#define E1000_DEV_ID_82544EI_FIBER             0x1009
+#define E1000_DEV_ID_82544GC_COPPER            0x100C
+#define E1000_DEV_ID_82544GC_LOM               0x100D
+#define E1000_DEV_ID_82540EM                   0x100E
+#define E1000_DEV_ID_82540EM_LOM               0x1015
+#define E1000_DEV_ID_82540EP_LOM               0x1016
+#define E1000_DEV_ID_82540EP                   0x1017
+#define E1000_DEV_ID_82540EP_LP                        0x101E
+#define E1000_DEV_ID_82545EM_COPPER            0x100F
+#define E1000_DEV_ID_82545EM_FIBER             0x1011
+#define E1000_DEV_ID_82545GM_COPPER            0x1026
+#define E1000_DEV_ID_82545GM_FIBER             0x1027
+#define E1000_DEV_ID_82545GM_SERDES            0x1028
+#define E1000_DEV_ID_82546EB_COPPER            0x1010
+#define E1000_DEV_ID_82546EB_FIBER             0x1012
+#define E1000_DEV_ID_82546EB_QUAD_COPPER       0x101D
+#define E1000_DEV_ID_82546GB_COPPER            0x1079
+#define E1000_DEV_ID_82546GB_FIBER             0x107A
+#define E1000_DEV_ID_82546GB_SERDES            0x107B
+#define E1000_DEV_ID_82546GB_PCIE              0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER       0x1099
+#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3  0x10B5
+#define E1000_DEV_ID_82541EI                   0x1013
+#define E1000_DEV_ID_82541EI_MOBILE            0x1018
+#define E1000_DEV_ID_82541ER_LOM               0x1014
+#define E1000_DEV_ID_82541ER                   0x1078
+#define E1000_DEV_ID_82541GI                   0x1076
+#define E1000_DEV_ID_82541GI_LF                        0x107C
+#define E1000_DEV_ID_82541GI_MOBILE            0x1077
+#define E1000_DEV_ID_82547EI                   0x1019
+#define E1000_DEV_ID_82547EI_MOBILE            0x101A
+#define E1000_DEV_ID_82547GI                   0x1075
+#define E1000_DEV_ID_82571EB_COPPER            0x105E
+#define E1000_DEV_ID_82571EB_FIBER             0x105F
+#define E1000_DEV_ID_82571EB_SERDES            0x1060
+#define E1000_DEV_ID_82571EB_SERDES_DUAL       0x10D9
+#define E1000_DEV_ID_82571EB_SERDES_QUAD       0x10DA
+#define E1000_DEV_ID_82571EB_QUAD_COPPER       0x10A4
+#define E1000_DEV_ID_82571PT_QUAD_COPPER       0x10D5
+#define E1000_DEV_ID_82571EB_QUAD_FIBER                0x10A5
+#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP    0x10BC
+#define E1000_DEV_ID_82572EI_COPPER            0x107D
+#define E1000_DEV_ID_82572EI_FIBER             0x107E
+#define E1000_DEV_ID_82572EI_SERDES            0x107F
+#define E1000_DEV_ID_82572EI                   0x10B9
+#define E1000_DEV_ID_82573E                    0x108B
+#define E1000_DEV_ID_82573E_IAMT               0x108C
+#define E1000_DEV_ID_82573L                    0x109A
+#define E1000_DEV_ID_82574L                    0x10D3
+#define E1000_DEV_ID_82574LA                   0x10F6
+#define E1000_DEV_ID_82583V                    0x150C
+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT    0x1096
+#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT    0x1098
+#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT    0x10BA
+#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT    0x10BB
+#define E1000_DEV_ID_ICH8_82567V_3             0x1501
+#define E1000_DEV_ID_ICH8_IGP_M_AMT            0x1049
+#define E1000_DEV_ID_ICH8_IGP_AMT              0x104A
+#define E1000_DEV_ID_ICH8_IGP_C                        0x104B
+#define E1000_DEV_ID_ICH8_IFE                  0x104C
+#define E1000_DEV_ID_ICH8_IFE_GT               0x10C4
+#define E1000_DEV_ID_ICH8_IFE_G                        0x10C5
+#define E1000_DEV_ID_ICH8_IGP_M                        0x104D
+#define E1000_DEV_ID_ICH9_IGP_M                        0x10BF
+#define E1000_DEV_ID_ICH9_IGP_M_AMT            0x10F5
+#define E1000_DEV_ID_ICH9_IGP_M_V              0x10CB
+#define E1000_DEV_ID_ICH9_IGP_AMT              0x10BD
+#define E1000_DEV_ID_ICH9_BM                   0x10E5
+#define E1000_DEV_ID_ICH9_IGP_C                        0x294C
+#define E1000_DEV_ID_ICH9_IFE                  0x10C0
+#define E1000_DEV_ID_ICH9_IFE_GT               0x10C3
+#define E1000_DEV_ID_ICH9_IFE_G                        0x10C2
+#define E1000_DEV_ID_ICH10_R_BM_LM             0x10CC
+#define E1000_DEV_ID_ICH10_R_BM_LF             0x10CD
+#define E1000_DEV_ID_ICH10_R_BM_V              0x10CE
+#define E1000_DEV_ID_ICH10_D_BM_LM             0x10DE
+#define E1000_DEV_ID_ICH10_D_BM_LF             0x10DF
+#define E1000_DEV_ID_ICH10_D_BM_V              0x1525
+
+#define E1000_DEV_ID_PCH_M_HV_LM               0x10EA
+#define E1000_DEV_ID_PCH_M_HV_LC               0x10EB
+#define E1000_DEV_ID_PCH_D_HV_DM               0x10EF
+#define E1000_DEV_ID_PCH_D_HV_DC               0x10F0
+#define E1000_DEV_ID_PCH2_LV_LM                        0x1502
+#define E1000_DEV_ID_PCH2_LV_V                 0x1503
 #define E1000_DEV_ID_82576                    0x10C9
 #define E1000_DEV_ID_82576_FIBER              0x10E6
 #define E1000_DEV_ID_82576_SERDES             0x10E7
@@ -49,7 +138,9 @@ struct e1000_hw;
 #define E1000_DEV_ID_82576_NS_SERDES          0x1518
 #define E1000_DEV_ID_82576_SERDES_QUAD        0x150D
 #define E1000_DEV_ID_82576_VF                 0x10CA
+#define E1000_DEV_ID_82576_VF_HV               0x152D
 #define E1000_DEV_ID_I350_VF                  0x1520
+#define E1000_DEV_ID_I350_VF_HV                        0x152F
 #define E1000_DEV_ID_82575EB_COPPER           0x10A7
 #define E1000_DEV_ID_82575EB_FIBER_SERDES     0x10A9
 #define E1000_DEV_ID_82575GB_QUAD_COPPER      0x10D6
@@ -64,6 +155,13 @@ struct e1000_hw;
 #define E1000_DEV_ID_I350_SERDES              0x1523
 #define E1000_DEV_ID_I350_SGMII               0x1524
 #define E1000_DEV_ID_I350_DA4                 0x1546
+#define E1000_DEV_ID_I210_COPPER               0x1533
+#define E1000_DEV_ID_I210_COPPER_OEM1          0x1534
+#define E1000_DEV_ID_I210_COPPER_IT            0x1535
+#define E1000_DEV_ID_I210_FIBER                        0x1536
+#define E1000_DEV_ID_I210_SERDES               0x1537
+#define E1000_DEV_ID_I210_SGMII                        0x1538
+#define E1000_DEV_ID_I211_COPPER               0x1539
 #define E1000_DEV_ID_DH89XXCC_SGMII           0x0438
 #define E1000_DEV_ID_DH89XXCC_SERDES          0x043A
 #define E1000_DEV_ID_DH89XXCC_BACKPLANE       0x043C
@@ -86,10 +184,35 @@ struct e1000_hw;
 
 enum e1000_mac_type {
        e1000_undefined = 0,
+       e1000_82542,
+       e1000_82543,
+       e1000_82544,
+       e1000_82540,
+       e1000_82545,
+       e1000_82545_rev_3,
+       e1000_82546,
+       e1000_82546_rev_3,
+       e1000_82541,
+       e1000_82541_rev_2,
+       e1000_82547,
+       e1000_82547_rev_2,
+       e1000_82571,
+       e1000_82572,
+       e1000_82573,
+       e1000_82574,
+       e1000_82583,
+       e1000_80003es2lan,
+       e1000_ich8lan,
+       e1000_ich9lan,
+       e1000_ich10lan,
+       e1000_pchlan,
+       e1000_pch2lan,
        e1000_82575,
        e1000_82576,
        e1000_82580,
        e1000_i350,
+       e1000_i210,
+       e1000_i211,
        e1000_vfadapt,
        e1000_vfadapt_i350,
        e1000_num_macs  /* List is 1-based, so subtract 1 for true count. */
@@ -129,8 +252,14 @@ enum e1000_phy_type {
        e1000_phy_gg82563,
        e1000_phy_igp_3,
        e1000_phy_ife,
+       e1000_phy_bm,
+       e1000_phy_82578,
+       e1000_phy_82577,
+       e1000_phy_82579,
+       e1000_phy_i217,
        e1000_phy_82580,
        e1000_phy_vf,
+       e1000_phy_i210,
 };
 
 enum e1000_bus_type {
@@ -184,6 +313,19 @@ enum e1000_fc_mode {
        e1000_fc_default = 0xFF
 };
 
+enum e1000_ffe_config {
+       e1000_ffe_config_enabled = 0,
+       e1000_ffe_config_active,
+       e1000_ffe_config_blocked
+};
+
+enum e1000_dsp_config {
+       e1000_dsp_config_disabled = 0,
+       e1000_dsp_config_enabled,
+       e1000_dsp_config_activated,
+       e1000_dsp_config_undefined = 0xFF
+};
+
 enum e1000_ms_type {
        e1000_ms_hw_default = 0,
        e1000_ms_force_master,
@@ -422,6 +564,10 @@ struct e1000_hw_stats {
        u64 scvpc;
        u64 hrmpc;
        u64 doosync;
+       u64 o2bgptc;
+       u64 o2bspc;
+       u64 b2ospc;
+       u64 b2ogprc;
 };
 
 struct e1000_vf_stats {
@@ -540,11 +686,29 @@ struct e1000_mac_operations {
                       struct e1000_host_mng_command_header*);
        s32  (*mng_enable_host_if)(struct e1000_hw *);
        s32  (*wait_autoneg)(struct e1000_hw *);
-};
-
+       s32  (*acquire_swfw_sync)(struct e1000_hw *, u16);
+       void (*release_swfw_sync)(struct e1000_hw *, u16);
+};
+
+/*
+ * When to use various PHY register access functions:
+ *
+ *                 Func   Caller
+ *   Function      Does   Does    When to use
+ *   ~~~~~~~~~~~~  ~~~~~  ~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *   X_reg         L,P,A  n/a     for simple PHY reg accesses
+ *   X_reg_locked  P,A    L       for multiple accesses of different regs
+ *                                on different pages
+ *   X_reg_page    A      L,P     for multiple accesses of different regs
+ *                                on the same page
+ *
+ * Where X=[read|write], L=locking, P=sets page, A=register access
+ *
+ */
 struct e1000_phy_operations {
        s32  (*init_params)(struct e1000_hw *);
        s32  (*acquire)(struct e1000_hw *);
+       s32  (*cfg_on_link_up)(struct e1000_hw *);
        s32  (*check_polarity)(struct e1000_hw *);
        s32  (*check_reset_block)(struct e1000_hw *);
        s32  (*commit)(struct e1000_hw *);
@@ -552,16 +716,21 @@ struct e1000_phy_operations {
        s32  (*get_cfg_done)(struct e1000_hw *hw);
        s32  (*get_cable_length)(struct e1000_hw *);
        s32  (*get_info)(struct e1000_hw *);
+       s32  (*set_page)(struct e1000_hw *, u16);
        s32  (*read_reg)(struct e1000_hw *, u32, u16 *);
        s32  (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
+       s32  (*read_reg_page)(struct e1000_hw *, u32, u16 *);
        void (*release)(struct e1000_hw *);
        s32  (*reset)(struct e1000_hw *);
        s32  (*set_d0_lplu_state)(struct e1000_hw *, bool);
        s32  (*set_d3_lplu_state)(struct e1000_hw *, bool);
        s32  (*write_reg)(struct e1000_hw *, u32, u16);
        s32  (*write_reg_locked)(struct e1000_hw *, u32, u16);
+       s32  (*write_reg_page)(struct e1000_hw *, u32, u16);
        void (*power_up)(struct e1000_hw *);
        void (*power_down)(struct e1000_hw *);
+       s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *);
+       s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8);
 };
 
 struct e1000_nvm_operations {
@@ -614,6 +783,7 @@ struct e1000_mac_info {
        bool autoneg_failed;
        bool get_link_status;
        bool in_ifs_mode;
+       bool report_tx_early;
        enum e1000_serdes_link_state serdes_link_state;
        bool serdes_has_link;
        bool tx_pkt_filtering;
@@ -648,7 +818,6 @@ struct e1000_phy_info {
        bool disable_polarity_correction;
        bool is_mdix;
        bool polarity_correction;
-       bool reset_disable;
        bool speed_downgraded;
        bool autoneg_wait_to_complete;
 };
@@ -716,10 +885,57 @@ struct e1000_mbx_info {
        u16 size;
 };
 
+struct e1000_dev_spec_82541 {
+       enum e1000_dsp_config dsp_config;
+       enum e1000_ffe_config ffe_config;
+       u16 spd_default;
+       bool phy_init_script;
+};
+
+struct e1000_dev_spec_82542 {
+       bool dma_fairness;
+};
+
+struct e1000_dev_spec_82543 {
+       u32  tbi_compatibility;
+       bool dma_fairness;
+       bool init_phy_disabled;
+};
+
+struct e1000_dev_spec_82571 {
+       bool laa_is_present;
+       u32 smb_counter;
+       E1000_MUTEX swflag_mutex;
+};
+
+struct e1000_dev_spec_80003es2lan {
+       bool  mdic_wa_enable;
+};
+
+struct e1000_shadow_ram {
+       u16  value;
+       bool modified;
+};
+
+#define E1000_SHADOW_RAM_WORDS  2048
+
+struct e1000_dev_spec_ich8lan {
+       bool kmrn_lock_loss_workaround_enabled;
+       struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS];
+       E1000_MUTEX nvm_mutex;
+       E1000_MUTEX swflag_mutex;
+       bool nvm_k1_enabled;
+       bool eee_disable;
+       u16 eee_lp_ability;
+};
+
 struct e1000_dev_spec_82575 {
        bool sgmii_active;
        bool global_device_reset;
        bool eee_disable;
+       bool module_plugged;
+       u32 mtu;
+       struct sfp_e1000_flags eth_flags;
 };
 
 struct e1000_dev_spec_vf {
@@ -743,6 +959,12 @@ struct e1000_hw {
        struct e1000_host_mng_dhcp_cookie mng_cookie;
 
        union {
+               struct e1000_dev_spec_82541 _82541;
+               struct e1000_dev_spec_82542 _82542;
+               struct e1000_dev_spec_82543 _82543;
+               struct e1000_dev_spec_82571 _82571;
+               struct e1000_dev_spec_80003es2lan _80003es2lan;
+               struct e1000_dev_spec_ich8lan ich8lan;
                struct e1000_dev_spec_82575 _82575;
                struct e1000_dev_spec_vf vf;
        } dev_spec;
@@ -755,9 +977,17 @@ struct e1000_hw {
        u8  revision_id;
 };
 
+#include "e1000_82541.h"
+#include "e1000_82543.h"
+#include "e1000_82571.h"
+#include "e1000_80003es2lan.h"
+#include "e1000_ich8lan.h"
 #include "e1000_82575.h"
+#include "e1000_i210.h"
 
 /* These functions must be implemented by drivers */
+void e1000_pci_clear_mwi(struct e1000_hw *hw);
+void e1000_pci_set_mwi(struct e1000_hw *hw);
 s32  e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
 s32  e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
 void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
index 746cd74..4ec7fa1 100644 (file)
@@ -33,11 +33,10 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include "e1000_api.h"
 
-static s32 e1000_set_default_fc_generic(struct e1000_hw *hw);
-static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw);
-static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw);
 STATIC s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
 STATIC void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
+STATIC void e1000_config_collision_dist_generic(struct e1000_hw *hw);
+STATIC void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
 
 /**
  *  e1000_init_mac_ops_generic - Initialize MAC function pointers
@@ -397,22 +396,30 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
 
        ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &nvm_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
-       if (!(nvm_data & NVM_COMPAT_LOM))
-               goto out;
+       /* not supported on older hardware or 82573 */
+       if ((hw->mac.type < e1000_82571) || (hw->mac.type == e1000_82573))
+               return E1000_SUCCESS;
+
+       /*
+        * Alternate MAC address is handled by the option ROM for 82580
+        * and newer. SW support not required.
+        */
+       if (hw->mac.type >= e1000_82580)
+               return E1000_SUCCESS;
 
        ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1,
                                 &nvm_alt_mac_addr_offset);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
-       if (nvm_alt_mac_addr_offset == 0xFFFF) {
+       if ((nvm_alt_mac_addr_offset == 0xFFFF) ||
+           (nvm_alt_mac_addr_offset == 0x0000))
                /* There is no Alternate MAC Address */
-               goto out;
-       }
+               return E1000_SUCCESS;
 
        if (hw->bus.func == E1000_FUNC_1)
                nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
@@ -426,7 +433,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
                ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
                if (ret_val) {
                        DEBUGOUT("NVM Read Error\n");
-                       goto out;
+                       return ret_val;
                }
 
                alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
@@ -436,7 +443,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
        /* if multicast bit is set, the alternate address will not be used */
        if (alt_mac_addr[0] & 0x01) {
                DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n");
-               goto out;
+               return E1000_SUCCESS;
        }
 
        /*
@@ -446,8 +453,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
         */
        hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -489,43 +495,6 @@ STATIC void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
        E1000_WRITE_FLUSH(hw);
 }
 
-/**
- *  e1000_update_mc_addr_list_generic - Update Multicast addresses
- *  @hw: pointer to the HW structure
- *  @mc_addr_list: array of multicast addresses to program
- *  @mc_addr_count: number of multicast addresses to program
- *
- *  Updates entire Multicast Table Array.
- *  The caller must have a packed mc_addr_list of multicast addresses.
- **/
-void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
-                                       u8 *mc_addr_list, u32 mc_addr_count)
-{
-       u32 hash_value, hash_bit, hash_reg;
-       int i;
-
-       DEBUGFUNC("e1000_update_mc_addr_list_generic");
-
-       /* clear mta_shadow */
-       memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
-
-       /* update mta_shadow from mc_addr_list */
-       for (i = 0; (u32) i < mc_addr_count; i++) {
-               hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
-
-               hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
-               hash_bit = hash_value & 0x1F;
-
-               hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
-               mc_addr_list += (ETH_ADDR_LEN);
-       }
-
-       /* replace the entire MTA table */
-       for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
-               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
-       E1000_WRITE_FLUSH(hw);
-}
-
 /**
  *  e1000_hash_mc_addr_generic - Generate a multicast hash value
  *  @hw: pointer to the HW structure
@@ -598,6 +567,43 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
        return hash_value;
 }
 
+/**
+ *  e1000_update_mc_addr_list_generic - Update Multicast addresses
+ *  @hw: pointer to the HW structure
+ *  @mc_addr_list: array of multicast addresses to program
+ *  @mc_addr_count: number of multicast addresses to program
+ *
+ *  Updates entire Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
+                                      u8 *mc_addr_list, u32 mc_addr_count)
+{
+       u32 hash_value, hash_bit, hash_reg;
+       int i;
+
+       DEBUGFUNC("e1000_update_mc_addr_list_generic");
+
+       /* clear mta_shadow */
+       memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
+
+       /* update mta_shadow from mc_addr_list */
+       for (i = 0; (u32) i < mc_addr_count; i++) {
+               hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
+
+               hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
+               hash_bit = hash_value & 0x1F;
+
+               hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
+               mc_addr_list += (ETH_ADDR_LEN);
+       }
+
+       /* replace the entire MTA table */
+       for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
+       E1000_WRITE_FLUSH(hw);
+}
+
 /**
  *  e1000_pcix_mmrbc_workaround_generic - Fix incorrect MMRBC value
  *  @hw: pointer to the HW structure
@@ -706,10 +712,8 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
         * get_link_status flag is set upon receiving a Link Status
         * Change or Rx Sequence Error interrupt.
         */
-       if (!mac->get_link_status) {
-               ret_val = E1000_SUCCESS;
-               goto out;
-       }
+       if (!mac->get_link_status)
+               return E1000_SUCCESS;
 
        /*
         * First we want to see if the MII Status Register reports
@@ -718,10 +722,10 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
         */
        ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if (!link)
-               goto out; /* No link detected */
+               return E1000_SUCCESS; /* No link detected */
 
        mac->get_link_status = false;
 
@@ -735,10 +739,8 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
         * If we are forcing speed/duplex, then we simply return since
         * we have already determined whether we have link or not.
         */
-       if (!mac->autoneg) {
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-       }
+       if (!mac->autoneg)
+               return -E1000_ERR_CONFIG;
 
        /*
         * Auto-Neg is enabled.  Auto Speed Detection takes care
@@ -757,7 +759,6 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
        if (ret_val)
                DEBUGOUT("Error configuring flow control\n");
 
-out:
        return ret_val;
 }
 
@@ -774,7 +775,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
        u32 rxcw;
        u32 ctrl;
        u32 status;
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_check_for_fiber_link_generic");
 
@@ -791,11 +792,11 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
         * was just plugged in. The autoneg_failed flag does this.
         */
        /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
-       if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&
-           (!(rxcw & E1000_RXCW_C))) {
-               if (mac->autoneg_failed == 0) {
-                       mac->autoneg_failed = 1;
-                       goto out;
+       if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) &&
+           !(rxcw & E1000_RXCW_C)) {
+               if (!mac->autoneg_failed) {
+                       mac->autoneg_failed = true;
+                       return E1000_SUCCESS;
                }
                DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
 
@@ -811,7 +812,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
                ret_val = e1000_config_fc_after_link_up_generic(hw);
                if (ret_val) {
                        DEBUGOUT("Error configuring flow control\n");
-                       goto out;
+                       return ret_val;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
                /*
@@ -827,8 +828,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
                mac->serdes_has_link = true;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -844,7 +844,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
        u32 rxcw;
        u32 ctrl;
        u32 status;
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_check_for_serdes_link_generic");
 
@@ -860,10 +860,10 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
         * time to complete.
         */
        /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
-       if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
-               if (mac->autoneg_failed == 0) {
-                       mac->autoneg_failed = 1;
-                       goto out;
+       if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) {
+               if (!mac->autoneg_failed) {
+                       mac->autoneg_failed = true;
+                       return E1000_SUCCESS;
                }
                DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
 
@@ -879,7 +879,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
                ret_val = e1000_config_fc_after_link_up_generic(hw);
                if (ret_val) {
                        DEBUGOUT("Error configuring flow control\n");
-                       goto out;
+                       return ret_val;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
                /*
@@ -921,26 +921,64 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
                        rxcw = E1000_READ_REG(hw, E1000_RXCW);
                        if (rxcw & E1000_RXCW_SYNCH) {
                                if (!(rxcw & E1000_RXCW_IV)) {
-                                       mac->serdes_has_link = TRUE;
-                                       DEBUGOUT("SERDES: Link up - autoneg "
-                                          "completed sucessfully.\n");
+                                       mac->serdes_has_link = true;
+                                       DEBUGOUT("SERDES: Link up - autoneg completed successfully.\n");
                                } else {
-                                       mac->serdes_has_link = FALSE;
-                                       DEBUGOUT("SERDES: Link down - invalid"
-                                          "codewords detected in autoneg.\n");
+                                       mac->serdes_has_link = false;
+                                       DEBUGOUT("SERDES: Link down - invalid codewords detected in autoneg.\n");
                                }
                        } else {
-                               mac->serdes_has_link = FALSE;
+                               mac->serdes_has_link = false;
                                DEBUGOUT("SERDES: Link down - no sync.\n");
                        }
                } else {
-                       mac->serdes_has_link = FALSE;
+                       mac->serdes_has_link = false;
                        DEBUGOUT("SERDES: Link down - autoneg failed\n");
                }
        }
 
-out:
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_set_default_fc_generic - Set flow control default values
+ *  @hw: pointer to the HW structure
+ *
+ *  Read the EEPROM for the default values for flow control and store the
+ *  values.
+ **/
+s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
+{
+       s32 ret_val;
+       u16 nvm_data;
+
+       DEBUGFUNC("e1000_set_default_fc_generic");
+
+       /*
+        * Read and store word 0x0F of the EEPROM. This word contains bits
+        * that determine the hardware's default PAUSE (flow control) mode,
+        * a bit that determines whether the HW defaults to enabling or
+        * disabling auto-negotiation, and the direction of the
+        * SW defined pins. If there is no SW over-ride of the flow
+        * control setting, then the variable hw->fc will
+        * be initialized based on a value in the EEPROM.
+        */
+       ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
+
+       if (ret_val) {
+               DEBUGOUT("NVM Read Error\n");
        return ret_val;
+       }
+
+       if (!(nvm_data & NVM_WORD0F_PAUSE_MASK))
+               hw->fc.requested_mode = e1000_fc_none;
+       else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
+                NVM_WORD0F_ASM_DIR)
+               hw->fc.requested_mode = e1000_fc_tx_pause;
+       else
+               hw->fc.requested_mode = e1000_fc_full;
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -955,7 +993,7 @@ out:
  **/
 s32 e1000_setup_link_generic(struct e1000_hw *hw)
 {
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_setup_link_generic");
 
@@ -963,8 +1001,8 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
         * In the case of the phy reset being blocked, we already have a link.
         * We do not need to set it up again.
         */
-       if (e1000_check_reset_block(hw))
-               goto out;
+       if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw))
+               return E1000_SUCCESS;
 
        /*
         * If requested flow control is set to default, set flow control
@@ -973,7 +1011,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
        if (hw->fc.requested_mode == e1000_fc_default) {
                ret_val = e1000_set_default_fc_generic(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        }
 
        /*
@@ -988,7 +1026,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
        /* Call the necessary media_type subroutine to configure the link. */
        ret_val = hw->mac.ops.setup_physical_interface(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /*
         * Initialize the flow control address, type, and PAUSE timer
@@ -1003,87 +1041,80 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
 
        E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
 
-       ret_val = e1000_set_fc_watermarks_generic(hw);
-
-out:
-       return ret_val;
+       return e1000_set_fc_watermarks_generic(hw);
 }
 
 /**
- *  e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes
+ *  e1000_commit_fc_settings_generic - Configure flow control
  *  @hw: pointer to the HW structure
  *
- *  Configures collision distance and flow control for fiber and serdes
- *  links.  Upon successful setup, poll for link.
+ *  Write the flow control settings to the Transmit Config Word Register (TXCW)
+ *  base on the flow control settings in e1000_mac_info.
  **/
-s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw)
+s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       u32 ctrl;
-       s32 ret_val = E1000_SUCCESS;
-
-       DEBUGFUNC("e1000_setup_fiber_serdes_link_generic");
-
-       ctrl = E1000_READ_REG(hw, E1000_CTRL);
-
-       /* Take the link out of reset */
-       ctrl &= ~E1000_CTRL_LRST;
-
-       mac->ops.config_collision_dist(hw);
+       u32 txcw;
 
-       ret_val = e1000_commit_fc_settings_generic(hw);
-       if (ret_val)
-               goto out;
+       DEBUGFUNC("e1000_commit_fc_settings_generic");
 
        /*
-        * Since auto-negotiation is enabled, take the link out of reset (the
-        * link will be in reset, because we previously reset the chip). This
-        * will restart auto-negotiation.  If auto-negotiation is successful
-        * then the link-up status bit will be set and the flow control enable
-        * bits (RFCE and TFCE) will be set according to their negotiated value.
+        * Check for a software override of the flow control settings, and
+        * setup the device accordingly.  If auto-negotiation is enabled, then
+        * software will have to set the "PAUSE" bits to the correct value in
+        * the Transmit Config Word Register (TXCW) and re-start auto-
+        * negotiation.  However, if auto-negotiation is disabled, then
+        * software will have to manually configure the two flow control enable
+        * bits in the CTRL register.
+        *
+        * The possible values of the "fc" parameter are:
+        *      0:  Flow control is completely disabled
+        *      1:  Rx flow control is enabled (we can receive pause frames,
+        *          but not send pause frames).
+        *      2:  Tx flow control is enabled (we can send pause frames but we
+        *          do not support receiving pause frames).
+        *      3:  Both Rx and Tx flow control (symmetric) are enabled.
         */
-       DEBUGOUT("Auto-negotiation enabled\n");
-
-       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
-       E1000_WRITE_FLUSH(hw);
-       msec_delay(1);
-
+       switch (hw->fc.current_mode) {
+       case e1000_fc_none:
+               /* Flow control completely disabled by a software over-ride. */
+               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
+               break;
+       case e1000_fc_rx_pause:
        /*
-        * For these adapters, the SW definable pin 1 is set when the optics
-        * detect a signal.  If we have a signal, then poll for a "Link-Up"
-        * indication.
+                * Rx Flow control is enabled and Tx Flow control is disabled
+                * by a software over-ride. Since there really isn't a way to
+                * advertise that we are capable of Rx Pause ONLY, we will
+                * advertise that we support both symmetric and asymmetric Rx
+                * PAUSE.  Later, we will disable the adapter's ability to send
+                * PAUSE frames.
         */
-       if (hw->phy.media_type == e1000_media_type_internal_serdes ||
-           (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
-               ret_val = e1000_poll_fiber_serdes_link_generic(hw);
-       } else {
-               DEBUGOUT("No signal detected\n");
+               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+               break;
+       case e1000_fc_tx_pause:
+               /*
+                * Tx Flow control is enabled, and Rx Flow control is disabled,
+                * by a software over-ride.
+                */
+               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
+               break;
+       case e1000_fc_full:
+               /*
+                * Flow control (both Rx and Tx) is enabled by a software
+                * over-ride.
+                */
+               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+               break;
+       default:
+               DEBUGOUT("Flow control param set incorrectly\n");
+               return -E1000_ERR_CONFIG;
+               break;
        }
 
-out:
-       return ret_val;
-}
-
-/**
- *  e1000_config_collision_dist_generic - Configure collision distance
- *  @hw: pointer to the HW structure
- *
- *  Configures the collision distance to the default value and is used
- *  during link setup.
- **/
-void e1000_config_collision_dist_generic(struct e1000_hw *hw)
-{
-       u32 tctl;
-
-       DEBUGFUNC("e1000_config_collision_dist_generic");
-
-       tctl = E1000_READ_REG(hw, E1000_TCTL);
-
-       tctl &= ~E1000_TCTL_COLD;
-       tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+       E1000_WRITE_REG(hw, E1000_TXCW, txcw);
+       mac->txcw = txcw;
 
-       E1000_WRITE_REG(hw, E1000_TCTL, tctl);
-       E1000_WRITE_FLUSH(hw);
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1093,11 +1124,11 @@ void e1000_config_collision_dist_generic(struct e1000_hw *hw)
  *  Polls for link up by reading the status register, if link fails to come
  *  up with auto-negotiation, then the link is forced if a signal is detected.
  **/
-static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
+s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 i, status;
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_poll_fiber_serdes_link_generic");
 
@@ -1116,7 +1147,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
        }
        if (i == FIBER_LINK_UP_LIMIT) {
                DEBUGOUT("Never got a valid link from auto-neg!!!\n");
-               mac->autoneg_failed = 1;
+               mac->autoneg_failed = true;
                /*
                 * AutoNeg failed to achieve a link, so we'll call
                 * mac->check_for_link. This routine will force the
@@ -1126,92 +1157,90 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
                ret_val = mac->ops.check_for_link(hw);
                if (ret_val) {
                        DEBUGOUT("Error while checking for link\n");
-                       goto out;
+                       return ret_val;
                }
-               mac->autoneg_failed = 0;
+               mac->autoneg_failed = false;
        } else {
-               mac->autoneg_failed = 0;
+               mac->autoneg_failed = false;
                DEBUGOUT("Valid Link Found\n");
        }
 
-out:
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures collision distance and flow control for fiber and serdes
+ *  links.  Upon successful setup, poll for link.
+ **/
+s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_setup_fiber_serdes_link_generic");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /* Take the link out of reset */
+       ctrl &= ~E1000_CTRL_LRST;
+
+       hw->mac.ops.config_collision_dist(hw);
+
+       ret_val = e1000_commit_fc_settings_generic(hw);
+       if (ret_val)
+               return ret_val;
+
+       /*
+        * Since auto-negotiation is enabled, take the link out of reset (the
+        * link will be in reset, because we previously reset the chip). This
+        * will restart auto-negotiation.  If auto-negotiation is successful
+        * then the link-up status bit will be set and the flow control enable
+        * bits (RFCE and TFCE) will be set according to their negotiated value.
+                */
+       DEBUGOUT("Auto-negotiation enabled\n");
+
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       E1000_WRITE_FLUSH(hw);
+       msec_delay(1);
+
+               /*
+        * For these adapters, the SW definable pin 1 is set when the optics
+        * detect a signal.  If we have a signal, then poll for a "Link-Up"
+        * indication.
+                */
+       if (hw->phy.media_type == e1000_media_type_internal_serdes ||
+           (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
+               ret_val = e1000_poll_fiber_serdes_link_generic(hw);
+       } else {
+               DEBUGOUT("No signal detected\n");
+       }
+
        return ret_val;
 }
 
 /**
- *  e1000_commit_fc_settings_generic - Configure flow control
+ *  e1000_config_collision_dist_generic - Configure collision distance
  *  @hw: pointer to the HW structure
  *
- *  Write the flow control settings to the Transmit Config Word Register (TXCW)
- *  base on the flow control settings in e1000_mac_info.
+ *  Configures the collision distance to the default value and is used
+ *  during link setup.
  **/
-static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
+STATIC void e1000_config_collision_dist_generic(struct e1000_hw *hw)
 {
-       struct e1000_mac_info *mac = &hw->mac;
-       u32 txcw;
-       s32 ret_val = E1000_SUCCESS;
+       u32 tctl;
 
-       DEBUGFUNC("e1000_commit_fc_settings_generic");
+       DEBUGFUNC("e1000_config_collision_dist_generic");
 
-       /*
-        * Check for a software override of the flow control settings, and
-        * setup the device accordingly.  If auto-negotiation is enabled, then
-        * software will have to set the "PAUSE" bits to the correct value in
-        * the Transmit Config Word Register (TXCW) and re-start auto-
-        * negotiation.  However, if auto-negotiation is disabled, then
-        * software will have to manually configure the two flow control enable
-        * bits in the CTRL register.
-        *
-        * The possible values of the "fc" parameter are:
-        *      0:  Flow control is completely disabled
-        *      1:  Rx flow control is enabled (we can receive pause frames,
-        *          but not send pause frames).
-        *      2:  Tx flow control is enabled (we can send pause frames but we
-        *          do not support receiving pause frames).
-        *      3:  Both Rx and Tx flow control (symmetric) are enabled.
-        */
-       switch (hw->fc.current_mode) {
-       case e1000_fc_none:
-               /* Flow control completely disabled by a software over-ride. */
-               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
-               break;
-       case e1000_fc_rx_pause:
-               /*
-                * Rx Flow control is enabled and Tx Flow control is disabled
-                * by a software over-ride. Since there really isn't a way to
-                * advertise that we are capable of Rx Pause ONLY, we will
-                * advertise that we support both symmetric and asymmetric Rx
-                * PAUSE.  Later, we will disable the adapter's ability to send
-                * PAUSE frames.
-                */
-               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-               break;
-       case e1000_fc_tx_pause:
-               /*
-                * Tx Flow control is enabled, and Rx Flow control is disabled,
-                * by a software over-ride.
-                */
-               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
-               break;
-       case e1000_fc_full:
-               /*
-                * Flow control (both Rx and Tx) is enabled by a software
-                * over-ride.
-                */
-               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-               break;
-       default:
-               DEBUGOUT("Flow control param set incorrectly\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-               break;
-       }
+       tctl = E1000_READ_REG(hw, E1000_TCTL);
 
-       E1000_WRITE_REG(hw, E1000_TXCW, txcw);
-       mac->txcw = txcw;
+       tctl &= ~E1000_TCTL_COLD;
+       tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
 
-out:
-       return ret_val;
+       E1000_WRITE_REG(hw, E1000_TCTL, tctl);
+       E1000_WRITE_FLUSH(hw);
 }
 
 /**
@@ -1253,48 +1282,6 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw)
        return E1000_SUCCESS;
 }
 
-/**
- *  e1000_set_default_fc_generic - Set flow control default values
- *  @hw: pointer to the HW structure
- *
- *  Read the EEPROM for the default values for flow control and store the
- *  values.
- **/
-static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
-{
-       s32 ret_val = E1000_SUCCESS;
-       u16 nvm_data;
-
-       DEBUGFUNC("e1000_set_default_fc_generic");
-
-       /*
-        * Read and store word 0x0F of the EEPROM. This word contains bits
-        * that determine the hardware's default PAUSE (flow control) mode,
-        * a bit that determines whether the HW defaults to enabling or
-        * disabling auto-negotiation, and the direction of the
-        * SW defined pins. If there is no SW over-ride of the flow
-        * control setting, then the variable hw->fc will
-        * be initialized based on a value in the EEPROM.
-        */
-       ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
-
-       if (ret_val) {
-               DEBUGOUT("NVM Read Error\n");
-               goto out;
-       }
-
-       if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
-               hw->fc.requested_mode = e1000_fc_none;
-       else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
-                NVM_WORD0F_ASM_DIR)
-               hw->fc.requested_mode = e1000_fc_tx_pause;
-       else
-               hw->fc.requested_mode = e1000_fc_full;
-
-out:
-       return ret_val;
-}
-
 /**
  *  e1000_force_mac_fc_generic - Force the MAC's flow control settings
  *  @hw: pointer to the HW structure
@@ -1308,7 +1295,6 @@ out:
 s32 e1000_force_mac_fc_generic(struct e1000_hw *hw)
 {
        u32 ctrl;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_force_mac_fc_generic");
 
@@ -1351,14 +1337,12 @@ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw)
                break;
        default:
                DEBUGOUT("Flow control param set incorrectly\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+               return -E1000_ERR_CONFIG;
        }
 
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1375,6 +1359,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val = E1000_SUCCESS;
+       u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg;
        u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
        u16 speed, duplex;
 
@@ -1396,7 +1381,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
 
        if (ret_val) {
                DEBUGOUT("Error forcing flow control settings\n");
-               goto out;
+               return ret_val;
        }
 
        /*
@@ -1413,15 +1398,14 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                 */
                ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
                if (ret_val)
-                       goto out;
+                       return ret_val;
                ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
-                       DEBUGOUT("Copper PHY and Auto Neg "
-                                "has not completed.\n");
-                       goto out;
+                       DEBUGOUT("Copper PHY and Auto Neg has not completed.\n");
+                       return ret_val;
                }
 
                /*
@@ -1434,11 +1418,11 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
                                             &mii_nway_adv_reg);
                if (ret_val)
-                       goto out;
+                       return ret_val;
                ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
                                             &mii_nway_lp_ability_reg);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                /*
                 * Two bits in the Auto Negotiation Advertisement Register
@@ -1537,7 +1521,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
                if (ret_val) {
                        DEBUGOUT("Error getting link speed and duplex\n");
-                       goto out;
+                       return ret_val;
                }
 
                if (duplex == HALF_DUPLEX)
@@ -1550,12 +1534,144 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                ret_val = e1000_force_mac_fc_generic(hw);
                if (ret_val) {
                        DEBUGOUT("Error forcing flow control settings\n");
-                       goto out;
+                       return ret_val;
+               }
+       }
+
+       /*
+        * Check for the case where we have SerDes media and auto-neg is
+        * enabled.  In this case, we need to check and see if Auto-Neg
+        * has completed, and if so, how the PHY and link partner has
+        * flow control configured.
+        */
+       if ((hw->phy.media_type == e1000_media_type_internal_serdes)
+               && mac->autoneg) {
+               /*
+                * Read the PCS_LSTS and check to see if AutoNeg
+                * has completed.
+                */
+               pcs_status_reg = E1000_READ_REG(hw, E1000_PCS_LSTAT);
+
+               if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) {
+                       DEBUGOUT("PCS Auto Neg has not completed.\n");
+                       return ret_val;
+               }
+
+               /*
+                * The AutoNeg process has completed, so we now need to
+                * read both the Auto Negotiation Advertisement
+                * Register (PCS_ANADV) and the Auto_Negotiation Base
+                * Page Ability Register (PCS_LPAB) to determine how
+                * flow control was negotiated.
+                */
+               pcs_adv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV);
+               pcs_lp_ability_reg = E1000_READ_REG(hw, E1000_PCS_LPAB);
+
+               /*
+                * Two bits in the Auto Negotiation Advertisement Register
+                * (PCS_ANADV) and two bits in the Auto Negotiation Base
+                * Page Ability Register (PCS_LPAB) determine flow control
+                * for both the PHY and the link partner.  The following
+                * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+                * 1999, describes these PAUSE resolution bits and how flow
+                * control is determined based upon these settings.
+                * NOTE:  DC = Don't Care
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+                *-------|---------|-------|---------|--------------------
+                *   0   |    0    |  DC   |   DC    | e1000_fc_none
+                *   0   |    1    |   0   |   DC    | e1000_fc_none
+                *   0   |    1    |   1   |    0    | e1000_fc_none
+                *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+                *   1   |    0    |   0   |   DC    | e1000_fc_none
+                *   1   |   DC    |   1   |   DC    | e1000_fc_full
+                *   1   |    1    |   0   |    0    | e1000_fc_none
+                *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+                *
+                * Are both PAUSE bits set to 1?  If so, this implies
+                * Symmetric Flow Control is enabled at both ends.  The
+                * ASM_DIR bits are irrelevant per the spec.
+                *
+                * For Symmetric Flow Control:
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+                *-------|---------|-------|---------|--------------------
+                *   1   |   DC    |   1   |   DC    | e1000_fc_full
+                *
+                */
+               if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+                   (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) {
+                       /*
+                        * Now we need to check if the user selected Rx ONLY
+                        * of pause frames.  In this case, we had to advertise
+                        * FULL flow control because we could not advertise Rx
+                        * ONLY. Hence, we must now check to see if we need to
+                        * turn OFF the TRANSMISSION of PAUSE frames.
+                        */
+                       if (hw->fc.requested_mode == e1000_fc_full) {
+                               hw->fc.current_mode = e1000_fc_full;
+                               DEBUGOUT("Flow Control = FULL.\n");
+                       } else {
+                               hw->fc.current_mode = e1000_fc_rx_pause;
+                               DEBUGOUT("Flow Control = Rx PAUSE frames only.\n");
                }
        }
+               /*
+                * For receiving PAUSE frames ONLY.
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+                *-------|---------|-------|---------|--------------------
+                *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+                */
+               else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) &&
+                         (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+                         (pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+                         (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+                       hw->fc.current_mode = e1000_fc_tx_pause;
+                       DEBUGOUT("Flow Control = Tx PAUSE frames only.\n");
+               }
+               /*
+                * For transmitting PAUSE frames ONLY.
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+                *-------|---------|-------|---------|--------------------
+                *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+                */
+               else if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+                        (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+                        !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+                        (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+                       hw->fc.current_mode = e1000_fc_rx_pause;
+                       DEBUGOUT("Flow Control = Rx PAUSE frames only.\n");
+               } else {
+                       /*
+                        * Per the IEEE spec, at this point flow control
+                        * should be disabled.
+                        */
+                       hw->fc.current_mode = e1000_fc_none;
+                       DEBUGOUT("Flow Control = NONE.\n");
+               }
+
+               /*
+                * Now we call a subroutine to actually force the MAC
+                * controller to use the correct flow control settings.
+                */
+               pcs_ctrl_reg = E1000_READ_REG(hw, E1000_PCS_LCTL);
+               pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+               E1000_WRITE_REG(hw, E1000_PCS_LCTL, pcs_ctrl_reg);
 
-out:
+               ret_val = e1000_force_mac_fc_generic(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error forcing flow control settings\n");
        return ret_val;
+               }
+       }
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1626,7 +1742,6 @@ s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
 s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
 {
        u32 swsm;
-       s32 ret_val = E1000_SUCCESS;
        s32 timeout = hw->nvm.word_size + 1;
        s32 i = 0;
 
@@ -1644,8 +1759,7 @@ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
 
        if (i == timeout) {
                DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
        /* Get the FW semaphore. */
@@ -1664,12 +1778,10 @@ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
                /* Release semaphores */
                e1000_put_hw_semaphore_generic(hw);
                DEBUGOUT("Driver can't access the NVM\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1700,7 +1812,6 @@ void e1000_put_hw_semaphore_generic(struct e1000_hw *hw)
 s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw)
 {
        s32 i = 0;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_get_auto_rd_done_generic");
 
@@ -1713,12 +1824,10 @@ s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw)
 
        if (i == AUTO_READ_DONE_TIMEOUT) {
                DEBUGOUT("Auto read by HW from NVM has not completed.\n");
-               ret_val = -E1000_ERR_RESET;
-               goto out;
+               return -E1000_ERR_RESET;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1738,14 +1847,13 @@ s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data)
        ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
        if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
                *data = ID_LED_DEFAULT;
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1767,7 +1875,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw)
 
        ret_val = hw->nvm.ops.valid_led_default(hw, &data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL);
        mac->ledctl_mode1 = mac->ledctl_default;
@@ -1811,8 +1919,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw)
                }
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1825,14 +1932,11 @@ out:
 s32 e1000_setup_led_generic(struct e1000_hw *hw)
 {
        u32 ledctl;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_setup_led_generic");
 
-       if (hw->mac.ops.setup_led != e1000_setup_led_generic) {
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-       }
+       if (hw->mac.ops.setup_led != e1000_setup_led_generic)
+               return -E1000_ERR_CONFIG;
 
        if (hw->phy.media_type == e1000_media_type_fiber) {
                ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
@@ -1847,8 +1951,7 @@ s32 e1000_setup_led_generic(struct e1000_hw *hw)
                E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1973,7 +2076,7 @@ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop)
        DEBUGFUNC("e1000_set_pcie_no_snoop_generic");
 
        if (hw->bus.type != e1000_bus_type_pci_express)
-               goto out;
+               return;
 
        if (no_snoop) {
                gcr = E1000_READ_REG(hw, E1000_GCR);
@@ -1981,8 +2084,6 @@ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop)
                gcr |= no_snoop;
                E1000_WRITE_REG(hw, E1000_GCR, gcr);
        }
-out:
-       return;
 }
 
 /**
@@ -2000,12 +2101,11 @@ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32 timeout = MASTER_DISABLE_TIMEOUT;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_disable_pcie_master_generic");
 
        if (hw->bus.type != e1000_bus_type_pci_express)
-               goto out;
+               return E1000_SUCCESS;
 
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
        ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
@@ -2021,11 +2121,10 @@ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw)
 
        if (!timeout) {
                DEBUGOUT("Master requests are pending.\n");
-               ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING;
+               return -E1000_ERR_MASTER_REQUESTS_PENDING;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -2042,7 +2141,7 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw)
 
        if (!mac->adaptive_ifs) {
                DEBUGOUT("Not in Adaptive IFS mode!\n");
-               goto out;
+               return;
        }
 
        mac->current_ifs_val = 0;
@@ -2053,8 +2152,6 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw)
 
        mac->in_ifs_mode = false;
        E1000_WRITE_REG(hw, E1000_AIT, 0);
-out:
-       return;
 }
 
 /**
@@ -2072,7 +2169,7 @@ void e1000_update_adaptive_generic(struct e1000_hw *hw)
 
        if (!mac->adaptive_ifs) {
                DEBUGOUT("Not in Adaptive IFS mode!\n");
-               goto out;
+               return;
        }
 
        if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) {
@@ -2096,8 +2193,6 @@ void e1000_update_adaptive_generic(struct e1000_hw *hw)
                        E1000_WRITE_REG(hw, E1000_AIT, 0);
                }
        }
-out:
-       return;
 }
 
 /**
@@ -2109,19 +2204,29 @@ out:
  **/
 STATIC s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
 {
-       s32 ret_val = E1000_SUCCESS;
-
        DEBUGFUNC("e1000_validate_mdi_setting_generic");
 
        if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) {
                DEBUGOUT("Invalid MDI setting detected\n");
                hw->phy.mdix = 1;
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+               return -E1000_ERR_CONFIG;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_validate_mdi_setting_crossover_generic - Verify MDI/MDIx settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Validate the MDI/MDIx setting, allowing for auto-crossover during forced
+ *  operation.
+ **/
+s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_validate_mdi_setting_crossover_generic");
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -2139,7 +2244,6 @@ s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
                                       u32 offset, u8 data)
 {
        u32 i, regvalue = 0;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_write_8bit_ctrl_reg_generic");
 
@@ -2156,10 +2260,8 @@ s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
        }
        if (!(regvalue & E1000_GEN_CTL_READY)) {
                DEBUGOUT1("Reg %08x did not indicate ready\n", reg);
-               ret_val = -E1000_ERR_PHY;
-               goto out;
+               return -E1000_ERR_PHY;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
index 8c830c0..b18d846 100644 (file)
@@ -51,6 +51,8 @@ s32  e1000_check_for_copper_link_generic(struct e1000_hw *hw);
 s32  e1000_check_for_fiber_link_generic(struct e1000_hw *hw);
 s32  e1000_check_for_serdes_link_generic(struct e1000_hw *hw);
 s32  e1000_cleanup_led_generic(struct e1000_hw *hw);
+s32  e1000_commit_fc_settings_generic(struct e1000_hw *hw);
+s32  e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw);
 s32  e1000_config_fc_after_link_up_generic(struct e1000_hw *hw);
 s32  e1000_disable_pcie_master_generic(struct e1000_hw *hw);
 s32  e1000_force_mac_fc_generic(struct e1000_hw *hw);
@@ -69,10 +71,12 @@ s32  e1000_led_on_generic(struct e1000_hw *hw);
 s32  e1000_led_off_generic(struct e1000_hw *hw);
 void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
                                        u8 *mc_addr_list, u32 mc_addr_count);
+s32  e1000_set_default_fc_generic(struct e1000_hw *hw);
 s32  e1000_set_fc_watermarks_generic(struct e1000_hw *hw);
 s32  e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw);
 s32  e1000_setup_led_generic(struct e1000_hw *hw);
 s32  e1000_setup_link_generic(struct e1000_hw *hw);
+s32  e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw);
 s32  e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
                                        u32 offset, u8 data);
 
@@ -80,11 +84,9 @@ u32  e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr);
 
 void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw);
 void e1000_clear_vfta_generic(struct e1000_hw *hw);
-void e1000_config_collision_dist_generic(struct e1000_hw *hw);
 void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count);
 void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw);
 void e1000_put_hw_semaphore_generic(struct e1000_hw *hw);
-void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
 s32  e1000_check_alt_mac_addr_generic(struct e1000_hw *hw);
 void e1000_reset_adaptive_generic(struct e1000_hw *hw);
 void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop);
index a8f911b..f7d6c26 100644 (file)
@@ -70,23 +70,20 @@ u8 e1000_calculate_checksum(u8 *buffer, u32 length)
 s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
 {
        u32 hicr;
-       s32 ret_val = E1000_SUCCESS;
        u8 i;
 
        DEBUGFUNC("e1000_mng_enable_host_if_generic");
 
        if (!hw->mac.arc_subsystem_valid) {
                DEBUGOUT("ARC subsystem not valid.\n");
-               ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
        }
 
        /* Check that the host interface is enabled. */
        hicr = E1000_READ_REG(hw, E1000_HICR);
        if (!(hicr & E1000_HICR_EN)) {
                DEBUGOUT("E1000_HOST_EN bit disabled.\n");
-               ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
        }
        /* check the previous command is completed */
        for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
@@ -98,12 +95,10 @@ s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
 
        if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
                DEBUGOUT("Previous command timeout failed .\n");
-               ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -146,7 +141,7 @@ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
        /* No manageability, no filtering */
        if (!hw->mac.ops.check_mng_mode(hw)) {
                hw->mac.tx_pkt_filtering = false;
-               goto out;
+               return hw->mac.tx_pkt_filtering;
        }
 
        /*
@@ -156,7 +151,7 @@ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
        ret_val = hw->mac.ops.mng_enable_host_if(hw);
        if (ret_val != E1000_SUCCESS) {
                hw->mac.tx_pkt_filtering = false;
-               goto out;
+               return hw->mac.tx_pkt_filtering;
        }
 
        /* Read in the header.  Length and offset are in dwords. */
@@ -175,67 +170,17 @@ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
         * take the safe route of assuming Tx filtering is enabled.
         */
        if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
-               hw->mac.tx_pkt_filtering = TRUE;
-               goto out;
+               hw->mac.tx_pkt_filtering = true;
+               return hw->mac.tx_pkt_filtering;
        }
 
        /* Cookie area is valid, make the final check for filtering. */
-       if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
-               hw->mac.tx_pkt_filtering = FALSE;
-               goto out;
-       }
+       if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
+               hw->mac.tx_pkt_filtering = false;
 
-out:
        return hw->mac.tx_pkt_filtering;
 }
 
-/**
- *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
- *  @hw: pointer to the HW structure
- *  @buffer: pointer to the host interface
- *  @length: size of the buffer
- *
- *  Writes the DHCP information to the host interface.
- **/
-s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
-                                      u16 length)
-{
-       struct e1000_host_mng_command_header hdr;
-       s32 ret_val;
-       u32 hicr;
-
-       DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
-
-       hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
-       hdr.command_length = length;
-       hdr.reserved1 = 0;
-       hdr.reserved2 = 0;
-       hdr.checksum = 0;
-
-       /* Enable the host interface */
-       ret_val = hw->mac.ops.mng_enable_host_if(hw);
-       if (ret_val)
-               goto out;
-
-       /* Populate the host interface with the contents of "buffer". */
-       ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
-                                         sizeof(hdr), &(hdr.checksum));
-       if (ret_val)
-               goto out;
-
-       /* Write the manageability command header */
-       ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
-       if (ret_val)
-               goto out;
-
-       /* Tell the ARC a new command is pending. */
-       hicr = E1000_READ_REG(hw, E1000_HICR);
-       E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
-
-out:
-       return ret_val;
-}
-
 /**
  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
  *  @hw: pointer to the HW structure
@@ -283,17 +228,14 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
        u8 *tmp;
        u8 *bufptr = buffer;
        u32 data = 0;
-       s32 ret_val = E1000_SUCCESS;
        u16 remaining, i, j, prev_bytes;
 
        DEBUGFUNC("e1000_mng_host_if_write_generic");
 
        /* sum = only sum of the data and it is not checksum */
 
-       if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
-               ret_val = -E1000_ERR_PARAM;
-               goto out;
-       }
+       if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
+               return -E1000_ERR_PARAM;
 
        tmp = (u8 *)&data;
        prev_bytes = offset & 0x3;
@@ -338,11 +280,57 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
 
                        *sum += *(tmp + j);
                }
-               E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
+               E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
+                                           data);
        }
 
-out:
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
+ *  @hw: pointer to the HW structure
+ *  @buffer: pointer to the host interface
+ *  @length: size of the buffer
+ *
+ *  Writes the DHCP information to the host interface.
+ **/
+s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
+                                     u16 length)
+{
+       struct e1000_host_mng_command_header hdr;
+       s32 ret_val;
+       u32 hicr;
+
+       DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
+
+       hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
+       hdr.command_length = length;
+       hdr.reserved1 = 0;
+       hdr.reserved2 = 0;
+       hdr.checksum = 0;
+
+       /* Enable the host interface */
+       ret_val = hw->mac.ops.mng_enable_host_if(hw);
+       if (ret_val)
+               return ret_val;
+
+       /* Populate the host interface with the contents of "buffer". */
+       ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
+                                               sizeof(hdr), &(hdr.checksum));
+       if (ret_val)
        return ret_val;
+
+       /* Write the manageability command header */
+       ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
+       if (ret_val)
+               return ret_val;
+
+       /* Tell the ARC a new command is pending. */
+       hicr = E1000_READ_REG(hw, E1000_HICR);
+       E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -356,17 +344,16 @@ bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
 {
        u32 manc;
        u32 fwsm, factps;
-       bool ret_val = FALSE;
 
        DEBUGFUNC("e1000_enable_mng_pass_thru");
 
        if (!hw->mac.asf_firmware_present)
-               goto out;
+               return false;
 
        manc = E1000_READ_REG(hw, E1000_MANC);
 
        if (!(manc & E1000_MANC_RCV_TCO_EN))
-               goto out;
+               return false;
 
        if (hw->mac.has_fwsm) {
                fwsm = E1000_READ_REG(hw, E1000_FWSM);
@@ -374,18 +361,25 @@ bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
 
                if (!(factps & E1000_FACTPS_MNGCG) &&
                    ((fwsm & E1000_FWSM_MODE_MASK) ==
-                    (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
-                       ret_val = TRUE;
-                       goto out;
-               }
+                    (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
+                       return true;
+       } else if ((hw->mac.type == e1000_82574) ||
+                  (hw->mac.type == e1000_82583)) {
+               u16 data;
+
+               factps = E1000_READ_REG(hw, E1000_FACTPS);
+               e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+
+               if (!(factps & E1000_FACTPS_MNGCG) &&
+                   ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
+                    (e1000_mng_mode_pt << 13)))
+                       return true;
        } else if ((manc & E1000_MANC_SMBUS_EN) &&
                    !(manc & E1000_MANC_ASF_EN)) {
-                       ret_val = TRUE;
-                       goto out;
+                       return true;
        }
 
-out:
-       return ret_val;
+       return false;
 }
 
 /**
@@ -400,33 +394,30 @@ out:
 s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
 {
        u32 hicr, i;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_host_interface_command");
 
        if (!(hw->mac.arc_subsystem_valid)) {
                DEBUGOUT("Hardware doesn't support host interface command.\n");
-               goto out;
+               return E1000_SUCCESS;
        }
 
        if (!hw->mac.asf_firmware_present) {
                DEBUGOUT("Firmware is not present.\n");
-               goto out;
+               return E1000_SUCCESS;
        }
 
        if (length == 0 || length & 0x3 ||
            length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
                DEBUGOUT("Buffer length failure.\n");
-               ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
        }
 
        /* Check that the host interface is enabled. */
        hicr = E1000_READ_REG(hw, E1000_HICR);
-       if ((hicr & E1000_HICR_EN) == 0) {
+       if (!(hicr & E1000_HICR_EN)) {
                DEBUGOUT("E1000_HOST_EN bit disabled.\n");
-               ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
        }
 
        /* Calculate length in DWORDs */
@@ -454,8 +445,7 @@ s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
        if (i == E1000_HI_COMMAND_TIMEOUT ||
            (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
                DEBUGOUT("Command has failed with no status valid.\n");
-               ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
        }
 
        for (i = 0; i < length; i++)
@@ -463,7 +453,126 @@ s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
                                                                  E1000_HOST_IF,
                                                                  i);
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
+}
+/**
+ *  e1000_load_firmware - Writes proxy FW code buffer to host interface
+ *                        and execute.
+ *  @hw: pointer to the HW structure
+ *  @buffer: contains a firmware to write
+ *  @length: the byte length of the buffer, must be multiple of 4 bytes
+ *
+ *  Upon success returns E1000_SUCCESS, returns E1000_ERR_CONFIG if not enabled
+ *  in HW else returns E1000_ERR_HOST_INTERFACE_COMMAND.
+ **/
+s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length)
+{
+       u32 hicr, hibba, fwsm, icr, i;
+
+       DEBUGFUNC("e1000_load_firmware");
+
+       if (hw->mac.type < e1000_i210) {
+               DEBUGOUT("Hardware doesn't support loading FW by the driver\n");
+               return -E1000_ERR_CONFIG;
+       }
+
+       /* Check that the host interface is enabled. */
+       hicr = E1000_READ_REG(hw, E1000_HICR);
+       if (!(hicr & E1000_HICR_EN)) {
+               DEBUGOUT("E1000_HOST_EN bit disabled.\n");
+               return -E1000_ERR_CONFIG;
+       }
+       if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) {
+               DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n");
+               return -E1000_ERR_CONFIG;
+       }
+
+       if (length == 0 || length & 0x3 || length > E1000_HI_FW_MAX_LENGTH) {
+               DEBUGOUT("Buffer length failure.\n");
+               return -E1000_ERR_INVALID_ARGUMENT;
+       }
+
+       /* Clear notification from ROM-FW by reading ICR register */
+       icr = E1000_READ_REG(hw, E1000_ICR_V2);
+
+       /* Reset ROM-FW */
+       hicr = E1000_READ_REG(hw, E1000_HICR);
+       hicr |= E1000_HICR_FW_RESET_ENABLE;
+       E1000_WRITE_REG(hw, E1000_HICR, hicr);
+       hicr |= E1000_HICR_FW_RESET;
+       E1000_WRITE_REG(hw, E1000_HICR, hicr);
+       E1000_WRITE_FLUSH(hw);
+
+       /* Wait till MAC notifies about its readiness after ROM-FW reset */
+       for (i = 0; i < (E1000_HI_COMMAND_TIMEOUT * 2); i++) {
+               icr = E1000_READ_REG(hw, E1000_ICR_V2);
+               if (icr & E1000_ICR_MNG)
+                       break;
+               msec_delay(1);
+       }
+
+       /* Check for timeout */
+       if (i == E1000_HI_COMMAND_TIMEOUT) {
+               DEBUGOUT("FW reset failed.\n");
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
+       }
+
+       /* Wait till MAC is ready to accept new FW code */
+       for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
+               fwsm = E1000_READ_REG(hw, E1000_FWSM);
+               if ((fwsm & E1000_FWSM_FW_VALID) &&
+                   ((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT ==
+                   E1000_FWSM_HI_EN_ONLY_MODE))
+                       break;
+               msec_delay(1);
+       }
+
+       /* Check for timeout */
+       if (i == E1000_HI_COMMAND_TIMEOUT) {
+               DEBUGOUT("FW reset failed.\n");
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
+       }
+
+       /* Calculate length in DWORDs */
+       length >>= 2;
+
+       /*
+        * The device driver writes the relevant FW code block
+        * into the ram area in DWORDs via 1kB ram addressing window.
+        */
+       for (i = 0; i < length; i++) {
+               if (!(i % E1000_HI_FW_BLOCK_DWORD_LENGTH)) {
+                       /* Point to correct 1kB ram window */
+                       hibba = E1000_HI_FW_BASE_ADDRESS +
+                               ((E1000_HI_FW_BLOCK_DWORD_LENGTH << 2) *
+                               (i / E1000_HI_FW_BLOCK_DWORD_LENGTH));
+
+                       E1000_WRITE_REG(hw, E1000_HIBBA, hibba);
+               }
+
+               E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
+                                           i % E1000_HI_FW_BLOCK_DWORD_LENGTH,
+                                           *((u32 *)buffer + i));
+       }
+
+       /* Setting this bit tells the ARC that a new FW is ready to execute. */
+       hicr = E1000_READ_REG(hw, E1000_HICR);
+       E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
+
+       for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
+               hicr = E1000_READ_REG(hw, E1000_HICR);
+               if (!(hicr & E1000_HICR_C))
+                       break;
+               msec_delay(1);
+       }
+
+       /* Check for successful FW start. */
+       if (i == E1000_HI_COMMAND_TIMEOUT) {
+               DEBUGOUT("New FW did not start within timeout period.\n");
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
+       }
+
+       return E1000_SUCCESS;
 }
 
+
index 0265795..9a736a8 100644 (file)
@@ -46,6 +46,7 @@ s32  e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw,
 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw);
 u8 e1000_calculate_checksum(u8 *buffer, u32 length);
 s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length);
+s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length);
 
 enum e1000_mng_mode {
        e1000_mng_mode_none = 0,
@@ -59,6 +60,8 @@ enum e1000_mng_mode {
 
 #define E1000_FWSM_MODE_MASK  0xE
 #define E1000_FWSM_MODE_SHIFT 1
+#define E1000_FWSM_FW_VALID                    0x00008000
+#define E1000_FWSM_HI_EN_ONLY_MODE             0x4
 
 #define E1000_MNG_IAMT_MODE                  0x3
 #define E1000_MNG_DHCP_COOKIE_LENGTH         0x10
@@ -75,6 +78,10 @@ enum e1000_mng_mode {
 #define E1000_HI_MAX_BLOCK_BYTE_LENGTH       1792 /* Num of bytes in range */
 #define E1000_HI_MAX_BLOCK_DWORD_LENGTH      448 /* Num of dwords in range */
 #define E1000_HI_COMMAND_TIMEOUT               500 /* Process HI cmd limit */
+#define E1000_HI_FW_BASE_ADDRESS               0x10000
+#define E1000_HI_FW_MAX_LENGTH                 (64 * 1024) /* Num of bytes */
+#define E1000_HI_FW_BLOCK_DWORD_LENGTH         256 /* Num of DWORDs per page */
+#define E1000_HICR_MEMORY_BASE_EN              0x200 /* MB Enable bit - RO */
 #define E1000_HICR_EN              0x01  /* Enable bit - RO */
 /* Driver sets this bit when done to put command in RAM */
 #define E1000_HICR_C               0x02
index e2d3974..fc586fe 100644 (file)
@@ -33,7 +33,6 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include "e1000_api.h"
 
-static void e1000_stop_nvm(struct e1000_hw *hw);
 STATIC void e1000_reload_nvm_generic(struct e1000_hw *hw);
 
 /**
@@ -227,7 +226,6 @@ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
 {
        u32 attempts = 100000;
        u32 i, reg = 0;
-       s32 ret_val = -E1000_ERR_NVM;
 
        DEBUGFUNC("e1000_poll_eerd_eewr_done");
 
@@ -237,15 +235,13 @@ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
                else
                        reg = E1000_READ_REG(hw, E1000_EEWR);
 
-               if (reg & E1000_NVM_RW_REG_DONE) {
-                       ret_val = E1000_SUCCESS;
-                       break;
-               }
+               if (reg & E1000_NVM_RW_REG_DONE)
+                       return E1000_SUCCESS;
 
                usec_delay(5);
        }
 
-       return ret_val;
+       return -E1000_ERR_NVM;
 }
 
 /**
@@ -260,7 +256,6 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
 {
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
        s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_acquire_nvm_generic");
 
@@ -279,10 +274,10 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
                eecd &= ~E1000_EECD_REQ;
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
                DEBUGOUT("Could not acquire NVM grant\n");
-               ret_val = -E1000_ERR_NVM;
+               return -E1000_ERR_NVM;
        }
 
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -313,8 +308,7 @@ static void e1000_standby_nvm(struct e1000_hw *hw)
                usec_delay(nvm->delay_usec);
 
                e1000_lower_eec_clk(hw, &eecd);
-       } else
-       if (nvm->type == e1000_nvm_eeprom_spi) {
+       } else if (nvm->type == e1000_nvm_eeprom_spi) {
                /* Toggle CS to flush commands */
                eecd |= E1000_EECD_CS;
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
@@ -333,7 +327,7 @@ static void e1000_standby_nvm(struct e1000_hw *hw)
  *
  *  Terminates the current command by inverting the EEPROM's chip select pin.
  **/
-static void e1000_stop_nvm(struct e1000_hw *hw)
+void e1000_stop_nvm(struct e1000_hw *hw)
 {
        u32 eecd;
 
@@ -382,7 +376,6 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
-       s32 ret_val = E1000_SUCCESS;
        u8 spi_stat_reg;
 
        DEBUGFUNC("e1000_ready_nvm_eeprom");
@@ -394,13 +387,13 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
                /* Set CS */
                eecd |= E1000_EECD_CS;
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
-       } else
-       if (nvm->type == e1000_nvm_eeprom_spi) {
+       } else if (nvm->type == e1000_nvm_eeprom_spi) {
                u16 timeout = NVM_MAX_RETRY_SPI;
 
                /* Clear SK and CS */
                eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
+               E1000_WRITE_FLUSH(hw);
                usec_delay(1);
 
                /*
@@ -423,13 +416,11 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
 
                if (!timeout) {
                        DEBUGOUT("SPI NVM Status error\n");
-                       ret_val = -E1000_ERR_NVM;
-                       goto out;
+                       return -E1000_ERR_NVM;
                }
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -458,13 +449,12 @@ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
        ret_val = nvm->ops.acquire(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        ret_val = e1000_ready_nvm_eeprom(hw);
        if (ret_val)
@@ -492,7 +482,6 @@ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 release:
        nvm->ops.release(hw);
 
-out:
        return ret_val;
 }
 
@@ -522,13 +511,12 @@ s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
        ret_val = nvm->ops.acquire(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        ret_val = e1000_ready_nvm_eeprom(hw);
        if (ret_val)
@@ -551,7 +539,6 @@ s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
 release:
        nvm->ops.release(hw);
 
-out:
        return ret_val;
 }
 
@@ -579,8 +566,7 @@ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
        for (i = 0; i < words; i++) {
@@ -596,7 +582,6 @@ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
                           E1000_NVM_RW_REG_DATA);
        }
 
-out:
        return ret_val;
 }
 
@@ -615,7 +600,7 @@ out:
 s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       s32 ret_val;
+       s32 ret_val = -E1000_ERR_NVM;
        u16 widx = 0;
 
        DEBUGFUNC("e1000_write_nvm_spi");
@@ -627,20 +612,21 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
-       ret_val = nvm->ops.acquire(hw);
-       if (ret_val)
-               goto out;
-
        while (widx < words) {
                u8 write_opcode = NVM_WRITE_OPCODE_SPI;
 
-               ret_val = e1000_ready_nvm_eeprom(hw);
+               ret_val = nvm->ops.acquire(hw);
                if (ret_val)
-                       goto release;
+                       return ret_val;
+
+               ret_val = e1000_ready_nvm_eeprom(hw);
+               if (ret_val) {
+                       nvm->ops.release(hw);
+                       return ret_val;
+               }
 
                e1000_standby_nvm(hw);
 
@@ -674,13 +660,10 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
                                break;
                        }
                }
-       }
-
        msec_delay(10);
-release:
        nvm->ops.release(hw);
+       }
 
-out:
        return ret_val;
 }
 
@@ -714,13 +697,12 @@ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
        ret_val = nvm->ops.acquire(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        ret_val = e1000_ready_nvm_eeprom(hw);
        if (ret_val)
@@ -770,7 +752,6 @@ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
 release:
        nvm->ops.release(hw);
 
-out:
        return ret_val;
 }
 
@@ -796,20 +777,19 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
 
        if (pba_num == NULL) {
                DEBUGOUT("PBA string buffer was null\n");
-               ret_val = E1000_ERR_INVALID_ARGUMENT;
-               goto out;
+               return -E1000_ERR_INVALID_ARGUMENT;
        }
 
        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
        /*
@@ -820,8 +800,8 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
        if (nvm_data != NVM_PBA_PTR_GUARD) {
                DEBUGOUT("NVM PBA number is not stored as string\n");
 
-               /* we will need 11 characters to store the PBA */
-               if (pba_num_size < 11) {
+               /* make sure callers buffer is big enough to store the PBA */
+               if (pba_num_size < E1000_PBANUM_LENGTH) {
                        DEBUGOUT("PBA string buffer too small\n");
                        return E1000_ERR_NO_SPACE;
                }
@@ -849,25 +829,23 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
                                pba_num[offset] += 'A' - 0xA;
                }
 
-               goto out;
+               return E1000_SUCCESS;
        }
 
        ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
        if (length == 0xFFFF || length == 0) {
                DEBUGOUT("NVM PBA number section invalid length\n");
-               ret_val = E1000_ERR_NVM_PBA_SECTION;
-               goto out;
+               return -E1000_ERR_NVM_PBA_SECTION;
        }
        /* check if pba_num buffer is big enough */
        if (pba_num_size < (((u32)length * 2) - 1)) {
                DEBUGOUT("PBA string buffer too small\n");
-               ret_val = E1000_ERR_NO_SPACE;
-               goto out;
+               return -E1000_ERR_NO_SPACE;
        }
 
        /* trim pba length from start of string */
@@ -878,15 +856,14 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
                ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
                if (ret_val) {
                        DEBUGOUT("NVM Read Error\n");
-                       goto out;
+                       return ret_val;
                }
                pba_num[offset * 2] = (u8)(nvm_data >> 8);
                pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
        }
        pba_num[offset * 2] = '\0';
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -908,38 +885,36 @@ s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size)
 
        if (pba_num_size == NULL) {
                DEBUGOUT("PBA buffer size was null\n");
-               ret_val = E1000_ERR_INVALID_ARGUMENT;
-               goto out;
+               return -E1000_ERR_INVALID_ARGUMENT;
        }
 
        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
         /* if data is not ptr guard the PBA must be in legacy format */
        if (nvm_data != NVM_PBA_PTR_GUARD) {
-               *pba_num_size = 11;
-               goto out;
+               *pba_num_size = E1000_PBANUM_LENGTH;
+               return E1000_SUCCESS;
        }
 
        ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
        if (length == 0xFFFF || length == 0) {
                DEBUGOUT("NVM PBA number section invalid length\n");
-               ret_val = E1000_ERR_NVM_PBA_SECTION;
-               goto out;
+               return -E1000_ERR_NVM_PBA_SECTION;
        }
 
        /*
@@ -948,8 +923,196 @@ s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size)
         */
        *pba_num_size = ((u32)length * 2) - 1;
 
-out:
+       return E1000_SUCCESS;
+}
+
+
+/**
+ *  e1000_read_pba_raw
+ *  @hw: pointer to the HW structure
+ *  @eeprom_buf: optional pointer to EEPROM image
+ *  @eeprom_buf_size: size of EEPROM image in words
+ *  @max_pba_block_size: PBA block size limit
+ *  @pba: pointer to output PBA structure
+ *
+ *  Reads PBA from EEPROM image when eeprom_buf is not NULL.
+ *  Reads PBA from physical EEPROM device when eeprom_buf is NULL.
+ *
+ **/
+s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
+                      u32 eeprom_buf_size, u16 max_pba_block_size,
+                      struct e1000_pba *pba)
+{
+       s32 ret_val;
+       u16 pba_block_size;
+
+       if (pba == NULL)
+               return -E1000_ERR_PARAM;
+
+       if (eeprom_buf == NULL) {
+               ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2,
+                                        &pba->word[0]);
+               if (ret_val)
+                       return ret_val;
+       } else {
+               if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
+                       pba->word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
+                       pba->word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
+               } else {
+                       return -E1000_ERR_PARAM;
+               }
+       }
+
+       if (pba->word[0] == NVM_PBA_PTR_GUARD) {
+               if (pba->pba_block == NULL)
+                       return -E1000_ERR_PARAM;
+
+               ret_val = e1000_get_pba_block_size(hw, eeprom_buf,
+                                                  eeprom_buf_size,
+                                                  &pba_block_size);
+               if (ret_val)
+                       return ret_val;
+
+               if (pba_block_size > max_pba_block_size)
+                       return -E1000_ERR_PARAM;
+
+               if (eeprom_buf == NULL) {
+                       ret_val = e1000_read_nvm(hw, pba->word[1],
+                                                pba_block_size,
+                                                pba->pba_block);
+                       if (ret_val)
+                               return ret_val;
+               } else {
+                       if (eeprom_buf_size > (u32)(pba->word[1] +
+                                             pba->pba_block[0])) {
+                               memcpy(pba->pba_block,
+                                      &eeprom_buf[pba->word[1]],
+                                      pba_block_size * sizeof(u16));
+                       } else {
+                               return -E1000_ERR_PARAM;
+                       }
+               }
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_write_pba_raw
+ *  @hw: pointer to the HW structure
+ *  @eeprom_buf: optional pointer to EEPROM image
+ *  @eeprom_buf_size: size of EEPROM image in words
+ *  @pba: pointer to PBA structure
+ *
+ *  Writes PBA to EEPROM image when eeprom_buf is not NULL.
+ *  Writes PBA to physical EEPROM device when eeprom_buf is NULL.
+ *
+ **/
+s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
+                       u32 eeprom_buf_size, struct e1000_pba *pba)
+{
+       s32 ret_val;
+
+       if (pba == NULL)
+               return -E1000_ERR_PARAM;
+
+       if (eeprom_buf == NULL) {
+               ret_val = e1000_write_nvm(hw, NVM_PBA_OFFSET_0, 2,
+                                         &pba->word[0]);
+               if (ret_val)
+                       return ret_val;
+       } else {
+               if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
+                       eeprom_buf[NVM_PBA_OFFSET_0] = pba->word[0];
+                       eeprom_buf[NVM_PBA_OFFSET_1] = pba->word[1];
+               } else {
+                       return -E1000_ERR_PARAM;
+               }
+       }
+
+       if (pba->word[0] == NVM_PBA_PTR_GUARD) {
+               if (pba->pba_block == NULL)
+                       return -E1000_ERR_PARAM;
+
+               if (eeprom_buf == NULL) {
+                       ret_val = e1000_write_nvm(hw, pba->word[1],
+                                                 pba->pba_block[0],
+                                                 pba->pba_block);
+                       if (ret_val)
+                               return ret_val;
+               } else {
+                       if (eeprom_buf_size > (u32)(pba->word[1] +
+                                             pba->pba_block[0])) {
+                               memcpy(&eeprom_buf[pba->word[1]],
+                                      pba->pba_block,
+                                      pba->pba_block[0] * sizeof(u16));
+                       } else {
+                               return -E1000_ERR_PARAM;
+                       }
+               }
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_get_pba_block_size
+ *  @hw: pointer to the HW structure
+ *  @eeprom_buf: optional pointer to EEPROM image
+ *  @eeprom_buf_size: size of EEPROM image in words
+ *  @pba_data_size: pointer to output variable
+ *
+ *  Returns the size of the PBA block in words. Function operates on EEPROM
+ *  image if the eeprom_buf pointer is not NULL otherwise it accesses physical
+ *  EEPROM device.
+ *
+ **/
+s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf,
+                            u32 eeprom_buf_size, u16 *pba_block_size)
+{
+       s32 ret_val;
+       u16 pba_word[2];
+       u16 length;
+
+       DEBUGFUNC("e1000_get_pba_block_size");
+
+       if (eeprom_buf == NULL) {
+               ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba_word[0]);
+               if (ret_val)
+                       return ret_val;
+       } else {
+               if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
+                       pba_word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
+                       pba_word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
+               } else {
+                       return -E1000_ERR_PARAM;
+               }
+       }
+
+       if (pba_word[0] == NVM_PBA_PTR_GUARD) {
+               if (eeprom_buf == NULL) {
+                       ret_val = e1000_read_nvm(hw, pba_word[1] + 0, 1,
+                                                &length);
+                       if (ret_val)
        return ret_val;
+               } else {
+                       if (eeprom_buf_size > pba_word[1])
+                               length = eeprom_buf[pba_word[1] + 0];
+                       else
+                               return -E1000_ERR_PARAM;
+               }
+
+               if (length == 0xFFFF || length == 0)
+                       return -E1000_ERR_NVM_PBA_SECTION;
+       } else {
+               /* PBA number in legacy format, there is no PBA Block. */
+               length = 0;
+       }
+
+       if (pba_block_size != NULL)
+               *pba_block_size = length;
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -990,7 +1153,7 @@ s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
  **/
 s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
 {
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
        u16 checksum = 0;
        u16 i, nvm_data;
 
@@ -1000,19 +1163,17 @@ s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
                ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
                if (ret_val) {
                        DEBUGOUT("NVM Read Error\n");
-                       goto out;
+                       return ret_val;
                }
                checksum += nvm_data;
        }
 
        if (checksum != (u16) NVM_SUM) {
                DEBUGOUT("NVM Checksum Invalid\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1035,7 +1196,7 @@ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
                ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
                if (ret_val) {
                        DEBUGOUT("NVM Read Error while updating checksum.\n");
-                       goto out;
+                       return ret_val;
                }
                checksum += nvm_data;
        }
@@ -1044,7 +1205,6 @@ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
        if (ret_val)
                DEBUGOUT("NVM Write Error while updating checksum.\n");
 
-out:
        return ret_val;
 }
 
@@ -1068,3 +1228,79 @@ STATIC void e1000_reload_nvm_generic(struct e1000_hw *hw)
        E1000_WRITE_FLUSH(hw);
 }
 
+/**
+ *  e1000_get_fw_version - Get firmware version information
+ *  @hw: pointer to the HW structure
+ *  @fw_vers: pointer to output version structure
+ *
+ *  unsupported/not present features return 0 in version structure
+ **/
+void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers)
+{
+       u16 eeprom_verh, eeprom_verl, fw_version;
+       u16 comb_verh, comb_verl, comb_offset;
+
+       memset(fw_vers, 0, sizeof(struct e1000_fw_version));
+
+       /* this code only applies to certain mac types */
+       switch (hw->mac.type) {
+       case e1000_i211:
+               e1000_read_invm_version(hw, fw_vers);
+               return;
+       case e1000_82575:
+       case e1000_82576:
+       case e1000_82580:
+       case e1000_i350:
+       case e1000_i210:
+               break;
+       default:
+               return;
+       }
+
+       /* basic eeprom version numbers */
+       hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
+       fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT;
+       fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK);
+
+       /* etrack id */
+       hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
+       hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
+       fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | eeprom_verl;
+
+       switch (hw->mac.type) {
+       case e1000_i210:
+       case e1000_i350:
+               /* find combo image version */
+               hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
+               if ((comb_offset != 0x0) &&
+                   (comb_offset != NVM_VER_INVALID)) {
+
+                       hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
+                                        + 1), 1, &comb_verh);
+                       hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
+                                        1, &comb_verl);
+
+                       /* get Option Rom version if it exists and is valid */
+                       if ((comb_verh && comb_verl) &&
+                           ((comb_verh != NVM_VER_INVALID) &&
+                            (comb_verl != NVM_VER_INVALID))) {
+
+                               fw_vers->or_valid = true;
+                               fw_vers->or_major =
+                                       comb_verl >> NVM_COMB_VER_SHFT;
+                               fw_vers->or_build =
+                                       (comb_verl << NVM_COMB_VER_SHFT)
+                                       | (comb_verh >> NVM_COMB_VER_SHFT);
+                               fw_vers->or_patch =
+                                       comb_verh & NVM_COMB_VER_MASK;
+                       }
+               }
+               break;
+
+       default:
+               break;
+       }
+       return;
+}
+
+
index 97e421d..5696f13 100644 (file)
@@ -34,6 +34,27 @@ POSSIBILITY OF SUCH DAMAGE.
 #ifndef _E1000_NVM_H_
 #define _E1000_NVM_H_
 
+struct e1000_pba {
+       u16 word[2];
+       u16 *pba_block;
+};
+
+struct e1000_fw_version {
+       u32 etrack_id;
+       u16 eep_major;
+       u16 eep_minor;
+
+       u8 invm_major;
+       u8 invm_minor;
+       u8 invm_img_type;
+
+       bool or_valid;
+       u16 or_major;
+       u16 or_build;
+       u16 or_patch;
+};
+
+
 void e1000_init_nvm_ops_generic(struct e1000_hw *hw);
 s32  e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c);
 void e1000_null_nvm_generic(struct e1000_hw *hw);
@@ -46,6 +67,13 @@ s32  e1000_read_mac_addr_generic(struct e1000_hw *hw);
 s32  e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
                                    u32 pba_num_size);
 s32  e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size);
+s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
+                      u32 eeprom_buf_size, u16 max_pba_block_size,
+                      struct e1000_pba *pba);
+s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
+                       u32 eeprom_buf_size, struct e1000_pba *pba);
+s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf,
+                            u32 eeprom_buf_size, u16 *pba_block_size);
 s32  e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset,
                               u16 words, u16 *data);
@@ -58,7 +86,10 @@ s32  e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset,
 s32  e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words,
                          u16 *data);
 s32  e1000_update_nvm_checksum_generic(struct e1000_hw *hw);
+void e1000_stop_nvm(struct e1000_hw *hw);
 void e1000_release_nvm_generic(struct e1000_hw *hw);
+void e1000_get_fw_version(struct e1000_hw *hw,
+                         struct e1000_fw_version *fw_vers);
 
 #define E1000_STM_OPCODE  0xDB00
 
index 203dcc8..7a569b2 100644 (file)
@@ -53,6 +53,17 @@ e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value)
        return;
 }
 
+void
+e1000_pci_set_mwi(struct e1000_hw *hw)
+{
+}
+
+void
+e1000_pci_clear_mwi(struct e1000_hw *hw)
+{
+}
+
+
 /*
  * Read the PCI Express capabilities
  */
index bf03bbf..737f873 100644 (file)
@@ -42,6 +42,7 @@
 #include <rte_common.h>
 #include <rte_cycles.h>
 #include <rte_log.h>
+#include <rte_debug.h>
 
 #include "../e1000_logs.h"
 
 #pragma warning(disable:2259) /* conversion may lose significant bits */
 #pragma warning(disable:869)  /* Parameter was never referenced */
 #pragma warning(disable:181)  /* Arg incompatible with format string */
+#pragma warning(disable:188)  /* enumerated type mixed with another type */
+#pragma warning(disable:1599) /* declaration hides variable */
+#pragma warning(disable:177)  /* declared but never referenced */
 #else
 #pragma GCC diagnostic ignored "-Wunused-parameter"
 #pragma GCC diagnostic ignored "-Wformat"
 #pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-variable"
 #if (((__GNUC__) >= 4) && ((__GNUC_MINOR__) >= 7))
 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
 #endif
 #define FALSE                  0
 #define TRUE                   1
 
+#define        CMD_MEM_WRT_INVALIDATE  0x0010  /* BIT_4 */
+
+/* Mutex used in the shared code */
+#define E1000_MUTEX                     uintptr_t
+#define E1000_MUTEX_INIT(mutex)         (*(mutex) = 0)
+#define E1000_MUTEX_LOCK(mutex)         (*(mutex) = 1)
+#define E1000_MUTEX_UNLOCK(mutex)       (*(mutex) = 0)
+
 typedef uint64_t       u64;
 typedef uint32_t       u32;
 typedef uint16_t       u16;
@@ -125,6 +138,43 @@ static inline uint32_t e1000_read_addr(volatile void* addr)
 #define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
 #define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
 
+#define        E1000_ACCESS_PANIC(x, hw, reg, value) \
+       rte_panic("%s:%u\t" RTE_STR(x) "(%p, 0x%x, 0x%x)", \
+               __FILE__, __LINE__, (hw), (reg), (value))
+
+/*
+ * To be able to do IO write, we need to map IO BAR
+ * (bar 2/4 depending on device).
+ * Right now mapping multiple BARs is not supported by DPDK.
+ * Fortunatelly we need it only for legacy hw support.
+ */
+
+#define E1000_WRITE_REG_IO(hw, reg, value) \
+       E1000_WRITE_REG(hw, reg, value)
+
+/*
+ * Not implemented.
+ */
+
+#define E1000_READ_FLASH_REG(hw, reg) \
+       (E1000_ACCESS_PANIC(E1000_READ_FLASH_REG, hw, reg, 0), 0)
+
+#define E1000_READ_FLASH_REG16(hw, reg)  \
+       (E1000_ACCESS_PANIC(E1000_READ_FLASH_REG16, hw, reg, 0), 0)
+
+#define E1000_WRITE_FLASH_REG(hw, reg, value)  \
+       E1000_ACCESS_PANIC(E1000_WRITE_FLASH_REG, hw, reg, value)
+
+#define E1000_WRITE_FLASH_REG16(hw, reg, value) \
+       E1000_ACCESS_PANIC(E1000_WRITE_FLASH_REG16, hw, reg, value)
+
 #define STATIC static
 
+#ifndef ETH_ADDR_LEN
+#define ETH_ADDR_LEN                  6
+#endif
+
+#define false                         FALSE
+#define true                          TRUE
+
 #endif /* _E1000_OSDEP_H_ */
index 0519b3d..ef2b958 100644 (file)
@@ -33,8 +33,13 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include "e1000_api.h"
 
-static s32 e1000_copper_link_autoneg(struct e1000_hw *hw);
-static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
+static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
+STATIC s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
+                                         u16 *data, bool read, bool page_set);
+STATIC u32 e1000_get_phy_addr_for_hv_page(u32 page);
+STATIC s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
+                                         u16 *data, bool read);
+
 /* Cable length tables */
 static const u16 e1000_m88_cable_length_table[] = {
        0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
@@ -76,16 +81,32 @@ void e1000_init_phy_ops_generic(struct e1000_hw *hw)
        phy->ops.get_cfg_done = e1000_null_ops_generic;
        phy->ops.get_cable_length = e1000_null_ops_generic;
        phy->ops.get_info = e1000_null_ops_generic;
+       phy->ops.set_page = e1000_null_set_page;
        phy->ops.read_reg = e1000_null_read_reg;
        phy->ops.read_reg_locked = e1000_null_read_reg;
+       phy->ops.read_reg_page = e1000_null_read_reg;
        phy->ops.release = e1000_null_phy_generic;
        phy->ops.reset = e1000_null_ops_generic;
        phy->ops.set_d0_lplu_state = e1000_null_lplu_state;
        phy->ops.set_d3_lplu_state = e1000_null_lplu_state;
        phy->ops.write_reg = e1000_null_write_reg;
        phy->ops.write_reg_locked = e1000_null_write_reg;
+       phy->ops.write_reg_page = e1000_null_write_reg;
        phy->ops.power_up = e1000_null_phy_generic;
        phy->ops.power_down = e1000_null_phy_generic;
+       phy->ops.read_i2c_byte = e1000_read_i2c_byte_null;
+       phy->ops.write_i2c_byte = e1000_write_i2c_byte_null;
+       phy->ops.cfg_on_link_up = e1000_null_ops_generic;
+}
+
+/**
+ *  e1000_null_set_page - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_set_page(struct e1000_hw *hw, u16 data)
+{
+       DEBUGFUNC("e1000_null_set_page");
+       return E1000_SUCCESS;
 }
 
 /**
@@ -128,6 +149,36 @@ s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data)
        return E1000_SUCCESS;
 }
 
+/**
+ *  e1000_read_i2c_byte_null - No-op function, return 0
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @dev_addr: device address
+ *  @data: data value read
+ *
+ **/
+s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
+                            u8 dev_addr, u8 *data)
+{
+       DEBUGFUNC("e1000_read_i2c_byte_null");
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_write_i2c_byte_null - No-op function, return 0
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @dev_addr: device address
+ *  @data: data value to write
+ *
+ **/
+s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
+                             u8 dev_addr, u8 data)
+{
+       DEBUGFUNC("e1000_write_i2c_byte_null");
+       return E1000_SUCCESS;
+}
+
 /**
  *  e1000_check_reset_block_generic - Check if PHY reset is blocked
  *  @hw: pointer to the HW structure
@@ -160,27 +211,34 @@ s32 e1000_get_phy_id(struct e1000_hw *hw)
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val = E1000_SUCCESS;
        u16 phy_id;
+       u16 retry_count = 0;
 
        DEBUGFUNC("e1000_get_phy_id");
 
-       if (!(phy->ops.read_reg))
-               goto out;
+       if (!phy->ops.read_reg)
+               return E1000_SUCCESS;
 
+       while (retry_count < 2) {
        ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
        if (ret_val)
-               goto out;
+                       return ret_val;
 
        phy->id = (u32)(phy_id << 16);
        usec_delay(20);
        ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
        if (ret_val)
-               goto out;
+                       return ret_val;
 
        phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
        phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
 
-out:
-       return ret_val;
+               if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
+                       return E1000_SUCCESS;
+
+               retry_count++;
+       }
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -191,21 +249,18 @@ out:
  **/
 s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw)
 {
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_phy_reset_dsp_generic");
 
-       if (!(hw->phy.ops.write_reg))
-               goto out;
+       if (!hw->phy.ops.write_reg)
+               return E1000_SUCCESS;
 
        ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
        if (ret_val)
-               goto out;
-
-       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
-
-out:
        return ret_val;
+
+       return hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
 }
 
 /**
@@ -221,7 +276,6 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, mdic = 0;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_read_phy_reg_mdic");
 
@@ -254,18 +308,22 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
        }
        if (!(mdic & E1000_MDIC_READY)) {
                DEBUGOUT("MDI Read did not complete\n");
-               ret_val = -E1000_ERR_PHY;
-               goto out;
+               return -E1000_ERR_PHY;
        }
        if (mdic & E1000_MDIC_ERROR) {
                DEBUGOUT("MDI Error\n");
-               ret_val = -E1000_ERR_PHY;
-               goto out;
+               return -E1000_ERR_PHY;
        }
        *data = (u16) mdic;
 
-out:
-       return ret_val;
+       /*
+        * Allow some time after each MDIC transaction to avoid
+        * reading duplicate data in the next MDIC transaction.
+        */
+       if (hw->mac.type == e1000_pch2lan)
+               usec_delay(100);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -280,7 +338,6 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, mdic = 0;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_write_phy_reg_mdic");
 
@@ -314,17 +371,21 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
        }
        if (!(mdic & E1000_MDIC_READY)) {
                DEBUGOUT("MDI Write did not complete\n");
-               ret_val = -E1000_ERR_PHY;
-               goto out;
+               return -E1000_ERR_PHY;
        }
        if (mdic & E1000_MDIC_ERROR) {
                DEBUGOUT("MDI Error\n");
-               ret_val = -E1000_ERR_PHY;
-               goto out;
+               return -E1000_ERR_PHY;
        }
 
-out:
-       return ret_val;
+       /*
+        * Allow some time after each MDIC transaction to avoid
+        * reading duplicate data in the next MDIC transaction.
+        */
+       if (hw->mac.type == e1000_pch2lan)
+               usec_delay(100);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -392,6 +453,13 @@ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
 
        DEBUGFUNC("e1000_write_phy_reg_i2c");
 
+       /* Prevent overwritting SFP I2C EEPROM which is at A0 address.*/
+       if ((hw->phy.addr == 0) || (hw->phy.addr > 7)) {
+               DEBUGOUT1("PHY I2C Address %d is out of range.\n",
+                         hw->phy.addr);
+               return -E1000_ERR_CONFIG;
+       }
+
        /* Swap the data bytes for the I2C interface */
        phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
 
@@ -426,6 +494,139 @@ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
        return E1000_SUCCESS;
 }
 
+/**
+ *  e1000_read_sfp_data_byte - Reads SFP module data.
+ *  @hw: pointer to the HW structure
+ *  @offset: byte location offset to be read
+ *  @data: read data buffer pointer
+ *
+ *  Reads one byte from SFP module data stored
+ *  in SFP resided EEPROM memory or SFP diagnostic area.
+ *  Function should be called with
+ *  E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
+ *  E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
+ *  access
+ **/
+s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data)
+{
+       u32 i = 0;
+       u32 i2ccmd = 0;
+       u32 data_local = 0;
+
+       DEBUGFUNC("e1000_read_sfp_data_byte");
+
+       if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
+               DEBUGOUT("I2CCMD command address exceeds upper limit\n");
+               return -E1000_ERR_PHY;
+       }
+
+       /*
+        * Set up Op-code, EEPROM Address,in the I2CCMD
+        * register. The MAC will take care of interfacing with the
+        * EEPROM to retrieve the desired data.
+        */
+       i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+                 E1000_I2CCMD_OPCODE_READ);
+
+       E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
+
+       /* Poll the ready bit to see if the I2C read completed */
+       for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
+               usec_delay(50);
+               data_local = E1000_READ_REG(hw, E1000_I2CCMD);
+               if (data_local & E1000_I2CCMD_READY)
+                       break;
+       }
+       if (!(data_local & E1000_I2CCMD_READY)) {
+               DEBUGOUT("I2CCMD Read did not complete\n");
+               return -E1000_ERR_PHY;
+       }
+       if (data_local & E1000_I2CCMD_ERROR) {
+               DEBUGOUT("I2CCMD Error bit set\n");
+               return -E1000_ERR_PHY;
+       }
+       *data = (u8) data_local & 0xFF;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_write_sfp_data_byte - Writes SFP module data.
+ *  @hw: pointer to the HW structure
+ *  @offset: byte location offset to write to
+ *  @data: data to write
+ *
+ *  Writes one byte to SFP module data stored
+ *  in SFP resided EEPROM memory or SFP diagnostic area.
+ *  Function should be called with
+ *  E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
+ *  E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
+ *  access
+ **/
+s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
+{
+       u32 i = 0;
+       u32 i2ccmd = 0;
+       u32 data_local = 0;
+
+       DEBUGFUNC("e1000_write_sfp_data_byte");
+
+       if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
+               DEBUGOUT("I2CCMD command address exceeds upper limit\n");
+               return -E1000_ERR_PHY;
+       }
+       /*
+        * The programming interface is 16 bits wide
+        * so we need to read the whole word first
+        * then update appropriate byte lane and write
+        * the updated word back.
+        */
+       /*
+        * Set up Op-code, EEPROM Address,in the I2CCMD
+        * register. The MAC will take care of interfacing
+        * with an EEPROM to write the data given.
+        */
+       i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+                 E1000_I2CCMD_OPCODE_READ);
+       /* Set a command to read single word */
+       E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
+       for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
+               usec_delay(50);
+               /*
+                * Poll the ready bit to see if lastly
+                * launched I2C operation completed
+                */
+               i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
+               if (i2ccmd & E1000_I2CCMD_READY) {
+                       /* Check if this is READ or WRITE phase */
+                       if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) ==
+                           E1000_I2CCMD_OPCODE_READ) {
+                               /*
+                                * Write the selected byte
+                                * lane and update whole word
+                                */
+                               data_local = i2ccmd & 0xFF00;
+                               data_local |= data;
+                               i2ccmd = ((offset <<
+                                       E1000_I2CCMD_REG_ADDR_SHIFT) |
+                                       E1000_I2CCMD_OPCODE_WRITE | data_local);
+                               E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
+                       } else {
+                               break;
+                       }
+               }
+       }
+       if (!(i2ccmd & E1000_I2CCMD_READY)) {
+               DEBUGOUT("I2CCMD Write did not complete\n");
+               return -E1000_ERR_PHY;
+       }
+       if (i2ccmd & E1000_I2CCMD_ERROR) {
+               DEBUGOUT("I2CCMD Error bit set\n");
+               return -E1000_ERR_PHY;
+       }
+       return E1000_SUCCESS;
+}
+
 /**
  *  e1000_read_phy_reg_m88 - Read m88 PHY register
  *  @hw: pointer to the HW structure
@@ -438,23 +639,22 @@ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
  **/
 s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_read_phy_reg_m88");
 
-       if (!(hw->phy.ops.acquire))
-               goto out;
+       if (!hw->phy.ops.acquire)
+               return E1000_SUCCESS;
 
        ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                          data);
 
        hw->phy.ops.release(hw);
 
-out:
        return ret_val;
 }
 
@@ -469,26 +669,45 @@ out:
  **/
 s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
 {
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_write_phy_reg_m88");
 
-       if (!(hw->phy.ops.acquire))
-               goto out;
+       if (!hw->phy.ops.acquire)
+               return E1000_SUCCESS;
 
        ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                           data);
 
        hw->phy.ops.release(hw);
 
-out:
        return ret_val;
 }
 
+/**
+ *  e1000_set_page_igp - Set page as on IGP-like PHY(s)
+ *  @hw: pointer to the HW structure
+ *  @page: page to set (shifted left when necessary)
+ *
+ *  Sets PHY page required for PHY register access.  Assumes semaphore is
+ *  already acquired.  Note, this function sets phy.addr to 1 so the caller
+ *  must set it appropriately (if necessary) after this function returns.
+ **/
+s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
+{
+       DEBUGFUNC("e1000_set_page_igp");
+
+       DEBUGOUT1("Setting page 0x%x\n", page);
+
+       hw->phy.addr = 1;
+
+       return e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
+}
+
 /**
  *  __e1000_read_phy_reg_igp - Read igp PHY register
  *  @hw: pointer to the HW structure
@@ -508,29 +727,25 @@ static s32 __e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
        DEBUGFUNC("__e1000_read_phy_reg_igp");
 
        if (!locked) {
-               if (!(hw->phy.ops.acquire))
-                       goto out;
+               if (!hw->phy.ops.acquire)
+                       return E1000_SUCCESS;
 
                ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        }
 
-       if (offset > MAX_PHY_MULTI_PAGE_REG) {
+       if (offset > MAX_PHY_MULTI_PAGE_REG)
                ret_val = e1000_write_phy_reg_mdic(hw,
                                                   IGP01E1000_PHY_PAGE_SELECT,
                                                   (u16)offset);
-               if (ret_val)
-                       goto release;
-       }
-
-       ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+       if (!ret_val)
+               ret_val = e1000_read_phy_reg_mdic(hw,
+                                                 MAX_PHY_REG_ADDRESS & offset,
                                          data);
-
-release:
        if (!locked)
                hw->phy.ops.release(hw);
-out:
+
        return ret_val;
 }
 
@@ -581,30 +796,25 @@ static s32 __e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
        DEBUGFUNC("e1000_write_phy_reg_igp");
 
        if (!locked) {
-               if (!(hw->phy.ops.acquire))
-                       goto out;
+               if (!hw->phy.ops.acquire)
+                       return E1000_SUCCESS;
 
                ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        }
 
-       if (offset > MAX_PHY_MULTI_PAGE_REG) {
+       if (offset > MAX_PHY_MULTI_PAGE_REG)
                ret_val = e1000_write_phy_reg_mdic(hw,
                                                   IGP01E1000_PHY_PAGE_SELECT,
                                                   (u16)offset);
-               if (ret_val)
-                       goto release;
-       }
-
-       ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+       if (!ret_val)
+               ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS &
+                                                      offset,
                                           data);
-
-release:
        if (!locked)
                hw->phy.ops.release(hw);
 
-out:
        return ret_val;
 }
 
@@ -651,22 +861,24 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
                                  bool locked)
 {
        u32 kmrnctrlsta;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("__e1000_read_kmrn_reg");
 
        if (!locked) {
-               if (!(hw->phy.ops.acquire))
-                       goto out;
+               s32 ret_val = E1000_SUCCESS;
+
+               if (!hw->phy.ops.acquire)
+                       return E1000_SUCCESS;
 
                ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        }
 
        kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
                       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
        E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
+       E1000_WRITE_FLUSH(hw);
 
        usec_delay(2);
 
@@ -676,8 +888,7 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
        if (!locked)
                hw->phy.ops.release(hw);
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -725,30 +936,31 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
                                   bool locked)
 {
        u32 kmrnctrlsta;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_write_kmrn_reg_generic");
 
        if (!locked) {
-               if (!(hw->phy.ops.acquire))
-                       goto out;
+               s32 ret_val = E1000_SUCCESS;
+
+               if (!hw->phy.ops.acquire)
+                       return E1000_SUCCESS;
 
                ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        }
 
        kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
                       E1000_KMRNCTRLSTA_OFFSET) | data;
        E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
+       E1000_WRITE_FLUSH(hw);
 
        usec_delay(2);
 
        if (!locked)
                hw->phy.ops.release(hw);
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -779,6 +991,46 @@ s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
        return __e1000_write_kmrn_reg(hw, offset, data, true);
 }
 
+/**
+ *  e1000_set_master_slave_mode - Setup PHY for Master/slave mode
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets up Master/slave mode
+ **/
+STATIC s32 e1000_set_master_slave_mode(struct e1000_hw *hw)
+{
+       s32 ret_val;
+       u16 phy_data;
+
+       /* Resolve Master/Slave mode */
+       ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data);
+       if (ret_val)
+               return ret_val;
+
+       /* load defaults for future use */
+       hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
+                                  ((phy_data & CR_1000T_MS_VALUE) ?
+                                   e1000_ms_force_master :
+                                   e1000_ms_force_slave) : e1000_ms_auto;
+
+       switch (hw->phy.ms_type) {
+       case e1000_ms_force_master:
+               phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+               break;
+       case e1000_ms_force_slave:
+               phy_data |= CR_1000T_MS_ENABLE;
+               phy_data &= ~(CR_1000T_MS_VALUE);
+               break;
+       case e1000_ms_auto:
+               phy_data &= ~CR_1000T_MS_ENABLE;
+               /* fall-through */
+       default:
+               break;
+       }
+
+       return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
+}
+
 /**
  *  e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
  *  @hw: pointer to the HW structure
@@ -792,23 +1044,18 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_copper_link_setup_82577");
 
-       if (hw->phy.reset_disable) {
-               ret_val = E1000_SUCCESS;
-               goto out;
-       }
-
        if (hw->phy.type == e1000_phy_82580) {
                ret_val = hw->phy.ops.reset(hw);
                if (ret_val) {
                        DEBUGOUT("Error resetting the PHY.\n");
-                       goto out;
+                       return ret_val;
                }
        }
 
        /* Enable CRS on Tx. This must be set for half-duplex operation. */
        ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
 
@@ -816,9 +1063,36 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
        phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
 
        ret_val = hw->phy.ops.write_reg(hw, I82577_CFG_REG, phy_data);
-
-out:
+       if (ret_val)
        return ret_val;
+
+       /* Set MDI/MDIX mode */
+       ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data);
+       if (ret_val)
+               return ret_val;
+       phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK;
+       /*
+        * Options:
+        *   0 - Auto (default)
+        *   1 - MDI mode
+        *   2 - MDI-X mode
+        */
+       switch (hw->phy.mdix) {
+       case 1:
+               break;
+       case 2:
+               phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX;
+               break;
+       case 0:
+       default:
+               phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX;
+               break;
+       }
+       ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data);
+       if (ret_val)
+               return ret_val;
+
+       return e1000_set_master_slave_mode(hw);
 }
 
 /**
@@ -836,16 +1110,14 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_copper_link_setup_m88");
 
-       if (phy->reset_disable) {
-               ret_val = E1000_SUCCESS;
-               goto out;
-       }
 
        /* Enable CRS on Tx. This must be set for half-duplex operation. */
        ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
+       /* For BM PHY this bit is downshift enable */
+       if (phy->type != e1000_phy_bm)
        phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
 
        /*
@@ -882,14 +1154,36 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
         *   1 - Enabled
         */
        phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
-       if (phy->disable_polarity_correction == 1)
+       if (phy->disable_polarity_correction)
                phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
 
+       /* Enable downshift on BM (disabled by default) */
+       if (phy->type == e1000_phy_bm) {
+               /* For 82574/82583, first disable then enable downshift */
+               if (phy->id == BME1000_E_PHY_ID_R2) {
+                       phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT;
+                       ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+                                                    phy_data);
+                       if (ret_val)
+                               return ret_val;
+                       /* Commit the changes. */
+                       ret_val = phy->ops.commit(hw);
+                       if (ret_val) {
+                               DEBUGOUT("Error committing the PHY changes\n");
+                               return ret_val;
+                       }
+               }
+
+               phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
+       }
+
        ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
-       if (phy->revision < E1000_REVISION_4) {
+       if ((phy->type == e1000_phy_m88) &&
+           (phy->revision < E1000_REVISION_4) &&
+           (phy->id != BME1000_E_PHY_ID_R2)) {
                /*
                 * Force TX_CLK in the Extended PHY Specific Control Register
                 * to 25MHz clock.
@@ -897,7 +1191,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
                ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
                                             &phy_data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                phy_data |= M88E1000_EPSCR_TX_CLK_25;
 
@@ -916,21 +1210,53 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
                ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
                                             phy_data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
+       }
+
+       if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) {
+               /* Set PHY page 0, register 29 to 0x0003 */
+               ret_val = phy->ops.write_reg(hw, 29, 0x0003);
+               if (ret_val)
+                       return ret_val;
+
+               /* Set PHY page 0, register 30 to 0x0000 */
+               ret_val = phy->ops.write_reg(hw, 30, 0x0000);
+               if (ret_val)
+                       return ret_val;
        }
 
        /* Commit the changes. */
        ret_val = phy->ops.commit(hw);
        if (ret_val) {
                DEBUGOUT("Error committing the PHY changes\n");
-               goto out;
+               return ret_val;
        }
 
-out:
-       return ret_val;
-}
-
-/**
+       if (phy->type == e1000_phy_82578) {
+               ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+                                           &phy_data);
+               if (ret_val)
+                       return ret_val;
+
+               /* 82578 PHY - set the downshift count to 1x. */
+               phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
+               phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK;
+               ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+                                            phy_data);
+               if (ret_val)
+                       return ret_val;
+       }
+
+       if (phy->type == e1000_phy_i210) {
+               ret_val = e1000_set_master_slave_mode(hw);
+               if (ret_val)
+       return ret_val;
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
  *  e1000_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
  *  @hw: pointer to the HW structure
  *
@@ -945,15 +1271,11 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_copper_link_setup_m88_gen2");
 
-       if (phy->reset_disable) {
-               ret_val = E1000_SUCCESS;
-               goto out;
-       }
 
        /* Enable CRS on Tx. This must be set for half-duplex operation. */
        ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /*
         * Options:
@@ -992,7 +1314,7 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
         *   1 - Enabled
         */
        phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
-       if (phy->disable_polarity_correction == 1)
+       if (phy->disable_polarity_correction)
                phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
 
        /* Enable downshift and setting it to X6 */
@@ -1002,17 +1324,16 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
 
        ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /* Commit the changes. */
        ret_val = phy->ops.commit(hw);
        if (ret_val) {
                DEBUGOUT("Error committing the PHY changes\n");
-               goto out;
+               return ret_val;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1030,15 +1351,11 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_copper_link_setup_igp");
 
-       if (phy->reset_disable) {
-               ret_val = E1000_SUCCESS;
-               goto out;
-       }
 
        ret_val = hw->phy.ops.reset(hw);
        if (ret_val) {
                DEBUGOUT("Error resetting the PHY.\n");
-               goto out;
+               return ret_val;
        }
 
        /*
@@ -1047,18 +1364,31 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
         */
        msec_delay(100);
 
+       /*
+        * The NVM settings will configure LPLU in D3 for
+        * non-IGP1 PHYs.
+        */
+       if (phy->type == e1000_phy_igp) {
+               /* disable lplu d3 during driver init */
+               ret_val = hw->phy.ops.set_d3_lplu_state(hw, false);
+               if (ret_val) {
+                       DEBUGOUT("Error Disabling LPLU D3\n");
+                       return ret_val;
+               }
+       }
+
        /* disable lplu d0 during driver init */
        if (hw->phy.ops.set_d0_lplu_state) {
-               ret_val = hw->phy.ops.set_d0_lplu_state(hw, FALSE);
+               ret_val = hw->phy.ops.set_d0_lplu_state(hw, false);
                if (ret_val) {
                        DEBUGOUT("Error Disabling LPLU D0\n");
-                       goto out;
+                       return ret_val;
                }
        }
        /* Configure mdi-mdix settings */
        ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        data &= ~IGP01E1000_PSCR_AUTO_MDIX;
 
@@ -1076,7 +1406,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
        }
        ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /* set auto-master slave resolution settings */
        if (hw->mac.autoneg) {
@@ -1091,126 +1421,29 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     &data);
                        if (ret_val)
-                               goto out;
+                               return ret_val;
 
                        data &= ~IGP01E1000_PSCFR_SMART_SPEED;
                        ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
-                               goto out;
+                               return ret_val;
 
                        /* Set auto Master/Slave resolution process */
                        ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
                        if (ret_val)
-                               goto out;
-
-                       data &= ~CR_1000T_MS_ENABLE;
-                       ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
-                       if (ret_val)
-                               goto out;
-               }
+                               return ret_val;
 
-               ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
-               if (ret_val)
-                       goto out;
-
-               /* load defaults for future use */
-               phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ?
-                       ((data & CR_1000T_MS_VALUE) ?
-                       e1000_ms_force_master :
-                       e1000_ms_force_slave) :
-                       e1000_ms_auto;
-
-               switch (phy->ms_type) {
-               case e1000_ms_force_master:
-                       data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
-                       break;
-               case e1000_ms_force_slave:
-                       data |= CR_1000T_MS_ENABLE;
-                       data &= ~(CR_1000T_MS_VALUE);
-                       break;
-               case e1000_ms_auto:
                        data &= ~CR_1000T_MS_ENABLE;
-               default:
-                       break;
-               }
                ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
                if (ret_val)
-                       goto out;
-       }
-
-out:
        return ret_val;
-}
-
-/**
- *  e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
- *  @hw: pointer to the HW structure
- *
- *  Performs initial bounds checking on autoneg advertisement parameter, then
- *  configure to advertise the full capability.  Setup the PHY to autoneg
- *  and restart the negotiation process between the link partner.  If
- *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
- **/
-static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
-{
-       struct e1000_phy_info *phy = &hw->phy;
-       s32 ret_val;
-       u16 phy_ctrl;
-
-       DEBUGFUNC("e1000_copper_link_autoneg");
-
-       /*
-        * Perform some bounds checking on the autoneg advertisement
-        * parameter.
-        */
-       phy->autoneg_advertised &= phy->autoneg_mask;
-
-       /*
-        * If autoneg_advertised is zero, we assume it was not defaulted
-        * by the calling code so we set to advertise full capability.
-        */
-       if (phy->autoneg_advertised == 0)
-               phy->autoneg_advertised = phy->autoneg_mask;
-
-       DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
-       ret_val = e1000_phy_setup_autoneg(hw);
-       if (ret_val) {
-               DEBUGOUT("Error Setting up Auto-Negotiation\n");
-               goto out;
        }
-       DEBUGOUT("Restarting Auto-Neg\n");
-
-       /*
-        * Restart auto-negotiation by setting the Auto Neg Enable bit and
-        * the Auto Neg Restart bit in the PHY control register.
-        */
-       ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
-       if (ret_val)
-               goto out;
-
-       phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
-       ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
-       if (ret_val)
-               goto out;
 
-       /*
-        * Does the user want to wait for Auto-Neg to complete here, or
-        * check at a later time (for example, callback routine).
-        */
-       if (phy->autoneg_wait_to_complete) {
-               ret_val = hw->mac.ops.wait_autoneg(hw);
-               if (ret_val) {
-                       DEBUGOUT("Error while waiting for "
-                                "autoneg to complete\n");
-                       goto out;
+               ret_val = e1000_set_master_slave_mode(hw);
                }
-       }
 
-       hw->mac.get_link_status = TRUE;
-
-out:
        return ret_val;
 }
 
@@ -1223,7 +1456,7 @@ out:
  *  return successful.  Otherwise, setup advertisement and flow control to
  *  the appropriate values for the wanted auto-negotiation.
  **/
-static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -1237,14 +1470,14 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
        /* Read the MII Auto-Neg Advertisement Register (Address 4). */
        ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
                /* Read the MII 1000Base-T Control Register (Address 9). */
                ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
                                            &mii_1000t_ctrl_reg);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        }
 
        /*
@@ -1358,25 +1591,87 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
                break;
        default:
                DEBUGOUT("Flow control param set incorrectly\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+               return -E1000_ERR_CONFIG;
        }
 
        ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
 
-       if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
-               ret_val = phy->ops.write_reg(hw,
-                                             PHY_1000T_CTRL,
+       if (phy->autoneg_mask & ADVERTISE_1000_FULL)
+               ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
                                              mii_1000t_ctrl_reg);
-               if (ret_val)
-                       goto out;
+
+       return ret_val;
+}
+
+/**
+ *  e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
+ *  @hw: pointer to the HW structure
+ *
+ *  Performs initial bounds checking on autoneg advertisement parameter, then
+ *  configure to advertise the full capability.  Setup the PHY to autoneg
+ *  and restart the negotiation process between the link partner.  If
+ *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
+ **/
+s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 phy_ctrl;
+
+       DEBUGFUNC("e1000_copper_link_autoneg");
+
+               /*
+        * Perform some bounds checking on the autoneg advertisement
+        * parameter.
+                */
+       phy->autoneg_advertised &= phy->autoneg_mask;
+
+               /*
+        * If autoneg_advertised is zero, we assume it was not defaulted
+        * by the calling code so we set to advertise full capability.
+                */
+       if (!phy->autoneg_advertised)
+               phy->autoneg_advertised = phy->autoneg_mask;
+
+       DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
+       ret_val = e1000_phy_setup_autoneg(hw);
+               if (ret_val) {
+               DEBUGOUT("Error Setting up Auto-Negotiation\n");
+               return ret_val;
        }
+       DEBUGOUT("Restarting Auto-Neg\n");
+
+       /*
+        * Restart auto-negotiation by setting the Auto Neg Enable bit and
+        * the Auto Neg Restart bit in the PHY control register.
+        */
+       ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
+       if (ret_val)
+               return ret_val;
+
+       phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+       ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
+       if (ret_val)
+               return ret_val;
+
+       /*
+        * Does the user want to wait for Auto-Neg to complete here, or
+        * check at a later time (for example, callback routine).
+        */
+       if (phy->autoneg_wait_to_complete) {
+               ret_val = hw->mac.ops.wait_autoneg(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error while waiting for autoneg to complete\n");
+                       return ret_val;
+               }
+       }
+
+       hw->mac.get_link_status = true;
 
-out:
        return ret_val;
 }
 
@@ -1403,7 +1698,7 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
                 */
                ret_val = e1000_copper_link_autoneg(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        } else {
                /*
                 * PHY will be set to 10H, 10F, 100H or 100F
@@ -1413,7 +1708,7 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
                ret_val = hw->phy.ops.force_speed_duplex(hw);
                if (ret_val) {
                        DEBUGOUT("Error Forcing Speed and Duplex\n");
-                       goto out;
+                       return ret_val;
                }
        }
 
@@ -1424,17 +1719,16 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
        ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
                                             &link);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if (link) {
                DEBUGOUT("Valid link established!!!\n");
-               e1000_config_collision_dist_generic(hw);
+               hw->mac.ops.config_collision_dist(hw);
                ret_val = e1000_config_fc_after_link_up_generic(hw);
        } else {
                DEBUGOUT("Unable to establish link!!!\n");
        }
 
-out:
        return ret_val;
 }
 
@@ -1457,13 +1751,13 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
 
        ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        e1000_phy_force_speed_duplex_setup(hw, &phy_data);
 
        ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /*
         * Clear Auto-Crossover to force MDI manually.  IGP requires MDI
@@ -1471,14 +1765,14 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
         */
        ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
        phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
 
        ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        DEBUGOUT1("IGP PSCR: %X\n", phy_data);
 
@@ -1490,21 +1784,16 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
                ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
                                                     100000, &link);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                if (!link)
                        DEBUGOUT("Link taking longer than expected.\n");
 
                /* Try once more */
-               ret_val = e1000_phy_has_link_generic(hw,
-                                                    PHY_FORCE_LIMIT,
-                                                    100000,
-                                                    &link);
-               if (ret_val)
-                       goto out;
+               ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+                                                    100000, &link);
        }
 
-out:
        return ret_val;
 }
 
@@ -1527,35 +1816,40 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_phy_force_speed_duplex_m88");
 
+       /* I210 and I211 devices support Auto-Crossover in forced operation. */
+       if (phy->type != e1000_phy_i210) {
        /*
-        * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
-        * forced whenever speed and duplex are forced.
+                * Clear Auto-Crossover to force MDI manually.  M88E1000
+                * requires MDI forced whenever speed and duplex are forced.
         */
-       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+               ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
+                                           &phy_data);
        if (ret_val)
-               goto out;
+                       return ret_val;
 
        phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-       ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+               ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+                                            phy_data);
        if (ret_val)
-               goto out;
+                       return ret_val;
+       }
 
        DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
 
        ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        e1000_phy_force_speed_duplex_setup(hw, &phy_data);
 
        ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /* Reset the phy to commit changes. */
        ret_val = hw->phy.ops.commit(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if (phy->autoneg_wait_to_complete) {
                DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n");
@@ -1563,13 +1857,25 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
                                                     100000, &link);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                if (!link) {
-                       if (hw->phy.type != e1000_phy_m88 ||
-                           hw->phy.id == I347AT4_E_PHY_ID ||
-                           hw->phy.id == M88E1340M_E_PHY_ID ||
-                           hw->phy.id == M88E1112_E_PHY_ID) {
+                       bool reset_dsp = true;
+
+                       switch (hw->phy.id) {
+                       case I347AT4_E_PHY_ID:
+                       case M88E1340M_E_PHY_ID:
+                       case M88E1112_E_PHY_ID:
+                       case I210_I_PHY_ID:
+                               reset_dsp = false;
+                               break;
+                       default:
+                               if (hw->phy.type != e1000_phy_m88)
+                                       reset_dsp = false;
+                               break;
+                       }
+
+                       if (!reset_dsp) {
                                DEBUGOUT("Link taking longer than expected.\n");
                        } else {
                                /*
@@ -1580,10 +1886,10 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                                                M88E1000_PHY_PAGE_SELECT,
                                                0x001d);
                                if (ret_val)
-                                       goto out;
+                                       return ret_val;
                                ret_val = e1000_phy_reset_dsp_generic(hw);
                                if (ret_val)
-                                       goto out;
+                                       return ret_val;
                        }
                }
 
@@ -1591,18 +1897,21 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
                                                     100000, &link);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        }
 
-       if (hw->phy.type != e1000_phy_m88 ||
-           hw->phy.id == I347AT4_E_PHY_ID ||
+       if (hw->phy.type != e1000_phy_m88)
+               return E1000_SUCCESS;
+
+       if (hw->phy.id == I347AT4_E_PHY_ID ||
            hw->phy.id == M88E1340M_E_PHY_ID ||
            hw->phy.id == M88E1112_E_PHY_ID)
-               goto out;
-
+               return E1000_SUCCESS;
+       if (hw->phy.id == I210_I_PHY_ID)
+               return E1000_SUCCESS;
        ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /*
         * Resetting the phy means we need to re-force TX_CLK in the
@@ -1612,7 +1921,7 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
        phy_data |= M88E1000_EPSCR_TX_CLK_25;
        ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /*
         * In addition, we must re-enable CRS on Tx for both half and full
@@ -1620,12 +1929,11 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
         */
        ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
        ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
 
-out:
        return ret_val;
 }
 
@@ -1648,25 +1956,25 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
 
        ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        e1000_phy_force_speed_duplex_setup(hw, &data);
 
        ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /* Disable MDI-X support for 10/100 */
        ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        data &= ~IFE_PMC_AUTO_MDIX;
        data &= ~IFE_PMC_FORCE_MDIX;
 
        ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        DEBUGOUT1("IFE PMC: %X\n", data);
 
@@ -1675,12 +1983,10 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
        if (phy->autoneg_wait_to_complete) {
                DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n");
 
-               ret_val = e1000_phy_has_link_generic(hw,
-                                                    PHY_FORCE_LIMIT,
-                                                    100000,
-                                                    &link);
+               ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+                                                    100000, &link);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                if (!link)
                        DEBUGOUT("Link taking longer than expected.\n");
@@ -1688,10 +1994,11 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
                /* Try once more */
                ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
                                                     100000, &link);
+               if (ret_val)
+                       return ret_val;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1751,7 +2058,7 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
                DEBUGOUT("Forcing 10mb\n");
        }
 
-       e1000_config_collision_dist_generic(hw);
+       hw->mac.ops.config_collision_dist(hw);
 
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
 }
@@ -1773,24 +2080,24 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
 s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
        u16 data;
 
        DEBUGFUNC("e1000_set_d3_lplu_state_generic");
 
-       if (!(hw->phy.ops.read_reg))
-               goto out;
+       if (!hw->phy.ops.read_reg)
+               return E1000_SUCCESS;
 
        ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if (!active) {
                data &= ~IGP02E1000_PM_D3_LPLU;
                ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
                                             data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
                /*
                 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
                 * during Dx states where the power conservation is most
@@ -1802,27 +2109,27 @@ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
                                                    IGP01E1000_PHY_PORT_CONFIG,
                                                    &data);
                        if (ret_val)
-                               goto out;
+                               return ret_val;
 
                        data |= IGP01E1000_PSCFR_SMART_SPEED;
                        ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
-                               goto out;
+                               return ret_val;
                } else if (phy->smart_speed == e1000_smart_speed_off) {
                        ret_val = phy->ops.read_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     &data);
                        if (ret_val)
-                               goto out;
+                               return ret_val;
 
                        data &= ~IGP01E1000_PSCFR_SMART_SPEED;
                        ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
-                               goto out;
+                               return ret_val;
                }
        } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
                   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
@@ -1831,20 +2138,19 @@ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
                ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
                                              data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                /* When LPLU is enabled, we should disable SmartSpeed */
                ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                             &data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                data &= ~IGP01E1000_PSCFR_SMART_SPEED;
                ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                              data);
        }
 
-out:
        return ret_val;
 }
 
@@ -1865,11 +2171,15 @@ s32 e1000_check_downshift_generic(struct e1000_hw *hw)
        DEBUGFUNC("e1000_check_downshift_generic");
 
        switch (phy->type) {
+       case e1000_phy_i210:
        case e1000_phy_m88:
        case e1000_phy_gg82563:
+       case e1000_phy_bm:
+       case e1000_phy_82578:
                offset  = M88E1000_PHY_SPEC_STATUS;
                mask    = M88E1000_PSSR_DOWNSHIFT;
                break;
+       case e1000_phy_igp:
        case e1000_phy_igp_2:
        case e1000_phy_igp_3:
                offset  = IGP01E1000_PHY_LINK_HEALTH;
@@ -1878,8 +2188,7 @@ s32 e1000_check_downshift_generic(struct e1000_hw *hw)
        default:
                /* speed downshift not supported */
                phy->speed_downgraded = false;
-               ret_val = E1000_SUCCESS;
-               goto out;
+               return E1000_SUCCESS;
        }
 
        ret_val = phy->ops.read_reg(hw, offset, &phy_data);
@@ -1887,7 +2196,6 @@ s32 e1000_check_downshift_generic(struct e1000_hw *hw)
        if (!ret_val)
                phy->speed_downgraded = !!(phy_data & mask);
 
-out:
        return ret_val;
 }
 
@@ -1940,7 +2248,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
         */
        ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
            IGP01E1000_PSSR_SPEED_1000MBPS) {
@@ -1962,7 +2270,6 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
                                      ? e1000_rev_polarity_reversed
                                      : e1000_rev_polarity_normal;
 
-out:
        return ret_val;
 }
 
@@ -2113,22 +2420,20 @@ s32 e1000_get_cable_length_m88(struct e1000_hw *hw)
 
        ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
                M88E1000_PSSR_CABLE_LENGTH_SHIFT;
-       if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
-               ret_val = -E1000_ERR_PHY;
-               goto out;
-       }
+
+       if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
+               return -E1000_ERR_PHY;
 
        phy->min_cable_length = e1000_m88_cable_length_table[index];
        phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
 
        phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
@@ -2140,30 +2445,51 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
        DEBUGFUNC("e1000_get_cable_length_m88_gen2");
 
        switch (hw->phy.id) {
+       case I210_I_PHY_ID:
+               /* Get cable length from PHY Cable Diagnostics Control Reg */
+               ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+                                           (I347AT4_PCDL + phy->addr),
+                                           &phy_data);
+               if (ret_val)
+                       return ret_val;
+
+               /* Check if the unit of cable length is meters or cm */
+               ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+                                           I347AT4_PCDC, &phy_data2);
+               if (ret_val)
+                       return ret_val;
+
+               is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+               /* Populate the phy structure with cable length in meters */
+               phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+               phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+               phy->cable_length = phy_data / (is_cm ? 100 : 1);
+               break;
        case M88E1340M_E_PHY_ID:
        case I347AT4_E_PHY_ID:
                /* Remember the original page select and set it to 7 */
                ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
                                            &default_page);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                /* Get cable length from PHY Cable Diagnostics Control Reg */
                ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr),
                                            &phy_data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                /* Check if the unit of cable length is meters or cm */
                ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
-               is_cm = !(phy_data & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+               is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
 
                /* Populate the phy structure with cable length in meters */
                phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
@@ -2174,7 +2500,7 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
                ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
                                             default_page);
                if (ret_val)
-                       goto out;
+                       return ret_val;
                break;
 
        case M88E1112_E_PHY_ID:
@@ -2182,23 +2508,22 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
                ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
                                            &default_page);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
                                            &phy_data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
                        M88E1000_PSSR_CABLE_LENGTH_SHIFT;
-               if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
-                       ret_val = -E1000_ERR_PHY;
-                       goto out;
-               }
+
+               if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
+                       return -E1000_ERR_PHY;
 
                phy->min_cable_length = e1000_m88_cable_length_table[index];
                phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
@@ -2210,15 +2535,13 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
                ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
                                             default_page);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                break;
        default:
-               ret_val = -E1000_ERR_PHY;
-               goto out;
+               return -E1000_ERR_PHY;
        }
 
-out:
        return ret_val;
 }
 
@@ -2236,7 +2559,7 @@ out:
 s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
        u16 phy_data, i, agc_value = 0;
        u16 cur_agc_index, max_agc_index = 0;
        u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
@@ -2253,7 +2576,7 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
        for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
                ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                /*
                 * Getting bits 15:9, which represent the combination of
@@ -2266,10 +2589,8 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
 
                /* Array index bound check. */
                if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
-                   (cur_agc_index == 0)) {
-                       ret_val = -E1000_ERR_PHY;
-                       goto out;
-               }
+                   (cur_agc_index == 0))
+                       return -E1000_ERR_PHY;
 
                /* Remove min & max AGC values from calculation. */
                if (e1000_igp_2_cable_length_table[min_agc_index] >
@@ -2293,8 +2614,7 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
 
        phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -2318,45 +2638,43 @@ s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
 
        if (phy->media_type != e1000_media_type_copper) {
                DEBUGOUT("Phy info is only valid for copper media\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+               return -E1000_ERR_CONFIG;
        }
 
        ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if (!link) {
                DEBUGOUT("Phy info is only valid if link is up\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+               return -E1000_ERR_CONFIG;
        }
 
        ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        phy->polarity_correction = !!(phy_data &
                                      M88E1000_PSCR_POLARITY_REVERSAL);
 
        ret_val = e1000_check_polarity_m88(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX);
 
        if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
                ret_val = hw->phy.ops.get_cable_length(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS)
                                ? e1000_1000t_rx_status_ok
@@ -2372,7 +2690,6 @@ s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
                phy->remote_rx = e1000_1000t_rx_status_undefined;
        }
 
-out:
        return ret_val;
 }
 
@@ -2396,23 +2713,22 @@ s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
 
        ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if (!link) {
                DEBUGOUT("Phy info is only valid if link is up\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+               return -E1000_ERR_CONFIG;
        }
 
        phy->polarity_correction = true;
 
        ret_val = e1000_check_polarity_igp(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX);
 
@@ -2420,11 +2736,11 @@ s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
            IGP01E1000_PSSR_SPEED_1000MBPS) {
                ret_val = phy->ops.get_cable_length(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
                                ? e1000_1000t_rx_status_ok
@@ -2439,7 +2755,6 @@ s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
                phy->remote_rx = e1000_1000t_rx_status_undefined;
        }
 
-out:
        return ret_val;
 }
 
@@ -2460,24 +2775,22 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
 
        ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if (!link) {
                DEBUGOUT("Phy info is only valid if link is up\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+               return -E1000_ERR_CONFIG;
        }
 
        ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data);
        if (ret_val)
-               goto out;
-       phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE)
-                                  ? FALSE : TRUE;
+               return ret_val;
+       phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE);
 
        if (phy->polarity_correction) {
                ret_val = e1000_check_polarity_ife(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        } else {
                /* Polarity is forced */
                phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
@@ -2487,7 +2800,7 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
 
        ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS);
 
@@ -2496,8 +2809,7 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
        phy->local_rx = e1000_1000t_rx_status_undefined;
        phy->remote_rx = e1000_1000t_rx_status_undefined;
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -2509,26 +2821,25 @@ out:
  **/
 s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw)
 {
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
        u16 phy_ctrl;
 
        DEBUGFUNC("e1000_phy_sw_reset_generic");
 
-       if (!(hw->phy.ops.read_reg))
-               goto out;
+       if (!hw->phy.ops.read_reg)
+               return E1000_SUCCESS;
 
        ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        phy_ctrl |= MII_CR_RESET;
        ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        usec_delay(1);
 
-out:
        return ret_val;
 }
 
@@ -2544,20 +2855,20 @@ out:
 s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
        u32 ctrl;
 
        DEBUGFUNC("e1000_phy_hw_reset_generic");
 
+       if (phy->ops.check_reset_block) {
        ret_val = phy->ops.check_reset_block(hw);
-       if (ret_val) {
-               ret_val = E1000_SUCCESS;
-               goto out;
+               if (ret_val)
+                       return E1000_SUCCESS;
        }
 
        ret_val = phy->ops.acquire(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST);
@@ -2572,10 +2883,7 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
 
        phy->ops.release(hw);
 
-       ret_val = phy->ops.get_cfg_done(hw);
-
-out:
-       return ret_val;
+       return phy->ops.get_cfg_done(hw);
 }
 
 /**
@@ -2713,9 +3021,28 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
        case IFE_C_E_PHY_ID:
                phy_type = e1000_phy_ife;
                break;
+       case BME1000_E_PHY_ID:
+       case BME1000_E_PHY_ID_R2:
+               phy_type = e1000_phy_bm;
+               break;
+       case I82578_E_PHY_ID:
+               phy_type = e1000_phy_82578;
+               break;
+       case I82577_E_PHY_ID:
+               phy_type = e1000_phy_82577;
+               break;
+       case I82579_E_PHY_ID:
+               phy_type = e1000_phy_82579;
+               break;
+       case I217_E_PHY_ID:
+               phy_type = e1000_phy_i217;
+               break;
        case I82580_I_PHY_ID:
                phy_type = e1000_phy_82580;
                break;
+       case I210_I_PHY_ID:
+               phy_type = e1000_phy_i210;
+               break;
        default:
                phy_type = e1000_phy_unknown;
                break;
@@ -2733,7 +3060,6 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
  **/
 s32 e1000_determine_phy_address(struct e1000_hw *hw)
 {
-       s32 ret_val = -E1000_ERR_PHY_TYPE;
        u32 phy_addr = 0;
        u32 i;
        enum e1000_phy_type phy_type = e1000_phy_unknown;
@@ -2752,229 +3078,1047 @@ s32 e1000_determine_phy_address(struct e1000_hw *hw)
                         * If phy_type is valid, break - we found our
                         * PHY address
                         */
-                       if (phy_type != e1000_phy_unknown) {
-                               ret_val = E1000_SUCCESS;
-                               goto out;
-                       }
+                       if (phy_type != e1000_phy_unknown)
+                               return E1000_SUCCESS;
+
                        msec_delay(1);
                        i++;
                } while (i < 10);
        }
 
-out:
-       return ret_val;
+       return -E1000_ERR_PHY_TYPE;
 }
 
 /**
- * e1000_power_up_phy_copper - Restore copper link in case of PHY power down
- * @hw: pointer to the HW structure
+ *  e1000_get_phy_addr_for_bm_page - Retrieve PHY page address
+ *  @page: page to access
  *
- * In the case of a PHY power down to save power, or to turn off link during a
- * driver unload, or wake on lan is not enabled, restore the link to previous
- * settings.
+ *  Returns the phy address for the page requested.
  **/
-void e1000_power_up_phy_copper(struct e1000_hw *hw)
+static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
 {
-       u16 mii_reg = 0;
+       u32 phy_addr = 2;
 
-       /* The PHY will retain its settings across a power down/up cycle */
-       hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
-       mii_reg &= ~MII_CR_POWER_DOWN;
-       hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
+       if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31))
+               phy_addr = 1;
+
+       return phy_addr;
 }
 
 /**
- * e1000_power_down_phy_copper - Restore copper link in case of PHY power down
- * @hw: pointer to the HW structure
+ *  e1000_write_phy_reg_bm - Write BM PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
  *
- * In the case of a PHY power down to save power, or to turn off link during a
- * driver unload, or wake on lan is not enabled, restore the link to previous
- * settings.
+ *  Acquires semaphore, if necessary, then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
  **/
-void e1000_power_down_phy_copper(struct e1000_hw *hw)
+s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
 {
-       u16 mii_reg = 0;
+       s32 ret_val;
+       u32 page = offset >> IGP_PAGE_SHIFT;
 
-       /* The PHY will retain its settings across a power down/up cycle */
-       hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
-       mii_reg |= MII_CR_POWER_DOWN;
-       hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
-       msec_delay(1);
+       DEBUGFUNC("e1000_write_phy_reg_bm");
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               return ret_val;
+
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+                                                        false, false);
+               goto release;
+       }
+
+       hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
+
+       if (offset > MAX_PHY_MULTI_PAGE_REG) {
+               u32 page_shift, page_select;
+
+               /*
+                * Page select is register 31 for phy address 1 and 22 for
+                * phy address 2 and 3. Page select is shifted only for
+                * phy address 1.
+                */
+               if (hw->phy.addr == 1) {
+                       page_shift = IGP_PAGE_SHIFT;
+                       page_select = IGP01E1000_PHY_PAGE_SELECT;
+               } else {
+                       page_shift = 0;
+                       page_select = BM_PHY_PAGE_SELECT;
+               }
+
+               /* Page is shifted left, PHY expects (page x 32) */
+               ret_val = e1000_write_phy_reg_mdic(hw, page_select,
+                                                  (page << page_shift));
+               if (ret_val)
+                       goto release;
+       }
+
+       ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
+
+release:
+       hw->phy.ops.release(hw);
+       return ret_val;
 }
 
 /**
- *  e1000_check_polarity_82577 - Checks the polarity.
+ *  e1000_read_phy_reg_bm - Read BM PHY register
  *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
  *
- *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
- *
- *  Polarity is determined based on the PHY specific status register.
+ *  Acquires semaphore, if necessary, then reads the PHY register at offset
+ *  and storing the retrieved information in data.  Release any acquired
+ *  semaphores before exiting.
  **/
-s32 e1000_check_polarity_82577(struct e1000_hw *hw)
+s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-       struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
-       u16 data;
+       u32 page = offset >> IGP_PAGE_SHIFT;
 
-       DEBUGFUNC("e1000_check_polarity_82577");
+       DEBUGFUNC("e1000_read_phy_reg_bm");
 
-       ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               return ret_val;
 
-       if (!ret_val)
-               phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
-                                     ? e1000_rev_polarity_reversed
-                                     : e1000_rev_polarity_normal;
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+                                                        true, false);
+               goto release;
+       }
+
+       hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
+
+       if (offset > MAX_PHY_MULTI_PAGE_REG) {
+               u32 page_shift, page_select;
+
+               /*
+                * Page select is register 31 for phy address 1 and 22 for
+                * phy address 2 and 3. Page select is shifted only for
+                * phy address 1.
+                */
+               if (hw->phy.addr == 1) {
+                       page_shift = IGP_PAGE_SHIFT;
+                       page_select = IGP01E1000_PHY_PAGE_SELECT;
+               } else {
+                       page_shift = 0;
+                       page_select = BM_PHY_PAGE_SELECT;
+               }
+
+               /* Page is shifted left, PHY expects (page x 32) */
+               ret_val = e1000_write_phy_reg_mdic(hw, page_select,
+                                                  (page << page_shift));
+               if (ret_val)
+                       goto release;
+       }
 
+       ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                         data);
+release:
+       hw->phy.ops.release(hw);
        return ret_val;
 }
 
 /**
- *  e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY
+ *  e1000_read_phy_reg_bm2 - Read BM PHY register
  *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
  *
- *  Calls the PHY setup function to force speed and duplex.
+ *  Acquires semaphore, if necessary, then reads the PHY register at offset
+ *  and storing the retrieved information in data.  Release any acquired
+ *  semaphores before exiting.
  **/
-s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
+s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-       struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
-       u16 phy_data;
-       bool link;
-
-       DEBUGFUNC("e1000_phy_force_speed_duplex_82577");
+       u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
 
-       ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
-       if (ret_val)
-               goto out;
-
-       e1000_phy_force_speed_duplex_setup(hw, &phy_data);
+       DEBUGFUNC("e1000_read_phy_reg_bm2");
 
-       ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
-       usec_delay(1);
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+                                                        true, false);
+               goto release;
+       }
 
-       if (phy->autoneg_wait_to_complete) {
-               DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n");
+       hw->phy.addr = 1;
 
-               ret_val = e1000_phy_has_link_generic(hw,
-                                                    PHY_FORCE_LIMIT,
-                                                    100000,
-                                                    &link);
-               if (ret_val)
-                       goto out;
+       if (offset > MAX_PHY_MULTI_PAGE_REG) {
 
-               if (!link)
-                       DEBUGOUT("Link taking longer than expected.\n");
+               /* Page is shifted left, PHY expects (page x 32) */
+               ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
+                                                  page);
 
-               /* Try once more */
-               ret_val = e1000_phy_has_link_generic(hw,
-                                                    PHY_FORCE_LIMIT,
-                                                    100000,
-                                                    &link);
                if (ret_val)
-                       goto out;
+                       goto release;
        }
 
-out:
+       ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                         data);
+release:
+       hw->phy.ops.release(hw);
        return ret_val;
 }
 
 /**
- *  e1000_get_phy_info_82577 - Retrieve I82577 PHY information
+ *  e1000_write_phy_reg_bm2 - Write BM PHY register
  *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
  *
- *  Read PHY status to determine if link is up.  If link is up, then
- *  set/determine 10base-T extended distance and polarity correction.  Read
- *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
- *  determine on the cable length, local and remote receiver.
+ *  Acquires semaphore, if necessary, then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
  **/
-s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
+s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
 {
-       struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
-       u16 data;
-       bool link;
+       u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
 
-       DEBUGFUNC("e1000_get_phy_info_82577");
+       DEBUGFUNC("e1000_write_phy_reg_bm2");
 
-       ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
-       if (!link) {
-               DEBUGOUT("Phy info is only valid if link is up\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+                                                        false, false);
+               goto release;
        }
 
-       phy->polarity_correction = TRUE;
-
-       ret_val = e1000_check_polarity_82577(hw);
-       if (ret_val)
-               goto out;
-
-       ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
-       if (ret_val)
-               goto out;
-
-       phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? TRUE : FALSE;
+       hw->phy.addr = 1;
 
-       if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
-           I82577_PHY_STATUS2_SPEED_1000MBPS) {
-               ret_val = hw->phy.ops.get_cable_length(hw);
-               if (ret_val)
-                       goto out;
+       if (offset > MAX_PHY_MULTI_PAGE_REG) {
+               /* Page is shifted left, PHY expects (page x 32) */
+               ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
+                                                  page);
 
-               ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
                if (ret_val)
-                       goto out;
-
-               phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
-                               ? e1000_1000t_rx_status_ok
-                               : e1000_1000t_rx_status_not_ok;
-
-               phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
-                                ? e1000_1000t_rx_status_ok
-                                : e1000_1000t_rx_status_not_ok;
-       } else {
-               phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
-               phy->local_rx = e1000_1000t_rx_status_undefined;
-               phy->remote_rx = e1000_1000t_rx_status_undefined;
+                       goto release;
        }
 
-out:
+       ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
+
+release:
+       hw->phy.ops.release(hw);
        return ret_val;
 }
 
 /**
- *  e1000_get_cable_length_82577 - Determine cable length for 82577 PHY
+ *  e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
  *  @hw: pointer to the HW structure
+ *  @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
  *
- * Reads the diagnostic status register and verifies result is valid before
- * placing it in the phy_cable_length field.
+ *  Assumes semaphore already acquired and phy_reg points to a valid memory
+ *  address to store contents of the BM_WUC_ENABLE_REG register.
  **/
-s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
+s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
 {
-       struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
-       u16 phy_data, length;
+       u16 temp;
 
-       DEBUGFUNC("e1000_get_cable_length_82577");
+       DEBUGFUNC("e1000_enable_phy_wakeup_reg_access_bm");
 
-       ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
-       if (ret_val)
-               goto out;
+       if (!phy_reg)
+               return -E1000_ERR_PARAM;
 
-       length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
-                I82577_DSTATUS_CABLE_LENGTH_SHIFT;
+       /* All page select, port ctrl and wakeup registers use phy address 1 */
+       hw->phy.addr = 1;
 
-       if (length == E1000_CABLE_LENGTH_UNDEFINED)
-               ret_val = -E1000_ERR_PHY;
+       /* Select Port Control Registers page */
+       ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+       if (ret_val) {
+               DEBUGOUT("Could not set Port Control page\n");
+               return ret_val;
+       }
 
-       phy->cable_length = length;
+       ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+       if (ret_val) {
+               DEBUGOUT2("Could not read PHY register %d.%d\n",
+                         BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+               return ret_val;
+       }
 
-out:
-       return ret_val;
+       /*
+        * Enable both PHY wakeup mode and Wakeup register page writes.
+        * Prevent a power state change by disabling ME and Host PHY wakeup.
+        */
+       temp = *phy_reg;
+       temp |= BM_WUC_ENABLE_BIT;
+       temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
+
+       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
+       if (ret_val) {
+               DEBUGOUT2("Could not write PHY register %d.%d\n",
+                         BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+               return ret_val;
+       }
+
+       /*
+        * Select Host Wakeup Registers page - caller now able to write
+        * registers on the Wakeup registers page
+        */
+       return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+}
+
+/**
+ *  e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
+ *  @hw: pointer to the HW structure
+ *  @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
+ *
+ *  Restore BM_WUC_ENABLE_REG to its original value.
+ *
+ *  Assumes semaphore already acquired and *phy_reg is the contents of the
+ *  BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
+ *  caller.
+ **/
+s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_disable_phy_wakeup_reg_access_bm");
+
+       if (!phy_reg)
+               return -E1000_ERR_PARAM;
+
+       /* Select Port Control Registers page */
+       ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+       if (ret_val) {
+               DEBUGOUT("Could not set Port Control page\n");
+               return ret_val;
+       }
+
+       /* Restore 769.17 to its original value */
+       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
+       if (ret_val)
+               DEBUGOUT2("Could not restore PHY register %d.%d\n",
+                         BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read or written
+ *  @data: pointer to the data to read or write
+ *  @read: determines if operation is read or write
+ *  @page_set: BM_WUC_PAGE already set and access enabled
+ *
+ *  Read the PHY register at offset and store the retrieved information in
+ *  data, or write data to PHY register at offset.  Note the procedure to
+ *  access the PHY wakeup registers is different than reading the other PHY
+ *  registers. It works as such:
+ *  1) Set 769.17.2 (page 769, register 17, bit 2) = 1
+ *  2) Set page to 800 for host (801 if we were manageability)
+ *  3) Write the address using the address opcode (0x11)
+ *  4) Read or write the data using the data opcode (0x12)
+ *  5) Restore 769.17.2 to its original value
+ *
+ *  Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
+ *  step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
+ *
+ *  Assumes semaphore is already acquired.  When page_set==true, assumes
+ *  the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
+ *  is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
+ **/
+STATIC s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
+                                         u16 *data, bool read, bool page_set)
+{
+       s32 ret_val;
+       u16 reg = BM_PHY_REG_NUM(offset);
+       u16 page = BM_PHY_REG_PAGE(offset);
+       u16 phy_reg = 0;
+
+       DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
+
+       /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
+       if ((hw->mac.type == e1000_pchlan) &&
+          (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
+               DEBUGOUT1("Attempting to access page %d while gig enabled.\n",
+                         page);
+
+       if (!page_set) {
+               /* Enable access to PHY wakeup registers */
+               ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+               if (ret_val) {
+                       DEBUGOUT("Could not enable PHY wakeup reg access\n");
+                       return ret_val;
+               }
+       }
+
+       DEBUGOUT2("Accessing PHY page %d reg 0x%x\n", page, reg);
+
+       /* Write the Wakeup register page offset value using opcode 0x11 */
+       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
+       if (ret_val) {
+               DEBUGOUT1("Could not write address opcode to page %d\n", page);
+               return ret_val;
+       }
+
+       if (read) {
+               /* Read the Wakeup register page value using opcode 0x12 */
+               ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
+                                                 data);
+       } else {
+               /* Write the Wakeup register page value using opcode 0x12 */
+               ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
+                                                  *data);
+       }
+
+       if (ret_val) {
+               DEBUGOUT2("Could not access PHY reg %d.%d\n", page, reg);
+               return ret_val;
+       }
+
+       if (!page_set)
+               ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+
+       return ret_val;
+}
+
+/**
+ * e1000_power_up_phy_copper - Restore copper link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, restore the link to previous
+ * settings.
+ **/
+void e1000_power_up_phy_copper(struct e1000_hw *hw)
+{
+       u16 mii_reg = 0;
+       u16 power_reg = 0;
+
+       /* The PHY will retain its settings across a power down/up cycle */
+       hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
+       mii_reg &= ~MII_CR_POWER_DOWN;
+       if (hw->phy.type == e1000_phy_i210) {
+               hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+               power_reg &= ~GS40G_CS_POWER_DOWN;
+               hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+       }
+       hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
+}
+
+/**
+ * e1000_power_down_phy_copper - Restore copper link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, restore the link to previous
+ * settings.
+ **/
+void e1000_power_down_phy_copper(struct e1000_hw *hw)
+{
+       u16 mii_reg = 0;
+       u16 power_reg = 0;
+
+       /* The PHY will retain its settings across a power down/up cycle */
+       hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
+       mii_reg |= MII_CR_POWER_DOWN;
+       /* i210 Phy requires an additional bit for power up/down */
+       if (hw->phy.type == e1000_phy_i210) {
+               hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+               power_reg |= GS40G_CS_POWER_DOWN;
+               hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+       }
+       hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
+       msec_delay(1);
+}
+
+/**
+ *  __e1000_read_phy_reg_hv -  Read HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *  @locked: semaphore has already been acquired or not
+ *
+ *  Acquires semaphore, if necessary, then reads the PHY register at offset
+ *  and stores the retrieved information in data.  Release any acquired
+ *  semaphore before exiting.
+ **/
+static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
+                                  bool locked, bool page_set)
+{
+       s32 ret_val;
+       u16 page = BM_PHY_REG_PAGE(offset);
+       u16 reg = BM_PHY_REG_NUM(offset);
+       u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
+
+       DEBUGFUNC("__e1000_read_phy_reg_hv");
+
+       if (!locked) {
+               ret_val = hw->phy.ops.acquire(hw);
+               if (ret_val)
+                       return ret_val;
+       }
+
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+                                                        true, page_set);
+               goto out;
+       }
+
+       if (page > 0 && page < HV_INTC_FC_PAGE_START) {
+               ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
+                                                        data, true);
+               goto out;
+       }
+
+       if (!page_set) {
+               if (page == HV_INTC_FC_PAGE_START)
+                       page = 0;
+
+               if (reg > MAX_PHY_MULTI_PAGE_REG) {
+                       /* Page is shifted left, PHY expects (page x 32) */
+                       ret_val = e1000_set_page_igp(hw,
+                                                    (page << IGP_PAGE_SHIFT));
+
+                       hw->phy.addr = phy_addr;
+
+                       if (ret_val)
+                               goto out;
+               }
+       }
+
+       DEBUGOUT3("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+                 page << IGP_PAGE_SHIFT, reg);
+
+       ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
+                                         data);
+out:
+       if (!locked)
+               hw->phy.ops.release(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_read_phy_reg_hv -  Read HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Acquires semaphore then reads the PHY register at offset and stores
+ *  the retrieved information in data.  Release the acquired semaphore
+ *  before exiting.
+ **/
+s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000_read_phy_reg_hv(hw, offset, data, false, false);
+}
+
+/**
+ *  e1000_read_phy_reg_hv_locked -  Read HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY register at offset and stores the retrieved information
+ *  in data.  Assumes semaphore already acquired.
+ **/
+s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000_read_phy_reg_hv(hw, offset, data, true, false);
+}
+
+/**
+ *  e1000_read_phy_reg_page_hv - Read HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Reads the PHY register at offset and stores the retrieved information
+ *  in data.  Assumes semaphore already acquired and page already set.
+ **/
+s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000_read_phy_reg_hv(hw, offset, data, true, true);
+}
+
+/**
+ *  __e1000_write_phy_reg_hv - Write HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *  @locked: semaphore has already been acquired or not
+ *
+ *  Acquires semaphore, if necessary, then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
+                                   bool locked, bool page_set)
+{
+       s32 ret_val;
+       u16 page = BM_PHY_REG_PAGE(offset);
+       u16 reg = BM_PHY_REG_NUM(offset);
+       u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
+
+       DEBUGFUNC("__e1000_write_phy_reg_hv");
+
+       if (!locked) {
+               ret_val = hw->phy.ops.acquire(hw);
+               if (ret_val)
+                       return ret_val;
+       }
+
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+                                                        false, page_set);
+               goto out;
+       }
+
+       if (page > 0 && page < HV_INTC_FC_PAGE_START) {
+               ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
+                                                        &data, false);
+               goto out;
+       }
+
+       if (!page_set) {
+               if (page == HV_INTC_FC_PAGE_START)
+                       page = 0;
+
+               /*
+                * Workaround MDIO accesses being disabled after entering IEEE
+                * Power Down (when bit 11 of the PHY Control register is set)
+                */
+               if ((hw->phy.type == e1000_phy_82578) &&
+                   (hw->phy.revision >= 1) &&
+                   (hw->phy.addr == 2) &&
+                   !(MAX_PHY_REG_ADDRESS & reg) &&
+                   (data & (1 << 11))) {
+                       u16 data2 = 0x7EFF;
+                       ret_val = e1000_access_phy_debug_regs_hv(hw,
+                                                                (1 << 6) | 0x3,
+                                                                &data2, false);
+                       if (ret_val)
+                               goto out;
+               }
+
+               if (reg > MAX_PHY_MULTI_PAGE_REG) {
+                       /* Page is shifted left, PHY expects (page x 32) */
+                       ret_val = e1000_set_page_igp(hw,
+                                                    (page << IGP_PAGE_SHIFT));
+
+                       hw->phy.addr = phy_addr;
+
+                       if (ret_val)
+                               goto out;
+               }
+       }
+
+       DEBUGOUT3("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+                 page << IGP_PAGE_SHIFT, reg);
+
+       ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
+                                          data);
+
+out:
+       if (!locked)
+               hw->phy.ops.release(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_write_phy_reg_hv - Write HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore then writes the data to PHY register at the offset.
+ *  Release the acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000_write_phy_reg_hv(hw, offset, data, false, false);
+}
+
+/**
+ *  e1000_write_phy_reg_hv_locked - Write HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Writes the data to PHY register at the offset.  Assumes semaphore
+ *  already acquired.
+ **/
+s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000_write_phy_reg_hv(hw, offset, data, true, false);
+}
+
+/**
+ *  e1000_write_phy_reg_page_hv - Write HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Writes the data to PHY register at the offset.  Assumes semaphore
+ *  already acquired and page already set.
+ **/
+s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000_write_phy_reg_hv(hw, offset, data, true, true);
 }
+
+/**
+ *  e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
+ *  @page: page to be accessed
+ **/
+STATIC u32 e1000_get_phy_addr_for_hv_page(u32 page)
+{
+       u32 phy_addr = 2;
+
+       if (page >= HV_INTC_FC_PAGE_START)
+               phy_addr = 1;
+
+       return phy_addr;
+}
+
+/**
+ *  e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read or written
+ *  @data: pointer to the data to be read or written
+ *  @read: determines if operation is read or write
+ *
+ *  Reads the PHY register at offset and stores the retreived information
+ *  in data.  Assumes semaphore already acquired.  Note that the procedure
+ *  to access these regs uses the address port and data port to read/write.
+ *  These accesses done with PHY address 2 and without using pages.
+ **/
+STATIC s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
+                                         u16 *data, bool read)
+{
+       s32 ret_val;
+       u32 addr_reg = 0;
+       u32 data_reg = 0;
+
+       DEBUGFUNC("e1000_access_phy_debug_regs_hv");
+
+       /* This takes care of the difference with desktop vs mobile phy */
+       addr_reg = (hw->phy.type == e1000_phy_82578) ?
+                  I82578_ADDR_REG : I82577_ADDR_REG;
+       data_reg = addr_reg + 1;
+
+       /* All operations in this function are phy address 2 */
+       hw->phy.addr = 2;
+
+       /* masking with 0x3F to remove the page from offset */
+       ret_val = e1000_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
+       if (ret_val) {
+               DEBUGOUT("Could not write the Address Offset port register\n");
+               return ret_val;
+       }
+
+       /* Read or write the data value next */
+       if (read)
+               ret_val = e1000_read_phy_reg_mdic(hw, data_reg, data);
+       else
+               ret_val = e1000_write_phy_reg_mdic(hw, data_reg, *data);
+
+       if (ret_val)
+               DEBUGOUT("Could not access the Data port register\n");
+
+       return ret_val;
+}
+
+/**
+ *  e1000_link_stall_workaround_hv - Si workaround
+ *  @hw: pointer to the HW structure
+ *
+ *  This function works around a Si bug where the link partner can get
+ *  a link up indication before the PHY does.  If small packets are sent
+ *  by the link partner they can be placed in the packet buffer without
+ *  being properly accounted for by the PHY and will stall preventing
+ *  further packets from being received.  The workaround is to clear the
+ *  packet buffer after the PHY detects link up.
+ **/
+s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 data;
+
+       DEBUGFUNC("e1000_link_stall_workaround_hv");
+
+       if (hw->phy.type != e1000_phy_82578)
+               return E1000_SUCCESS;
+
+       /* Do not apply workaround if in PHY loopback bit 14 set */
+       hw->phy.ops.read_reg(hw, PHY_CONTROL, &data);
+       if (data & PHY_CONTROL_LB)
+               return E1000_SUCCESS;
+
+       /* check if link is up and at 1Gbps */
+       ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data);
+       if (ret_val)
+               return ret_val;
+
+       data &= BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
+               BM_CS_STATUS_SPEED_MASK;
+
+       if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
+                    BM_CS_STATUS_SPEED_1000))
+               return E1000_SUCCESS;
+
+       msec_delay(200);
+
+       /* flush the packets in the fifo buffer */
+       ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
+                                       HV_MUX_DATA_CTRL_GEN_TO_MAC |
+                                       HV_MUX_DATA_CTRL_FORCE_SPEED);
+       if (ret_val)
+               return ret_val;
+
+       return hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
+                                    HV_MUX_DATA_CTRL_GEN_TO_MAC);
+}
+
+/**
+ *  e1000_check_polarity_82577 - Checks the polarity.
+ *  @hw: pointer to the HW structure
+ *
+ *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
+ *
+ *  Polarity is determined based on the PHY specific status register.
+ **/
+s32 e1000_check_polarity_82577(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 data;
+
+       DEBUGFUNC("e1000_check_polarity_82577");
+
+       ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
+
+       if (!ret_val)
+               phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
+                                     ? e1000_rev_polarity_reversed
+                                     : e1000_rev_polarity_normal;
+
+       return ret_val;
+}
+
+/**
+ *  e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the PHY setup function to force speed and duplex.
+ **/
+s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 phy_data;
+       bool link;
+
+       DEBUGFUNC("e1000_phy_force_speed_duplex_82577");
+
+       ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
+       if (ret_val)
+               return ret_val;
+
+       e1000_phy_force_speed_duplex_setup(hw, &phy_data);
+
+       ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
+       if (ret_val)
+               return ret_val;
+
+       usec_delay(1);
+
+       if (phy->autoneg_wait_to_complete) {
+               DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n");
+
+               ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+                                                    100000, &link);
+               if (ret_val)
+                       return ret_val;
+
+               if (!link)
+                       DEBUGOUT("Link taking longer than expected.\n");
+
+               /* Try once more */
+               ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+                                                    100000, &link);
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_get_phy_info_82577 - Retrieve I82577 PHY information
+ *  @hw: pointer to the HW structure
+ *
+ *  Read PHY status to determine if link is up.  If link is up, then
+ *  set/determine 10base-T extended distance and polarity correction.  Read
+ *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
+ *  determine on the cable length, local and remote receiver.
+ **/
+s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 data;
+       bool link;
+
+       DEBUGFUNC("e1000_get_phy_info_82577");
+
+       ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
+       if (ret_val)
+               return ret_val;
+
+       if (!link) {
+               DEBUGOUT("Phy info is only valid if link is up\n");
+               return -E1000_ERR_CONFIG;
+       }
+
+       phy->polarity_correction = true;
+
+       ret_val = e1000_check_polarity_82577(hw);
+       if (ret_val)
+               return ret_val;
+
+       ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
+       if (ret_val)
+               return ret_val;
+
+       phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX);
+
+       if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
+           I82577_PHY_STATUS2_SPEED_1000MBPS) {
+               ret_val = hw->phy.ops.get_cable_length(hw);
+               if (ret_val)
+                       return ret_val;
+
+               ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
+               if (ret_val)
+                       return ret_val;
+
+               phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
+                               ? e1000_1000t_rx_status_ok
+                               : e1000_1000t_rx_status_not_ok;
+
+               phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
+                                ? e1000_1000t_rx_status_ok
+                                : e1000_1000t_rx_status_not_ok;
+       } else {
+               phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
+               phy->local_rx = e1000_1000t_rx_status_undefined;
+               phy->remote_rx = e1000_1000t_rx_status_undefined;
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_get_cable_length_82577 - Determine cable length for 82577 PHY
+ *  @hw: pointer to the HW structure
+ *
+ * Reads the diagnostic status register and verifies result is valid before
+ * placing it in the phy_cable_length field.
+ **/
+s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 phy_data, length;
+
+       DEBUGFUNC("e1000_get_cable_length_82577");
+
+       ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
+       if (ret_val)
+               return ret_val;
+
+       length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
+                I82577_DSTATUS_CABLE_LENGTH_SHIFT;
+
+       if (length == E1000_CABLE_LENGTH_UNDEFINED)
+               ret_val = -E1000_ERR_PHY;
+
+       phy->cable_length = length;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_write_phy_reg_gs40g - Write GS40G  PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore, if necessary, then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       s32 ret_val;
+       u16 page = offset >> GS40G_PAGE_SHIFT;
+
+       DEBUGFUNC("e1000_write_phy_reg_gs40g");
+
+       offset = offset & GS40G_OFFSET_MASK;
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               return ret_val;
+
+       ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+       if (ret_val)
+               goto release;
+       ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
+
+release:
+       hw->phy.ops.release(hw);
+       return ret_val;
+}
+
+/**
+ *  e1000_read_phy_reg_gs40g - Read GS40G  PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: lower half is register offset to read to
+ *     upper half is page to use.
+ *  @data: data to read at register offset
+ *
+ *  Acquires semaphore, if necessary, then reads the data in the PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       s32 ret_val;
+       u16 page = offset >> GS40G_PAGE_SHIFT;
+
+       DEBUGFUNC("e1000_read_phy_reg_gs40g");
+
+       offset = offset & GS40G_OFFSET_MASK;
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               return ret_val;
+
+       ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+       if (ret_val)
+               goto release;
+       ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
+
+release:
+       hw->phy.ops.release(hw);
+       return ret_val;
+}
+
index 1e39ef9..7a542cd 100644 (file)
@@ -39,11 +39,18 @@ s32  e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data);
 void e1000_null_phy_generic(struct e1000_hw *hw);
 s32  e1000_null_lplu_state(struct e1000_hw *hw, bool active);
 s32  e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_null_set_page(struct e1000_hw *hw, u16 data);
+s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
+                            u8 dev_addr, u8 *data);
+s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
+                             u8 dev_addr, u8 data);
 s32  e1000_check_downshift_generic(struct e1000_hw *hw);
 s32  e1000_check_polarity_m88(struct e1000_hw *hw);
 s32  e1000_check_polarity_igp(struct e1000_hw *hw);
 s32  e1000_check_polarity_ife(struct e1000_hw *hw);
 s32  e1000_check_reset_block_generic(struct e1000_hw *hw);
+s32  e1000_phy_setup_autoneg(struct e1000_hw *hw);
+s32  e1000_copper_link_autoneg(struct e1000_hw *hw);
 s32  e1000_copper_link_setup_igp(struct e1000_hw *hw);
 s32  e1000_copper_link_setup_m88(struct e1000_hw *hw);
 s32  e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw);
@@ -64,6 +71,7 @@ s32  e1000_phy_hw_reset_generic(struct e1000_hw *hw);
 s32  e1000_phy_reset_dsp_generic(struct e1000_hw *hw);
 s32  e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_set_page_igp(struct e1000_hw *hw, u16 page);
 s32  e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
@@ -81,19 +89,36 @@ s32  e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
 s32  e1000_phy_init_script_igp3(struct e1000_hw *hw);
 enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id);
 s32  e1000_determine_phy_address(struct e1000_hw *hw);
+s32  e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg);
+s32  e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg);
+s32  e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
 void e1000_power_up_phy_copper(struct e1000_hw *hw);
 void e1000_power_down_phy_copper(struct e1000_hw *hw);
 s32  e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
 s32  e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data);
+s32  e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data);
+s32  e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_link_stall_workaround_hv(struct e1000_hw *hw);
 s32  e1000_copper_link_setup_82577(struct e1000_hw *hw);
 s32  e1000_check_polarity_82577(struct e1000_hw *hw);
 s32  e1000_get_phy_info_82577(struct e1000_hw *hw);
 s32  e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw);
 s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
+s32  e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
 
-#define E1000_MAX_PHY_ADDR                4
+#define E1000_MAX_PHY_ADDR             8
 
 /* IGP01E1000 Specific Registers */
 #define IGP01E1000_PHY_PORT_CONFIG        0x10 /* Port Config */
@@ -108,6 +133,41 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 #define IGP_PAGE_SHIFT                    5
 #define PHY_REG_MASK                      0x1F
 
+/* GS40G - I210 PHY defines */
+#define GS40G_PAGE_SELECT              0x16
+#define GS40G_PAGE_SHIFT               16
+#define GS40G_OFFSET_MASK              0xFFFF
+#define GS40G_PAGE_2                   0x20000
+#define GS40G_MAC_REG2                 0x15
+#define GS40G_MAC_LB                   0x4140
+#define GS40G_MAC_SPEED_1G             0X0006
+#define GS40G_COPPER_SPEC              0x0010
+#define GS40G_CS_POWER_DOWN            0x0002
+
+/* BM/HV Specific Registers */
+#define BM_PORT_CTRL_PAGE              769
+#define BM_PCIE_PAGE                   770
+#define BM_WUC_PAGE                    800
+#define BM_WUC_ADDRESS_OPCODE          0x11
+#define BM_WUC_DATA_OPCODE             0x12
+#define BM_WUC_ENABLE_PAGE             BM_PORT_CTRL_PAGE
+#define BM_WUC_ENABLE_REG              17
+#define BM_WUC_ENABLE_BIT              (1 << 2)
+#define BM_WUC_HOST_WU_BIT             (1 << 4)
+#define BM_WUC_ME_WU_BIT               (1 << 5)
+
+#define PHY_UPPER_SHIFT                        21
+#define BM_PHY_REG(page, reg) \
+       (((reg) & MAX_PHY_REG_ADDRESS) |\
+        (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\
+        (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)))
+#define BM_PHY_REG_PAGE(offset) \
+       ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF))
+#define BM_PHY_REG_NUM(offset) \
+       ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\
+        (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\
+               ~MAX_PHY_REG_ADDRESS)))
+
 #define HV_INTC_FC_PAGE_START             768
 #define I82578_ADDR_REG                   29
 #define I82577_ADDR_REG                   16
@@ -130,8 +190,9 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 #define I82577_PHY_STATUS2_SPEED_100MBPS  0x0100
 
 /* I82577 PHY Control 2 */
-#define I82577_PHY_CTRL2_AUTO_MDIX        0x0400
-#define I82577_PHY_CTRL2_FORCE_MDI_MDIX   0x0200
+#define I82577_PHY_CTRL2_MANUAL_MDIX           0x0200
+#define I82577_PHY_CTRL2_AUTO_MDI_MDIX         0x0400
+#define I82577_PHY_CTRL2_MDIX_CFG_MASK         0x0600
 
 /* I82577 PHY Diagnostics Status */
 #define I82577_DSTATUS_CABLE_LENGTH       0x03FC
@@ -142,6 +203,26 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 #define E1000_82580_PM_SPD                0x0001 /* Smart Power Down */
 #define E1000_82580_PM_D0_LPLU            0x0002 /* For D0a states */
 #define E1000_82580_PM_D3_LPLU            0x0004 /* For all other states */
+#define E1000_82580_PM_GO_LINKD                0x0020 /* Go Link Disconnect */
+
+/* BM PHY Copper Specific Control 1 */
+#define BM_CS_CTRL1                    16
+#define BM_CS_CTRL1_ENERGY_DETECT      0x0300 /* Enable Energy Detect */
+
+/* BM PHY Copper Specific Status */
+#define BM_CS_STATUS                   17
+#define BM_CS_STATUS_ENERGY_DETECT     0x0010 /* Energy Detect Status */
+#define BM_CS_STATUS_LINK_UP           0x0400
+#define BM_CS_STATUS_RESOLVED          0x0800
+#define BM_CS_STATUS_SPEED_MASK                0xC000
+#define BM_CS_STATUS_SPEED_1000                0x8000
+
+/* 82577 Mobile Phy Status Register */
+#define HV_M_STATUS                    26
+#define HV_M_STATUS_AUTONEG_COMPLETE   0x1000
+#define HV_M_STATUS_SPEED_MASK         0x0300
+#define HV_M_STATUS_SPEED_1000         0x0200
+#define HV_M_STATUS_LINK_UP            0x0040
 
 #define IGP01E1000_PHY_PCS_INIT_REG       0x00B4
 #define IGP01E1000_PHY_POLARITY_MASK      0x0078
@@ -184,11 +265,21 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 #define E1000_KMRNCTRLSTA_OFFSET          0x001F0000
 #define E1000_KMRNCTRLSTA_OFFSET_SHIFT    16
 #define E1000_KMRNCTRLSTA_REN             0x00200000
+#define E1000_KMRNCTRLSTA_CTRL_OFFSET  0x1    /* Kumeran Control */
 #define E1000_KMRNCTRLSTA_DIAG_OFFSET     0x3    /* Kumeran Diagnostic */
 #define E1000_KMRNCTRLSTA_TIMEOUTS        0x4    /* Kumeran Timeouts */
 #define E1000_KMRNCTRLSTA_INBAND_PARAM    0x9    /* Kumeran InBand Parameters */
 #define E1000_KMRNCTRLSTA_IBIST_DISABLE   0x0200 /* Kumeran IBIST Disable */
 #define E1000_KMRNCTRLSTA_DIAG_NELPBK     0x1000 /* Nearend Loopback mode */
+#define E1000_KMRNCTRLSTA_K1_CONFIG    0x7
+#define E1000_KMRNCTRLSTA_K1_ENABLE    0x0002 /* enable K1 */
+#define E1000_KMRNCTRLSTA_UNBLOCK_RX   0x0004 /* unblock Kumeran Rx in K0/K1 */
+#define E1000_KMRNCTRLSTA_PLL_STOP_EN  0x0008 /* enable PLL stop in K1 mode */
+
+#define E1000_KMRNCTRLSTA_HD_CTRL      0x10   /* Kumeran HD Control */
+#define E1000_KMRNCTRLSTA_K0_CTRL      0x1E   /* Kumeran K0s Control */
+#define E1000_KMRNCTRLSTA_K0_GBE_EN    0x1000 /* ena K0s mode for 1G link */
+#define E1000_KMRNCTRLSTA_K0_100_EN    0x2000 /* ena K0s mode for 10/100 lnk */
 
 #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
 #define IFE_PHY_SPECIAL_CONTROL     0x11 /* 100BaseTx PHY Special Control */
@@ -211,6 +302,30 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 /* IFE PHY MDIX Control */
 #define IFE_PMC_MDIX_STATUS      0x0020 /* 1=MDI-X, 0=MDI */
 #define IFE_PMC_FORCE_MDIX       0x0040 /* 1=force MDI-X, 0=force MDI */
-#define IFE_PMC_AUTO_MDIX        0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */
+#define IFE_PMC_AUTO_MDIX              0x0080 /* 1=enable auto, 0=disable */
+
+/* SFP modules ID memory locations */
+#define E1000_SFF_IDENTIFIER_OFFSET    0x00
+#define E1000_SFF_IDENTIFIER_SFF       0x02
+#define E1000_SFF_IDENTIFIER_SFP       0x03
+
+#define E1000_SFF_ETH_FLAGS_OFFSET     0x06
+/* Flags for SFP modules compatible with ETH up to 1Gb */
+struct sfp_e1000_flags {
+       u8 e1000_base_sx:1;
+       u8 e1000_base_lx:1;
+       u8 e1000_base_cx:1;
+       u8 e1000_base_t:1;
+       u8 e100_base_lx:1;
+       u8 e100_base_fx:1;
+       u8 e10_base_bx10:1;
+       u8 e10_base_px:1;
+};
+
+/* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */
+#define E1000_SFF_VENDOR_OUI_TYCO      0x00407600
+#define E1000_SFF_VENDOR_OUI_FTL       0x00906500
+#define E1000_SFF_VENDOR_OUI_AVAGO     0x00176A00
+#define E1000_SFF_VENDOR_OUI_INTEL     0x001B2100
 
 #endif
index 3ba900f..693fd14 100644 (file)
@@ -45,15 +45,20 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_MDICNFG  0x00E04  /* MDI Config - RW */
 #define E1000_REGISTER_SET_SIZE        0x20000 /* CSR Size */
 #define E1000_EEPROM_INIT_CTRL_WORD_2  0x0F /* EEPROM Init Ctrl Word 2 */
+#define E1000_EEPROM_PCIE_CTRL_WORD_2  0x28 /* EEPROM PCIe Ctrl Word 2 */
 #define E1000_BARCTRL                  0x5BBC /* BAR ctrl reg */
 #define E1000_BARCTRL_FLSIZE           0x0700 /* BAR ctrl Flsize */
 #define E1000_BARCTRL_CSRSIZE          0x2000 /* BAR ctrl CSR size */
+#define E1000_I350_BARCTRL             0x5BFC /* BAR ctrl reg */
+#define E1000_I350_DTXMXPKTSZ          0x355C /* Maximum sent packet size reg*/
 #define E1000_SCTL     0x00024  /* SerDes Control - RW */
 #define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
 #define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
 #define E1000_FEXT     0x0002C  /* Future Extended - RW */
-#define E1000_FEXTNVM4 0x00024  /* Future Extended NVM 4 - RW */
 #define E1000_FEXTNVM  0x00028  /* Future Extended NVM - RW */
+#define E1000_FEXTNVM2 0x00030  /* Future Extended NVM 2 - RW */
+#define E1000_FEXTNVM3 0x0003C  /* Future Extended NVM 3 - RW */
+#define E1000_FEXTNVM4 0x00024  /* Future Extended NVM 4 - RW */
 #define E1000_FCT      0x00030  /* Flow Control Type - RW */
 #define E1000_CONNSW   0x00034  /* Copper/Fiber switch control - RW */
 #define E1000_VET      0x00038  /* VLAN Ether Type - RW */
@@ -63,10 +68,15 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_IMS      0x000D0  /* Interrupt Mask Set - RW */
 #define E1000_IMC      0x000D8  /* Interrupt Mask Clear - WO */
 #define E1000_IAM      0x000E0  /* Interrupt Acknowledge Auto Mask */
+#define E1000_IVAR     0x000E4  /* Interrupt Vector Allocation Register - RW */
+#define E1000_SVCR     0x000F0
+#define E1000_SVT      0x000F4
+#define E1000_LPIC  0x000FC  /* Low Power IDLE control */
 #define E1000_RCTL     0x00100  /* Rx Control - RW */
 #define E1000_FCTTV    0x00170  /* Flow Control Transmit Timer Value - RW */
 #define E1000_TXCW     0x00178  /* Tx Configuration Word - RW */
 #define E1000_RXCW     0x00180  /* Rx Configuration Word - RO */
+#define E1000_PBA_ECC  0x01100  /* PBA ECC Register */
 #define E1000_EICR     0x01580  /* Ext. Interrupt Cause Read - R/clr */
 #define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
 #define E1000_EICS     0x01520  /* Ext. Interrupt Cause Set - W0 */
@@ -86,6 +96,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_EXTCNF_CTRL  0x00F00  /* Extended Configuration Control */
 #define E1000_EXTCNF_SIZE  0x00F08  /* Extended Configuration Size */
 #define E1000_PHY_CTRL     0x00F10  /* PHY Control Register in CSR */
+#define E1000_POEMB    E1000_PHY_CTRL /* PHY OEM Bits */
 #define E1000_PBA      0x01000  /* Packet Buffer Allocation - RW */
 #define E1000_PBS      0x01008  /* Packet Buffer Size */
 #define E1000_EEMNGCTL 0x01010  /* MNG EEprom Control */
@@ -98,6 +109,14 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_FLOP     0x0103C  /* FLASH Opcode Register */
 #define E1000_I2CCMD   0x01028  /* SFPI2C Command Register - RW */
 #define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
+#define E1000_I2CBB_EN 0x00000100  /* I2C - Bit Bang Enable */
+#define E1000_I2C_CLK_OUT      0x00000200  /* I2C- Clock */
+#define E1000_I2C_DATA_OUT     0x00000400  /* I2C- Data Out */
+#define E1000_I2C_DATA_OE_N    0x00000800  /* I2C- Data Output Enable */
+#define E1000_I2C_DATA_IN      0x00001000  /* I2C- Data In */
+#define E1000_I2C_CLK_OE_N     0x00002000  /* I2C- Clock Output Enable */
+#define E1000_I2C_CLK_IN       0x00004000  /* I2C- Clock In */
+#define E1000_I2C_CLK_STRETCH_DIS      0x00008000 /* I2C- Dis Clk Stretching */
 #define E1000_WDSTP    0x01040  /* Watchdog Setup - RW */
 #define E1000_SWDSTS   0x01044  /* SW Device Status - RW */
 #define E1000_FRTIMER  0x01048  /* Free Running Timer - RW */
@@ -123,10 +142,66 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_RDPUCTL  0x025DC  /* DMA Rx Descriptor uC Control - RW */
 #define E1000_PBDIAG   0x02458  /* Packet Buffer Diagnostic - RW */
 #define E1000_RXPBS    0x02404  /* Rx Packet Buffer Size - RW */
-#define E1000_IRPBS 0x02404 /* Same as RXPBS, renamed for newer adapters - RW */
+#define E1000_IRPBS    0x02404 /* Same as RXPBS, renamed for newer Si - RW */
 #define E1000_PBRWAC   0x024E8 /* Rx packet buffer wrap around counter - RO */
 #define E1000_RDTR     0x02820  /* Rx Delay Timer - RW */
 #define E1000_RADV     0x0282C  /* Rx Interrupt Absolute Delay Timer - RW */
+#define E1000_SRWR             0x12018  /* Shadow Ram Write Register - RW */
+#define E1000_I210_FLMNGCTL    0x12038
+#define E1000_I210_FLMNGDATA   0x1203C
+#define E1000_I210_FLMNGCNT    0x12040
+
+#define E1000_I210_FLSWCTL     0x12048
+#define E1000_I210_FLSWDATA    0x1204C
+#define E1000_I210_FLSWCNT     0x12050
+
+#define E1000_I210_FLA         0x1201C
+
+#define E1000_INVM_DATA_REG(_n)        (0x12120 + 4*(_n))
+#define E1000_INVM_SIZE                64 /* Number of INVM Data Registers */
+
+/* QAV Tx mode control register */
+#define E1000_I210_TQAVCTRL    0x3570
+
+/* QAV Tx mode control register bitfields masks */
+/* QAV enable */
+#define E1000_TQAVCTRL_MODE                    (1 << 0)
+/* Fetching arbitration type */
+#define E1000_TQAVCTRL_FETCH_ARB               (1 << 4)
+/* Fetching timer enable */
+#define E1000_TQAVCTRL_FETCH_TIMER_ENABLE      (1 << 5)
+/* Launch arbitration type */
+#define E1000_TQAVCTRL_LAUNCH_ARB              (1 << 8)
+/* Launch timer enable */
+#define E1000_TQAVCTRL_LAUNCH_TIMER_ENABLE     (1 << 9)
+/* SP waits for SR enable */
+#define E1000_TQAVCTRL_SP_WAIT_SR              (1 << 10)
+/* Fetching timer correction */
+#define E1000_TQAVCTRL_FETCH_TIMER_DELTA_OFFSET        16
+#define E1000_TQAVCTRL_FETCH_TIMER_DELTA       \
+                       (0xFFFF << E1000_TQAVCTRL_FETCH_TIMER_DELTA_OFFSET)
+
+/* High credit registers where _n can be 0 or 1. */
+#define E1000_I210_TQAVHC(_n)                  (0x300C + 0x40 * (_n))
+
+/* Queues fetch arbitration priority control register */
+#define E1000_I210_TQAVARBCTRL                 0x3574
+/* Queues priority masks where _n and _p can be 0-3. */
+#define E1000_TQAVARBCTRL_QUEUE_PRI(_n, _p)    ((_p) << (2 * _n))
+/* QAV Tx mode control registers where _n can be 0 or 1. */
+#define E1000_I210_TQAVCC(_n)                  (0x3004 + 0x40 * (_n))
+
+/* QAV Tx mode control register bitfields masks */
+#define E1000_TQAVCC_IDLE_SLOPE                0xFFFF /* Idle slope */
+#define E1000_TQAVCC_KEEP_CREDITS      (1 << 30) /* Keep credits opt enable */
+#define E1000_TQAVCC_QUEUE_MODE                (1 << 31) /* SP vs. SR Tx mode */
+
+/* Good transmitted packets counter registers */
+#define E1000_PQGPTC(_n)               (0x010014 + (0x100 * (_n)))
+
+/* Queues packet buffer size masks where _n can be 0-3 and _s 0-63 [kB] */
+#define E1000_I210_TXPBS_SIZE(_n, _s)  ((_s) << (6 * _n))
+
 /*
  * Convenience macros
  *
@@ -281,6 +356,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_ICTXQMTC 0x0411C  /* Interrupt Cause Tx Queue Min Thresh Count */
 #define E1000_ICRXDMTC 0x04120  /* Interrupt Cause Rx Desc Min Thresh Count */
 #define E1000_ICRXOC   0x04124  /* Interrupt Cause Receiver Overrun Count */
+#define E1000_CRC_OFFSET       0x05F50  /* CRC Offset register */
 
 #define E1000_VFGPRC   0x00F10
 #define E1000_VFGORC   0x00F18
@@ -407,6 +483,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_HOST_IF  0x08800  /* Host Interface */
 #define E1000_FFMT     0x09000  /* Flexible Filter Mask Table - RW Array */
 #define E1000_FFVT     0x09800  /* Flexible Filter Value Table - RW Array */
+#define E1000_HIBBA    0x8F40   /* Host Interface Buffer Base Address */
 /* Flexible Host Filter Table */
 #define E1000_FHFT(_n) (0x09000 + ((_n) * 0x100))
 /* Ext Flexible Host Filter Table */
@@ -492,7 +569,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_VLVF(_n)         (0x05D00 + (4 * (_n)))
 #define E1000_VMVIR(_n)        (0x03700 + (4 * (_n)))
 #define E1000_DVMOLR(_n)       (0x0C038 + (0x40 * (_n))) /* DMA VM offload */
-/* Time Sync */
+#define E1000_VTCTRL(_n)       (0x10000 + (0x100 * (_n))) /* VT Control */
 #define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
 #define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
 #define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
@@ -505,8 +582,14 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_SYSTIML    0x0B600 /* System time register Low - RO */
 #define E1000_SYSTIMH    0x0B604 /* System time register High - RO */
 #define E1000_TIMINCA    0x0B608 /* Increment attributes register - RW */
+#define E1000_TIMADJL  0x0B60C /* Time sync time adjustment offset Low - RW */
+#define E1000_TIMADJH  0x0B610 /* Time sync time adjustment offset High - RW */
 #define E1000_TSAUXC     0x0B640 /* Timesync Auxiliary Control register */
 #define E1000_SYSTIMR    0x0B6F8 /* System time register Residue */
+#define E1000_TSICR    0x0B66C /* Interrupt Cause Register */
+#define E1000_TSIM     0x0B674 /* Interrupt Mask Register */
+#define E1000_RXMTRL   0x0B634 /* Time sync Rx EtherType and Msg Type - RW */
+#define E1000_RXUDP    0x0B638 /* Time Sync Rx UDP Port - RW */
 
 /* Filtering Registers */
 #define E1000_SAQF(_n)  (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */
index b3a6b01..86c67a6 100644 (file)
@@ -373,6 +373,17 @@ STATIC u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
        return hash_value;
 }
 
+static void e1000_write_msg_read_ack(struct e1000_hw *hw,
+                                    u32 *msg, u16 size)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       u32 retmsg[E1000_VFMAILBOX_SIZE];
+       s32 retval = mbx->ops.write_posted(hw, msg, size, 0);
+
+       if (!retval)
+               mbx->ops.read_posted(hw, retmsg, E1000_VFMAILBOX_SIZE, 0);
+}
+
 /**
  *  e1000_update_mc_addr_list_vf - Update Multicast addresses
  *  @hw: pointer to the HW structure
@@ -385,7 +396,6 @@ STATIC u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
 void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
                                   u8 *mc_addr_list, u32 mc_addr_count)
 {
-       struct e1000_mbx_info *mbx = &hw->mbx;
        u32 msgbuf[E1000_VFMAILBOX_SIZE];
        u16 *hash_list = (u16 *)&msgbuf[1];
        u32 hash_value;
@@ -419,18 +429,17 @@ void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
                mc_addr_list += ETH_ADDR_LEN;
        }
 
-       mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE, 0);
+       e1000_write_msg_read_ack(hw, msgbuf, E1000_VFMAILBOX_SIZE);
 }
 
 /**
  *  e1000_vfta_set_vf - Set/Unset vlan filter table address
  *  @hw: pointer to the HW structure
  *  @vid: determines the vfta register and bit to set/unset
- *  @set: if TRUE then set bit, else clear bit
+ *  @set: if true then set bit, else clear bit
  **/
 void e1000_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set)
 {
-       struct e1000_mbx_info *mbx = &hw->mbx;
        u32 msgbuf[2];
 
        msgbuf[0] = E1000_VF_SET_VLAN;
@@ -439,7 +448,7 @@ void e1000_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set)
        if (set)
                msgbuf[0] |= E1000_VF_SET_VLAN_ADD;
 
-       mbx->ops.write_posted(hw, msgbuf, 2, 0);
+       e1000_write_msg_read_ack(hw, msgbuf, 2);
 }
 
 /** e1000_rlpml_set_vf - Set the maximum receive packet length
@@ -448,13 +457,12 @@ void e1000_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set)
  **/
 void e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size)
 {
-       struct e1000_mbx_info *mbx = &hw->mbx;
        u32 msgbuf[2];
 
        msgbuf[0] = E1000_VF_SET_LPE;
        msgbuf[1] = max_size;
 
-       mbx->ops.write_posted(hw, msgbuf, 2, 0);
+       e1000_write_msg_read_ack(hw, msgbuf, 2);
 }
 
 /**
diff --git a/lib/librte_pmd_e1000/e1000/if_igb.c b/lib/librte_pmd_e1000/e1000/if_igb.c
deleted file mode 100644 (file)
index 4aa08f6..0000000
+++ /dev/null
@@ -1,5567 +0,0 @@
-/******************************************************************************
-
-  Copyright (c) 2001-2011, Intel Corporation 
-  All rights reserved.
-  
-  Redistribution and use in source and binary forms, with or without 
-  modification, are permitted provided that the following conditions are met:
-  
-   1. Redistributions of source code must retain the above copyright notice, 
-      this list of conditions and the following disclaimer.
-  
-   2. Redistributions in binary form must reproduce the above copyright 
-      notice, this list of conditions and the following disclaimer in the 
-      documentation and/or other materials provided with the distribution.
-  
-   3. Neither the name of the Intel Corporation nor the names of its 
-      contributors may be used to endorse or promote products derived from 
-      this software without specific prior written permission.
-  
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
-  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
-  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
-  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
-  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-  POSSIBILITY OF SUCH DAMAGE.
-
-******************************************************************************/
-/*$FreeBSD$*/
-
-
-#ifdef HAVE_KERNEL_OPTION_HEADERS
-#include "opt_device_polling.h"
-#include "opt_inet.h"
-#include "opt_altq.h"
-#endif
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#if __FreeBSD_version >= 800000
-#include <sys/buf_ring.h>
-#endif
-#include <sys/bus.h>
-#include <sys/endian.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/sysctl.h>
-#include <sys/taskqueue.h>
-#include <sys/eventhandler.h>
-#include <sys/pcpu.h>
-#include <sys/smp.h>
-#include <machine/smp.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-
-#include <net/bpf.h>
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-
-#include <net/if_types.h>
-#include <net/if_vlan_var.h>
-
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_lro.h>
-#include <netinet/udp.h>
-
-#include <machine/in_cksum.h>
-#include <dev/led/led.h>
-#include <dev/pci/pcivar.h>
-#include <dev/pci/pcireg.h>
-
-#include "e1000_api.h"
-#include "e1000_82575.h"
-#include "if_igb.h"
-
-/*********************************************************************
- *  Set this to one to display debug statistics
- *********************************************************************/
-int    igb_display_debug_stats = 0;
-
-/*********************************************************************
- *  Driver version:
- *********************************************************************/
-char igb_driver_version[] = "version - 2.2.3";
-
-
-/*********************************************************************
- *  PCI Device ID Table
- *
- *  Used by probe to select devices to load on
- *  Last field stores an index into e1000_strings
- *  Last entry must be all 0s
- *
- *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
- *********************************************************************/
-
-static igb_vendor_info_t igb_vendor_info_array[] =
-{
-       { 0x8086, E1000_DEV_ID_82575EB_COPPER,  PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82575EB_FIBER_SERDES,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82575GB_QUAD_COPPER,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82576,           PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82576_NS,        PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82576_NS_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82576_FIBER,     PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82576_SERDES,    PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82576_SERDES_QUAD,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82576_QUAD_COPPER,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82576_QUAD_COPPER_ET2,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82576_VF,        PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82580_COPPER,    PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82580_FIBER,     PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82580_SERDES,    PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82580_SGMII,     PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82580_COPPER_DUAL,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82580_QUAD_FIBER,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_DH89XXCC_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_DH89XXCC_SGMII,  PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_DH89XXCC_SFP,    PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_DH89XXCC_BACKPLANE,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_I350_COPPER,     PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_I350_FIBER,      PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_I350_SERDES,     PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_I350_SGMII,      PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_I350_VF,         PCI_ANY_ID, PCI_ANY_ID, 0},
-       /* required last entry */
-       { 0, 0, 0, 0, 0}
-};
-
-/*********************************************************************
- *  Table of branding strings for all supported NICs.
- *********************************************************************/
-
-static char *igb_strings[] = {
-       "Intel(R) PRO/1000 Network Connection"
-};
-
-/*********************************************************************
- *  Function prototypes
- *********************************************************************/
-static int     igb_probe(device_t);
-static int     igb_attach(device_t);
-static int     igb_detach(device_t);
-static int     igb_shutdown(device_t);
-static int     igb_suspend(device_t);
-static int     igb_resume(device_t);
-static void    igb_start(struct ifnet *);
-static void    igb_start_locked(struct tx_ring *, struct ifnet *ifp);
-#if __FreeBSD_version >= 800000
-static int     igb_mq_start(struct ifnet *, struct mbuf *);
-static int     igb_mq_start_locked(struct ifnet *,
-                   struct tx_ring *, struct mbuf *);
-static void    igb_qflush(struct ifnet *);
-#endif
-static int     igb_ioctl(struct ifnet *, u_long, caddr_t);
-static void    igb_init(void *);
-static void    igb_init_locked(struct adapter *);
-static void    igb_stop(void *);
-static void    igb_media_status(struct ifnet *, struct ifmediareq *);
-static int     igb_media_change(struct ifnet *);
-static void    igb_identify_hardware(struct adapter *);
-static int     igb_allocate_pci_resources(struct adapter *);
-static int     igb_allocate_msix(struct adapter *);
-static int     igb_allocate_legacy(struct adapter *);
-static int     igb_setup_msix(struct adapter *);
-static void    igb_free_pci_resources(struct adapter *);
-static void    igb_local_timer(void *);
-static void    igb_reset(struct adapter *);
-static int     igb_setup_interface(device_t, struct adapter *);
-static int     igb_allocate_queues(struct adapter *);
-static void    igb_configure_queues(struct adapter *);
-
-static int     igb_allocate_transmit_buffers(struct tx_ring *);
-static void    igb_setup_transmit_structures(struct adapter *);
-static void    igb_setup_transmit_ring(struct tx_ring *);
-static void    igb_initialize_transmit_units(struct adapter *);
-static void    igb_free_transmit_structures(struct adapter *);
-static void    igb_free_transmit_buffers(struct tx_ring *);
-
-static int     igb_allocate_receive_buffers(struct rx_ring *);
-static int     igb_setup_receive_structures(struct adapter *);
-static int     igb_setup_receive_ring(struct rx_ring *);
-static void    igb_initialize_receive_units(struct adapter *);
-static void    igb_free_receive_structures(struct adapter *);
-static void    igb_free_receive_buffers(struct rx_ring *);
-static void    igb_free_receive_ring(struct rx_ring *);
-
-static void    igb_enable_intr(struct adapter *);
-static void    igb_disable_intr(struct adapter *);
-static void    igb_update_stats_counters(struct adapter *);
-static bool    igb_txeof(struct tx_ring *);
-
-static __inline        void igb_rx_discard(struct rx_ring *, int);
-static __inline void igb_rx_input(struct rx_ring *,
-                   struct ifnet *, struct mbuf *, u32);
-
-static bool    igb_rxeof(struct igb_queue *, int, int *);
-static void    igb_rx_checksum(u32, struct mbuf *, u32);
-static int     igb_tx_ctx_setup(struct tx_ring *, struct mbuf *);
-static bool    igb_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
-static void    igb_set_promisc(struct adapter *);
-static void    igb_disable_promisc(struct adapter *);
-static void    igb_set_multi(struct adapter *);
-static void    igb_update_link_status(struct adapter *);
-static void    igb_refresh_mbufs(struct rx_ring *, int);
-
-static void    igb_register_vlan(void *, struct ifnet *, u16);
-static void    igb_unregister_vlan(void *, struct ifnet *, u16);
-static void    igb_setup_vlan_hw_support(struct adapter *);
-
-static int     igb_xmit(struct tx_ring *, struct mbuf **);
-static int     igb_dma_malloc(struct adapter *, bus_size_t,
-                   struct igb_dma_alloc *, int);
-static void    igb_dma_free(struct adapter *, struct igb_dma_alloc *);
-static int     igb_sysctl_nvm_info(SYSCTL_HANDLER_ARGS);
-static void    igb_print_nvm_info(struct adapter *);
-static int     igb_is_valid_ether_addr(u8 *);
-static void     igb_add_hw_stats(struct adapter *);
-
-static void    igb_vf_init_stats(struct adapter *);
-static void    igb_update_vf_stats_counters(struct adapter *);
-
-/* Management and WOL Support */
-static void    igb_init_manageability(struct adapter *);
-static void    igb_release_manageability(struct adapter *);
-static void     igb_get_hw_control(struct adapter *);
-static void     igb_release_hw_control(struct adapter *);
-static void     igb_enable_wakeup(device_t);
-static void     igb_led_func(void *, int);
-
-static int     igb_irq_fast(void *);
-static void    igb_msix_que(void *);
-static void    igb_msix_link(void *);
-static void    igb_handle_que(void *context, int pending);
-static void    igb_handle_link(void *context, int pending);
-
-static void    igb_set_sysctl_value(struct adapter *, const char *,
-                   const char *, int *, int);
-static int     igb_set_flowcntl(SYSCTL_HANDLER_ARGS);
-
-#ifdef DEVICE_POLLING
-static poll_handler_t igb_poll;
-#endif /* POLLING */
-
-/*********************************************************************
- *  FreeBSD Device Interface Entry Points
- *********************************************************************/
-
-static device_method_t igb_methods[] = {
-       /* Device interface */
-       DEVMETHOD(device_probe, igb_probe),
-       DEVMETHOD(device_attach, igb_attach),
-       DEVMETHOD(device_detach, igb_detach),
-       DEVMETHOD(device_shutdown, igb_shutdown),
-       DEVMETHOD(device_suspend, igb_suspend),
-       DEVMETHOD(device_resume, igb_resume),
-       {0, 0}
-};
-
-static driver_t igb_driver = {
-       "igb", igb_methods, sizeof(struct adapter),
-};
-
-static devclass_t igb_devclass;
-DRIVER_MODULE(igb, pci, igb_driver, igb_devclass, 0, 0);
-MODULE_DEPEND(igb, pci, 1, 1, 1);
-MODULE_DEPEND(igb, ether, 1, 1, 1);
-
-/*********************************************************************
- *  Tunable default values.
- *********************************************************************/
-
-/* Descriptor defaults */
-static int igb_rxd = IGB_DEFAULT_RXD;
-static int igb_txd = IGB_DEFAULT_TXD;
-TUNABLE_INT("hw.igb.rxd", &igb_rxd);
-TUNABLE_INT("hw.igb.txd", &igb_txd);
-
-/*
-** AIM: Adaptive Interrupt Moderation
-** which means that the interrupt rate
-** is varied over time based on the
-** traffic for that interrupt vector
-*/
-static int igb_enable_aim = TRUE;
-TUNABLE_INT("hw.igb.enable_aim", &igb_enable_aim);
-
-/*
- * MSIX should be the default for best performance,
- * but this allows it to be forced off for testing.
- */         
-static int igb_enable_msix = 1;
-TUNABLE_INT("hw.igb.enable_msix", &igb_enable_msix);
-
-/*
-** Tuneable Interrupt rate
-*/
-static int igb_max_interrupt_rate = 8000;
-TUNABLE_INT("hw.igb.max_interrupt_rate", &igb_max_interrupt_rate);
-
-/*
-** Header split causes the packet header to
-** be dma'd to a seperate mbuf from the payload.
-** this can have memory alignment benefits. But
-** another plus is that small packets often fit
-** into the header and thus use no cluster. Its
-** a very workload dependent type feature.
-*/
-static bool igb_header_split = FALSE;
-TUNABLE_INT("hw.igb.hdr_split", &igb_header_split);
-
-/*
-** This will autoconfigure based on
-** the number of CPUs if left at 0.
-*/
-static int igb_num_queues = 0;
-TUNABLE_INT("hw.igb.num_queues", &igb_num_queues);
-
-/* How many packets rxeof tries to clean at a time */
-static int igb_rx_process_limit = 100;
-TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit);
-
-/* Flow control setting - default to FULL */
-static int igb_fc_setting = e1000_fc_full;
-TUNABLE_INT("hw.igb.fc_setting", &igb_fc_setting);
-
-/* Energy Efficient Ethernet - default to off */
-static int igb_eee_disabled = TRUE;
-TUNABLE_INT("hw.igb.eee_disabled", &igb_eee_disabled);
-
-/*
-** DMA Coalescing, only for i350 - default to off,
-** this feature is for power savings
-*/
-static int igb_dma_coalesce = FALSE;
-TUNABLE_INT("hw.igb.dma_coalesce", &igb_dma_coalesce);
-
-/*********************************************************************
- *  Device identification routine
- *
- *  igb_probe determines if the driver should be loaded on
- *  adapter based on PCI vendor/device id of the adapter.
- *
- *  return BUS_PROBE_DEFAULT on success, positive on failure
- *********************************************************************/
-
-static int
-igb_probe(device_t dev)
-{
-       char            adapter_name[60];
-       uint16_t        pci_vendor_id = 0;
-       uint16_t        pci_device_id = 0;
-       uint16_t        pci_subvendor_id = 0;
-       uint16_t        pci_subdevice_id = 0;
-       igb_vendor_info_t *ent;
-
-       INIT_DEBUGOUT("igb_probe: begin");
-
-       pci_vendor_id = pci_get_vendor(dev);
-       if (pci_vendor_id != IGB_VENDOR_ID)
-               return (ENXIO);
-
-       pci_device_id = pci_get_device(dev);
-       pci_subvendor_id = pci_get_subvendor(dev);
-       pci_subdevice_id = pci_get_subdevice(dev);
-
-       ent = igb_vendor_info_array;
-       while (ent->vendor_id != 0) {
-               if ((pci_vendor_id == ent->vendor_id) &&
-                   (pci_device_id == ent->device_id) &&
-
-                   ((pci_subvendor_id == ent->subvendor_id) ||
-                   (ent->subvendor_id == PCI_ANY_ID)) &&
-
-                   ((pci_subdevice_id == ent->subdevice_id) ||
-                   (ent->subdevice_id == PCI_ANY_ID))) {
-                       sprintf(adapter_name, "%s %s",
-                               igb_strings[ent->index],
-                               igb_driver_version);
-                       device_set_desc_copy(dev, adapter_name);
-                       return (BUS_PROBE_DEFAULT);
-               }
-               ent++;
-       }
-
-       return (ENXIO);
-}
-
-/*********************************************************************
- *  Device initialization routine
- *
- *  The attach entry point is called when the driver is being loaded.
- *  This routine identifies the type of hardware, allocates all resources
- *  and initializes the hardware.
- *
- *  return 0 on success, positive on failure
- *********************************************************************/
-
-static int
-igb_attach(device_t dev)
-{
-       struct adapter  *adapter;
-       int             error = 0;
-       u16             eeprom_data;
-
-       INIT_DEBUGOUT("igb_attach: begin");
-
-       adapter = device_get_softc(dev);
-       adapter->dev = adapter->osdep.dev = dev;
-       IGB_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
-
-       /* SYSCTL stuff */
-       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-           OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
-           igb_sysctl_nvm_info, "I", "NVM Information");
-
-       SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
-           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-           OID_AUTO, "enable_aim", CTLTYPE_INT|CTLFLAG_RW,
-           &igb_enable_aim, 1, "Interrupt Moderation");
-
-       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-           OID_AUTO, "flow_control", CTLTYPE_INT|CTLFLAG_RW,
-           adapter, 0, igb_set_flowcntl, "I", "Flow Control");
-
-       callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
-
-       /* Determine hardware and mac info */
-       igb_identify_hardware(adapter);
-
-       /* Setup PCI resources */
-       if (igb_allocate_pci_resources(adapter)) {
-               device_printf(dev, "Allocation of PCI resources failed\n");
-               error = ENXIO;
-               goto err_pci;
-       }
-
-       /* Do Shared Code initialization */
-       if (e1000_setup_init_funcs(&adapter->hw, TRUE)) {
-               device_printf(dev, "Setup of Shared code failed\n");
-               error = ENXIO;
-               goto err_pci;
-       }
-
-       e1000_get_bus_info(&adapter->hw);
-
-       /* Sysctl for limiting the amount of work done in the taskqueue */
-       igb_set_sysctl_value(adapter, "rx_processing_limit",
-           "max number of rx packets to process", &adapter->rx_process_limit,
-           igb_rx_process_limit);
-
-       /*
-        * Validate number of transmit and receive descriptors. It
-        * must not exceed hardware maximum, and must be multiple
-        * of E1000_DBA_ALIGN.
-        */
-       if (((igb_txd * sizeof(struct e1000_tx_desc)) % IGB_DBA_ALIGN) != 0 ||
-           (igb_txd > IGB_MAX_TXD) || (igb_txd < IGB_MIN_TXD)) {
-               device_printf(dev, "Using %d TX descriptors instead of %d!\n",
-                   IGB_DEFAULT_TXD, igb_txd);
-               adapter->num_tx_desc = IGB_DEFAULT_TXD;
-       } else
-               adapter->num_tx_desc = igb_txd;
-       if (((igb_rxd * sizeof(struct e1000_rx_desc)) % IGB_DBA_ALIGN) != 0 ||
-           (igb_rxd > IGB_MAX_RXD) || (igb_rxd < IGB_MIN_RXD)) {
-               device_printf(dev, "Using %d RX descriptors instead of %d!\n",
-                   IGB_DEFAULT_RXD, igb_rxd);
-               adapter->num_rx_desc = IGB_DEFAULT_RXD;
-       } else
-               adapter->num_rx_desc = igb_rxd;
-
-       adapter->hw.mac.autoneg = DO_AUTO_NEG;
-       adapter->hw.phy.autoneg_wait_to_complete = FALSE;
-       adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT;
-
-       /* Copper options */
-       if (adapter->hw.phy.media_type == e1000_media_type_copper) {
-               adapter->hw.phy.mdix = AUTO_ALL_MODES;
-               adapter->hw.phy.disable_polarity_correction = FALSE;
-               adapter->hw.phy.ms_type = IGB_MASTER_SLAVE;
-       }
-
-       /*
-        * Set the frame limits assuming
-        * standard ethernet sized frames.
-        */
-       adapter->max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE;
-       adapter->min_frame_size = ETH_ZLEN + ETHERNET_FCS_SIZE;
-
-       /*
-       ** Allocate and Setup Queues
-       */
-       if (igb_allocate_queues(adapter)) {
-               error = ENOMEM;
-               goto err_pci;
-       }
-
-       /* Allocate the appropriate stats memory */
-       if (adapter->vf_ifp) {
-               adapter->stats =
-                   (struct e1000_vf_stats *)malloc(sizeof \
-                   (struct e1000_vf_stats), M_DEVBUF, M_NOWAIT | M_ZERO);
-               igb_vf_init_stats(adapter);
-       } else
-               adapter->stats =
-                   (struct e1000_hw_stats *)malloc(sizeof \
-                   (struct e1000_hw_stats), M_DEVBUF, M_NOWAIT | M_ZERO);
-       if (adapter->stats == NULL) {
-               device_printf(dev, "Can not allocate stats memory\n");
-               error = ENOMEM;
-               goto err_late;
-       }
-
-       /* Allocate multicast array memory. */
-       adapter->mta = malloc(sizeof(u8) * ETH_ADDR_LEN *
-           MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
-       if (adapter->mta == NULL) {
-               device_printf(dev, "Can not allocate multicast setup array\n");
-               error = ENOMEM;
-               goto err_late;
-       }
-
-       /* Some adapter-specific advanced features */
-       if (adapter->hw.mac.type >= e1000_i350) {
-               igb_set_sysctl_value(adapter, "dma_coalesce",
-                   "configure dma coalesce",
-                   &adapter->dma_coalesce, igb_dma_coalesce);
-               igb_set_sysctl_value(adapter, "eee_disabled",
-                   "enable Energy Efficient Ethernet",
-                   &adapter->hw.dev_spec._82575.eee_disable,
-                   igb_eee_disabled);
-               e1000_set_eee_i350(&adapter->hw);
-       }
-
-       /*
-       ** Start from a known state, this is
-       ** important in reading the nvm and
-       ** mac from that.
-       */
-       e1000_reset_hw(&adapter->hw);
-
-       /* Make sure we have a good EEPROM before we read from it */
-       if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
-               /*
-               ** Some PCI-E parts fail the first check due to
-               ** the link being in sleep state, call it again,
-               ** if it fails a second time its a real issue.
-               */
-               if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
-                       device_printf(dev,
-                           "The EEPROM Checksum Is Not Valid\n");
-                       error = EIO;
-                       goto err_late;
-               }
-       }
-
-       /*
-       ** Copy the permanent MAC address out of the EEPROM
-       */
-       if (e1000_read_mac_addr(&adapter->hw) < 0) {
-               device_printf(dev, "EEPROM read error while reading MAC"
-                   " address\n");
-               error = EIO;
-               goto err_late;
-       }
-       /* Check its sanity */
-       if (!igb_is_valid_ether_addr(adapter->hw.mac.addr)) {
-               device_printf(dev, "Invalid MAC address\n");
-               error = EIO;
-               goto err_late;
-       }
-
-       /* 
-       ** Configure Interrupts
-       */
-       if ((adapter->msix > 1) && (igb_enable_msix))
-               error = igb_allocate_msix(adapter);
-       else /* MSI or Legacy */
-               error = igb_allocate_legacy(adapter);
-       if (error)
-               goto err_late;
-
-       /* Setup OS specific network interface */
-       if (igb_setup_interface(dev, adapter) != 0)
-               goto err_late;
-
-       /* Now get a good starting state */
-       igb_reset(adapter);
-
-       /* Initialize statistics */
-       igb_update_stats_counters(adapter);
-
-       adapter->hw.mac.get_link_status = 1;
-       igb_update_link_status(adapter);
-
-       /* Indicate SOL/IDER usage */
-       if (e1000_check_reset_block(&adapter->hw))
-               device_printf(dev,
-                   "PHY reset is blocked due to SOL/IDER session.\n");
-
-       /* Determine if we have to control management hardware */
-       adapter->has_manage = e1000_enable_mng_pass_thru(&adapter->hw);
-
-       /*
-        * Setup Wake-on-Lan
-        */
-       /* APME bit in EEPROM is mapped to WUC.APME */
-       eeprom_data = E1000_READ_REG(&adapter->hw, E1000_WUC) & E1000_WUC_APME;
-       if (eeprom_data)
-               adapter->wol = E1000_WUFC_MAG;
-
-       /* Register for VLAN events */
-       adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
-            igb_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);
-       adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
-            igb_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
-
-       igb_add_hw_stats(adapter);
-
-       /* Tell the stack that the interface is not active */
-       adapter->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
-       adapter->led_dev = led_create(igb_led_func, adapter,
-           device_get_nameunit(dev));
-
-       INIT_DEBUGOUT("igb_attach: end");
-
-       return (0);
-
-err_late:
-       igb_free_transmit_structures(adapter);
-       igb_free_receive_structures(adapter);
-       igb_release_hw_control(adapter);
-       if (adapter->ifp != NULL)
-               if_free(adapter->ifp);
-err_pci:
-       igb_free_pci_resources(adapter);
-       free(adapter->mta, M_DEVBUF);
-       IGB_CORE_LOCK_DESTROY(adapter);
-
-       return (error);
-}
-
-/*********************************************************************
- *  Device removal routine
- *
- *  The detach entry point is called when the driver is being removed.
- *  This routine stops the adapter and deallocates all the resources
- *  that were allocated for driver operation.
- *
- *  return 0 on success, positive on failure
- *********************************************************************/
-
-static int
-igb_detach(device_t dev)
-{
-       struct adapter  *adapter = device_get_softc(dev);
-       struct ifnet    *ifp = adapter->ifp;
-
-       INIT_DEBUGOUT("igb_detach: begin");
-
-       /* Make sure VLANS are not using driver */
-       if (adapter->ifp->if_vlantrunk != NULL) {
-               device_printf(dev,"Vlan in use, detach first\n");
-               return (EBUSY);
-       }
-
-       if (adapter->led_dev != NULL)
-               led_destroy(adapter->led_dev);
-
-#ifdef DEVICE_POLLING
-       if (ifp->if_capenable & IFCAP_POLLING)
-               ether_poll_deregister(ifp);
-#endif
-
-       IGB_CORE_LOCK(adapter);
-       adapter->in_detach = 1;
-       igb_stop(adapter);
-       IGB_CORE_UNLOCK(adapter);
-
-       e1000_phy_hw_reset(&adapter->hw);
-
-       /* Give control back to firmware */
-       igb_release_manageability(adapter);
-       igb_release_hw_control(adapter);
-
-       if (adapter->wol) {
-               E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
-               E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
-               igb_enable_wakeup(dev);
-       }
-
-       /* Unregister VLAN events */
-       if (adapter->vlan_attach != NULL)
-               EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
-       if (adapter->vlan_detach != NULL)
-               EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
-
-       ether_ifdetach(adapter->ifp);
-
-       callout_drain(&adapter->timer);
-
-       igb_free_pci_resources(adapter);
-       bus_generic_detach(dev);
-       if_free(ifp);
-
-       igb_free_transmit_structures(adapter);
-       igb_free_receive_structures(adapter);
-       free(adapter->mta, M_DEVBUF);
-
-       IGB_CORE_LOCK_DESTROY(adapter);
-
-       return (0);
-}
-
-/*********************************************************************
- *
- *  Shutdown entry point
- *
- **********************************************************************/
-
-static int
-igb_shutdown(device_t dev)
-{
-       return igb_suspend(dev);
-}
-
-/*
- * Suspend/resume device methods.
- */
-static int
-igb_suspend(device_t dev)
-{
-       struct adapter *adapter = device_get_softc(dev);
-
-       IGB_CORE_LOCK(adapter);
-
-       igb_stop(adapter);
-
-        igb_release_manageability(adapter);
-       igb_release_hw_control(adapter);
-
-        if (adapter->wol) {
-                E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
-                E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
-                igb_enable_wakeup(dev);
-        }
-
-       IGB_CORE_UNLOCK(adapter);
-
-       return bus_generic_suspend(dev);
-}
-
-static int
-igb_resume(device_t dev)
-{
-       struct adapter *adapter = device_get_softc(dev);
-       struct ifnet *ifp = adapter->ifp;
-
-       IGB_CORE_LOCK(adapter);
-       igb_init_locked(adapter);
-       igb_init_manageability(adapter);
-
-       if ((ifp->if_flags & IFF_UP) &&
-           (ifp->if_drv_flags & IFF_DRV_RUNNING))
-               igb_start(ifp);
-
-       IGB_CORE_UNLOCK(adapter);
-
-       return bus_generic_resume(dev);
-}
-
-
-/*********************************************************************
- *  Transmit entry point
- *
- *  igb_start is called by the stack to initiate a transmit.
- *  The driver will remain in this routine as long as there are
- *  packets to transmit and transmit resources are available.
- *  In case resources are not available stack is notified and
- *  the packet is requeued.
- **********************************************************************/
-
-static void
-igb_start_locked(struct tx_ring *txr, struct ifnet *ifp)
-{
-       struct adapter  *adapter = ifp->if_softc;
-       struct mbuf     *m_head;
-
-       IGB_TX_LOCK_ASSERT(txr);
-
-       if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
-           IFF_DRV_RUNNING)
-               return;
-       if (!adapter->link_active)
-               return;
-
-       /* Call cleanup if number of TX descriptors low */
-       if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD)
-               igb_txeof(txr);
-
-       while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
-               if (txr->tx_avail <= IGB_MAX_SCATTER) {
-                       ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-                       break;
-               }
-               IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
-               if (m_head == NULL)
-                       break;
-               /*
-                *  Encapsulation can modify our pointer, and or make it
-                *  NULL on failure.  In that event, we can't requeue.
-                */
-               if (igb_xmit(txr, &m_head)) {
-                       if (m_head == NULL)
-                               break;
-                       ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-                       IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
-                       break;
-               }
-
-               /* Send a copy of the frame to the BPF listener */
-               ETHER_BPF_MTAP(ifp, m_head);
-
-               /* Set watchdog on */
-               txr->watchdog_time = ticks;
-               txr->queue_status = IGB_QUEUE_WORKING;
-       }
-}
-/*
- * Legacy TX driver routine, called from the
- * stack, always uses tx[0], and spins for it.
- * Should not be used with multiqueue tx
- */
-static void
-igb_start(struct ifnet *ifp)
-{
-       struct adapter  *adapter = ifp->if_softc;
-       struct tx_ring  *txr = adapter->tx_rings;
-
-       if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-               IGB_TX_LOCK(txr);
-               igb_start_locked(txr, ifp);
-               IGB_TX_UNLOCK(txr);
-       }
-       return;
-}
-
-#if __FreeBSD_version >= 800000
-/*
-** Multiqueue Transmit driver
-**
-*/
-static int
-igb_mq_start(struct ifnet *ifp, struct mbuf *m)
-{
-       struct adapter          *adapter = ifp->if_softc;
-       struct igb_queue        *que;
-       struct tx_ring          *txr;
-       int                     i = 0, err = 0;
-
-       /* Which queue to use */
-       if ((m->m_flags & M_FLOWID) != 0)
-               i = m->m_pkthdr.flowid % adapter->num_queues;
-
-       txr = &adapter->tx_rings[i];
-       que = &adapter->queues[i];
-
-       if (IGB_TX_TRYLOCK(txr)) {
-               err = igb_mq_start_locked(ifp, txr, m);
-               IGB_TX_UNLOCK(txr);
-       } else {
-               err = drbr_enqueue(ifp, txr->br, m);
-               taskqueue_enqueue(que->tq, &que->que_task);
-       }
-
-       return (err);
-}
-
-static int
-igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
-{
-       struct adapter  *adapter = txr->adapter;
-        struct mbuf     *next;
-        int             err = 0, enq;
-
-       IGB_TX_LOCK_ASSERT(txr);
-
-       if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
-           IFF_DRV_RUNNING || adapter->link_active == 0) {
-               if (m != NULL)
-                       err = drbr_enqueue(ifp, txr->br, m);
-               return (err);
-       }
-
-       enq = 0;
-       if (m == NULL) {
-               next = drbr_dequeue(ifp, txr->br);
-       } else if (drbr_needs_enqueue(ifp, txr->br)) {
-               if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
-                       return (err);
-               next = drbr_dequeue(ifp, txr->br);
-       } else
-               next = m;
-
-       /* Process the queue */
-       while (next != NULL) {
-               if ((err = igb_xmit(txr, &next)) != 0) {
-                       if (next != NULL)
-                               err = drbr_enqueue(ifp, txr->br, next);
-                       break;
-               }
-               enq++;
-               drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags);
-               ETHER_BPF_MTAP(ifp, next);
-               if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
-                       break;
-               if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD)
-                       igb_txeof(txr);
-               if (txr->tx_avail <= IGB_MAX_SCATTER) {
-                       ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-                       break;
-               }
-               next = drbr_dequeue(ifp, txr->br);
-       }
-       if (enq > 0) {
-               /* Set the watchdog */
-               txr->queue_status = IGB_QUEUE_WORKING;
-               txr->watchdog_time = ticks;
-       }
-       return (err);
-}
-
-/*
-** Flush all ring buffers
-*/
-static void
-igb_qflush(struct ifnet *ifp)
-{
-       struct adapter  *adapter = ifp->if_softc;
-       struct tx_ring  *txr = adapter->tx_rings;
-       struct mbuf     *m;
-
-       for (int i = 0; i < adapter->num_queues; i++, txr++) {
-               IGB_TX_LOCK(txr);
-               while ((m = buf_ring_dequeue_sc(txr->br)) != NULL)
-                       m_freem(m);
-               IGB_TX_UNLOCK(txr);
-       }
-       if_qflush(ifp);
-}
-#endif /* __FreeBSD_version >= 800000 */
-
-/*********************************************************************
- *  Ioctl entry point
- *
- *  igb_ioctl is called when the user wants to configure the
- *  interface.
- *
- *  return 0 on success, positive on failure
- **********************************************************************/
-
-static int
-igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
-{
-       struct adapter  *adapter = ifp->if_softc;
-       struct ifreq *ifr = (struct ifreq *)data;
-#ifdef INET
-       struct ifaddr *ifa = (struct ifaddr *)data;
-#endif
-       int error = 0;
-
-       if (adapter->in_detach)
-               return (error);
-
-       switch (command) {
-       case SIOCSIFADDR:
-#ifdef INET
-               if (ifa->ifa_addr->sa_family == AF_INET) {
-                       /*
-                        * XXX
-                        * Since resetting hardware takes a very long time
-                        * and results in link renegotiation we only
-                        * initialize the hardware only when it is absolutely
-                        * required.
-                        */
-                       ifp->if_flags |= IFF_UP;
-                       if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-                               IGB_CORE_LOCK(adapter);
-                               igb_init_locked(adapter);
-                               IGB_CORE_UNLOCK(adapter);
-                       }
-                       if (!(ifp->if_flags & IFF_NOARP))
-                               arp_ifinit(ifp, ifa);
-               } else
-#endif
-                       error = ether_ioctl(ifp, command, data);
-               break;
-       case SIOCSIFMTU:
-           {
-               int max_frame_size;
-
-               IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
-
-               IGB_CORE_LOCK(adapter);
-               max_frame_size = 9234;
-               if (ifr->ifr_mtu > max_frame_size - ETHER_HDR_LEN -
-                   ETHER_CRC_LEN) {
-                       IGB_CORE_UNLOCK(adapter);
-                       error = EINVAL;
-                       break;
-               }
-
-               ifp->if_mtu = ifr->ifr_mtu;
-               adapter->max_frame_size =
-                   ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
-               igb_init_locked(adapter);
-               IGB_CORE_UNLOCK(adapter);
-               break;
-           }
-       case SIOCSIFFLAGS:
-               IOCTL_DEBUGOUT("ioctl rcv'd:\
-                   SIOCSIFFLAGS (Set Interface Flags)");
-               IGB_CORE_LOCK(adapter);
-               if (ifp->if_flags & IFF_UP) {
-                       if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-                               if ((ifp->if_flags ^ adapter->if_flags) &
-                                   (IFF_PROMISC | IFF_ALLMULTI)) {
-                                       igb_disable_promisc(adapter);
-                                       igb_set_promisc(adapter);
-                               }
-                       } else
-                               igb_init_locked(adapter);
-               } else
-                       if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-                               igb_stop(adapter);
-               adapter->if_flags = ifp->if_flags;
-               IGB_CORE_UNLOCK(adapter);
-               break;
-       case SIOCADDMULTI:
-       case SIOCDELMULTI:
-               IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI");
-               if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-                       IGB_CORE_LOCK(adapter);
-                       igb_disable_intr(adapter);
-                       igb_set_multi(adapter);
-#ifdef DEVICE_POLLING
-                       if (!(ifp->if_capenable & IFCAP_POLLING))
-#endif
-                               igb_enable_intr(adapter);
-                       IGB_CORE_UNLOCK(adapter);
-               }
-               break;
-       case SIOCSIFMEDIA:
-               /*
-               ** As the speed/duplex settings are being
-               ** changed, we need toreset the PHY.
-               */
-               adapter->hw.phy.reset_disable = FALSE;
-               /* Check SOL/IDER usage */
-               IGB_CORE_LOCK(adapter);
-               if (e1000_check_reset_block(&adapter->hw)) {
-                       IGB_CORE_UNLOCK(adapter);
-                       device_printf(adapter->dev, "Media change is"
-                           " blocked due to SOL/IDER session.\n");
-                       break;
-               }
-               IGB_CORE_UNLOCK(adapter);
-       case SIOCGIFMEDIA:
-               IOCTL_DEBUGOUT("ioctl rcv'd: \
-                   SIOCxIFMEDIA (Get/Set Interface Media)");
-               error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
-               break;
-       case SIOCSIFCAP:
-           {
-               int mask, reinit;
-
-               IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
-               reinit = 0;
-               mask = ifr->ifr_reqcap ^ ifp->if_capenable;
-#ifdef DEVICE_POLLING
-               if (mask & IFCAP_POLLING) {
-                       if (ifr->ifr_reqcap & IFCAP_POLLING) {
-                               error = ether_poll_register(igb_poll, ifp);
-                               if (error)
-                                       return (error);
-                               IGB_CORE_LOCK(adapter);
-                               igb_disable_intr(adapter);
-                               ifp->if_capenable |= IFCAP_POLLING;
-                               IGB_CORE_UNLOCK(adapter);
-                       } else {
-                               error = ether_poll_deregister(ifp);
-                               /* Enable interrupt even in error case */
-                               IGB_CORE_LOCK(adapter);
-                               igb_enable_intr(adapter);
-                               ifp->if_capenable &= ~IFCAP_POLLING;
-                               IGB_CORE_UNLOCK(adapter);
-                       }
-               }
-#endif
-               if (mask & IFCAP_HWCSUM) {
-                       ifp->if_capenable ^= IFCAP_HWCSUM;
-                       reinit = 1;
-               }
-               if (mask & IFCAP_TSO4) {
-                       ifp->if_capenable ^= IFCAP_TSO4;
-                       reinit = 1;
-               }
-               if (mask & IFCAP_VLAN_HWTAGGING) {
-                       ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
-                       reinit = 1;
-               }
-               if (mask & IFCAP_VLAN_HWFILTER) {
-                       ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
-                       reinit = 1;
-               }
-               if (mask & IFCAP_LRO) {
-                       ifp->if_capenable ^= IFCAP_LRO;
-                       reinit = 1;
-               }
-               if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING))
-                       igb_init(adapter);
-               VLAN_CAPABILITIES(ifp);
-               break;
-           }
-
-       default:
-               error = ether_ioctl(ifp, command, data);
-               break;
-       }
-
-       return (error);
-}
-
-
-/*********************************************************************
- *  Init entry point
- *
- *  This routine is used in two ways. It is used by the stack as
- *  init entry point in network interface structure. It is also used
- *  by the driver as a hw/sw initialization routine to get to a
- *  consistent state.
- *
- *  return 0 on success, positive on failure
- **********************************************************************/
-
-static void
-igb_init_locked(struct adapter *adapter)
-{
-       struct ifnet    *ifp = adapter->ifp;
-       device_t        dev = adapter->dev;
-
-       INIT_DEBUGOUT("igb_init: begin");
-
-       IGB_CORE_LOCK_ASSERT(adapter);
-
-       igb_disable_intr(adapter);
-       callout_stop(&adapter->timer);
-
-       /* Get the latest mac address, User can use a LAA */
-        bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr,
-              ETHER_ADDR_LEN);
-
-       /* Put the address into the Receive Address Array */
-       e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
-
-       igb_reset(adapter);
-       igb_update_link_status(adapter);
-
-       E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
-
-       /* Set hardware offload abilities */
-       ifp->if_hwassist = 0;
-       if (ifp->if_capenable & IFCAP_TXCSUM) {
-               ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
-#if __FreeBSD_version >= 800000
-               if (adapter->hw.mac.type == e1000_82576)
-                       ifp->if_hwassist |= CSUM_SCTP;
-#endif
-       }
-
-       if (ifp->if_capenable & IFCAP_TSO4)
-               ifp->if_hwassist |= CSUM_TSO;
-
-       /* Configure for OS presence */
-       igb_init_manageability(adapter);
-
-       /* Prepare transmit descriptors and buffers */
-       igb_setup_transmit_structures(adapter);
-       igb_initialize_transmit_units(adapter);
-
-       /* Setup Multicast table */
-       igb_set_multi(adapter);
-
-       /*
-       ** Figure out the desired mbuf pool
-       ** for doing jumbo/packetsplit
-       */
-       if (adapter->max_frame_size <= 2048)
-               adapter->rx_mbuf_sz = MCLBYTES;
-       else if (adapter->max_frame_size <= 4096)
-               adapter->rx_mbuf_sz = MJUMPAGESIZE;
-       else
-               adapter->rx_mbuf_sz = MJUM9BYTES;
-
-       /* Prepare receive descriptors and buffers */
-       if (igb_setup_receive_structures(adapter)) {
-               device_printf(dev, "Could not setup receive structures\n");
-               return;
-       }
-       igb_initialize_receive_units(adapter);
-
-        /* Enable VLAN support */
-       if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
-               igb_setup_vlan_hw_support(adapter);
-                                
-       /* Don't lose promiscuous settings */
-       igb_set_promisc(adapter);
-
-       ifp->if_drv_flags |= IFF_DRV_RUNNING;
-       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
-       callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
-       e1000_clear_hw_cntrs_base_generic(&adapter->hw);
-
-       if (adapter->msix > 1) /* Set up queue routing */
-               igb_configure_queues(adapter);
-
-       /* this clears any pending interrupts */
-       E1000_READ_REG(&adapter->hw, E1000_ICR);
-#ifdef DEVICE_POLLING
-       /*
-        * Only enable interrupts if we are not polling, make sure
-        * they are off otherwise.
-        */
-       if (ifp->if_capenable & IFCAP_POLLING)
-               igb_disable_intr(adapter);
-       else
-#endif /* DEVICE_POLLING */
-       {
-               igb_enable_intr(adapter);
-               E1000_WRITE_REG(&adapter->hw, E1000_ICS, E1000_ICS_LSC);
-       }
-
-       /* Set Energy Efficient Ethernet */
-       e1000_set_eee_i350(&adapter->hw);
-
-       /* Don't reset the phy next time init gets called */
-       adapter->hw.phy.reset_disable = TRUE;
-}
-
-static void
-igb_init(void *arg)
-{
-       struct adapter *adapter = arg;
-
-       IGB_CORE_LOCK(adapter);
-       igb_init_locked(adapter);
-       IGB_CORE_UNLOCK(adapter);
-}
-
-
-static void
-igb_handle_que(void *context, int pending)
-{
-       struct igb_queue *que = context;
-       struct adapter *adapter = que->adapter;
-       struct tx_ring *txr = que->txr;
-       struct ifnet    *ifp = adapter->ifp;
-
-       if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-               bool    more;
-
-               more = igb_rxeof(que, -1, NULL);
-
-               IGB_TX_LOCK(txr);
-               if (igb_txeof(txr))
-                       more = TRUE;
-#if __FreeBSD_version >= 800000
-               if (!drbr_empty(ifp, txr->br))
-                       igb_mq_start_locked(ifp, txr, NULL);
-#else
-               igb_start_locked(txr, ifp);
-#endif
-               IGB_TX_UNLOCK(txr);
-               if (more || (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
-                       taskqueue_enqueue(que->tq, &que->que_task);
-                       return;
-               }
-       }
-
-#ifdef DEVICE_POLLING
-       if (ifp->if_capenable & IFCAP_POLLING)
-               return;
-#endif
-       /* Reenable this interrupt */
-       if (que->eims)
-               E1000_WRITE_REG(&adapter->hw, E1000_EIMS, que->eims);
-       else
-               igb_enable_intr(adapter);
-}
-
-/* Deal with link in a sleepable context */
-static void
-igb_handle_link(void *context, int pending)
-{
-       struct adapter *adapter = context;
-
-       adapter->hw.mac.get_link_status = 1;
-       igb_update_link_status(adapter);
-}
-
-/*********************************************************************
- *
- *  MSI/Legacy Deferred
- *  Interrupt Service routine  
- *
- *********************************************************************/
-static int
-igb_irq_fast(void *arg)
-{
-       struct adapter          *adapter = arg;
-       struct igb_queue        *que = adapter->queues;
-       u32                     reg_icr;
-
-
-       reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
-
-       /* Hot eject?  */
-       if (reg_icr == 0xffffffff)
-               return FILTER_STRAY;
-
-       /* Definitely not our interrupt.  */
-       if (reg_icr == 0x0)
-               return FILTER_STRAY;
-
-       if ((reg_icr & E1000_ICR_INT_ASSERTED) == 0)
-               return FILTER_STRAY;
-
-       /*
-        * Mask interrupts until the taskqueue is finished running.  This is
-        * cheap, just assume that it is needed.  This also works around the
-        * MSI message reordering errata on certain systems.
-        */
-       igb_disable_intr(adapter);
-       taskqueue_enqueue(que->tq, &que->que_task);
-
-       /* Link status change */
-       if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))
-               taskqueue_enqueue(que->tq, &adapter->link_task);
-
-       if (reg_icr & E1000_ICR_RXO)
-               adapter->rx_overruns++;
-       return FILTER_HANDLED;
-}
-
-#ifdef DEVICE_POLLING
-/*********************************************************************
- *
- *  Legacy polling routine : if using this code you MUST be sure that
- *  multiqueue is not defined, ie, set igb_num_queues to 1.
- *
- *********************************************************************/
-#if __FreeBSD_version >= 800000
-#define POLL_RETURN_COUNT(a) (a)
-static int
-#else
-#define POLL_RETURN_COUNT(a)
-static void
-#endif
-igb_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
-{
-       struct adapter          *adapter = ifp->if_softc;
-       struct igb_queue        *que = adapter->queues;
-       struct tx_ring          *txr = adapter->tx_rings;
-       u32                     reg_icr, rx_done = 0;
-       u32                     loop = IGB_MAX_LOOP;
-       bool                    more;
-
-       IGB_CORE_LOCK(adapter);
-       if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
-               IGB_CORE_UNLOCK(adapter);
-               return POLL_RETURN_COUNT(rx_done);
-       }
-
-       if (cmd == POLL_AND_CHECK_STATUS) {
-               reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
-               /* Link status change */
-               if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))
-                       igb_handle_link(adapter, 0);
-
-               if (reg_icr & E1000_ICR_RXO)
-                       adapter->rx_overruns++;
-       }
-       IGB_CORE_UNLOCK(adapter);
-
-       igb_rxeof(que, count, &rx_done);
-
-       IGB_TX_LOCK(txr);
-       do {
-               more = igb_txeof(txr);
-       } while (loop-- && more);
-#if __FreeBSD_version >= 800000
-       if (!drbr_empty(ifp, txr->br))
-               igb_mq_start_locked(ifp, txr, NULL);
-#else
-       igb_start_locked(txr, ifp);
-#endif
-       IGB_TX_UNLOCK(txr);
-       return POLL_RETURN_COUNT(rx_done);
-}
-#endif /* DEVICE_POLLING */
-
-/*********************************************************************
- *
- *  MSIX TX Interrupt Service routine
- *
- **********************************************************************/
-static void
-igb_msix_que(void *arg)
-{
-       struct igb_queue *que = arg;
-       struct adapter *adapter = que->adapter;
-       struct tx_ring *txr = que->txr;
-       struct rx_ring *rxr = que->rxr;
-       u32             newitr = 0;
-       bool            more_tx, more_rx;
-
-       E1000_WRITE_REG(&adapter->hw, E1000_EIMC, que->eims);
-       ++que->irqs;
-
-       IGB_TX_LOCK(txr);
-       more_tx = igb_txeof(txr);
-       IGB_TX_UNLOCK(txr);
-
-       more_rx = igb_rxeof(que, adapter->rx_process_limit, NULL);
-
-       if (igb_enable_aim == FALSE)
-               goto no_calc;
-       /*
-       ** Do Adaptive Interrupt Moderation:
-        **  - Write out last calculated setting
-       **  - Calculate based on average size over
-       **    the last interval.
-       */
-        if (que->eitr_setting)
-                E1000_WRITE_REG(&adapter->hw,
-                    E1000_EITR(que->msix), que->eitr_setting);
-        que->eitr_setting = 0;
-
-        /* Idle, do nothing */
-        if ((txr->bytes == 0) && (rxr->bytes == 0))
-                goto no_calc;
-                                
-        /* Used half Default if sub-gig */
-        if (adapter->link_speed != 1000)
-                newitr = IGB_DEFAULT_ITR / 2;
-        else {
-               if ((txr->bytes) && (txr->packets))
-                       newitr = txr->bytes/txr->packets;
-               if ((rxr->bytes) && (rxr->packets))
-                       newitr = max(newitr,
-                           (rxr->bytes / rxr->packets));
-                newitr += 24; /* account for hardware frame, crc */
-               /* set an upper boundary */
-               newitr = min(newitr, 3000);
-               /* Be nice to the mid range */
-                if ((newitr > 300) && (newitr < 1200))
-                        newitr = (newitr / 3);
-                else
-                        newitr = (newitr / 2);
-        }
-        newitr &= 0x7FFC;  /* Mask invalid bits */
-        if (adapter->hw.mac.type == e1000_82575)
-                newitr |= newitr << 16;
-        else
-                newitr |= E1000_EITR_CNT_IGNR;
-                 
-        /* save for next interrupt */
-        que->eitr_setting = newitr;
-
-        /* Reset state */
-        txr->bytes = 0;
-        txr->packets = 0;
-        rxr->bytes = 0;
-        rxr->packets = 0;
-
-no_calc:
-       /* Schedule a clean task if needed*/
-       if (more_tx || more_rx ||
-           (adapter->ifp->if_drv_flags & IFF_DRV_OACTIVE))
-               taskqueue_enqueue(que->tq, &que->que_task);
-       else
-               /* Reenable this interrupt */
-               E1000_WRITE_REG(&adapter->hw, E1000_EIMS, que->eims);
-       return;
-}
-
-
-/*********************************************************************
- *
- *  MSIX Link Interrupt Service routine
- *
- **********************************************************************/
-
-static void
-igb_msix_link(void *arg)
-{
-       struct adapter  *adapter = arg;
-       u32             icr;
-
-       ++adapter->link_irq;
-       icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
-       if (!(icr & E1000_ICR_LSC))
-               goto spurious;
-       igb_handle_link(adapter, 0);
-
-spurious:
-       /* Rearm */
-       E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC);
-       E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask);
-       return;
-}
-
-
-/*********************************************************************
- *
- *  Media Ioctl callback
- *
- *  This routine is called whenever the user queries the status of
- *  the interface using ifconfig.
- *
- **********************************************************************/
-static void
-igb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
-{
-       struct adapter *adapter = ifp->if_softc;
-       u_char fiber_type = IFM_1000_SX;
-
-       INIT_DEBUGOUT("igb_media_status: begin");
-
-       IGB_CORE_LOCK(adapter);
-       igb_update_link_status(adapter);
-
-       ifmr->ifm_status = IFM_AVALID;
-       ifmr->ifm_active = IFM_ETHER;
-
-       if (!adapter->link_active) {
-               IGB_CORE_UNLOCK(adapter);
-               return;
-       }
-
-       ifmr->ifm_status |= IFM_ACTIVE;
-
-       if ((adapter->hw.phy.media_type == e1000_media_type_fiber) ||
-           (adapter->hw.phy.media_type == e1000_media_type_internal_serdes))
-               ifmr->ifm_active |= fiber_type | IFM_FDX;
-       else {
-               switch (adapter->link_speed) {
-               case 10:
-                       ifmr->ifm_active |= IFM_10_T;
-                       break;
-               case 100:
-                       ifmr->ifm_active |= IFM_100_TX;
-                       break;
-               case 1000:
-                       ifmr->ifm_active |= IFM_1000_T;
-                       break;
-               }
-               if (adapter->link_duplex == FULL_DUPLEX)
-                       ifmr->ifm_active |= IFM_FDX;
-               else
-                       ifmr->ifm_active |= IFM_HDX;
-       }
-       IGB_CORE_UNLOCK(adapter);
-}
-
-/*********************************************************************
- *
- *  Media Ioctl callback
- *
- *  This routine is called when the user changes speed/duplex using
- *  media/mediopt option with ifconfig.
- *
- **********************************************************************/
-static int
-igb_media_change(struct ifnet *ifp)
-{
-       struct adapter *adapter = ifp->if_softc;
-       struct ifmedia  *ifm = &adapter->media;
-
-       INIT_DEBUGOUT("igb_media_change: begin");
-
-       if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
-               return (EINVAL);
-
-       IGB_CORE_LOCK(adapter);
-       switch (IFM_SUBTYPE(ifm->ifm_media)) {
-       case IFM_AUTO:
-               adapter->hw.mac.autoneg = DO_AUTO_NEG;
-               adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT;
-               break;
-       case IFM_1000_LX:
-       case IFM_1000_SX:
-       case IFM_1000_T:
-               adapter->hw.mac.autoneg = DO_AUTO_NEG;
-               adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL;
-               break;
-       case IFM_100_TX:
-               adapter->hw.mac.autoneg = FALSE;
-               adapter->hw.phy.autoneg_advertised = 0;
-               if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
-                       adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_FULL;
-               else
-                       adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_HALF;
-               break;
-       case IFM_10_T:
-               adapter->hw.mac.autoneg = FALSE;
-               adapter->hw.phy.autoneg_advertised = 0;
-               if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
-                       adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_FULL;
-               else
-                       adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_HALF;
-               break;
-       default:
-               device_printf(adapter->dev, "Unsupported media type\n");
-       }
-
-       igb_init_locked(adapter);
-       IGB_CORE_UNLOCK(adapter);
-
-       return (0);
-}
-
-
-/*********************************************************************
- *
- *  This routine maps the mbufs to Advanced TX descriptors.
- *  used by the 82575 adapter.
- *  
- **********************************************************************/
-
-static int
-igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
-{
-       struct adapter          *adapter = txr->adapter;
-       bus_dma_segment_t       segs[IGB_MAX_SCATTER];
-       bus_dmamap_t            map;
-       struct igb_tx_buffer    *tx_buffer, *tx_buffer_mapped;
-       union e1000_adv_tx_desc *txd = NULL;
-       struct mbuf             *m_head;
-       u32                     olinfo_status = 0, cmd_type_len = 0;
-       int                     nsegs, i, j, error, first, last = 0;
-       u32                     hdrlen = 0;
-
-       m_head = *m_headp;
-
-
-       /* Set basic descriptor constants */
-       cmd_type_len |= E1000_ADVTXD_DTYP_DATA;
-       cmd_type_len |= E1000_ADVTXD_DCMD_IFCS | E1000_ADVTXD_DCMD_DEXT;
-       if (m_head->m_flags & M_VLANTAG)
-               cmd_type_len |= E1000_ADVTXD_DCMD_VLE;
-
-       /*
-         * Map the packet for DMA.
-        *
-        * Capture the first descriptor index,
-        * this descriptor will have the index
-        * of the EOP which is the only one that
-        * now gets a DONE bit writeback.
-        */
-       first = txr->next_avail_desc;
-       tx_buffer = &txr->tx_buffers[first];
-       tx_buffer_mapped = tx_buffer;
-       map = tx_buffer->map;
-
-       error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
-           *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
-       if (error == EFBIG) {
-               struct mbuf *m;
-
-               m = m_defrag(*m_headp, M_DONTWAIT);
-               if (m == NULL) {
-                       adapter->mbuf_defrag_failed++;
-                       m_freem(*m_headp);
-                       *m_headp = NULL;
-                       return (ENOBUFS);
-               }
-               *m_headp = m;
-
-               /* Try it again */
-               error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
-                   *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
-               if (error == ENOMEM) {
-                       adapter->no_tx_dma_setup++;
-                       return (error);
-               } else if (error != 0) {
-                       adapter->no_tx_dma_setup++;
-                       m_freem(*m_headp);
-                       *m_headp = NULL;
-                       return (error);
-               }
-       } else if (error == ENOMEM) {
-               adapter->no_tx_dma_setup++;
-               return (error);
-       } else if (error != 0) {
-               adapter->no_tx_dma_setup++;
-               m_freem(*m_headp);
-               *m_headp = NULL;
-               return (error);
-       }
-
-       /* Check again to be sure we have enough descriptors */
-        if (nsegs > (txr->tx_avail - 2)) {
-                txr->no_desc_avail++;
-               bus_dmamap_unload(txr->txtag, map);
-               return (ENOBUFS);
-        }
-       m_head = *m_headp;
-
-        /*
-         * Set up the context descriptor:
-         * used when any hardware offload is done.
-        * This includes CSUM, VLAN, and TSO. It
-        * will use the first descriptor.
-         */
-        if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
-               if (igb_tso_setup(txr, m_head, &hdrlen)) {
-                       cmd_type_len |= E1000_ADVTXD_DCMD_TSE;
-                       olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
-                       olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
-               } else
-                       return (ENXIO); 
-       } else if (igb_tx_ctx_setup(txr, m_head))
-               olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
-
-       /* Calculate payload length */
-       olinfo_status |= ((m_head->m_pkthdr.len - hdrlen)
-           << E1000_ADVTXD_PAYLEN_SHIFT);
-
-       /* 82575 needs the queue index added */
-       if (adapter->hw.mac.type == e1000_82575)
-               olinfo_status |= txr->me << 4;
-
-       /* Set up our transmit descriptors */
-       i = txr->next_avail_desc;
-       for (j = 0; j < nsegs; j++) {
-               bus_size_t seg_len;
-               bus_addr_t seg_addr;
-
-               tx_buffer = &txr->tx_buffers[i];
-               txd = (union e1000_adv_tx_desc *)&txr->tx_base[i];
-               seg_addr = segs[j].ds_addr;
-               seg_len  = segs[j].ds_len;
-
-               txd->read.buffer_addr = htole64(seg_addr);
-               txd->read.cmd_type_len = htole32(cmd_type_len | seg_len);
-               txd->read.olinfo_status = htole32(olinfo_status);
-               last = i;
-               if (++i == adapter->num_tx_desc)
-                       i = 0;
-               tx_buffer->m_head = NULL;
-               tx_buffer->next_eop = -1;
-       }
-
-       txr->next_avail_desc = i;
-       txr->tx_avail -= nsegs;
-
-        tx_buffer->m_head = m_head;
-       tx_buffer_mapped->map = tx_buffer->map;
-       tx_buffer->map = map;
-        bus_dmamap_sync(txr->txtag, map, BUS_DMASYNC_PREWRITE);
-
-        /*
-         * Last Descriptor of Packet
-        * needs End Of Packet (EOP)
-        * and Report Status (RS)
-         */
-        txd->read.cmd_type_len |=
-           htole32(E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS);
-       /*
-        * Keep track in the first buffer which
-        * descriptor will be written back
-        */
-       tx_buffer = &txr->tx_buffers[first];
-       tx_buffer->next_eop = last;
-       txr->watchdog_time = ticks;
-
-       /*
-        * Advance the Transmit Descriptor Tail (TDT), this tells the E1000
-        * that this frame is available to transmit.
-        */
-       bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
-           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-       E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), i);
-       ++txr->tx_packets;
-
-       return (0);
-
-}
-
-static void
-igb_set_promisc(struct adapter *adapter)
-{
-       struct ifnet    *ifp = adapter->ifp;
-       struct e1000_hw *hw = &adapter->hw;
-       u32             reg;
-
-       if (adapter->vf_ifp) {
-               e1000_promisc_set_vf(hw, e1000_promisc_enabled);
-               return;
-       }
-
-       reg = E1000_READ_REG(hw, E1000_RCTL);
-       if (ifp->if_flags & IFF_PROMISC) {
-               reg |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
-               E1000_WRITE_REG(hw, E1000_RCTL, reg);
-       } else if (ifp->if_flags & IFF_ALLMULTI) {
-               reg |= E1000_RCTL_MPE;
-               reg &= ~E1000_RCTL_UPE;
-               E1000_WRITE_REG(hw, E1000_RCTL, reg);
-       }
-}
-
-static void
-igb_disable_promisc(struct adapter *adapter)
-{
-       struct e1000_hw *hw = &adapter->hw;
-       u32             reg;
-
-       if (adapter->vf_ifp) {
-               e1000_promisc_set_vf(hw, e1000_promisc_disabled);
-               return;
-       }
-       reg = E1000_READ_REG(hw, E1000_RCTL);
-       reg &=  (~E1000_RCTL_UPE);
-       reg &=  (~E1000_RCTL_MPE);
-       E1000_WRITE_REG(hw, E1000_RCTL, reg);
-}
-
-
-/*********************************************************************
- *  Multicast Update
- *
- *  This routine is called whenever multicast address list is updated.
- *
- **********************************************************************/
-
-static void
-igb_set_multi(struct adapter *adapter)
-{
-       struct ifnet    *ifp = adapter->ifp;
-       struct ifmultiaddr *ifma;
-       u32 reg_rctl = 0;
-       u8  *mta;
-
-       int mcnt = 0;
-
-       IOCTL_DEBUGOUT("igb_set_multi: begin");
-
-       mta = adapter->mta;
-       bzero(mta, sizeof(uint8_t) * ETH_ADDR_LEN *
-           MAX_NUM_MULTICAST_ADDRESSES);
-
-#if __FreeBSD_version < 800000
-       IF_ADDR_LOCK(ifp);
-#else
-       if_maddr_rlock(ifp);
-#endif
-       TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-               if (ifma->ifma_addr->sa_family != AF_LINK)
-                       continue;
-
-               if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
-                       break;
-
-               bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
-                   &mta[mcnt * ETH_ADDR_LEN], ETH_ADDR_LEN);
-               mcnt++;
-       }
-#if __FreeBSD_version < 800000
-       IF_ADDR_UNLOCK(ifp);
-#else
-       if_maddr_runlock(ifp);
-#endif
-
-       if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) {
-               reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
-               reg_rctl |= E1000_RCTL_MPE;
-               E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
-       } else
-               e1000_update_mc_addr_list(&adapter->hw, mta, mcnt);
-}
-
-
-/*********************************************************************
- *  Timer routine:
- *     This routine checks for link status,
- *     updates statistics, and does the watchdog.
- *
- **********************************************************************/
-
-static void
-igb_local_timer(void *arg)
-{
-       struct adapter          *adapter = arg;
-       device_t                dev = adapter->dev;
-       struct tx_ring          *txr = adapter->tx_rings;
-
-
-       IGB_CORE_LOCK_ASSERT(adapter);
-
-       igb_update_link_status(adapter);
-       igb_update_stats_counters(adapter);
-
-       /* 
-       ** If flow control has paused us since last checking
-       ** it invalidates the watchdog timing, so dont run it.
-       */
-       if (adapter->pause_frames) {
-               adapter->pause_frames = 0;
-               goto out;
-       }
-
-        /*
-        ** Watchdog: check for time since any descriptor was cleaned
-        */
-       for (int i = 0; i < adapter->num_queues; i++, txr++)
-               if (txr->queue_status == IGB_QUEUE_HUNG) 
-                       goto timeout;
-out:
-       callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
-#ifndef DEVICE_POLLING
-       /* Schedule all queue interrupts - deadlock protection */
-       E1000_WRITE_REG(&adapter->hw, E1000_EICS, adapter->que_mask);
-#endif
-       return;
-
-timeout:
-       device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
-       device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", txr->me,
-            E1000_READ_REG(&adapter->hw, E1000_TDH(txr->me)),
-            E1000_READ_REG(&adapter->hw, E1000_TDT(txr->me)));
-       device_printf(dev,"TX(%d) desc avail = %d,"
-            "Next TX to Clean = %d\n",
-            txr->me, txr->tx_avail, txr->next_to_clean);
-       adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-       adapter->watchdog_events++;
-       igb_init_locked(adapter);
-}
-
-static void
-igb_update_link_status(struct adapter *adapter)
-{
-       struct e1000_hw *hw = &adapter->hw;
-       struct ifnet *ifp = adapter->ifp;
-       device_t dev = adapter->dev;
-       struct tx_ring *txr = adapter->tx_rings;
-       u32 link_check, thstat, ctrl;
-
-       link_check = thstat = ctrl = 0;
-
-       /* Get the cached link value or read for real */
-        switch (hw->phy.media_type) {
-        case e1000_media_type_copper:
-                if (hw->mac.get_link_status) {
-                       /* Do the work to read phy */
-                        e1000_check_for_link(hw);
-                        link_check = !hw->mac.get_link_status;
-                } else
-                        link_check = TRUE;
-                break;
-        case e1000_media_type_fiber:
-                e1000_check_for_link(hw);
-                link_check = (E1000_READ_REG(hw, E1000_STATUS) &
-                                 E1000_STATUS_LU);
-                break;
-        case e1000_media_type_internal_serdes:
-                e1000_check_for_link(hw);
-                link_check = adapter->hw.mac.serdes_has_link;
-                break;
-       /* VF device is type_unknown */
-        case e1000_media_type_unknown:
-                e1000_check_for_link(hw);
-               link_check = !hw->mac.get_link_status;
-               /* Fall thru */
-        default:
-                break;
-        }
-
-       /* Check for thermal downshift or shutdown */
-       if (hw->mac.type == e1000_i350) {
-               thstat = E1000_READ_REG(hw, E1000_THSTAT);
-               ctrl = E1000_READ_REG(hw, E1000_CTRL_EXT);
-       }
-
-       /* Now we check if a transition has happened */
-       if (link_check && (adapter->link_active == 0)) {
-               e1000_get_speed_and_duplex(&adapter->hw, 
-                   &adapter->link_speed, &adapter->link_duplex);
-               if (bootverbose)
-                       device_printf(dev, "Link is up %d Mbps %s\n",
-                           adapter->link_speed,
-                           ((adapter->link_duplex == FULL_DUPLEX) ?
-                           "Full Duplex" : "Half Duplex"));
-               adapter->link_active = 1;
-               ifp->if_baudrate = adapter->link_speed * 1000000;
-               if ((ctrl & E1000_CTRL_EXT_LINK_MODE_GMII) &&
-                   (thstat & E1000_THSTAT_LINK_THROTTLE))
-                       device_printf(dev, "Link: thermal downshift\n");
-               /* This can sleep */
-               if_link_state_change(ifp, LINK_STATE_UP);
-       } else if (!link_check && (adapter->link_active == 1)) {
-               ifp->if_baudrate = adapter->link_speed = 0;
-               adapter->link_duplex = 0;
-               if (bootverbose)
-                       device_printf(dev, "Link is Down\n");
-               if ((ctrl & E1000_CTRL_EXT_LINK_MODE_GMII) &&
-                   (thstat & E1000_THSTAT_PWR_DOWN))
-                       device_printf(dev, "Link: thermal shutdown\n");
-               adapter->link_active = 0;
-               /* This can sleep */
-               if_link_state_change(ifp, LINK_STATE_DOWN);
-               /* Turn off watchdogs */
-               for (int i = 0; i < adapter->num_queues; i++, txr++)
-                       txr->queue_status = IGB_QUEUE_IDLE;
-       }
-}
-
-/*********************************************************************
- *
- *  This routine disables all traffic on the adapter by issuing a
- *  global reset on the MAC and deallocates TX/RX buffers.
- *
- **********************************************************************/
-
-static void
-igb_stop(void *arg)
-{
-       struct adapter  *adapter = arg;
-       struct ifnet    *ifp = adapter->ifp;
-       struct tx_ring *txr = adapter->tx_rings;
-
-       IGB_CORE_LOCK_ASSERT(adapter);
-
-       INIT_DEBUGOUT("igb_stop: begin");
-
-       igb_disable_intr(adapter);
-
-       callout_stop(&adapter->timer);
-
-       /* Tell the stack that the interface is no longer active */
-       ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
-       /* Unarm watchdog timer. */
-       for (int i = 0; i < adapter->num_queues; i++, txr++) {
-               IGB_TX_LOCK(txr);
-               txr->queue_status = IGB_QUEUE_IDLE;
-               IGB_TX_UNLOCK(txr);
-       }
-
-       e1000_reset_hw(&adapter->hw);
-       E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0);
-
-       e1000_led_off(&adapter->hw);
-       e1000_cleanup_led(&adapter->hw);
-}
-
-
-/*********************************************************************
- *
- *  Determine hardware revision.
- *
- **********************************************************************/
-static void
-igb_identify_hardware(struct adapter *adapter)
-{
-       device_t dev = adapter->dev;
-
-       /* Make sure our PCI config space has the necessary stuff set */
-       adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);
-       if (!((adapter->hw.bus.pci_cmd_word & PCIM_CMD_BUSMASTEREN) &&
-           (adapter->hw.bus.pci_cmd_word & PCIM_CMD_MEMEN))) {
-               INIT_DEBUGOUT("Memory Access and/or Bus Master "
-                   "bits were not set!\n");
-               adapter->hw.bus.pci_cmd_word |=
-               (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
-               pci_write_config(dev, PCIR_COMMAND,
-                   adapter->hw.bus.pci_cmd_word, 2);
-       }
-
-       /* Save off the information about this board */
-       adapter->hw.vendor_id = pci_get_vendor(dev);
-       adapter->hw.device_id = pci_get_device(dev);
-       adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1);
-       adapter->hw.subsystem_vendor_id =
-           pci_read_config(dev, PCIR_SUBVEND_0, 2);
-       adapter->hw.subsystem_device_id =
-           pci_read_config(dev, PCIR_SUBDEV_0, 2);
-
-       /* Set MAC type early for PCI setup */
-       e1000_set_mac_type(&adapter->hw);
-
-       /* Are we a VF device? */
-       if ((adapter->hw.mac.type == e1000_vfadapt) ||
-           (adapter->hw.mac.type == e1000_vfadapt_i350))
-               adapter->vf_ifp = 1;
-       else
-               adapter->vf_ifp = 0;
-}
-
-static int
-igb_allocate_pci_resources(struct adapter *adapter)
-{
-       device_t        dev = adapter->dev;
-       int             rid;
-
-       rid = PCIR_BAR(0);
-       adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
-           &rid, RF_ACTIVE);
-       if (adapter->pci_mem == NULL) {
-               device_printf(dev, "Unable to allocate bus resource: memory\n");
-               return (ENXIO);
-       }
-       adapter->osdep.mem_bus_space_tag =
-           rman_get_bustag(adapter->pci_mem);
-       adapter->osdep.mem_bus_space_handle =
-           rman_get_bushandle(adapter->pci_mem);
-       adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle;
-
-       adapter->num_queues = 1; /* Defaults for Legacy or MSI */
-
-       /* This will setup either MSI/X or MSI */
-       adapter->msix = igb_setup_msix(adapter);
-       adapter->hw.back = &adapter->osdep;
-
-       return (0);
-}
-
-/*********************************************************************
- *
- *  Setup the Legacy or MSI Interrupt handler
- *
- **********************************************************************/
-static int
-igb_allocate_legacy(struct adapter *adapter)
-{
-       device_t                dev = adapter->dev;
-       struct igb_queue        *que = adapter->queues;
-       int                     error, rid = 0;
-
-       /* Turn off all interrupts */
-       E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff);
-
-       /* MSI RID is 1 */
-       if (adapter->msix == 1)
-               rid = 1;
-
-       /* We allocate a single interrupt resource */
-       adapter->res = bus_alloc_resource_any(dev,
-           SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
-       if (adapter->res == NULL) {
-               device_printf(dev, "Unable to allocate bus resource: "
-                   "interrupt\n");
-               return (ENXIO);
-       }
-
-       /*
-        * Try allocating a fast interrupt and the associated deferred
-        * processing contexts.
-        */
-       TASK_INIT(&que->que_task, 0, igb_handle_que, que);
-       /* Make tasklet for deferred link handling */
-       TASK_INIT(&adapter->link_task, 0, igb_handle_link, adapter);
-       que->tq = taskqueue_create_fast("igb_taskq", M_NOWAIT,
-           taskqueue_thread_enqueue, &que->tq);
-       taskqueue_start_threads(&que->tq, 1, PI_NET, "%s taskq",
-           device_get_nameunit(adapter->dev));
-       if ((error = bus_setup_intr(dev, adapter->res,
-           INTR_TYPE_NET | INTR_MPSAFE, igb_irq_fast, NULL,
-           adapter, &adapter->tag)) != 0) {
-               device_printf(dev, "Failed to register fast interrupt "
-                           "handler: %d\n", error);
-               taskqueue_free(que->tq);
-               que->tq = NULL;
-               return (error);
-       }
-
-       return (0);
-}
-
-
-/*********************************************************************
- *
- *  Setup the MSIX Queue Interrupt handlers: 
- *
- **********************************************************************/
-static int
-igb_allocate_msix(struct adapter *adapter)
-{
-       device_t                dev = adapter->dev;
-       struct igb_queue        *que = adapter->queues;
-       int                     error, rid, vector = 0;
-
-
-       for (int i = 0; i < adapter->num_queues; i++, vector++, que++) {
-               rid = vector +1;
-               que->res = bus_alloc_resource_any(dev,
-                   SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
-               if (que->res == NULL) {
-                       device_printf(dev,
-                           "Unable to allocate bus resource: "
-                           "MSIX Queue Interrupt\n");
-                       return (ENXIO);
-               }
-               error = bus_setup_intr(dev, que->res,
-                   INTR_TYPE_NET | INTR_MPSAFE, NULL,
-                   igb_msix_que, que, &que->tag);
-               if (error) {
-                       que->res = NULL;
-                       device_printf(dev, "Failed to register Queue handler");
-                       return (error);
-               }
-#if __FreeBSD_version >= 800504
-               bus_describe_intr(dev, que->res, que->tag, "que %d", i);
-#endif
-               que->msix = vector;
-               if (adapter->hw.mac.type == e1000_82575)
-                       que->eims = E1000_EICR_TX_QUEUE0 << i;
-               else
-                       que->eims = 1 << vector;
-               /*
-               ** Bind the msix vector, and thus the
-               ** rings to the corresponding cpu.
-               */
-               if (adapter->num_queues > 1)
-                       bus_bind_intr(dev, que->res, i);
-               /* Make tasklet for deferred handling */
-               TASK_INIT(&que->que_task, 0, igb_handle_que, que);
-               que->tq = taskqueue_create_fast("igb_que", M_NOWAIT,
-                   taskqueue_thread_enqueue, &que->tq);
-               taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que",
-                   device_get_nameunit(adapter->dev));
-       }
-
-       /* And Link */
-       rid = vector + 1;
-       adapter->res = bus_alloc_resource_any(dev,
-           SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
-       if (adapter->res == NULL) {
-               device_printf(dev,
-                   "Unable to allocate bus resource: "
-                   "MSIX Link Interrupt\n");
-               return (ENXIO);
-       }
-       if ((error = bus_setup_intr(dev, adapter->res,
-           INTR_TYPE_NET | INTR_MPSAFE, NULL,
-           igb_msix_link, adapter, &adapter->tag)) != 0) {
-               device_printf(dev, "Failed to register Link handler");
-               return (error);
-       }
-#if __FreeBSD_version >= 800504
-       bus_describe_intr(dev, adapter->res, adapter->tag, "link");
-#endif
-       adapter->linkvec = vector;
-
-       return (0);
-}
-
-
-static void
-igb_configure_queues(struct adapter *adapter)
-{
-       struct  e1000_hw        *hw = &adapter->hw;
-       struct  igb_queue       *que;
-       u32                     tmp, ivar = 0, newitr = 0;
-
-       /* First turn on RSS capability */
-       if (adapter->hw.mac.type != e1000_82575)
-               E1000_WRITE_REG(hw, E1000_GPIE,
-                   E1000_GPIE_MSIX_MODE | E1000_GPIE_EIAME |
-                   E1000_GPIE_PBA | E1000_GPIE_NSICR);
-
-       /* Turn on MSIX */
-       switch (adapter->hw.mac.type) {
-       case e1000_82580:
-       case e1000_i350:
-       case e1000_vfadapt:
-       case e1000_vfadapt_i350:
-               /* RX entries */
-               for (int i = 0; i < adapter->num_queues; i++) {
-                       u32 index = i >> 1;
-                       ivar = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index);
-                       que = &adapter->queues[i];
-                       if (i & 1) {
-                               ivar &= 0xFF00FFFF;
-                               ivar |= (que->msix | E1000_IVAR_VALID) << 16;
-                       } else {
-                               ivar &= 0xFFFFFF00;
-                               ivar |= que->msix | E1000_IVAR_VALID;
-                       }
-                       E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
-               }
-               /* TX entries */
-               for (int i = 0; i < adapter->num_queues; i++) {
-                       u32 index = i >> 1;
-                       ivar = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index);
-                       que = &adapter->queues[i];
-                       if (i & 1) {
-                               ivar &= 0x00FFFFFF;
-                               ivar |= (que->msix | E1000_IVAR_VALID) << 24;
-                       } else {
-                               ivar &= 0xFFFF00FF;
-                               ivar |= (que->msix | E1000_IVAR_VALID) << 8;
-                       }
-                       E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
-                       adapter->que_mask |= que->eims;
-               }
-
-               /* And for the link interrupt */
-               ivar = (adapter->linkvec | E1000_IVAR_VALID) << 8;
-               adapter->link_mask = 1 << adapter->linkvec;
-               E1000_WRITE_REG(hw, E1000_IVAR_MISC, ivar);
-               break;
-       case e1000_82576:
-               /* RX entries */
-               for (int i = 0; i < adapter->num_queues; i++) {
-                       u32 index = i & 0x7; /* Each IVAR has two entries */
-                       ivar = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index);
-                       que = &adapter->queues[i];
-                       if (i < 8) {
-                               ivar &= 0xFFFFFF00;
-                               ivar |= que->msix | E1000_IVAR_VALID;
-                       } else {
-                               ivar &= 0xFF00FFFF;
-                               ivar |= (que->msix | E1000_IVAR_VALID) << 16;
-                       }
-                       E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
-                       adapter->que_mask |= que->eims;
-               }
-               /* TX entries */
-               for (int i = 0; i < adapter->num_queues; i++) {
-                       u32 index = i & 0x7; /* Each IVAR has two entries */
-                       ivar = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index);
-                       que = &adapter->queues[i];
-                       if (i < 8) {
-                               ivar &= 0xFFFF00FF;
-                               ivar |= (que->msix | E1000_IVAR_VALID) << 8;
-                       } else {
-                               ivar &= 0x00FFFFFF;
-                               ivar |= (que->msix | E1000_IVAR_VALID) << 24;
-                       }
-                       E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
-                       adapter->que_mask |= que->eims;
-               }
-
-               /* And for the link interrupt */
-               ivar = (adapter->linkvec | E1000_IVAR_VALID) << 8;
-               adapter->link_mask = 1 << adapter->linkvec;
-               E1000_WRITE_REG(hw, E1000_IVAR_MISC, ivar);
-               break;
-
-       case e1000_82575:
-                /* enable MSI-X support*/
-               tmp = E1000_READ_REG(hw, E1000_CTRL_EXT);
-                tmp |= E1000_CTRL_EXT_PBA_CLR;
-                /* Auto-Mask interrupts upon ICR read. */
-                tmp |= E1000_CTRL_EXT_EIAME;
-                tmp |= E1000_CTRL_EXT_IRCA;
-                E1000_WRITE_REG(hw, E1000_CTRL_EXT, tmp);
-
-               /* Queues */
-               for (int i = 0; i < adapter->num_queues; i++) {
-                       que = &adapter->queues[i];
-                       tmp = E1000_EICR_RX_QUEUE0 << i;
-                       tmp |= E1000_EICR_TX_QUEUE0 << i;
-                       que->eims = tmp;
-                       E1000_WRITE_REG_ARRAY(hw, E1000_MSIXBM(0),
-                           i, que->eims);
-                       adapter->que_mask |= que->eims;
-               }
-
-               /* Link */
-               E1000_WRITE_REG(hw, E1000_MSIXBM(adapter->linkvec),
-                   E1000_EIMS_OTHER);
-               adapter->link_mask |= E1000_EIMS_OTHER;
-       default:
-               break;
-       }
-
-       /* Set the starting interrupt rate */
-       if (igb_max_interrupt_rate > 0)
-               newitr = (4000000 / igb_max_interrupt_rate) & 0x7FFC;
-
-        if (hw->mac.type == e1000_82575)
-                newitr |= newitr << 16;
-        else
-                newitr |= E1000_EITR_CNT_IGNR;
-
-       for (int i = 0; i < adapter->num_queues; i++) {
-               que = &adapter->queues[i];
-               E1000_WRITE_REG(hw, E1000_EITR(que->msix), newitr);
-       }
-
-       return;
-}
-
-
-static void
-igb_free_pci_resources(struct adapter *adapter)
-{
-       struct          igb_queue *que = adapter->queues;
-       device_t        dev = adapter->dev;
-       int             rid;
-
-       /*
-       ** There is a slight possibility of a failure mode
-       ** in attach that will result in entering this function
-       ** before interrupt resources have been initialized, and
-       ** in that case we do not want to execute the loops below
-       ** We can detect this reliably by the state of the adapter
-       ** res pointer.
-       */
-       if (adapter->res == NULL)
-               goto mem;
-
-       /*
-        * First release all the interrupt resources:
-        */
-       for (int i = 0; i < adapter->num_queues; i++, que++) {
-               rid = que->msix + 1;
-               if (que->tag != NULL) {
-                       bus_teardown_intr(dev, que->res, que->tag);
-                       que->tag = NULL;
-               }
-               if (que->res != NULL)
-                       bus_release_resource(dev,
-                           SYS_RES_IRQ, rid, que->res);
-       }
-
-       /* Clean the Legacy or Link interrupt last */
-       if (adapter->linkvec) /* we are doing MSIX */
-               rid = adapter->linkvec + 1;
-       else
-               (adapter->msix != 0) ? (rid = 1):(rid = 0);
-
-       if (adapter->tag != NULL) {
-               bus_teardown_intr(dev, adapter->res, adapter->tag);
-               adapter->tag = NULL;
-       }
-       if (adapter->res != NULL)
-               bus_release_resource(dev, SYS_RES_IRQ, rid, adapter->res);
-
-mem:
-       if (adapter->msix)
-               pci_release_msi(dev);
-
-       if (adapter->msix_mem != NULL)
-               bus_release_resource(dev, SYS_RES_MEMORY,
-                   PCIR_BAR(IGB_MSIX_BAR), adapter->msix_mem);
-
-       if (adapter->pci_mem != NULL)
-               bus_release_resource(dev, SYS_RES_MEMORY,
-                   PCIR_BAR(0), adapter->pci_mem);
-
-}
-
-/*
- * Setup Either MSI/X or MSI
- */
-static int
-igb_setup_msix(struct adapter *adapter)
-{
-       device_t dev = adapter->dev;
-       int rid, want, queues, msgs;
-
-       /* tuneable override */
-       if (igb_enable_msix == 0)
-               goto msi;
-
-       /* First try MSI/X */
-       rid = PCIR_BAR(IGB_MSIX_BAR);
-       adapter->msix_mem = bus_alloc_resource_any(dev,
-           SYS_RES_MEMORY, &rid, RF_ACTIVE);
-               if (!adapter->msix_mem) {
-               /* May not be enabled */
-               device_printf(adapter->dev,
-                   "Unable to map MSIX table \n");
-               goto msi;
-       }
-
-       msgs = pci_msix_count(dev); 
-       if (msgs == 0) { /* system has msix disabled */
-               bus_release_resource(dev, SYS_RES_MEMORY,
-                   PCIR_BAR(IGB_MSIX_BAR), adapter->msix_mem);
-               adapter->msix_mem = NULL;
-               goto msi;
-       }
-
-       /* Figure out a reasonable auto config value */
-       queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus;
-
-       /* Manual override */
-       if (igb_num_queues != 0)
-               queues = igb_num_queues;
-       if (queues > 8)  /* max queues */
-               queues = 8;
-
-       /* Can have max of 4 queues on 82575 */
-       if ((adapter->hw.mac.type == e1000_82575) && (queues > 4))
-               queues = 4;
-
-       /* Limit the VF devices to one queue */
-       if (adapter->vf_ifp)
-               queues = 1;
-
-       /*
-       ** One vector (RX/TX pair) per queue
-       ** plus an additional for Link interrupt
-       */
-       want = queues + 1;
-       if (msgs >= want)
-               msgs = want;
-       else {
-                       device_printf(adapter->dev,
-                   "MSIX Configuration Problem, "
-                   "%d vectors configured, but %d queues wanted!\n",
-                   msgs, want);
-               return (ENXIO);
-       }
-       if ((msgs) && pci_alloc_msix(dev, &msgs) == 0) {
-                       device_printf(adapter->dev,
-                   "Using MSIX interrupts with %d vectors\n", msgs);
-               adapter->num_queues = queues;
-               return (msgs);
-       }
-msi:
-               msgs = pci_msi_count(dev);
-               if (msgs == 1 && pci_alloc_msi(dev, &msgs) == 0)
-                       device_printf(adapter->dev,"Using MSI interrupt\n");
-       return (msgs);
-}
-
-/*********************************************************************
- *
- *  Set up an fresh starting state
- *
- **********************************************************************/
-static void
-igb_reset(struct adapter *adapter)
-{
-       device_t        dev = adapter->dev;
-       struct e1000_hw *hw = &adapter->hw;
-       struct e1000_fc_info *fc = &hw->fc;
-       struct ifnet    *ifp = adapter->ifp;
-       u32             pba = 0;
-       u16             hwm;
-
-       INIT_DEBUGOUT("igb_reset: begin");
-
-       /* Let the firmware know the OS is in control */
-       igb_get_hw_control(adapter);
-
-       /*
-        * Packet Buffer Allocation (PBA)
-        * Writing PBA sets the receive portion of the buffer
-        * the remainder is used for the transmit buffer.
-        */
-       switch (hw->mac.type) {
-       case e1000_82575:
-               pba = E1000_PBA_32K;
-               break;
-       case e1000_82576:
-       case e1000_vfadapt:
-               pba = E1000_READ_REG(hw, E1000_RXPBS);
-               pba &= E1000_RXPBS_SIZE_MASK_82576;
-               break;
-       case e1000_82580:
-       case e1000_i350:
-       case e1000_vfadapt_i350:
-               pba = E1000_READ_REG(hw, E1000_RXPBS);
-               pba = e1000_rxpbs_adjust_82580(pba);
-               break;
-               pba = E1000_PBA_35K;
-       default:
-               break;
-       }
-
-       /* Special needs in case of Jumbo frames */
-       if ((hw->mac.type == e1000_82575) && (ifp->if_mtu > ETHERMTU)) {
-               u32 tx_space, min_tx, min_rx;
-               pba = E1000_READ_REG(hw, E1000_PBA);
-               tx_space = pba >> 16;
-               pba &= 0xffff;
-               min_tx = (adapter->max_frame_size +
-                   sizeof(struct e1000_tx_desc) - ETHERNET_FCS_SIZE) * 2;
-               min_tx = roundup2(min_tx, 1024);
-               min_tx >>= 10;
-                min_rx = adapter->max_frame_size;
-                min_rx = roundup2(min_rx, 1024);
-                min_rx >>= 10;
-               if (tx_space < min_tx &&
-                   ((min_tx - tx_space) < pba)) {
-                       pba = pba - (min_tx - tx_space);
-                       /*
-                         * if short on rx space, rx wins
-                         * and must trump tx adjustment
-                        */
-                        if (pba < min_rx)
-                                pba = min_rx;
-               }
-               E1000_WRITE_REG(hw, E1000_PBA, pba);
-       }
-
-       INIT_DEBUGOUT1("igb_init: pba=%dK",pba);
-
-       /*
-        * These parameters control the automatic generation (Tx) and
-        * response (Rx) to Ethernet PAUSE frames.
-        * - High water mark should allow for at least two frames to be
-        *   received after sending an XOFF.
-        * - Low water mark works best when it is very near the high water mark.
-        *   This allows the receiver to restart by sending XON when it has
-        *   drained a bit.
-        */
-       hwm = min(((pba << 10) * 9 / 10),
-           ((pba << 10) - 2 * adapter->max_frame_size));
-
-       if (hw->mac.type < e1000_82576) {
-               fc->high_water = hwm & 0xFFF8;  /* 8-byte granularity */
-               fc->low_water = fc->high_water - 8;
-       } else {
-               fc->high_water = hwm & 0xFFF0;  /* 16-byte granularity */
-               fc->low_water = fc->high_water - 16;
-       }
-
-       fc->pause_time = IGB_FC_PAUSE_TIME;
-       fc->send_xon = TRUE;
-
-       /* Issue a global reset */
-       e1000_reset_hw(hw);
-       E1000_WRITE_REG(hw, E1000_WUC, 0);
-
-       if (e1000_init_hw(hw) < 0)
-               device_printf(dev, "Hardware Initialization Failed\n");
-
-       /* Setup DMA Coalescing */
-       if ((hw->mac.type == e1000_i350) &&
-           (adapter->dma_coalesce == TRUE)) {
-               u32 reg;
-
-               hwm = (pba - 4) << 10;
-               reg = (((pba-6) << E1000_DMACR_DMACTHR_SHIFT)
-                   & E1000_DMACR_DMACTHR_MASK);
-
-               /* transition to L0x or L1 if available..*/
-               reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK);
-
-               /* timer = +-1000 usec in 32usec intervals */
-               reg |= (1000 >> 5);
-               E1000_WRITE_REG(hw, E1000_DMACR, reg);
-
-               /* No lower threshold */
-               E1000_WRITE_REG(hw, E1000_DMCRTRH, 0);
-
-               /* set hwm to PBA -  2 * max frame size */
-               E1000_WRITE_REG(hw, E1000_FCRTC, hwm);
-
-               /* Set the interval before transition */
-               reg = E1000_READ_REG(hw, E1000_DMCTLX);
-               reg |= 0x800000FF; /* 255 usec */
-               E1000_WRITE_REG(hw, E1000_DMCTLX, reg);
-
-               /* free space in tx packet buffer to wake from DMA coal */
-               E1000_WRITE_REG(hw, E1000_DMCTXTH,
-                   (20480 - (2 * adapter->max_frame_size)) >> 6);
-
-               /* make low power state decision controlled by DMA coal */
-               reg = E1000_READ_REG(hw, E1000_PCIEMISC);
-               E1000_WRITE_REG(hw, E1000_PCIEMISC,
-                   reg | E1000_PCIEMISC_LX_DECISION);
-               device_printf(dev, "DMA Coalescing enabled\n");
-       }
-
-       E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
-       e1000_get_phy_info(hw);
-       e1000_check_for_link(hw);
-       return;
-}
-
-/*********************************************************************
- *
- *  Setup networking device structure and register an interface.
- *
- **********************************************************************/
-static int
-igb_setup_interface(device_t dev, struct adapter *adapter)
-{
-       struct ifnet   *ifp;
-
-       INIT_DEBUGOUT("igb_setup_interface: begin");
-
-       ifp = adapter->ifp = if_alloc(IFT_ETHER);
-       if (ifp == NULL) {
-               device_printf(dev, "can not allocate ifnet structure\n");
-               return (-1);
-       }
-       if_initname(ifp, device_get_name(dev), device_get_unit(dev));
-       ifp->if_mtu = ETHERMTU;
-       ifp->if_init =  igb_init;
-       ifp->if_softc = adapter;
-       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-       ifp->if_ioctl = igb_ioctl;
-       ifp->if_start = igb_start;
-#if __FreeBSD_version >= 800000
-       ifp->if_transmit = igb_mq_start;
-       ifp->if_qflush = igb_qflush;
-#endif
-       IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1);
-       ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1;
-       IFQ_SET_READY(&ifp->if_snd);
-
-       ether_ifattach(ifp, adapter->hw.mac.addr);
-
-       ifp->if_capabilities = ifp->if_capenable = 0;
-
-       ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
-       ifp->if_capabilities |= IFCAP_TSO4;
-       ifp->if_capabilities |= IFCAP_JUMBO_MTU;
-       ifp->if_capenable = ifp->if_capabilities;
-
-       /* Don't enable LRO by default */
-       ifp->if_capabilities |= IFCAP_LRO;
-
-#ifdef DEVICE_POLLING
-       ifp->if_capabilities |= IFCAP_POLLING;
-#endif
-
-       /*
-        * Tell the upper layer(s) we
-        * support full VLAN capability.
-        */
-       ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
-       ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
-       ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
-
-       /*
-       ** Dont turn this on by default, if vlans are
-       ** created on another pseudo device (eg. lagg)
-       ** then vlan events are not passed thru, breaking
-       ** operation, but with HW FILTER off it works. If
-       ** using vlans directly on the em driver you can
-       ** enable this and get full hardware tag filtering.
-       */
-       ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
-
-       /*
-        * Specify the media types supported by this adapter and register
-        * callbacks to update media and link information
-        */
-       ifmedia_init(&adapter->media, IFM_IMASK,
-           igb_media_change, igb_media_status);
-       if ((adapter->hw.phy.media_type == e1000_media_type_fiber) ||
-           (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) {
-               ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX | IFM_FDX, 
-                           0, NULL);
-               ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
-       } else {
-               ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL);
-               ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX,
-                           0, NULL);
-               ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX,
-                           0, NULL);
-               ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX,
-                           0, NULL);
-               if (adapter->hw.phy.type != e1000_phy_ife) {
-                       ifmedia_add(&adapter->media,
-                               IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
-                       ifmedia_add(&adapter->media,
-                               IFM_ETHER | IFM_1000_T, 0, NULL);
-               }
-       }
-       ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
-       ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
-       return (0);
-}
-
-
-/*
- * Manage DMA'able memory.
- */
-static void
-igb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
-       if (error)
-               return;
-       *(bus_addr_t *) arg = segs[0].ds_addr;
-}
-
-static int
-igb_dma_malloc(struct adapter *adapter, bus_size_t size,
-        struct igb_dma_alloc *dma, int mapflags)
-{
-       int error;
-
-       error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */
-                               IGB_DBA_ALIGN, 0,       /* alignment, bounds */
-                               BUS_SPACE_MAXADDR,      /* lowaddr */
-                               BUS_SPACE_MAXADDR,      /* highaddr */
-                               NULL, NULL,             /* filter, filterarg */
-                               size,                   /* maxsize */
-                               1,                      /* nsegments */
-                               size,                   /* maxsegsize */
-                               0,                      /* flags */
-                               NULL,                   /* lockfunc */
-                               NULL,                   /* lockarg */
-                               &dma->dma_tag);
-       if (error) {
-               device_printf(adapter->dev,
-                   "%s: bus_dma_tag_create failed: %d\n",
-                   __func__, error);
-               goto fail_0;
-       }
-
-       error = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr,
-           BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
-       if (error) {
-               device_printf(adapter->dev,
-                   "%s: bus_dmamem_alloc(%ju) failed: %d\n",
-                   __func__, (uintmax_t)size, error);
-               goto fail_2;
-       }
-
-       dma->dma_paddr = 0;
-       error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
-           size, igb_dmamap_cb, &dma->dma_paddr, mapflags | BUS_DMA_NOWAIT);
-       if (error || dma->dma_paddr == 0) {
-               device_printf(adapter->dev,
-                   "%s: bus_dmamap_load failed: %d\n",
-                   __func__, error);
-               goto fail_3;
-       }
-
-       return (0);
-
-fail_3:
-       bus_dmamap_unload(dma->dma_tag, dma->dma_map);
-fail_2:
-       bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
-       bus_dma_tag_destroy(dma->dma_tag);
-fail_0:
-       dma->dma_map = NULL;
-       dma->dma_tag = NULL;
-
-       return (error);
-}
-
-static void
-igb_dma_free(struct adapter *adapter, struct igb_dma_alloc *dma)
-{
-       if (dma->dma_tag == NULL)
-               return;
-       if (dma->dma_map != NULL) {
-               bus_dmamap_sync(dma->dma_tag, dma->dma_map,
-                   BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-               bus_dmamap_unload(dma->dma_tag, dma->dma_map);
-               bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
-               dma->dma_map = NULL;
-       }
-       bus_dma_tag_destroy(dma->dma_tag);
-       dma->dma_tag = NULL;
-}
-
-
-/*********************************************************************
- *
- *  Allocate memory for the transmit and receive rings, and then
- *  the descriptors associated with each, called only once at attach.
- *
- **********************************************************************/
-static int
-igb_allocate_queues(struct adapter *adapter)
-{
-       device_t dev = adapter->dev;
-       struct igb_queue        *que = NULL;
-       struct tx_ring          *txr = NULL;
-       struct rx_ring          *rxr = NULL;
-       int rsize, tsize, error = E1000_SUCCESS;
-       int txconf = 0, rxconf = 0;
-
-       /* First allocate the top level queue structs */
-       if (!(adapter->queues =
-           (struct igb_queue *) malloc(sizeof(struct igb_queue) *
-           adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
-               device_printf(dev, "Unable to allocate queue memory\n");
-               error = ENOMEM;
-               goto fail;
-       }
-
-       /* Next allocate the TX ring struct memory */
-       if (!(adapter->tx_rings =
-           (struct tx_ring *) malloc(sizeof(struct tx_ring) *
-           adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
-               device_printf(dev, "Unable to allocate TX ring memory\n");
-               error = ENOMEM;
-               goto tx_fail;
-       }
-
-       /* Now allocate the RX */
-       if (!(adapter->rx_rings =
-           (struct rx_ring *) malloc(sizeof(struct rx_ring) *
-           adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
-               device_printf(dev, "Unable to allocate RX ring memory\n");
-               error = ENOMEM;
-               goto rx_fail;
-       }
-
-       tsize = roundup2(adapter->num_tx_desc *
-           sizeof(union e1000_adv_tx_desc), IGB_DBA_ALIGN);
-       /*
-        * Now set up the TX queues, txconf is needed to handle the
-        * possibility that things fail midcourse and we need to
-        * undo memory gracefully
-        */ 
-       for (int i = 0; i < adapter->num_queues; i++, txconf++) {
-               /* Set up some basics */
-               txr = &adapter->tx_rings[i];
-               txr->adapter = adapter;
-               txr->me = i;
-
-               /* Initialize the TX lock */
-               snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)",
-                   device_get_nameunit(dev), txr->me);
-               mtx_init(&txr->tx_mtx, txr->mtx_name, NULL, MTX_DEF);
-
-               if (igb_dma_malloc(adapter, tsize,
-                       &txr->txdma, BUS_DMA_NOWAIT)) {
-                       device_printf(dev,
-                           "Unable to allocate TX Descriptor memory\n");
-                       error = ENOMEM;
-                       goto err_tx_desc;
-               }
-               txr->tx_base = (struct e1000_tx_desc *)txr->txdma.dma_vaddr;
-               bzero((void *)txr->tx_base, tsize);
-
-               /* Now allocate transmit buffers for the ring */
-               if (igb_allocate_transmit_buffers(txr)) {
-                       device_printf(dev,
-                           "Critical Failure setting up transmit buffers\n");
-                       error = ENOMEM;
-                       goto err_tx_desc;
-               }
-#if __FreeBSD_version >= 800000
-               /* Allocate a buf ring */
-               txr->br = buf_ring_alloc(IGB_BR_SIZE, M_DEVBUF,
-                   M_WAITOK, &txr->tx_mtx);
-#endif
-       }
-
-       /*
-        * Next the RX queues...
-        */ 
-       rsize = roundup2(adapter->num_rx_desc *
-           sizeof(union e1000_adv_rx_desc), IGB_DBA_ALIGN);
-       for (int i = 0; i < adapter->num_queues; i++, rxconf++) {
-               rxr = &adapter->rx_rings[i];
-               rxr->adapter = adapter;
-               rxr->me = i;
-
-               /* Initialize the RX lock */
-               snprintf(rxr->mtx_name, sizeof(rxr->mtx_name), "%s:rx(%d)",
-                   device_get_nameunit(dev), txr->me);
-               mtx_init(&rxr->rx_mtx, rxr->mtx_name, NULL, MTX_DEF);
-
-               if (igb_dma_malloc(adapter, rsize,
-                       &rxr->rxdma, BUS_DMA_NOWAIT)) {
-                       device_printf(dev,
-                           "Unable to allocate RxDescriptor memory\n");
-                       error = ENOMEM;
-                       goto err_rx_desc;
-               }
-               rxr->rx_base = (union e1000_adv_rx_desc *)rxr->rxdma.dma_vaddr;
-               bzero((void *)rxr->rx_base, rsize);
-
-               /* Allocate receive buffers for the ring*/
-               if (igb_allocate_receive_buffers(rxr)) {
-                       device_printf(dev,
-                           "Critical Failure setting up receive buffers\n");
-                       error = ENOMEM;
-                       goto err_rx_desc;
-               }
-       }
-
-       /*
-       ** Finally set up the queue holding structs
-       */
-       for (int i = 0; i < adapter->num_queues; i++) {
-               que = &adapter->queues[i];
-               que->adapter = adapter;
-               que->txr = &adapter->tx_rings[i];
-               que->rxr = &adapter->rx_rings[i];
-       }
-
-       return (0);
-
-err_rx_desc:
-       for (rxr = adapter->rx_rings; rxconf > 0; rxr++, rxconf--)
-               igb_dma_free(adapter, &rxr->rxdma);
-err_tx_desc:
-       for (txr = adapter->tx_rings; txconf > 0; txr++, txconf--)
-               igb_dma_free(adapter, &txr->txdma);
-       free(adapter->rx_rings, M_DEVBUF);
-rx_fail:
-#if __FreeBSD_version >= 800000
-       buf_ring_free(txr->br, M_DEVBUF);
-#endif
-       free(adapter->tx_rings, M_DEVBUF);
-tx_fail:
-       free(adapter->queues, M_DEVBUF);
-fail:
-       return (error);
-}
-
-/*********************************************************************
- *
- *  Allocate memory for tx_buffer structures. The tx_buffer stores all
- *  the information needed to transmit a packet on the wire. This is
- *  called only once at attach, setup is done every reset.
- *
- **********************************************************************/
-static int
-igb_allocate_transmit_buffers(struct tx_ring *txr)
-{
-       struct adapter *adapter = txr->adapter;
-       device_t dev = adapter->dev;
-       struct igb_tx_buffer *txbuf;
-       int error, i;
-
-       /*
-        * Setup DMA descriptor areas.
-        */
-       if ((error = bus_dma_tag_create(bus_get_dma_tag(dev),
-                              1, 0,                    /* alignment, bounds */
-                              BUS_SPACE_MAXADDR,       /* lowaddr */
-                              BUS_SPACE_MAXADDR,       /* highaddr */
-                              NULL, NULL,              /* filter, filterarg */
-                              IGB_TSO_SIZE,            /* maxsize */
-                              IGB_MAX_SCATTER,         /* nsegments */
-                              PAGE_SIZE,               /* maxsegsize */
-                              0,                       /* flags */
-                              NULL,                    /* lockfunc */
-                              NULL,                    /* lockfuncarg */
-                              &txr->txtag))) {
-               device_printf(dev,"Unable to allocate TX DMA tag\n");
-               goto fail;
-       }
-
-       if (!(txr->tx_buffers =
-           (struct igb_tx_buffer *) malloc(sizeof(struct igb_tx_buffer) *
-           adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO))) {
-               device_printf(dev, "Unable to allocate tx_buffer memory\n");
-               error = ENOMEM;
-               goto fail;
-       }
-
-        /* Create the descriptor buffer dma maps */
-       txbuf = txr->tx_buffers;
-       for (i = 0; i < adapter->num_tx_desc; i++, txbuf++) {
-               error = bus_dmamap_create(txr->txtag, 0, &txbuf->map);
-               if (error != 0) {
-                       device_printf(dev, "Unable to create TX DMA map\n");
-                       goto fail;
-               }
-       }
-
-       return 0;
-fail:
-       /* We free all, it handles case where we are in the middle */
-       igb_free_transmit_structures(adapter);
-       return (error);
-}
-
-/*********************************************************************
- *
- *  Initialize a transmit ring.
- *
- **********************************************************************/
-static void
-igb_setup_transmit_ring(struct tx_ring *txr)
-{
-       struct adapter *adapter = txr->adapter;
-       struct igb_tx_buffer *txbuf;
-       int i;
-
-       /* Clear the old descriptor contents */
-       IGB_TX_LOCK(txr);
-       bzero((void *)txr->tx_base,
-             (sizeof(union e1000_adv_tx_desc)) * adapter->num_tx_desc);
-       /* Reset indices */
-       txr->next_avail_desc = 0;
-       txr->next_to_clean = 0;
-
-       /* Free any existing tx buffers. */
-        txbuf = txr->tx_buffers;
-       for (i = 0; i < adapter->num_tx_desc; i++, txbuf++) {
-               if (txbuf->m_head != NULL) {
-                       bus_dmamap_sync(txr->txtag, txbuf->map,
-                           BUS_DMASYNC_POSTWRITE);
-                       bus_dmamap_unload(txr->txtag, txbuf->map);
-                       m_freem(txbuf->m_head);
-                       txbuf->m_head = NULL;
-               }
-               /* clear the watch index */
-               txbuf->next_eop = -1;
-        }
-
-       /* Set number of descriptors available */
-       txr->tx_avail = adapter->num_tx_desc;
-
-       bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
-           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-       IGB_TX_UNLOCK(txr);
-}
-
-/*********************************************************************
- *
- *  Initialize all transmit rings.
- *
- **********************************************************************/
-static void
-igb_setup_transmit_structures(struct adapter *adapter)
-{
-       struct tx_ring *txr = adapter->tx_rings;
-
-       for (int i = 0; i < adapter->num_queues; i++, txr++)
-               igb_setup_transmit_ring(txr);
-
-       return;
-}
-
-/*********************************************************************
- *
- *  Enable transmit unit.
- *
- **********************************************************************/
-static void
-igb_initialize_transmit_units(struct adapter *adapter)
-{
-       struct tx_ring  *txr = adapter->tx_rings;
-       struct e1000_hw *hw = &adapter->hw;
-       u32             tctl, txdctl;
-
-       INIT_DEBUGOUT("igb_initialize_transmit_units: begin");
-       tctl = txdctl = 0;
-
-       /* Setup the Tx Descriptor Rings */
-       for (int i = 0; i < adapter->num_queues; i++, txr++) {
-               u64 bus_addr = txr->txdma.dma_paddr;
-
-               E1000_WRITE_REG(hw, E1000_TDLEN(i),
-                   adapter->num_tx_desc * sizeof(struct e1000_tx_desc));
-               E1000_WRITE_REG(hw, E1000_TDBAH(i),
-                   (uint32_t)(bus_addr >> 32));
-               E1000_WRITE_REG(hw, E1000_TDBAL(i),
-                   (uint32_t)bus_addr);
-
-               /* Setup the HW Tx Head and Tail descriptor pointers */
-               E1000_WRITE_REG(hw, E1000_TDT(i), 0);
-               E1000_WRITE_REG(hw, E1000_TDH(i), 0);
-
-               HW_DEBUGOUT2("Base = %x, Length = %x\n",
-                   E1000_READ_REG(hw, E1000_TDBAL(i)),
-                   E1000_READ_REG(hw, E1000_TDLEN(i)));
-
-               txr->queue_status = IGB_QUEUE_IDLE;
-
-               txdctl |= IGB_TX_PTHRESH;
-               txdctl |= IGB_TX_HTHRESH << 8;
-               txdctl |= IGB_TX_WTHRESH << 16;
-               txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
-               E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl);
-       }
-
-       if (adapter->vf_ifp)
-               return;
-
-       e1000_config_collision_dist(hw);
-
-       /* Program the Transmit Control Register */
-       tctl = E1000_READ_REG(hw, E1000_TCTL);
-       tctl &= ~E1000_TCTL_CT;
-       tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN |
-                  (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT));
-
-       /* This write will effectively turn on the transmit unit. */
-       E1000_WRITE_REG(hw, E1000_TCTL, tctl);
-}
-
-/*********************************************************************
- *
- *  Free all transmit rings.
- *
- **********************************************************************/
-static void
-igb_free_transmit_structures(struct adapter *adapter)
-{
-       struct tx_ring *txr = adapter->tx_rings;
-
-       for (int i = 0; i < adapter->num_queues; i++, txr++) {
-               IGB_TX_LOCK(txr);
-               igb_free_transmit_buffers(txr);
-               igb_dma_free(adapter, &txr->txdma);
-               IGB_TX_UNLOCK(txr);
-               IGB_TX_LOCK_DESTROY(txr);
-       }
-       free(adapter->tx_rings, M_DEVBUF);
-}
-
-/*********************************************************************
- *
- *  Free transmit ring related data structures.
- *
- **********************************************************************/
-static void
-igb_free_transmit_buffers(struct tx_ring *txr)
-{
-       struct adapter *adapter = txr->adapter;
-       struct igb_tx_buffer *tx_buffer;
-       int             i;
-
-       INIT_DEBUGOUT("free_transmit_ring: begin");
-
-       if (txr->tx_buffers == NULL)
-               return;
-
-       tx_buffer = txr->tx_buffers;
-       for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
-               if (tx_buffer->m_head != NULL) {
-                       bus_dmamap_sync(txr->txtag, tx_buffer->map,
-                           BUS_DMASYNC_POSTWRITE);
-                       bus_dmamap_unload(txr->txtag,
-                           tx_buffer->map);
-                       m_freem(tx_buffer->m_head);
-                       tx_buffer->m_head = NULL;
-                       if (tx_buffer->map != NULL) {
-                               bus_dmamap_destroy(txr->txtag,
-                                   tx_buffer->map);
-                               tx_buffer->map = NULL;
-                       }
-               } else if (tx_buffer->map != NULL) {
-                       bus_dmamap_unload(txr->txtag,
-                           tx_buffer->map);
-                       bus_dmamap_destroy(txr->txtag,
-                           tx_buffer->map);
-                       tx_buffer->map = NULL;
-               }
-       }
-#if __FreeBSD_version >= 800000
-       if (txr->br != NULL)
-               buf_ring_free(txr->br, M_DEVBUF);
-#endif
-       if (txr->tx_buffers != NULL) {
-               free(txr->tx_buffers, M_DEVBUF);
-               txr->tx_buffers = NULL;
-       }
-       if (txr->txtag != NULL) {
-               bus_dma_tag_destroy(txr->txtag);
-               txr->txtag = NULL;
-       }
-       return;
-}
-
-/**********************************************************************
- *
- *  Setup work for hardware segmentation offload (TSO)
- *
- **********************************************************************/
-static boolean_t
-igb_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *hdrlen)
-{
-       struct adapter *adapter = txr->adapter;
-       struct e1000_adv_tx_context_desc *TXD;
-       struct igb_tx_buffer        *tx_buffer;
-       u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
-       u32 mss_l4len_idx = 0;
-       u16 vtag = 0;
-       int ctxd, ehdrlen, ip_hlen, tcp_hlen;
-       struct ether_vlan_header *eh;
-       struct ip *ip;
-       struct tcphdr *th;
-
-
-       /*
-        * Determine where frame payload starts.
-        * Jump over vlan headers if already present
-        */
-       eh = mtod(mp, struct ether_vlan_header *);
-       if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))
-               ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
-       else
-               ehdrlen = ETHER_HDR_LEN;
-
-       /* Ensure we have at least the IP+TCP header in the first mbuf. */
-       if (mp->m_len < ehdrlen + sizeof(struct ip) + sizeof(struct tcphdr))
-               return FALSE;
-
-       /* Only supports IPV4 for now */
-       ctxd = txr->next_avail_desc;
-       tx_buffer = &txr->tx_buffers[ctxd];
-       TXD = (struct e1000_adv_tx_context_desc *) &txr->tx_base[ctxd];
-
-       ip = (struct ip *)(mp->m_data + ehdrlen);
-       if (ip->ip_p != IPPROTO_TCP)
-                return FALSE;   /* 0 */
-       ip->ip_sum = 0;
-       ip_hlen = ip->ip_hl << 2;
-       th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
-       th->th_sum = in_pseudo(ip->ip_src.s_addr,
-           ip->ip_dst.s_addr, htons(IPPROTO_TCP));
-       tcp_hlen = th->th_off << 2;
-       /*
-        * Calculate header length, this is used
-        * in the transmit desc in igb_xmit
-        */
-       *hdrlen = ehdrlen + ip_hlen + tcp_hlen;
-
-       /* VLAN MACLEN IPLEN */
-       if (mp->m_flags & M_VLANTAG) {
-               vtag = htole16(mp->m_pkthdr.ether_vtag);
-               vlan_macip_lens |= (vtag << E1000_ADVTXD_VLAN_SHIFT);
-       }
-
-       vlan_macip_lens |= (ehdrlen << E1000_ADVTXD_MACLEN_SHIFT);
-       vlan_macip_lens |= ip_hlen;
-       TXD->vlan_macip_lens |= htole32(vlan_macip_lens);
-
-       /* ADV DTYPE TUCMD */
-       type_tucmd_mlhl |= E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
-       type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP;
-       type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
-       TXD->type_tucmd_mlhl |= htole32(type_tucmd_mlhl);
-
-       /* MSS L4LEN IDX */
-       mss_l4len_idx |= (mp->m_pkthdr.tso_segsz << E1000_ADVTXD_MSS_SHIFT);
-       mss_l4len_idx |= (tcp_hlen << E1000_ADVTXD_L4LEN_SHIFT);
-       /* 82575 needs the queue index added */
-       if (adapter->hw.mac.type == e1000_82575)
-               mss_l4len_idx |= txr->me << 4;
-       TXD->mss_l4len_idx = htole32(mss_l4len_idx);
-
-       TXD->seqnum_seed = htole32(0);
-       tx_buffer->m_head = NULL;
-       tx_buffer->next_eop = -1;
-
-       if (++ctxd == adapter->num_tx_desc)
-               ctxd = 0;
-
-       txr->tx_avail--;
-       txr->next_avail_desc = ctxd;
-       return TRUE;
-}
-
-
-/*********************************************************************
- *
- *  Context Descriptor setup for VLAN or CSUM
- *
- **********************************************************************/
-
-static bool
-igb_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
-{
-       struct adapter *adapter = txr->adapter;
-       struct e1000_adv_tx_context_desc *TXD;
-       struct igb_tx_buffer        *tx_buffer;
-       u32 vlan_macip_lens, type_tucmd_mlhl, mss_l4len_idx;
-       struct ether_vlan_header *eh;
-       struct ip *ip = NULL;
-       struct ip6_hdr *ip6;
-       int  ehdrlen, ctxd, ip_hlen = 0;
-       u16     etype, vtag = 0;
-       u8      ipproto = 0;
-       bool    offload = TRUE;
-
-       if ((mp->m_pkthdr.csum_flags & CSUM_OFFLOAD) == 0)
-               offload = FALSE;
-
-       vlan_macip_lens = type_tucmd_mlhl = mss_l4len_idx = 0;
-       ctxd = txr->next_avail_desc;
-       tx_buffer = &txr->tx_buffers[ctxd];
-       TXD = (struct e1000_adv_tx_context_desc *) &txr->tx_base[ctxd];
-
-       /*
-       ** In advanced descriptors the vlan tag must 
-       ** be placed into the context descriptor, thus
-       ** we need to be here just for that setup.
-       */
-       if (mp->m_flags & M_VLANTAG) {
-               vtag = htole16(mp->m_pkthdr.ether_vtag);
-               vlan_macip_lens |= (vtag << E1000_ADVTXD_VLAN_SHIFT);
-       } else if (offload == FALSE)
-               return FALSE;
-
-       /*
-        * Determine where frame payload starts.
-        * Jump over vlan headers if already present,
-        * helpful for QinQ too.
-        */
-       eh = mtod(mp, struct ether_vlan_header *);
-       if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
-               etype = ntohs(eh->evl_proto);
-               ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
-       } else {
-               etype = ntohs(eh->evl_encap_proto);
-               ehdrlen = ETHER_HDR_LEN;
-       }
-
-       /* Set the ether header length */
-       vlan_macip_lens |= ehdrlen << E1000_ADVTXD_MACLEN_SHIFT;
-
-       switch (etype) {
-               case ETHERTYPE_IP:
-                       ip = (struct ip *)(mp->m_data + ehdrlen);
-                       ip_hlen = ip->ip_hl << 2;
-                       if (mp->m_len < ehdrlen + ip_hlen) {
-                               offload = FALSE;
-                               break;
-                       }
-                       ipproto = ip->ip_p;
-                       type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
-                       break;
-               case ETHERTYPE_IPV6:
-                       ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
-                       ip_hlen = sizeof(struct ip6_hdr);
-                       ipproto = ip6->ip6_nxt;
-                       type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV6;
-                       break;
-               default:
-                       offload = FALSE;
-                       break;
-       }
-
-       vlan_macip_lens |= ip_hlen;
-       type_tucmd_mlhl |= E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
-
-       switch (ipproto) {
-               case IPPROTO_TCP:
-                       if (mp->m_pkthdr.csum_flags & CSUM_TCP)
-                               type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP;
-                       break;
-               case IPPROTO_UDP:
-                       if (mp->m_pkthdr.csum_flags & CSUM_UDP)
-                               type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_UDP;
-                       break;
-#if __FreeBSD_version >= 800000
-               case IPPROTO_SCTP:
-                       if (mp->m_pkthdr.csum_flags & CSUM_SCTP)
-                               type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_SCTP;
-                       break;
-#endif
-               default:
-                       offload = FALSE;
-                       break;
-       }
-
-       /* 82575 needs the queue index added */
-       if (adapter->hw.mac.type == e1000_82575)
-               mss_l4len_idx = txr->me << 4;
-
-       /* Now copy bits into descriptor */
-       TXD->vlan_macip_lens |= htole32(vlan_macip_lens);
-       TXD->type_tucmd_mlhl |= htole32(type_tucmd_mlhl);
-       TXD->seqnum_seed = htole32(0);
-       TXD->mss_l4len_idx = htole32(mss_l4len_idx);
-
-       tx_buffer->m_head = NULL;
-       tx_buffer->next_eop = -1;
-
-       /* We've consumed the first desc, adjust counters */
-       if (++ctxd == adapter->num_tx_desc)
-               ctxd = 0;
-       txr->next_avail_desc = ctxd;
-       --txr->tx_avail;
-
-        return (offload);
-}
-
-
-/**********************************************************************
- *
- *  Examine each tx_buffer in the used queue. If the hardware is done
- *  processing the packet then free associated resources. The
- *  tx_buffer is put back on the free queue.
- *
- *  TRUE return means there's work in the ring to clean, FALSE its empty.
- **********************************************************************/
-static bool
-igb_txeof(struct tx_ring *txr)
-{
-       struct adapter  *adapter = txr->adapter;
-        int first, last, done, processed;
-        struct igb_tx_buffer *tx_buffer;
-        struct e1000_tx_desc   *tx_desc, *eop_desc;
-       struct ifnet   *ifp = adapter->ifp;
-
-       IGB_TX_LOCK_ASSERT(txr);
-
-        if (txr->tx_avail == adapter->num_tx_desc) {
-               txr->queue_status = IGB_QUEUE_IDLE;
-                return FALSE;
-       }
-
-       processed = 0;
-        first = txr->next_to_clean;
-        tx_desc = &txr->tx_base[first];
-        tx_buffer = &txr->tx_buffers[first];
-       last = tx_buffer->next_eop;
-        eop_desc = &txr->tx_base[last];
-
-       /*
-        * What this does is get the index of the
-        * first descriptor AFTER the EOP of the 
-        * first packet, that way we can do the
-        * simple comparison on the inner while loop.
-        */
-       if (++last == adapter->num_tx_desc)
-               last = 0;
-       done = last;
-
-        bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
-            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-
-        while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) {
-               /* We clean the range of the packet */
-               while (first != done) {
-                       tx_desc->upper.data = 0;
-                       tx_desc->lower.data = 0;
-                       tx_desc->buffer_addr = 0;
-                       ++txr->tx_avail;
-                       ++processed;
-
-                       if (tx_buffer->m_head) {
-                               txr->bytes +=
-                                   tx_buffer->m_head->m_pkthdr.len;
-                               bus_dmamap_sync(txr->txtag,
-                                   tx_buffer->map,
-                                   BUS_DMASYNC_POSTWRITE);
-                               bus_dmamap_unload(txr->txtag,
-                                   tx_buffer->map);
-
-                               m_freem(tx_buffer->m_head);
-                               tx_buffer->m_head = NULL;
-                       }
-                       tx_buffer->next_eop = -1;
-                       txr->watchdog_time = ticks;
-
-                       if (++first == adapter->num_tx_desc)
-                               first = 0;
-
-                       tx_buffer = &txr->tx_buffers[first];
-                       tx_desc = &txr->tx_base[first];
-               }
-               ++txr->packets;
-               ++ifp->if_opackets;
-               /* See if we can continue to the next packet */
-               last = tx_buffer->next_eop;
-               if (last != -1) {
-                       eop_desc = &txr->tx_base[last];
-                       /* Get new done point */
-                       if (++last == adapter->num_tx_desc) last = 0;
-                       done = last;
-               } else
-                       break;
-        }
-        bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
-            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
-        txr->next_to_clean = first;
-
-       /*
-       ** Watchdog calculation, we know there's
-       ** work outstanding or the first return
-       ** would have been taken, so none processed
-       ** for too long indicates a hang.
-       */
-       if ((!processed) && ((ticks - txr->watchdog_time) > IGB_WATCHDOG))
-               txr->queue_status = IGB_QUEUE_HUNG;
-
-        /*
-         * If we have a minimum free, clear IFF_DRV_OACTIVE
-         * to tell the stack that it is OK to send packets.
-         */
-        if (txr->tx_avail > IGB_TX_CLEANUP_THRESHOLD) {                
-                ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-               /* All clean, turn off the watchdog */
-                if (txr->tx_avail == adapter->num_tx_desc) {
-                       txr->queue_status = IGB_QUEUE_IDLE;
-                       return (FALSE);
-               }
-        }
-       return (TRUE);
-}
-
-/*********************************************************************
- *
- *  Refresh mbuf buffers for RX descriptor rings
- *   - now keeps its own state so discards due to resource
- *     exhaustion are unnecessary, if an mbuf cannot be obtained
- *     it just returns, keeping its placeholder, thus it can simply
- *     be recalled to try again.
- *
- **********************************************************************/
-static void
-igb_refresh_mbufs(struct rx_ring *rxr, int limit)
-{
-       struct adapter          *adapter = rxr->adapter;
-       bus_dma_segment_t       hseg[1];
-       bus_dma_segment_t       pseg[1];
-       struct igb_rx_buf       *rxbuf;
-       struct mbuf             *mh, *mp;
-       int                     i, j, nsegs, error;
-       bool                    refreshed = FALSE;
-
-       i = j = rxr->next_to_refresh;
-       /*
-       ** Get one descriptor beyond
-       ** our work mark to control
-       ** the loop.
-        */
-       if (++j == adapter->num_rx_desc)
-               j = 0;
-
-       while (j != limit) {
-               rxbuf = &rxr->rx_buffers[i];
-               /* No hdr mbuf used with header split off */
-               if (rxr->hdr_split == FALSE)
-                       goto no_split;
-               if (rxbuf->m_head == NULL) {
-                       mh = m_gethdr(M_DONTWAIT, MT_DATA);
-                       if (mh == NULL)
-                               goto update;
-               } else
-                       mh = rxbuf->m_head;
-
-               mh->m_pkthdr.len = mh->m_len = MHLEN;
-               mh->m_len = MHLEN;
-               mh->m_flags |= M_PKTHDR;
-               /* Get the memory mapping */
-               error = bus_dmamap_load_mbuf_sg(rxr->htag,
-                   rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT);
-               if (error != 0) {
-                       printf("Refresh mbufs: hdr dmamap load"
-                           " failure - %d\n", error);
-                       m_free(mh);
-                       rxbuf->m_head = NULL;
-                       goto update;
-               }
-               rxbuf->m_head = mh;
-               bus_dmamap_sync(rxr->htag, rxbuf->hmap,
-                   BUS_DMASYNC_PREREAD);
-               rxr->rx_base[i].read.hdr_addr =
-                   htole64(hseg[0].ds_addr);
-no_split:
-               if (rxbuf->m_pack == NULL) {
-                       mp = m_getjcl(M_DONTWAIT, MT_DATA,
-                           M_PKTHDR, adapter->rx_mbuf_sz);
-                       if (mp == NULL)
-                               goto update;
-               } else
-                       mp = rxbuf->m_pack;
-
-               mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz;
-               /* Get the memory mapping */
-               error = bus_dmamap_load_mbuf_sg(rxr->ptag,
-                   rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT);
-               if (error != 0) {
-                       printf("Refresh mbufs: payload dmamap load"
-                           " failure - %d\n", error);
-                       m_free(mp);
-                       rxbuf->m_pack = NULL;
-                       goto update;
-               }
-               rxbuf->m_pack = mp;
-               bus_dmamap_sync(rxr->ptag, rxbuf->pmap,
-                   BUS_DMASYNC_PREREAD);
-               rxr->rx_base[i].read.pkt_addr =
-                   htole64(pseg[0].ds_addr);
-               refreshed = TRUE; /* I feel wefreshed :) */
-
-               i = j; /* our next is precalculated */
-               rxr->next_to_refresh = i;
-               if (++j == adapter->num_rx_desc)
-                       j = 0;
-       }
-update:
-       if (refreshed) /* update tail */
-               E1000_WRITE_REG(&adapter->hw,
-                   E1000_RDT(rxr->me), rxr->next_to_refresh);
-       return;
-}
-
-
-/*********************************************************************
- *
- *  Allocate memory for rx_buffer structures. Since we use one
- *  rx_buffer per received packet, the maximum number of rx_buffer's
- *  that we'll need is equal to the number of receive descriptors
- *  that we've allocated.
- *
- **********************************************************************/
-static int
-igb_allocate_receive_buffers(struct rx_ring *rxr)
-{
-       struct  adapter         *adapter = rxr->adapter;
-       device_t                dev = adapter->dev;
-       struct igb_rx_buf       *rxbuf;
-       int                     i, bsize, error;
-
-       bsize = sizeof(struct igb_rx_buf) * adapter->num_rx_desc;
-       if (!(rxr->rx_buffers =
-           (struct igb_rx_buf *) malloc(bsize,
-           M_DEVBUF, M_NOWAIT | M_ZERO))) {
-               device_printf(dev, "Unable to allocate rx_buffer memory\n");
-               error = ENOMEM;
-               goto fail;
-       }
-
-       if ((error = bus_dma_tag_create(bus_get_dma_tag(dev),
-                                  1, 0,                /* alignment, bounds */
-                                  BUS_SPACE_MAXADDR,   /* lowaddr */
-                                  BUS_SPACE_MAXADDR,   /* highaddr */
-                                  NULL, NULL,          /* filter, filterarg */
-                                  MSIZE,               /* maxsize */
-                                  1,                   /* nsegments */
-                                  MSIZE,               /* maxsegsize */
-                                  0,                   /* flags */
-                                  NULL,                /* lockfunc */
-                                  NULL,                /* lockfuncarg */
-                                  &rxr->htag))) {
-               device_printf(dev, "Unable to create RX DMA tag\n");
-               goto fail;
-       }
-
-       if ((error = bus_dma_tag_create(bus_get_dma_tag(dev),
-                                  1, 0,                /* alignment, bounds */
-                                  BUS_SPACE_MAXADDR,   /* lowaddr */
-                                  BUS_SPACE_MAXADDR,   /* highaddr */
-                                  NULL, NULL,          /* filter, filterarg */
-                                  MJUM9BYTES,          /* maxsize */
-                                  1,                   /* nsegments */
-                                  MJUM9BYTES,          /* maxsegsize */
-                                  0,                   /* flags */
-                                  NULL,                /* lockfunc */
-                                  NULL,                /* lockfuncarg */
-                                  &rxr->ptag))) {
-               device_printf(dev, "Unable to create RX payload DMA tag\n");
-               goto fail;
-       }
-
-       for (i = 0; i < adapter->num_rx_desc; i++) {
-               rxbuf = &rxr->rx_buffers[i];
-               error = bus_dmamap_create(rxr->htag,
-                   BUS_DMA_NOWAIT, &rxbuf->hmap);
-               if (error) {
-                       device_printf(dev,
-                           "Unable to create RX head DMA maps\n");
-                       goto fail;
-               }
-               error = bus_dmamap_create(rxr->ptag,
-                   BUS_DMA_NOWAIT, &rxbuf->pmap);
-               if (error) {
-                       device_printf(dev,
-                           "Unable to create RX packet DMA maps\n");
-                       goto fail;
-               }
-       }
-
-       return (0);
-
-fail:
-       /* Frees all, but can handle partial completion */
-       igb_free_receive_structures(adapter);
-       return (error);
-}
-
-
-static void
-igb_free_receive_ring(struct rx_ring *rxr)
-{
-       struct  adapter         *adapter = rxr->adapter;
-       struct igb_rx_buf       *rxbuf;
-
-
-       for (int i = 0; i < adapter->num_rx_desc; i++) {
-               rxbuf = &rxr->rx_buffers[i];
-               if (rxbuf->m_head != NULL) {
-                       bus_dmamap_sync(rxr->htag, rxbuf->hmap,
-                           BUS_DMASYNC_POSTREAD);
-                       bus_dmamap_unload(rxr->htag, rxbuf->hmap);
-                       rxbuf->m_head->m_flags |= M_PKTHDR;
-                       m_freem(rxbuf->m_head);
-               }
-               if (rxbuf->m_pack != NULL) {
-                       bus_dmamap_sync(rxr->ptag, rxbuf->pmap,
-                           BUS_DMASYNC_POSTREAD);
-                       bus_dmamap_unload(rxr->ptag, rxbuf->pmap);
-                       rxbuf->m_pack->m_flags |= M_PKTHDR;
-                       m_freem(rxbuf->m_pack);
-               }
-               rxbuf->m_head = NULL;
-               rxbuf->m_pack = NULL;
-       }
-}
-
-
-/*********************************************************************
- *
- *  Initialize a receive ring and its buffers.
- *
- **********************************************************************/
-static int
-igb_setup_receive_ring(struct rx_ring *rxr)
-{
-       struct  adapter         *adapter;
-       struct  ifnet           *ifp;
-       device_t                dev;
-       struct igb_rx_buf       *rxbuf;
-       bus_dma_segment_t       pseg[1], hseg[1];
-       struct lro_ctrl         *lro = &rxr->lro;
-       int                     rsize, nsegs, error = 0;
-
-       adapter = rxr->adapter;
-       dev = adapter->dev;
-       ifp = adapter->ifp;
-
-       /* Clear the ring contents */
-       IGB_RX_LOCK(rxr);
-       rsize = roundup2(adapter->num_rx_desc *
-           sizeof(union e1000_adv_rx_desc), IGB_DBA_ALIGN);
-       bzero((void *)rxr->rx_base, rsize);
-
-       /*
-       ** Free current RX buffer structures and their mbufs
-       */
-       igb_free_receive_ring(rxr);
-
-       /* Configure for header split? */
-       if (igb_header_split)
-               rxr->hdr_split = TRUE;
-
-        /* Now replenish the ring mbufs */
-       for (int j = 0; j < adapter->num_rx_desc; ++j) {
-               struct mbuf     *mh, *mp;
-
-               rxbuf = &rxr->rx_buffers[j];
-               if (rxr->hdr_split == FALSE)
-                       goto skip_head;
-
-               /* First the header */
-               rxbuf->m_head = m_gethdr(M_DONTWAIT, MT_DATA);
-               if (rxbuf->m_head == NULL) {
-                       error = ENOBUFS;
-                        goto fail;
-               }
-               m_adj(rxbuf->m_head, ETHER_ALIGN);
-               mh = rxbuf->m_head;
-               mh->m_len = mh->m_pkthdr.len = MHLEN;
-               mh->m_flags |= M_PKTHDR;
-               /* Get the memory mapping */
-               error = bus_dmamap_load_mbuf_sg(rxr->htag,
-                   rxbuf->hmap, rxbuf->m_head, hseg,
-                   &nsegs, BUS_DMA_NOWAIT);
-               if (error != 0) /* Nothing elegant to do here */
-                        goto fail;
-               bus_dmamap_sync(rxr->htag,
-                   rxbuf->hmap, BUS_DMASYNC_PREREAD);
-               /* Update descriptor */
-               rxr->rx_base[j].read.hdr_addr = htole64(hseg[0].ds_addr);
-
-skip_head:
-               /* Now the payload cluster */
-               rxbuf->m_pack = m_getjcl(M_DONTWAIT, MT_DATA,
-                   M_PKTHDR, adapter->rx_mbuf_sz);
-               if (rxbuf->m_pack == NULL) {
-                       error = ENOBUFS;
-                        goto fail;
-               }
-               mp = rxbuf->m_pack;
-               mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz;
-               /* Get the memory mapping */
-               error = bus_dmamap_load_mbuf_sg(rxr->ptag,
-                   rxbuf->pmap, mp, pseg,
-                   &nsegs, BUS_DMA_NOWAIT);
-               if (error != 0)
-                        goto fail;
-               bus_dmamap_sync(rxr->ptag,
-                   rxbuf->pmap, BUS_DMASYNC_PREREAD);
-               /* Update descriptor */
-               rxr->rx_base[j].read.pkt_addr = htole64(pseg[0].ds_addr);
-        }
-
-       /* Setup our descriptor indices */
-       rxr->next_to_check = 0;
-       rxr->next_to_refresh = adapter->num_rx_desc - 1;
-       rxr->lro_enabled = FALSE;
-       rxr->rx_split_packets = 0;
-       rxr->rx_bytes = 0;
-
-       rxr->fmp = NULL;
-       rxr->lmp = NULL;
-       rxr->discard = FALSE;
-
-       bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
-           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
-       /*
-       ** Now set up the LRO interface, we
-       ** also only do head split when LRO
-       ** is enabled, since so often they
-       ** are undesireable in similar setups.
-       */
-       if (ifp->if_capenable & IFCAP_LRO) {
-               error = tcp_lro_init(lro);
-               if (error) {
-                       device_printf(dev, "LRO Initialization failed!\n");
-                       goto fail;
-               }
-               INIT_DEBUGOUT("RX LRO Initialized\n");
-               rxr->lro_enabled = TRUE;
-               lro->ifp = adapter->ifp;
-       }
-
-       IGB_RX_UNLOCK(rxr);
-       return (0);
-
-fail:
-       igb_free_receive_ring(rxr);
-       IGB_RX_UNLOCK(rxr);
-       return (error);
-}
-
-
-/*********************************************************************
- *
- *  Initialize all receive rings.
- *
- **********************************************************************/
-static int
-igb_setup_receive_structures(struct adapter *adapter)
-{
-       struct rx_ring *rxr = adapter->rx_rings;
-       int i;
-
-       for (i = 0; i < adapter->num_queues; i++, rxr++)
-               if (igb_setup_receive_ring(rxr))
-                       goto fail;
-
-       return (0);
-fail:
-       /*
-        * Free RX buffers allocated so far, we will only handle
-        * the rings that completed, the failing case will have
-        * cleaned up for itself. 'i' is the endpoint.
-        */
-       for (int j = 0; j > i; ++j) {
-               rxr = &adapter->rx_rings[i];
-               IGB_RX_LOCK(rxr);
-               igb_free_receive_ring(rxr);
-               IGB_RX_UNLOCK(rxr);
-       }
-
-       return (ENOBUFS);
-}
-
-/*********************************************************************
- *
- *  Enable receive unit.
- *
- **********************************************************************/
-static void
-igb_initialize_receive_units(struct adapter *adapter)
-{
-       struct rx_ring  *rxr = adapter->rx_rings;
-       struct ifnet    *ifp = adapter->ifp;
-       struct e1000_hw *hw = &adapter->hw;
-       u32             rctl, rxcsum, psize, srrctl = 0;
-
-       INIT_DEBUGOUT("igb_initialize_receive_unit: begin");
-
-       /*
-        * Make sure receives are disabled while setting
-        * up the descriptor ring
-        */
-       rctl = E1000_READ_REG(hw, E1000_RCTL);
-       E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
-
-       /*
-       ** Set up for header split
-       */
-       if (igb_header_split) {
-               /* Use a standard mbuf for the header */
-               srrctl |= IGB_HDR_BUF << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
-               srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
-       } else
-               srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
-
-       /*
-       ** Set up for jumbo frames
-       */
-       if (ifp->if_mtu > ETHERMTU) {
-               rctl |= E1000_RCTL_LPE;
-               if (adapter->rx_mbuf_sz == MJUMPAGESIZE) {
-                       srrctl |= 4096 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-                       rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX;
-               } else if (adapter->rx_mbuf_sz > MJUMPAGESIZE) {
-                       srrctl |= 8192 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-                       rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX;
-               }
-               /* Set maximum packet len */
-               psize = adapter->max_frame_size;
-               /* are we on a vlan? */
-               if (adapter->ifp->if_vlantrunk != NULL)
-                       psize += VLAN_TAG_SIZE;
-               E1000_WRITE_REG(&adapter->hw, E1000_RLPML, psize);
-       } else {
-               rctl &= ~E1000_RCTL_LPE;
-               srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-               rctl |= E1000_RCTL_SZ_2048;
-       }
-
-       /* Setup the Base and Length of the Rx Descriptor Rings */
-       for (int i = 0; i < adapter->num_queues; i++, rxr++) {
-               u64 bus_addr = rxr->rxdma.dma_paddr;
-               u32 rxdctl;
-
-               E1000_WRITE_REG(hw, E1000_RDLEN(i),
-                   adapter->num_rx_desc * sizeof(struct e1000_rx_desc));
-               E1000_WRITE_REG(hw, E1000_RDBAH(i),
-                   (uint32_t)(bus_addr >> 32));
-               E1000_WRITE_REG(hw, E1000_RDBAL(i),
-                   (uint32_t)bus_addr);
-               E1000_WRITE_REG(hw, E1000_SRRCTL(i), srrctl);
-               /* Enable this Queue */
-               rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i));
-               rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
-               rxdctl &= 0xFFF00000;
-               rxdctl |= IGB_RX_PTHRESH;
-               rxdctl |= IGB_RX_HTHRESH << 8;
-               rxdctl |= IGB_RX_WTHRESH << 16;
-               E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl);
-       }
-
-       /*
-       ** Setup for RX MultiQueue
-       */
-       rxcsum = E1000_READ_REG(hw, E1000_RXCSUM);
-       if (adapter->num_queues >1) {
-               u32 random[10], mrqc, shift = 0;
-               union igb_reta {
-                       u32 dword;
-                       u8  bytes[4];
-               } reta;
-
-               arc4rand(&random, sizeof(random), 0);
-               if (adapter->hw.mac.type == e1000_82575)
-                       shift = 6;
-               /* Warning FM follows */
-               for (int i = 0; i < 128; i++) {
-                       reta.bytes[i & 3] =
-                           (i % adapter->num_queues) << shift;
-                       if ((i & 3) == 3)
-                               E1000_WRITE_REG(hw,
-                                   E1000_RETA(i >> 2), reta.dword);
-               }
-               /* Now fill in hash table */
-               mrqc = E1000_MRQC_ENABLE_RSS_4Q;
-               for (int i = 0; i < 10; i++)
-                       E1000_WRITE_REG_ARRAY(hw,
-                           E1000_RSSRK(0), i, random[i]);
-
-               mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
-                   E1000_MRQC_RSS_FIELD_IPV4_TCP);
-               mrqc |= (E1000_MRQC_RSS_FIELD_IPV6 |
-                   E1000_MRQC_RSS_FIELD_IPV6_TCP);
-               mrqc |=( E1000_MRQC_RSS_FIELD_IPV4_UDP |
-                   E1000_MRQC_RSS_FIELD_IPV6_UDP);
-               mrqc |=( E1000_MRQC_RSS_FIELD_IPV6_UDP_EX |
-                   E1000_MRQC_RSS_FIELD_IPV6_TCP_EX);
-
-               E1000_WRITE_REG(hw, E1000_MRQC, mrqc);
-
-               /*
-               ** NOTE: Receive Full-Packet Checksum Offload 
-               ** is mutually exclusive with Multiqueue. However
-               ** this is not the same as TCP/IP checksums which
-               ** still work.
-               */
-               rxcsum |= E1000_RXCSUM_PCSD;
-#if __FreeBSD_version >= 800000
-               /* For SCTP Offload */
-               if ((hw->mac.type == e1000_82576)
-                   && (ifp->if_capenable & IFCAP_RXCSUM))
-                       rxcsum |= E1000_RXCSUM_CRCOFL;
-#endif
-       } else {
-               /* Non RSS setup */
-               if (ifp->if_capenable & IFCAP_RXCSUM) {
-                       rxcsum |= E1000_RXCSUM_IPPCSE;
-#if __FreeBSD_version >= 800000
-                       if (adapter->hw.mac.type == e1000_82576)
-                               rxcsum |= E1000_RXCSUM_CRCOFL;
-#endif
-               } else
-                       rxcsum &= ~E1000_RXCSUM_TUOFL;
-       }
-       E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum);
-
-       /* Setup the Receive Control Register */
-       rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
-       rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
-                  E1000_RCTL_RDMTS_HALF |
-                  (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
-       /* Strip CRC bytes. */
-       rctl |= E1000_RCTL_SECRC;
-       /* Make sure VLAN Filters are off */
-       rctl &= ~E1000_RCTL_VFE;
-       /* Don't store bad packets */
-       rctl &= ~E1000_RCTL_SBP;
-
-       /* Enable Receives */
-       E1000_WRITE_REG(hw, E1000_RCTL, rctl);
-
-       /*
-        * Setup the HW Rx Head and Tail Descriptor Pointers
-        *   - needs to be after enable
-        */
-       for (int i = 0; i < adapter->num_queues; i++) {
-               rxr = &adapter->rx_rings[i];
-               E1000_WRITE_REG(hw, E1000_RDH(i), rxr->next_to_check);
-               E1000_WRITE_REG(hw, E1000_RDT(i), rxr->next_to_refresh);
-       }
-       return;
-}
-
-/*********************************************************************
- *
- *  Free receive rings.
- *
- **********************************************************************/
-static void
-igb_free_receive_structures(struct adapter *adapter)
-{
-       struct rx_ring *rxr = adapter->rx_rings;
-
-       for (int i = 0; i < adapter->num_queues; i++, rxr++) {
-               struct lro_ctrl *lro = &rxr->lro;
-               igb_free_receive_buffers(rxr);
-               tcp_lro_free(lro);
-               igb_dma_free(adapter, &rxr->rxdma);
-       }
-
-       free(adapter->rx_rings, M_DEVBUF);
-}
-
-/*********************************************************************
- *
- *  Free receive ring data structures.
- *
- **********************************************************************/
-static void
-igb_free_receive_buffers(struct rx_ring *rxr)
-{
-       struct adapter          *adapter = rxr->adapter;
-       struct igb_rx_buf       *rxbuf;
-       int i;
-
-       INIT_DEBUGOUT("free_receive_structures: begin");
-
-       /* Cleanup any existing buffers */
-       if (rxr->rx_buffers != NULL) {
-               for (i = 0; i < adapter->num_rx_desc; i++) {
-                       rxbuf = &rxr->rx_buffers[i];
-                       if (rxbuf->m_head != NULL) {
-                               bus_dmamap_sync(rxr->htag, rxbuf->hmap,
-                                   BUS_DMASYNC_POSTREAD);
-                               bus_dmamap_unload(rxr->htag, rxbuf->hmap);
-                               rxbuf->m_head->m_flags |= M_PKTHDR;
-                               m_freem(rxbuf->m_head);
-                       }
-                       if (rxbuf->m_pack != NULL) {
-                               bus_dmamap_sync(rxr->ptag, rxbuf->pmap,
-                                   BUS_DMASYNC_POSTREAD);
-                               bus_dmamap_unload(rxr->ptag, rxbuf->pmap);
-                               rxbuf->m_pack->m_flags |= M_PKTHDR;
-                               m_freem(rxbuf->m_pack);
-                       }
-                       rxbuf->m_head = NULL;
-                       rxbuf->m_pack = NULL;
-                       if (rxbuf->hmap != NULL) {
-                               bus_dmamap_destroy(rxr->htag, rxbuf->hmap);
-                               rxbuf->hmap = NULL;
-                       }
-                       if (rxbuf->pmap != NULL) {
-                               bus_dmamap_destroy(rxr->ptag, rxbuf->pmap);
-                               rxbuf->pmap = NULL;
-                       }
-               }
-               if (rxr->rx_buffers != NULL) {
-                       free(rxr->rx_buffers, M_DEVBUF);
-                       rxr->rx_buffers = NULL;
-               }
-       }
-
-       if (rxr->htag != NULL) {
-               bus_dma_tag_destroy(rxr->htag);
-               rxr->htag = NULL;
-       }
-       if (rxr->ptag != NULL) {
-               bus_dma_tag_destroy(rxr->ptag);
-               rxr->ptag = NULL;
-       }
-}
-
-static __inline void
-igb_rx_discard(struct rx_ring *rxr, int i)
-{
-       struct igb_rx_buf       *rbuf;
-
-       rbuf = &rxr->rx_buffers[i];
-
-       /* Partially received? Free the chain */
-       if (rxr->fmp != NULL) {
-               rxr->fmp->m_flags |= M_PKTHDR;
-               m_freem(rxr->fmp);
-               rxr->fmp = NULL;
-               rxr->lmp = NULL;
-       }
-
-       /*
-       ** With advanced descriptors the writeback
-       ** clobbers the buffer addrs, so its easier
-       ** to just free the existing mbufs and take
-       ** the normal refresh path to get new buffers
-       ** and mapping.
-       */
-       if (rbuf->m_head) {
-               m_free(rbuf->m_head);
-               rbuf->m_head = NULL;
-       }
-
-       if (rbuf->m_pack) {
-               m_free(rbuf->m_pack);
-               rbuf->m_pack = NULL;
-       }
-
-       return;
-}
-
-static __inline void
-igb_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u32 ptype)
-{
-
-       /*
-        * ATM LRO is only for IPv4/TCP packets and TCP checksum of the packet
-        * should be computed by hardware. Also it should not have VLAN tag in
-        * ethernet header.
-        */
-       if (rxr->lro_enabled &&
-           (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
-           (ptype & E1000_RXDADV_PKTTYPE_ETQF) == 0 &&
-           (ptype & (E1000_RXDADV_PKTTYPE_IPV4 | E1000_RXDADV_PKTTYPE_TCP)) ==
-           (E1000_RXDADV_PKTTYPE_IPV4 | E1000_RXDADV_PKTTYPE_TCP) &&
-           (m->m_pkthdr.csum_flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) == 
-           (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) {
-               /*
-                * Send to the stack if:
-                **  - LRO not enabled, or
-                **  - no LRO resources, or
-                **  - lro enqueue fails
-                */
-               if (rxr->lro.lro_cnt != 0)
-                       if (tcp_lro_rx(&rxr->lro, m, 0) == 0)
-                               return;
-       }
-       IGB_RX_UNLOCK(rxr);
-       (*ifp->if_input)(ifp, m);
-       IGB_RX_LOCK(rxr);
-}
-
-/*********************************************************************
- *
- *  This routine executes in interrupt context. It replenishes
- *  the mbufs in the descriptor and sends data which has been
- *  dma'ed into host memory to upper layer.
- *
- *  We loop at most count times if count is > 0, or until done if
- *  count < 0.
- *
- *  Return TRUE if more to clean, FALSE otherwise
- *********************************************************************/
-static bool
-igb_rxeof(struct igb_queue *que, int count, int *done)
-{
-       struct adapter          *adapter = que->adapter;
-       struct rx_ring          *rxr = que->rxr;
-       struct ifnet            *ifp = adapter->ifp;
-       struct lro_ctrl         *lro = &rxr->lro;
-       struct lro_entry        *queued;
-       int                     i, processed = 0, rxdone = 0;
-       u32                     ptype, staterr = 0;
-       union e1000_adv_rx_desc *cur;
-
-       IGB_RX_LOCK(rxr);
-       /* Sync the ring. */
-       bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
-           BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-
-       /* Main clean loop */
-       for (i = rxr->next_to_check; count != 0;) {
-               struct mbuf             *sendmp, *mh, *mp;
-               struct igb_rx_buf       *rxbuf;
-               u16                     hlen, plen, hdr, vtag;
-               bool                    eop = FALSE;
-               cur = &rxr->rx_base[i];
-               staterr = le32toh(cur->wb.upper.status_error);
-               if ((staterr & E1000_RXD_STAT_DD) == 0)
-                       break;
-               if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
-                       break;
-               count--;
-               sendmp = mh = mp = NULL;
-               cur->wb.upper.status_error = 0;
-               rxbuf = &rxr->rx_buffers[i];
-               plen = le16toh(cur->wb.upper.length);
-               ptype = le32toh(cur->wb.lower.lo_dword.data) & IGB_PKTTYPE_MASK;
-               if ((adapter->hw.mac.type == e1000_i350) &&
-                   (staterr & E1000_RXDEXT_STATERR_LB))
-                       vtag = be16toh(cur->wb.upper.vlan);
-               else
-                       vtag = le16toh(cur->wb.upper.vlan);
-               hdr = le16toh(cur->wb.lower.lo_dword.hs_rss.hdr_info);
-               eop = ((staterr & E1000_RXD_STAT_EOP) == E1000_RXD_STAT_EOP);
-
-               /* Make sure all segments of a bad packet are discarded */
-               if (((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) != 0) ||
-                   (rxr->discard)) {
-                       ifp->if_ierrors++;
-                       ++rxr->rx_discarded;
-                       if (!eop) /* Catch subsequent segs */
-                               rxr->discard = TRUE;
-                       else
-                               rxr->discard = FALSE;
-                       igb_rx_discard(rxr, i);
-                       goto next_desc;
-               }
-
-               /*
-               ** The way the hardware is configured to
-               ** split, it will ONLY use the header buffer
-               ** when header split is enabled, otherwise we
-               ** get normal behavior, ie, both header and
-               ** payload are DMA'd into the payload buffer.
-               **
-               ** The fmp test is to catch the case where a
-               ** packet spans multiple descriptors, in that
-               ** case only the first header is valid.
-               */
-               if (rxr->hdr_split && rxr->fmp == NULL) {
-                       hlen = (hdr & E1000_RXDADV_HDRBUFLEN_MASK) >>
-                           E1000_RXDADV_HDRBUFLEN_SHIFT;
-                       if (hlen > IGB_HDR_BUF)
-                               hlen = IGB_HDR_BUF;
-                       mh = rxr->rx_buffers[i].m_head;
-                       mh->m_len = hlen;
-                       /* clear buf pointer for refresh */
-                       rxbuf->m_head = NULL;
-                       /*
-                       ** Get the payload length, this
-                       ** could be zero if its a small
-                       ** packet.
-                       */
-                       if (plen > 0) {
-                               mp = rxr->rx_buffers[i].m_pack;
-                               mp->m_len = plen;
-                               mh->m_next = mp;
-                               /* clear buf pointer */
-                               rxbuf->m_pack = NULL;
-                               rxr->rx_split_packets++;
-                       }
-               } else {
-                       /*
-                       ** Either no header split, or a
-                       ** secondary piece of a fragmented
-                       ** split packet.
-                       */
-                       mh = rxr->rx_buffers[i].m_pack;
-                       mh->m_len = plen;
-                       /* clear buf info for refresh */
-                       rxbuf->m_pack = NULL;
-               }
-
-               ++processed; /* So we know when to refresh */
-
-               /* Initial frame - setup */
-               if (rxr->fmp == NULL) {
-                       mh->m_pkthdr.len = mh->m_len;
-                       /* Save the head of the chain */
-                       rxr->fmp = mh;
-                       rxr->lmp = mh;
-                       if (mp != NULL) {
-                               /* Add payload if split */
-                               mh->m_pkthdr.len += mp->m_len;
-                               rxr->lmp = mh->m_next;
-                       }
-               } else {
-                       /* Chain mbuf's together */
-                       rxr->lmp->m_next = mh;
-                       rxr->lmp = rxr->lmp->m_next;
-                       rxr->fmp->m_pkthdr.len += mh->m_len;
-               }
-
-               if (eop) {
-                       rxr->fmp->m_pkthdr.rcvif = ifp;
-                       ifp->if_ipackets++;
-                       rxr->rx_packets++;
-                       /* capture data for AIM */
-                       rxr->packets++;
-                       rxr->bytes += rxr->fmp->m_pkthdr.len;
-                       rxr->rx_bytes += rxr->fmp->m_pkthdr.len;
-
-                       if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
-                               igb_rx_checksum(staterr, rxr->fmp, ptype);
-
-                       if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
-                           (staterr & E1000_RXD_STAT_VP) != 0) {
-                               rxr->fmp->m_pkthdr.ether_vtag = vtag;
-                               rxr->fmp->m_flags |= M_VLANTAG;
-                       }
-#if __FreeBSD_version >= 800000
-                       rxr->fmp->m_pkthdr.flowid = que->msix;
-                       rxr->fmp->m_flags |= M_FLOWID;
-#endif
-                       sendmp = rxr->fmp;
-                       /* Make sure to set M_PKTHDR. */
-                       sendmp->m_flags |= M_PKTHDR;
-                       rxr->fmp = NULL;
-                       rxr->lmp = NULL;
-               }
-
-next_desc:
-               bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
-                   BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
-               /* Advance our pointers to the next descriptor. */
-               if (++i == adapter->num_rx_desc)
-                       i = 0;
-               /*
-               ** Send to the stack or LRO
-               */
-               if (sendmp != NULL) {
-                       rxr->next_to_check = i;
-                       igb_rx_input(rxr, ifp, sendmp, ptype);
-                       i = rxr->next_to_check;
-                       rxdone++;
-               }
-
-               /* Every 8 descriptors we go to refresh mbufs */
-               if (processed == 8) {
-                        igb_refresh_mbufs(rxr, i);
-                        processed = 0;
-               }
-       }
-
-       /* Catch any remainders */
-       if (igb_rx_unrefreshed(rxr))
-               igb_refresh_mbufs(rxr, i);
-
-       rxr->next_to_check = i;
-
-       /*
-        * Flush any outstanding LRO work
-        */
-       while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
-               SLIST_REMOVE_HEAD(&lro->lro_active, next);
-               tcp_lro_flush(lro, queued);
-       }
-
-       if (done != NULL)
-               *done = rxdone;
-
-       IGB_RX_UNLOCK(rxr);
-       return ((staterr & E1000_RXD_STAT_DD) ? TRUE : FALSE);
-}
-
-/*********************************************************************
- *
- *  Verify that the hardware indicated that the checksum is valid.
- *  Inform the stack about the status of checksum so that stack
- *  doesn't spend time verifying the checksum.
- *
- *********************************************************************/
-static void
-igb_rx_checksum(u32 staterr, struct mbuf *mp, u32 ptype)
-{
-       u16 status = (u16)staterr;
-       u8  errors = (u8) (staterr >> 24);
-       int sctp;
-
-       /* Ignore Checksum bit is set */
-       if (status & E1000_RXD_STAT_IXSM) {
-               mp->m_pkthdr.csum_flags = 0;
-               return;
-       }
-
-       if ((ptype & E1000_RXDADV_PKTTYPE_ETQF) == 0 &&
-           (ptype & E1000_RXDADV_PKTTYPE_SCTP) != 0)
-               sctp = 1;
-       else
-               sctp = 0;
-       if (status & E1000_RXD_STAT_IPCS) {
-               /* Did it pass? */
-               if (!(errors & E1000_RXD_ERR_IPE)) {
-                       /* IP Checksum Good */
-                       mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
-                       mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
-               } else
-                       mp->m_pkthdr.csum_flags = 0;
-       }
-
-       if (status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) {
-               u16 type = (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
-#if __FreeBSD_version >= 800000
-               if (sctp) /* reassign */
-                       type = CSUM_SCTP_VALID;
-#endif
-               /* Did it pass? */
-               if (!(errors & E1000_RXD_ERR_TCPE)) {
-                       mp->m_pkthdr.csum_flags |= type;
-                       if (sctp == 0)
-                               mp->m_pkthdr.csum_data = htons(0xffff);
-               }
-       }
-       return;
-}
-
-/*
- * This routine is run via an vlan
- * config EVENT
- */
-static void
-igb_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
-{
-       struct adapter  *adapter = ifp->if_softc;
-       u32             index, bit;
-
-       if (ifp->if_softc !=  arg)   /* Not our event */
-               return;
-
-       if ((vtag == 0) || (vtag > 4095))       /* Invalid */
-                return;
-
-       IGB_CORE_LOCK(adapter);
-       index = (vtag >> 5) & 0x7F;
-       bit = vtag & 0x1F;
-       adapter->shadow_vfta[index] |= (1 << bit);
-       ++adapter->num_vlans;
-       /* Change hw filter setting */
-       if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
-               igb_setup_vlan_hw_support(adapter);
-       IGB_CORE_UNLOCK(adapter);
-}
-
-/*
- * This routine is run via an vlan
- * unconfig EVENT
- */
-static void
-igb_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
-{
-       struct adapter  *adapter = ifp->if_softc;
-       u32             index, bit;
-
-       if (ifp->if_softc !=  arg)
-               return;
-
-       if ((vtag == 0) || (vtag > 4095))       /* Invalid */
-                return;
-
-       IGB_CORE_LOCK(adapter);
-       index = (vtag >> 5) & 0x7F;
-       bit = vtag & 0x1F;
-       adapter->shadow_vfta[index] &= ~(1 << bit);
-       --adapter->num_vlans;
-       /* Change hw filter setting */
-       if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
-               igb_setup_vlan_hw_support(adapter);
-       IGB_CORE_UNLOCK(adapter);
-}
-
-static void
-igb_setup_vlan_hw_support(struct adapter *adapter)
-{
-       struct e1000_hw *hw = &adapter->hw;
-       struct ifnet    *ifp = adapter->ifp;
-       u32             reg;
-
-       if (adapter->vf_ifp) {
-               e1000_rlpml_set_vf(hw,
-                   adapter->max_frame_size + VLAN_TAG_SIZE);
-               return;
-       }
-
-       reg = E1000_READ_REG(hw, E1000_CTRL);
-       reg |= E1000_CTRL_VME;
-       E1000_WRITE_REG(hw, E1000_CTRL, reg);
-
-       /* Enable the Filter Table */
-       if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
-               reg = E1000_READ_REG(hw, E1000_RCTL);
-               reg &= ~E1000_RCTL_CFIEN;
-               reg |= E1000_RCTL_VFE;
-               E1000_WRITE_REG(hw, E1000_RCTL, reg);
-       }
-
-       /* Update the frame size */
-       E1000_WRITE_REG(&adapter->hw, E1000_RLPML,
-           adapter->max_frame_size + VLAN_TAG_SIZE);
-
-       /* Don't bother with table if no vlans */
-       if ((adapter->num_vlans == 0) ||
-           ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0))
-                return;
-       /*
-       ** A soft reset zero's out the VFTA, so
-       ** we need to repopulate it now.
-       */
-       for (int i = 0; i < IGB_VFTA_SIZE; i++)
-                if (adapter->shadow_vfta[i] != 0) {
-                       if (adapter->vf_ifp)
-                               e1000_vfta_set_vf(hw,
-                                   adapter->shadow_vfta[i], TRUE);
-                       else
-                               E1000_WRITE_REG_ARRAY(hw, E1000_VFTA,
-                                i, adapter->shadow_vfta[i]);
-               }
-}
-
-static void
-igb_enable_intr(struct adapter *adapter)
-{
-       /* With RSS set up what to auto clear */
-       if (adapter->msix_mem) {
-               u32 mask = (adapter->que_mask | adapter->link_mask);
-               E1000_WRITE_REG(&adapter->hw, E1000_EIAC, mask);
-               E1000_WRITE_REG(&adapter->hw, E1000_EIAM, mask);
-               E1000_WRITE_REG(&adapter->hw, E1000_EIMS, mask);
-               E1000_WRITE_REG(&adapter->hw, E1000_IMS,
-                   E1000_IMS_LSC);
-       } else {
-               E1000_WRITE_REG(&adapter->hw, E1000_IMS,
-                   IMS_ENABLE_MASK);
-       }
-       E1000_WRITE_FLUSH(&adapter->hw);
-
-       return;
-}
-
-static void
-igb_disable_intr(struct adapter *adapter)
-{
-       if (adapter->msix_mem) {
-               E1000_WRITE_REG(&adapter->hw, E1000_EIMC, ~0);
-               E1000_WRITE_REG(&adapter->hw, E1000_EIAC, 0);
-       } 
-       E1000_WRITE_REG(&adapter->hw, E1000_IMC, ~0);
-       E1000_WRITE_FLUSH(&adapter->hw);
-       return;
-}
-
-/*
- * Bit of a misnomer, what this really means is
- * to enable OS management of the system... aka
- * to disable special hardware management features 
- */
-static void
-igb_init_manageability(struct adapter *adapter)
-{
-       if (adapter->has_manage) {
-               int manc2h = E1000_READ_REG(&adapter->hw, E1000_MANC2H);
-               int manc = E1000_READ_REG(&adapter->hw, E1000_MANC);
-
-               /* disable hardware interception of ARP */
-               manc &= ~(E1000_MANC_ARP_EN);
-
-                /* enable receiving management packets to the host */
-               manc |= E1000_MANC_EN_MNG2HOST;
-               manc2h |= 1 << 5;  /* Mng Port 623 */
-               manc2h |= 1 << 6;  /* Mng Port 664 */
-               E1000_WRITE_REG(&adapter->hw, E1000_MANC2H, manc2h);
-               E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc);
-       }
-}
-
-/*
- * Give control back to hardware management
- * controller if there is one.
- */
-static void
-igb_release_manageability(struct adapter *adapter)
-{
-       if (adapter->has_manage) {
-               int manc = E1000_READ_REG(&adapter->hw, E1000_MANC);
-
-               /* re-enable hardware interception of ARP */
-               manc |= E1000_MANC_ARP_EN;
-               manc &= ~E1000_MANC_EN_MNG2HOST;
-
-               E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc);
-       }
-}
-
-/*
- * igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that
- * the driver is loaded. 
- *
- */
-static void
-igb_get_hw_control(struct adapter *adapter)
-{
-       u32 ctrl_ext;
-
-       if (adapter->vf_ifp)
-               return;
-
-       /* Let firmware know the driver has taken over */
-       ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
-       E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
-           ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
-}
-
-/*
- * igb_release_hw_control resets CTRL_EXT:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that the
- * driver is no longer loaded.
- *
- */
-static void
-igb_release_hw_control(struct adapter *adapter)
-{
-       u32 ctrl_ext;
-
-       if (adapter->vf_ifp)
-               return;
-
-       /* Let firmware taken over control of h/w */
-       ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
-       E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
-           ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
-}
-
-static int
-igb_is_valid_ether_addr(uint8_t *addr)
-{
-       char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
-
-       if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) {
-               return (FALSE);
-       }
-
-       return (TRUE);
-}
-
-
-/*
- * Enable PCI Wake On Lan capability
- */
-static void
-igb_enable_wakeup(device_t dev)
-{
-       u16     cap, status;
-       u8      id;
-
-       /* First find the capabilities pointer*/
-       cap = pci_read_config(dev, PCIR_CAP_PTR, 2);
-       /* Read the PM Capabilities */
-       id = pci_read_config(dev, cap, 1);
-       if (id != PCIY_PMG)     /* Something wrong */
-               return;
-       /* OK, we have the power capabilities, so
-          now get the status register */
-       cap += PCIR_POWER_STATUS;
-       status = pci_read_config(dev, cap, 2);
-       status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
-       pci_write_config(dev, cap, status, 2);
-       return;
-}
-
-static void
-igb_led_func(void *arg, int onoff)
-{
-       struct adapter  *adapter = arg;
-
-       IGB_CORE_LOCK(adapter);
-       if (onoff) {
-               e1000_setup_led(&adapter->hw);
-               e1000_led_on(&adapter->hw);
-       } else {
-               e1000_led_off(&adapter->hw);
-               e1000_cleanup_led(&adapter->hw);
-       }
-       IGB_CORE_UNLOCK(adapter);
-}
-
-/**********************************************************************
- *
- *  Update the board statistics counters.
- *
- **********************************************************************/
-static void
-igb_update_stats_counters(struct adapter *adapter)
-{
-       struct ifnet            *ifp;
-        struct e1000_hw                *hw = &adapter->hw;
-       struct e1000_hw_stats   *stats;
-
-       /* 
-       ** The virtual function adapter has only a
-       ** small controlled set of stats, do only 
-       ** those and return.
-       */
-       if (adapter->vf_ifp) {
-               igb_update_vf_stats_counters(adapter);
-               return;
-       }
-
-       stats = (struct e1000_hw_stats  *)adapter->stats;
-
-       if(adapter->hw.phy.media_type == e1000_media_type_copper ||
-          (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
-               stats->symerrs +=
-                   E1000_READ_REG(hw,E1000_SYMERRS);
-               stats->sec += E1000_READ_REG(hw, E1000_SEC);
-       }
-
-       stats->crcerrs += E1000_READ_REG(hw, E1000_CRCERRS);
-       stats->mpc += E1000_READ_REG(hw, E1000_MPC);
-       stats->scc += E1000_READ_REG(hw, E1000_SCC);
-       stats->ecol += E1000_READ_REG(hw, E1000_ECOL);
-
-       stats->mcc += E1000_READ_REG(hw, E1000_MCC);
-       stats->latecol += E1000_READ_REG(hw, E1000_LATECOL);
-       stats->colc += E1000_READ_REG(hw, E1000_COLC);
-       stats->dc += E1000_READ_REG(hw, E1000_DC);
-       stats->rlec += E1000_READ_REG(hw, E1000_RLEC);
-       stats->xonrxc += E1000_READ_REG(hw, E1000_XONRXC);
-       stats->xontxc += E1000_READ_REG(hw, E1000_XONTXC);
-       /*
-       ** For watchdog management we need to know if we have been
-       ** paused during the last interval, so capture that here.
-       */ 
-        adapter->pause_frames = E1000_READ_REG(&adapter->hw, E1000_XOFFRXC);
-        stats->xoffrxc += adapter->pause_frames;
-       stats->xofftxc += E1000_READ_REG(hw, E1000_XOFFTXC);
-       stats->fcruc += E1000_READ_REG(hw, E1000_FCRUC);
-       stats->prc64 += E1000_READ_REG(hw, E1000_PRC64);
-       stats->prc127 += E1000_READ_REG(hw, E1000_PRC127);
-       stats->prc255 += E1000_READ_REG(hw, E1000_PRC255);
-       stats->prc511 += E1000_READ_REG(hw, E1000_PRC511);
-       stats->prc1023 += E1000_READ_REG(hw, E1000_PRC1023);
-       stats->prc1522 += E1000_READ_REG(hw, E1000_PRC1522);
-       stats->gprc += E1000_READ_REG(hw, E1000_GPRC);
-       stats->bprc += E1000_READ_REG(hw, E1000_BPRC);
-       stats->mprc += E1000_READ_REG(hw, E1000_MPRC);
-       stats->gptc += E1000_READ_REG(hw, E1000_GPTC);
-
-       /* For the 64-bit byte counters the low dword must be read first. */
-       /* Both registers clear on the read of the high dword */
-
-       stats->gorc += E1000_READ_REG(hw, E1000_GORCL) +
-           ((u64)E1000_READ_REG(hw, E1000_GORCH) << 32);
-       stats->gotc += E1000_READ_REG(hw, E1000_GOTCL) +
-           ((u64)E1000_READ_REG(hw, E1000_GOTCH) << 32);
-
-       stats->rnbc += E1000_READ_REG(hw, E1000_RNBC);
-       stats->ruc += E1000_READ_REG(hw, E1000_RUC);
-       stats->rfc += E1000_READ_REG(hw, E1000_RFC);
-       stats->roc += E1000_READ_REG(hw, E1000_ROC);
-       stats->rjc += E1000_READ_REG(hw, E1000_RJC);
-
-       stats->tor += E1000_READ_REG(hw, E1000_TORH);
-       stats->tot += E1000_READ_REG(hw, E1000_TOTH);
-
-       stats->tpr += E1000_READ_REG(hw, E1000_TPR);
-       stats->tpt += E1000_READ_REG(hw, E1000_TPT);
-       stats->ptc64 += E1000_READ_REG(hw, E1000_PTC64);
-       stats->ptc127 += E1000_READ_REG(hw, E1000_PTC127);
-       stats->ptc255 += E1000_READ_REG(hw, E1000_PTC255);
-       stats->ptc511 += E1000_READ_REG(hw, E1000_PTC511);
-       stats->ptc1023 += E1000_READ_REG(hw, E1000_PTC1023);
-       stats->ptc1522 += E1000_READ_REG(hw, E1000_PTC1522);
-       stats->mptc += E1000_READ_REG(hw, E1000_MPTC);
-       stats->bptc += E1000_READ_REG(hw, E1000_BPTC);
-
-       /* Interrupt Counts */
-
-       stats->iac += E1000_READ_REG(hw, E1000_IAC);
-       stats->icrxptc += E1000_READ_REG(hw, E1000_ICRXPTC);
-       stats->icrxatc += E1000_READ_REG(hw, E1000_ICRXATC);
-       stats->ictxptc += E1000_READ_REG(hw, E1000_ICTXPTC);
-       stats->ictxatc += E1000_READ_REG(hw, E1000_ICTXATC);
-       stats->ictxqec += E1000_READ_REG(hw, E1000_ICTXQEC);
-       stats->ictxqmtc += E1000_READ_REG(hw, E1000_ICTXQMTC);
-       stats->icrxdmtc += E1000_READ_REG(hw, E1000_ICRXDMTC);
-       stats->icrxoc += E1000_READ_REG(hw, E1000_ICRXOC);
-
-       /* Host to Card Statistics */
-
-       stats->cbtmpc += E1000_READ_REG(hw, E1000_CBTMPC);
-       stats->htdpmc += E1000_READ_REG(hw, E1000_HTDPMC);
-       stats->cbrdpc += E1000_READ_REG(hw, E1000_CBRDPC);
-       stats->cbrmpc += E1000_READ_REG(hw, E1000_CBRMPC);
-       stats->rpthc += E1000_READ_REG(hw, E1000_RPTHC);
-       stats->hgptc += E1000_READ_REG(hw, E1000_HGPTC);
-       stats->htcbdpc += E1000_READ_REG(hw, E1000_HTCBDPC);
-       stats->hgorc += (E1000_READ_REG(hw, E1000_HGORCL) +
-           ((u64)E1000_READ_REG(hw, E1000_HGORCH) << 32));
-       stats->hgotc += (E1000_READ_REG(hw, E1000_HGOTCL) +
-           ((u64)E1000_READ_REG(hw, E1000_HGOTCH) << 32));
-       stats->lenerrs += E1000_READ_REG(hw, E1000_LENERRS);
-       stats->scvpc += E1000_READ_REG(hw, E1000_SCVPC);
-       stats->hrmpc += E1000_READ_REG(hw, E1000_HRMPC);
-
-       stats->algnerrc += E1000_READ_REG(hw, E1000_ALGNERRC);
-       stats->rxerrc += E1000_READ_REG(hw, E1000_RXERRC);
-       stats->tncrs += E1000_READ_REG(hw, E1000_TNCRS);
-       stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR);
-       stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC);
-       stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC);
-
-       ifp = adapter->ifp;
-       ifp->if_collisions = stats->colc;
-
-       /* Rx Errors */
-       ifp->if_ierrors = adapter->dropped_pkts + stats->rxerrc +
-           stats->crcerrs + stats->algnerrc +
-           stats->ruc + stats->roc + stats->mpc + stats->cexterr;
-
-       /* Tx Errors */
-       ifp->if_oerrors = stats->ecol +
-           stats->latecol + adapter->watchdog_events;
-
-       /* Driver specific counters */
-       adapter->device_control = E1000_READ_REG(hw, E1000_CTRL);
-       adapter->rx_control = E1000_READ_REG(hw, E1000_RCTL);
-       adapter->int_mask = E1000_READ_REG(hw, E1000_IMS);
-       adapter->eint_mask = E1000_READ_REG(hw, E1000_EIMS);
-       adapter->packet_buf_alloc_tx =
-           ((E1000_READ_REG(hw, E1000_PBA) & 0xffff0000) >> 16);
-       adapter->packet_buf_alloc_rx =
-           (E1000_READ_REG(hw, E1000_PBA) & 0xffff);
-}
-
-
-/**********************************************************************
- *
- *  Initialize the VF board statistics counters.
- *
- **********************************************************************/
-static void
-igb_vf_init_stats(struct adapter *adapter)
-{
-        struct e1000_hw *hw = &adapter->hw;
-       struct e1000_vf_stats   *stats;
-
-       stats = (struct e1000_vf_stats  *)adapter->stats;
-       if (stats == NULL)
-               return;
-        stats->last_gprc = E1000_READ_REG(hw, E1000_VFGPRC);
-        stats->last_gorc = E1000_READ_REG(hw, E1000_VFGORC);
-        stats->last_gptc = E1000_READ_REG(hw, E1000_VFGPTC);
-        stats->last_gotc = E1000_READ_REG(hw, E1000_VFGOTC);
-        stats->last_mprc = E1000_READ_REG(hw, E1000_VFMPRC);
-}
-/**********************************************************************
- *
- *  Update the VF board statistics counters.
- *
- **********************************************************************/
-static void
-igb_update_vf_stats_counters(struct adapter *adapter)
-{
-       struct e1000_hw *hw = &adapter->hw;
-       struct e1000_vf_stats   *stats;
-
-       if (adapter->link_speed == 0)
-               return;
-
-       stats = (struct e1000_vf_stats  *)adapter->stats;
-
-       UPDATE_VF_REG(E1000_VFGPRC,
-           stats->last_gprc, stats->gprc);
-       UPDATE_VF_REG(E1000_VFGORC,
-           stats->last_gorc, stats->gorc);
-       UPDATE_VF_REG(E1000_VFGPTC,
-           stats->last_gptc, stats->gptc);
-       UPDATE_VF_REG(E1000_VFGOTC,
-           stats->last_gotc, stats->gotc);
-       UPDATE_VF_REG(E1000_VFMPRC,
-           stats->last_mprc, stats->mprc);
-}
-
-/* Export a single 32-bit register via a read-only sysctl. */
-static int
-igb_sysctl_reg_handler(SYSCTL_HANDLER_ARGS)
-{
-       struct adapter *adapter;
-       u_int val;
-
-       adapter = oidp->oid_arg1;
-       val = E1000_READ_REG(&adapter->hw, oidp->oid_arg2);
-       return (sysctl_handle_int(oidp, &val, 0, req));
-}
-
-/*
-**  Tuneable interrupt rate handler
-*/
-static int
-igb_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
-{
-       struct igb_queue        *que = ((struct igb_queue *)oidp->oid_arg1);
-       int                     error;
-       u32                     reg, usec, rate;
-                        
-       reg = E1000_READ_REG(&que->adapter->hw, E1000_EITR(que->msix));
-       usec = ((reg & 0x7FFC) >> 2);
-       if (usec > 0)
-               rate = 1000000 / usec;
-       else
-               rate = 0;
-       error = sysctl_handle_int(oidp, &rate, 0, req);
-       if (error || !req->newptr)
-               return error;
-       return 0;
-}
-
-/*
- * Add sysctl variables, one per statistic, to the system.
- */
-static void
-igb_add_hw_stats(struct adapter *adapter)
-{
-       device_t dev = adapter->dev;
-
-       struct tx_ring *txr = adapter->tx_rings;
-       struct rx_ring *rxr = adapter->rx_rings;
-
-       struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
-       struct sysctl_oid *tree = device_get_sysctl_tree(dev);
-       struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
-       struct e1000_hw_stats *stats = adapter->stats;
-
-       struct sysctl_oid *stat_node, *queue_node, *int_node, *host_node;
-       struct sysctl_oid_list *stat_list, *queue_list, *int_list, *host_list;
-
-#define QUEUE_NAME_LEN 32
-       char namebuf[QUEUE_NAME_LEN];
-
-       /* Driver Statistics */
-       SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "link_irq", 
-                       CTLFLAG_RD, &adapter->link_irq, 0,
-                       "Link MSIX IRQ Handled");
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 
-                       CTLFLAG_RD, &adapter->dropped_pkts,
-                       "Driver dropped packets");
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail", 
-                       CTLFLAG_RD, &adapter->no_tx_dma_setup,
-                       "Driver tx dma failure in xmit");
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns",
-                       CTLFLAG_RD, &adapter->rx_overruns,
-                       "RX overruns");
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_timeouts",
-                       CTLFLAG_RD, &adapter->watchdog_events,
-                       "Watchdog timeouts");
-
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "device_control", 
-                       CTLFLAG_RD, &adapter->device_control,
-                       "Device Control Register");
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_control", 
-                       CTLFLAG_RD, &adapter->rx_control,
-                       "Receiver Control Register");
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "interrupt_mask", 
-                       CTLFLAG_RD, &adapter->int_mask,
-                       "Interrupt Mask");
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "extended_int_mask", 
-                       CTLFLAG_RD, &adapter->eint_mask,
-                       "Extended Interrupt Mask");
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_buf_alloc", 
-                       CTLFLAG_RD, &adapter->packet_buf_alloc_tx,
-                       "Transmit Buffer Packet Allocation");
-       SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_buf_alloc", 
-                       CTLFLAG_RD, &adapter->packet_buf_alloc_rx,
-                       "Receive Buffer Packet Allocation");
-       SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_high_water",
-                       CTLFLAG_RD, &adapter->hw.fc.high_water, 0,
-                       "Flow Control High Watermark");
-       SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_low_water", 
-                       CTLFLAG_RD, &adapter->hw.fc.low_water, 0,
-                       "Flow Control Low Watermark");
-
-       for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) {
-               struct lro_ctrl *lro = &rxr->lro;
-
-               snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
-               queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
-                                           CTLFLAG_RD, NULL, "Queue Name");
-               queue_list = SYSCTL_CHILDREN(queue_node);
-
-               SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", 
-                               CTLFLAG_RD, &adapter->queues[i],
-                               sizeof(&adapter->queues[i]),
-                               igb_sysctl_interrupt_rate_handler,
-                               "IU", "Interrupt Rate");
-
-               SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", 
-                               CTLFLAG_RD, adapter, E1000_TDH(txr->me),
-                               igb_sysctl_reg_handler, "IU",
-                               "Transmit Descriptor Head");
-               SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail", 
-                               CTLFLAG_RD, adapter, E1000_TDT(txr->me),
-                               igb_sysctl_reg_handler, "IU",
-                               "Transmit Descriptor Tail");
-               SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "no_desc_avail", 
-                               CTLFLAG_RD, &txr->no_desc_avail,
-                               "Queue No Descriptor Available");
-               SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "tx_packets",
-                               CTLFLAG_RD, &txr->tx_packets,
-                               "Queue Packets Transmitted");
-
-               SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head", 
-                               CTLFLAG_RD, adapter, E1000_RDH(rxr->me),
-                               igb_sysctl_reg_handler, "IU",
-                               "Receive Descriptor Head");
-               SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail", 
-                               CTLFLAG_RD, adapter, E1000_RDT(rxr->me),
-                               igb_sysctl_reg_handler, "IU",
-                               "Receive Descriptor Tail");
-               SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "rx_packets",
-                               CTLFLAG_RD, &rxr->rx_packets,
-                               "Queue Packets Received");
-               SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
-                               CTLFLAG_RD, &rxr->rx_bytes,
-                               "Queue Bytes Received");
-               SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "lro_queued",
-                               CTLFLAG_RD, &lro->lro_queued, 0,
-                               "LRO Queued");
-               SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "lro_flushed",
-                               CTLFLAG_RD, &lro->lro_flushed, 0,
-                               "LRO Flushed");
-       }
-
-       /* MAC stats get their own sub node */
-
-       stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 
-                                   CTLFLAG_RD, NULL, "MAC Statistics");
-       stat_list = SYSCTL_CHILDREN(stat_node);
-
-       /*
-       ** VF adapter has a very limited set of stats
-       ** since its not managing the metal, so to speak.
-       */
-       if (adapter->vf_ifp) {
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd",
-                       CTLFLAG_RD, &stats->gprc,
-                       "Good Packets Received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
-                       CTLFLAG_RD, &stats->gptc,
-                       "Good Packets Transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd", 
-                       CTLFLAG_RD, &stats->gorc, 
-                       "Good Octets Received"); 
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 
-                       CTLFLAG_RD, &stats->gotc, 
-                       "Good Octets Transmitted"); 
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd",
-                       CTLFLAG_RD, &stats->mprc,
-                       "Multicast Packets Received");
-               return;
-       }
-
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "excess_coll", 
-                       CTLFLAG_RD, &stats->ecol,
-                       "Excessive collisions");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "single_coll", 
-                       CTLFLAG_RD, &stats->scc,
-                       "Single collisions");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "multiple_coll", 
-                       CTLFLAG_RD, &stats->mcc,
-                       "Multiple collisions");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "late_coll", 
-                       CTLFLAG_RD, &stats->latecol,
-                       "Late collisions");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "collision_count", 
-                       CTLFLAG_RD, &stats->colc,
-                       "Collision Count");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "symbol_errors",
-                       CTLFLAG_RD, &stats->symerrs,
-                       "Symbol Errors");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "sequence_errors",
-                       CTLFLAG_RD, &stats->sec,
-                       "Sequence Errors");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "defer_count",
-                       CTLFLAG_RD, &stats->dc,
-                       "Defer Count");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "missed_packets",
-                       CTLFLAG_RD, &stats->mpc,
-                       "Missed Packets");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_no_buff",
-                       CTLFLAG_RD, &stats->rnbc,
-                       "Receive No Buffers");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_undersize",
-                       CTLFLAG_RD, &stats->ruc,
-                       "Receive Undersize");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
-                       CTLFLAG_RD, &stats->rfc,
-                       "Fragmented Packets Received ");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_oversize",
-                       CTLFLAG_RD, &stats->roc,
-                       "Oversized Packets Received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_jabber",
-                       CTLFLAG_RD, &stats->rjc,
-                       "Recevied Jabber");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_errs",
-                       CTLFLAG_RD, &stats->rxerrc,
-                       "Receive Errors");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "crc_errs",
-                       CTLFLAG_RD, &stats->crcerrs,
-                       "CRC errors");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "alignment_errs",
-                       CTLFLAG_RD, &stats->algnerrc,
-                       "Alignment Errors");
-       /* On 82575 these are collision counts */
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs",
-                       CTLFLAG_RD, &stats->cexterr,
-                       "Collision/Carrier extension errors");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
-                       CTLFLAG_RD, &stats->xonrxc,
-                       "XON Received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xon_txd",
-                       CTLFLAG_RD, &stats->xontxc,
-                       "XON Transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
-                       CTLFLAG_RD, &stats->xoffrxc,
-                       "XOFF Received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
-                       CTLFLAG_RD, &stats->xofftxc,
-                       "XOFF Transmitted");
-       /* Packet Reception Stats */
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd",
-                       CTLFLAG_RD, &stats->tpr,
-                       "Total Packets Received ");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd",
-                       CTLFLAG_RD, &stats->gprc,
-                       "Good Packets Received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd",
-                       CTLFLAG_RD, &stats->bprc,
-                       "Broadcast Packets Received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd",
-                       CTLFLAG_RD, &stats->mprc,
-                       "Multicast Packets Received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
-                       CTLFLAG_RD, &stats->prc64,
-                       "64 byte frames received ");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
-                       CTLFLAG_RD, &stats->prc127,
-                       "65-127 byte frames received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
-                       CTLFLAG_RD, &stats->prc255,
-                       "128-255 byte frames received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
-                       CTLFLAG_RD, &stats->prc511,
-                       "256-511 byte frames received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
-                       CTLFLAG_RD, &stats->prc1023,
-                       "512-1023 byte frames received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
-                       CTLFLAG_RD, &stats->prc1522,
-                       "1023-1522 byte frames received");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd", 
-                       CTLFLAG_RD, &stats->gorc, 
-                       "Good Octets Received"); 
-
-       /* Packet Transmission Stats */
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 
-                       CTLFLAG_RD, &stats->gotc, 
-                       "Good Octets Transmitted"); 
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
-                       CTLFLAG_RD, &stats->tpt,
-                       "Total Packets Transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
-                       CTLFLAG_RD, &stats->gptc,
-                       "Good Packets Transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
-                       CTLFLAG_RD, &stats->bptc,
-                       "Broadcast Packets Transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
-                       CTLFLAG_RD, &stats->mptc,
-                       "Multicast Packets Transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
-                       CTLFLAG_RD, &stats->ptc64,
-                       "64 byte frames transmitted ");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
-                       CTLFLAG_RD, &stats->ptc127,
-                       "65-127 byte frames transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
-                       CTLFLAG_RD, &stats->ptc255,
-                       "128-255 byte frames transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
-                       CTLFLAG_RD, &stats->ptc511,
-                       "256-511 byte frames transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
-                       CTLFLAG_RD, &stats->ptc1023,
-                       "512-1023 byte frames transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
-                       CTLFLAG_RD, &stats->ptc1522,
-                       "1024-1522 byte frames transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tso_txd",
-                       CTLFLAG_RD, &stats->tsctc,
-                       "TSO Contexts Transmitted");
-       SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail",
-                       CTLFLAG_RD, &stats->tsctfc,
-                       "TSO Contexts Failed");
-
-
-       /* Interrupt Stats */
-
-       int_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "interrupts", 
-                                   CTLFLAG_RD, NULL, "Interrupt Statistics");
-       int_list = SYSCTL_CHILDREN(int_node);
-
-       SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "asserts",
-                       CTLFLAG_RD, &stats->iac,
-                       "Interrupt Assertion Count");
-
-       SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_pkt_timer",
-                       CTLFLAG_RD, &stats->icrxptc,
-                       "Interrupt Cause Rx Pkt Timer Expire Count");
-
-       SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_abs_timer",
-                       CTLFLAG_RD, &stats->icrxatc,
-                       "Interrupt Cause Rx Abs Timer Expire Count");
-
-       SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_pkt_timer",
-                       CTLFLAG_RD, &stats->ictxptc,
-                       "Interrupt Cause Tx Pkt Timer Expire Count");
-
-       SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_abs_timer",
-                       CTLFLAG_RD, &stats->ictxatc,
-                       "Interrupt Cause Tx Abs Timer Expire Count");
-
-       SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_queue_empty",
-                       CTLFLAG_RD, &stats->ictxqec,
-                       "Interrupt Cause Tx Queue Empty Count");
-
-       SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_queue_min_thresh",
-                       CTLFLAG_RD, &stats->ictxqmtc,
-                       "Interrupt Cause Tx Queue Min Thresh Count");
-
-       SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_desc_min_thresh",
-                       CTLFLAG_RD, &stats->icrxdmtc,
-                       "Interrupt Cause Rx Desc Min Thresh Count");
-
-       SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_overrun",
-                       CTLFLAG_RD, &stats->icrxoc,
-                       "Interrupt Cause Receiver Overrun Count");
-
-       /* Host to Card Stats */
-
-       host_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "host", 
-                                   CTLFLAG_RD, NULL, 
-                                   "Host to Card Statistics");
-
-       host_list = SYSCTL_CHILDREN(host_node);
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "breaker_tx_pkt",
-                       CTLFLAG_RD, &stats->cbtmpc,
-                       "Circuit Breaker Tx Packet Count");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "host_tx_pkt_discard",
-                       CTLFLAG_RD, &stats->htdpmc,
-                       "Host Transmit Discarded Packets");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "rx_pkt",
-                       CTLFLAG_RD, &stats->rpthc,
-                       "Rx Packets To Host");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "breaker_rx_pkts",
-                       CTLFLAG_RD, &stats->cbrmpc,
-                       "Circuit Breaker Rx Packet Count");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "breaker_rx_pkt_drop",
-                       CTLFLAG_RD, &stats->cbrdpc,
-                       "Circuit Breaker Rx Dropped Count");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "tx_good_pkt",
-                       CTLFLAG_RD, &stats->hgptc,
-                       "Host Good Packets Tx Count");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "breaker_tx_pkt_drop",
-                       CTLFLAG_RD, &stats->htcbdpc,
-                       "Host Tx Circuit Breaker Dropped Count");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "rx_good_bytes",
-                       CTLFLAG_RD, &stats->hgorc,
-                       "Host Good Octets Received Count");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "tx_good_bytes",
-                       CTLFLAG_RD, &stats->hgotc,
-                       "Host Good Octets Transmit Count");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "length_errors",
-                       CTLFLAG_RD, &stats->lenerrs,
-                       "Length Errors");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "serdes_violation_pkt",
-                       CTLFLAG_RD, &stats->scvpc,
-                       "SerDes/SGMII Code Violation Pkt Count");
-
-       SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "header_redir_missed",
-                       CTLFLAG_RD, &stats->hrmpc,
-                       "Header Redirection Missed Packet Count");
-}
-
-
-/**********************************************************************
- *
- *  This routine provides a way to dump out the adapter eeprom,
- *  often a useful debug/service tool. This only dumps the first
- *  32 words, stuff that matters is in that extent.
- *
- **********************************************************************/
-static int
-igb_sysctl_nvm_info(SYSCTL_HANDLER_ARGS)
-{
-       struct adapter *adapter;
-       int error;
-       int result;
-
-       result = -1;
-       error = sysctl_handle_int(oidp, &result, 0, req);
-
-       if (error || !req->newptr)
-               return (error);
-
-       /*
-        * This value will cause a hex dump of the
-        * first 32 16-bit words of the EEPROM to
-        * the screen.
-        */
-       if (result == 1) {
-               adapter = (struct adapter *)arg1;
-               igb_print_nvm_info(adapter);
-        }
-
-       return (error);
-}
-
-static void
-igb_print_nvm_info(struct adapter *adapter)
-{
-       u16     eeprom_data;
-       int     i, j, row = 0;
-
-       /* Its a bit crude, but it gets the job done */
-       printf("\nInterface EEPROM Dump:\n");
-       printf("Offset\n0x0000  ");
-       for (i = 0, j = 0; i < 32; i++, j++) {
-               if (j == 8) { /* Make the offset block */
-                       j = 0; ++row;
-                       printf("\n0x00%x0  ",row);
-               }
-               e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data);
-               printf("%04x ", eeprom_data);
-       }
-       printf("\n");
-}
-
-static void
-igb_set_sysctl_value(struct adapter *adapter, const char *name,
-       const char *description, int *limit, int value)
-{
-       *limit = value;
-       SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
-           SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
-           OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
-}
-
-/*
-** Set flow control using sysctl:
-** Flow control values:
-**     0 - off
-**     1 - rx pause
-**     2 - tx pause
-**     3 - full
-*/
-static int
-igb_set_flowcntl(SYSCTL_HANDLER_ARGS)
-{
-       int error;
-       struct adapter *adapter;
-
-       error = sysctl_handle_int(oidp, &igb_fc_setting, 0, req);
-
-       if (error)
-               return (error);
-
-       adapter = (struct adapter *) arg1;
-       switch (igb_fc_setting) {
-               case e1000_fc_rx_pause:
-               case e1000_fc_tx_pause:
-               case e1000_fc_full:
-                       adapter->hw.fc.requested_mode = igb_fc_setting;
-                       break;
-               case e1000_fc_none:
-               default:
-                       adapter->hw.fc.requested_mode = e1000_fc_none;
-       }
-
-       adapter->hw.fc.current_mode = adapter->hw.fc.requested_mode;
-       e1000_force_mac_fc(&adapter->hw);
-       return error;
-}
diff --git a/lib/librte_pmd_e1000/e1000/if_igb.h b/lib/librte_pmd_e1000/e1000/if_igb.h
deleted file mode 100644 (file)
index 9a0bb47..0000000
+++ /dev/null
@@ -1,541 +0,0 @@
-/******************************************************************************
-
-  Copyright (c) 2001-2011, Intel Corporation 
-  All rights reserved.
-  
-  Redistribution and use in source and binary forms, with or without 
-  modification, are permitted provided that the following conditions are met:
-  
-   1. Redistributions of source code must retain the above copyright notice, 
-      this list of conditions and the following disclaimer.
-  
-   2. Redistributions in binary form must reproduce the above copyright 
-      notice, this list of conditions and the following disclaimer in the 
-      documentation and/or other materials provided with the distribution.
-  
-   3. Neither the name of the Intel Corporation nor the names of its 
-      contributors may be used to endorse or promote products derived from 
-      this software without specific prior written permission.
-  
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
-  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
-  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
-  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
-  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-  POSSIBILITY OF SUCH DAMAGE.
-
-******************************************************************************/
-/*$FreeBSD$*/
-
-#ifndef _IGB_H_DEFINED_
-#define _IGB_H_DEFINED_
-
-/* Tunables */
-
-/*
- * IGB_TXD: Maximum number of Transmit Descriptors
- *
- *   This value is the number of transmit descriptors allocated by the driver.
- *   Increasing this value allows the driver to queue more transmits. Each
- *   descriptor is 16 bytes.
- *   Since TDLEN should be multiple of 128bytes, the number of transmit
- *   desscriptors should meet the following condition.
- *      (num_tx_desc * sizeof(struct e1000_tx_desc)) % 128 == 0
- */
-#define IGB_MIN_TXD            256
-#define IGB_DEFAULT_TXD                1024
-#define IGB_MAX_TXD            4096
-
-/*
- * IGB_RXD: Maximum number of Transmit Descriptors
- *
- *   This value is the number of receive descriptors allocated by the driver.
- *   Increasing this value allows the driver to buffer more incoming packets.
- *   Each descriptor is 16 bytes.  A receive buffer is also allocated for each
- *   descriptor. The maximum MTU size is 16110.
- *   Since TDLEN should be multiple of 128bytes, the number of transmit
- *   desscriptors should meet the following condition.
- *      (num_tx_desc * sizeof(struct e1000_tx_desc)) % 128 == 0
- */
-#define IGB_MIN_RXD            256
-#define IGB_DEFAULT_RXD                1024
-#define IGB_MAX_RXD            4096
-
-/*
- * IGB_TIDV - Transmit Interrupt Delay Value
- * Valid Range: 0-65535 (0=off)
- * Default Value: 64
- *   This value delays the generation of transmit interrupts in units of
- *   1.024 microseconds. Transmit interrupt reduction can improve CPU
- *   efficiency if properly tuned for specific network traffic. If the
- *   system is reporting dropped transmits, this value may be set too high
- *   causing the driver to run out of available transmit descriptors.
- */
-#define IGB_TIDV                         64
-
-/*
- * IGB_TADV - Transmit Absolute Interrupt Delay Value
- * Valid Range: 0-65535 (0=off)
- * Default Value: 64
- *   This value, in units of 1.024 microseconds, limits the delay in which a
- *   transmit interrupt is generated. Useful only if IGB_TIDV is non-zero,
- *   this value ensures that an interrupt is generated after the initial
- *   packet is sent on the wire within the set amount of time.  Proper tuning,
- *   along with IGB_TIDV, may improve traffic throughput in specific
- *   network conditions.
- */
-#define IGB_TADV                         64
-
-/*
- * IGB_RDTR - Receive Interrupt Delay Timer (Packet Timer)
- * Valid Range: 0-65535 (0=off)
- * Default Value: 0
- *   This value delays the generation of receive interrupts in units of 1.024
- *   microseconds.  Receive interrupt reduction can improve CPU efficiency if
- *   properly tuned for specific network traffic. Increasing this value adds
- *   extra latency to frame reception and can end up decreasing the throughput
- *   of TCP traffic. If the system is reporting dropped receives, this value
- *   may be set too high, causing the driver to run out of available receive
- *   descriptors.
- *
- *   CAUTION: When setting IGB_RDTR to a value other than 0, adapters
- *            may hang (stop transmitting) under certain network conditions.
- *            If this occurs a WATCHDOG message is logged in the system
- *            event log. In addition, the controller is automatically reset,
- *            restoring the network connection. To eliminate the potential
- *            for the hang ensure that IGB_RDTR is set to 0.
- */
-#define IGB_RDTR                         0
-
-/*
- * Receive Interrupt Absolute Delay Timer (Not valid for 82542/82543/82544)
- * Valid Range: 0-65535 (0=off)
- * Default Value: 64
- *   This value, in units of 1.024 microseconds, limits the delay in which a
- *   receive interrupt is generated. Useful only if IGB_RDTR is non-zero,
- *   this value ensures that an interrupt is generated after the initial
- *   packet is received within the set amount of time.  Proper tuning,
- *   along with IGB_RDTR, may improve traffic throughput in specific network
- *   conditions.
- */
-#define IGB_RADV                         64
-
-/*
- * This parameter controls the duration of transmit watchdog timer.
- */
-#define IGB_WATCHDOG                   (10 * hz)
-
-/*
- * This parameter controls when the driver calls the routine to reclaim
- * transmit descriptors. Cleaning earlier seems a win.
- */
-#define IGB_TX_CLEANUP_THRESHOLD       (adapter->num_tx_desc / 2)
-
-/*
- * This parameter controls whether or not autonegotation is enabled.
- *              0 - Disable autonegotiation
- *              1 - Enable  autonegotiation
- */
-#define DO_AUTO_NEG                     1
-
-/*
- * This parameter control whether or not the driver will wait for
- * autonegotiation to complete.
- *              1 - Wait for autonegotiation to complete
- *              0 - Don't wait for autonegotiation to complete
- */
-#define WAIT_FOR_AUTO_NEG_DEFAULT       0
-
-/* Tunables -- End */
-
-#define AUTONEG_ADV_DEFAULT    (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
-                               ADVERTISE_100_HALF | ADVERTISE_100_FULL | \
-                               ADVERTISE_1000_FULL)
-
-#define AUTO_ALL_MODES         0
-
-/* PHY master/slave setting */
-#define IGB_MASTER_SLAVE               e1000_ms_hw_default
-
-/*
- * Micellaneous constants
- */
-#define IGB_VENDOR_ID                  0x8086
-
-#define IGB_JUMBO_PBA                  0x00000028
-#define IGB_DEFAULT_PBA                        0x00000030
-#define IGB_SMARTSPEED_DOWNSHIFT       3
-#define IGB_SMARTSPEED_MAX             15
-#define IGB_MAX_LOOP                   10
-
-#define IGB_RX_PTHRESH                 (hw->mac.type <= e1000_82576 ? 16 : 8)
-#define IGB_RX_HTHRESH                 8
-#define IGB_RX_WTHRESH                 1
-
-#define IGB_TX_PTHRESH                 8
-#define IGB_TX_HTHRESH                 1
-#define IGB_TX_WTHRESH                 ((hw->mac.type != e1000_82575 && \
-                                          adapter->msix_mem) ? 1 : 16)
-
-#define MAX_NUM_MULTICAST_ADDRESSES     128
-#define PCI_ANY_ID                      (~0U)
-#define ETHER_ALIGN                     2
-#define IGB_TX_BUFFER_SIZE             ((uint32_t) 1514)
-#define IGB_FC_PAUSE_TIME              0x0680
-#define IGB_EEPROM_APME                        0x400;
-#define IGB_QUEUE_IDLE                 0
-#define IGB_QUEUE_WORKING              1
-#define IGB_QUEUE_HUNG                 2
-
-/*
- * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
- * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will
- * also optimize cache line size effect. H/W supports up to cache line size 128.
- */
-#define IGB_DBA_ALIGN                  128
-
-#define SPEED_MODE_BIT (1<<21)         /* On PCI-E MACs only */
-
-/* PCI Config defines */
-#define IGB_MSIX_BAR           3
-
-/* Defines for printing debug information */
-#define DEBUG_INIT  0
-#define DEBUG_IOCTL 0
-#define DEBUG_HW    0
-
-#define INIT_DEBUGOUT(S)            if (DEBUG_INIT)  printf(S "\n")
-#define INIT_DEBUGOUT1(S, A)        if (DEBUG_INIT)  printf(S "\n", A)
-#define INIT_DEBUGOUT2(S, A, B)     if (DEBUG_INIT)  printf(S "\n", A, B)
-#define IOCTL_DEBUGOUT(S)           if (DEBUG_IOCTL) printf(S "\n")
-#define IOCTL_DEBUGOUT1(S, A)       if (DEBUG_IOCTL) printf(S "\n", A)
-#define IOCTL_DEBUGOUT2(S, A, B)    if (DEBUG_IOCTL) printf(S "\n", A, B)
-#define HW_DEBUGOUT(S)              if (DEBUG_HW) printf(S "\n")
-#define HW_DEBUGOUT1(S, A)          if (DEBUG_HW) printf(S "\n", A)
-#define HW_DEBUGOUT2(S, A, B)       if (DEBUG_HW) printf(S "\n", A, B)
-
-#define IGB_MAX_SCATTER                64
-#define IGB_VFTA_SIZE          128
-#define IGB_BR_SIZE            4096    /* ring buf size */
-#define IGB_TSO_SIZE           (65535 + sizeof(struct ether_vlan_header))
-#define IGB_TSO_SEG_SIZE       4096    /* Max dma segment size */
-#define IGB_HDR_BUF            128
-#define IGB_PKTTYPE_MASK       0x0000FFF0
-#define ETH_ZLEN               60
-#define ETH_ADDR_LEN           6
-
-/* Offload bits in mbuf flag */
-#if __FreeBSD_version >= 800000
-#define CSUM_OFFLOAD           (CSUM_IP|CSUM_TCP|CSUM_UDP|CSUM_SCTP)
-#else
-#define CSUM_OFFLOAD           (CSUM_IP|CSUM_TCP|CSUM_UDP)
-#endif
-
-/* Define the starting Interrupt rate per Queue */
-#define IGB_INTS_PER_SEC        8000
-#define IGB_DEFAULT_ITR         ((1000000/IGB_INTS_PER_SEC) << 2)
-
-#define IGB_LINK_ITR            2000
-
-/* Precision Time Sync (IEEE 1588) defines */
-#define ETHERTYPE_IEEE1588     0x88F7
-#define PICOSECS_PER_TICK      20833
-#define TSYNC_PORT             319 /* UDP port for the protocol */
-
-/*
- * Bus dma allocation structure used by
- * e1000_dma_malloc and e1000_dma_free.
- */
-struct igb_dma_alloc {
-        bus_addr_t              dma_paddr;
-        caddr_t                 dma_vaddr;
-        bus_dma_tag_t           dma_tag;
-        bus_dmamap_t            dma_map;
-        bus_dma_segment_t       dma_seg;
-        int                     dma_nseg;
-};
-
-
-/*
-** Driver queue struct: this is the interrupt container
-**  for the associated tx and rx ring.
-*/
-struct igb_queue {
-       struct adapter          *adapter;
-       u32                     msix;           /* This queue's MSIX vector */
-       u32                     eims;           /* This queue's EIMS bit */
-       u32                     eitr_setting;
-       struct resource         *res;
-       void                    *tag;
-       struct tx_ring          *txr;
-       struct rx_ring          *rxr;
-       struct task             que_task;
-       struct taskqueue        *tq;
-       u64                     irqs;
-};
-
-/*
- * Transmit ring: one per queue
- */
-struct tx_ring {
-       struct adapter          *adapter;
-       u32                     me;
-       struct mtx              tx_mtx;
-       char                    mtx_name[16];
-       struct igb_dma_alloc    txdma;
-       struct e1000_tx_desc    *tx_base;
-       u32                     next_avail_desc;
-       u32                     next_to_clean;
-       volatile u16            tx_avail;
-       struct igb_tx_buffer    *tx_buffers;
-#if __FreeBSD_version >= 800000
-       struct buf_ring         *br;
-#endif
-       bus_dma_tag_t           txtag;
-
-       u32                     bytes;
-       u32                     packets;
-
-       int                     queue_status;
-       int                     watchdog_time;
-       int                     tdt;
-       int                     tdh;
-       u64                     no_desc_avail;
-       u64                     tx_packets;
-};
-
-/*
- * Receive ring: one per queue
- */
-struct rx_ring {
-       struct adapter          *adapter;
-       u32                     me;
-       struct igb_dma_alloc    rxdma;
-       union e1000_adv_rx_desc *rx_base;
-       struct lro_ctrl         lro;
-       bool                    lro_enabled;
-       bool                    hdr_split;
-       bool                    discard;
-       struct mtx              rx_mtx;
-       char                    mtx_name[16];
-       u32                     next_to_refresh;
-       u32                     next_to_check;
-       struct igb_rx_buf       *rx_buffers;
-       bus_dma_tag_t           htag;           /* dma tag for rx head */
-       bus_dma_tag_t           ptag;           /* dma tag for rx packet */
-       /*
-        * First/last mbuf pointers, for
-        * collecting multisegment RX packets.
-        */
-       struct mbuf            *fmp;
-       struct mbuf            *lmp;
-
-       u32                     bytes;
-       u32                     packets;
-       int                     rdt;
-       int                     rdh;
-
-       /* Soft stats */
-       u64                     rx_split_packets;
-       u64                     rx_discarded;
-       u64                     rx_packets;
-       u64                     rx_bytes;
-};
-
-struct adapter {
-       struct ifnet    *ifp;
-       struct e1000_hw hw;
-
-       struct e1000_osdep osdep;
-       struct device   *dev;
-       struct cdev     *led_dev;
-
-       struct resource *pci_mem;
-       struct resource *msix_mem;
-       struct resource *res;
-       void            *tag;
-       u32             que_mask;
-
-       int             linkvec;
-       int             link_mask;
-       struct task     link_task;
-       int             link_irq;
-
-       struct ifmedia  media;
-       struct callout  timer;
-       int             msix;   /* total vectors allocated */
-       int             if_flags;
-       int             max_frame_size;
-       int             min_frame_size;
-       int             pause_frames;
-       struct mtx      core_mtx;
-       int             igb_insert_vlan_header;
-        u16            num_queues;
-       u16             vf_ifp;  /* a VF interface */
-
-       eventhandler_tag vlan_attach;
-       eventhandler_tag vlan_detach;
-       u32             num_vlans;
-
-       /* Management and WOL features */
-       int             wol;
-       int             has_manage;
-
-       /*
-       ** Shadow VFTA table, this is needed because
-       ** the real vlan filter table gets cleared during
-       ** a soft reset and the driver needs to be able
-       ** to repopulate it.
-       */
-       u32             shadow_vfta[IGB_VFTA_SIZE];
-
-       /* Info about the interface */
-       u8              link_active;
-       u16             link_speed;
-       u16             link_duplex;
-       u32             smartspeed;
-       u32             dma_coalesce;
-
-       /* Interface queues */
-       struct igb_queue        *queues;
-
-       /*
-        * Transmit rings
-        */
-       struct tx_ring          *tx_rings;
-        u16                    num_tx_desc;
-
-       /* Multicast array pointer */
-       u8                      *mta;
-
-       /* 
-        * Receive rings
-        */
-       struct rx_ring          *rx_rings;
-       bool                    rx_hdr_split;
-        u16                    num_rx_desc;
-       int                     rx_process_limit;
-       u32                     rx_mbuf_sz;
-       u32                     rx_mask;
-
-       /* Misc stats maintained by the driver */
-       unsigned long   dropped_pkts;
-       unsigned long   mbuf_defrag_failed;
-       unsigned long   mbuf_header_failed;
-       unsigned long   mbuf_packet_failed;
-       unsigned long   no_tx_map_avail;
-        unsigned long  no_tx_dma_setup;
-       unsigned long   watchdog_events;
-       unsigned long   rx_overruns;
-       unsigned long   device_control;
-       unsigned long   rx_control;
-       unsigned long   int_mask;
-       unsigned long   eint_mask;
-       unsigned long   packet_buf_alloc_rx;
-       unsigned long   packet_buf_alloc_tx;
-
-       boolean_t       in_detach;
-
-#ifdef IGB_IEEE1588
-       /* IEEE 1588 precision time support */
-       struct cyclecounter     cycles;
-       struct nettimer         clock;
-       struct nettime_compare  compare;
-       struct hwtstamp_ctrl    hwtstamp;
-#endif
-
-       void                    *stats;
-};
-
-/* ******************************************************************************
- * vendor_info_array
- *
- * This array contains the list of Subvendor/Subdevice IDs on which the driver
- * should load.
- *
- * ******************************************************************************/
-typedef struct _igb_vendor_info_t {
-       unsigned int vendor_id;
-       unsigned int device_id;
-       unsigned int subvendor_id;
-       unsigned int subdevice_id;
-       unsigned int index;
-} igb_vendor_info_t;
-
-
-struct igb_tx_buffer {
-       int             next_eop;  /* Index of the desc to watch */
-        struct mbuf    *m_head;
-        bus_dmamap_t    map;         /* bus_dma map for packet */
-};
-
-struct igb_rx_buf {
-        struct mbuf    *m_head;
-        struct mbuf    *m_pack;
-       bus_dmamap_t    hmap;   /* bus_dma map for header */
-       bus_dmamap_t    pmap;   /* bus_dma map for packet */
-};
-
-/*
-** Find the number of unrefreshed RX descriptors
-*/
-static inline u16
-igb_rx_unrefreshed(struct rx_ring *rxr)
-{
-       struct adapter  *adapter = rxr->adapter;
-       if (rxr->next_to_check > rxr->next_to_refresh)
-               return (rxr->next_to_check - rxr->next_to_refresh - 1);
-       else
-               return ((adapter->num_rx_desc + rxr->next_to_check) -
-                   rxr->next_to_refresh - 1);
-}
-
-#define        IGB_CORE_LOCK_INIT(_sc, _name) \
-       mtx_init(&(_sc)->core_mtx, _name, "IGB Core Lock", MTX_DEF)
-#define        IGB_CORE_LOCK_DESTROY(_sc)      mtx_destroy(&(_sc)->core_mtx)
-#define        IGB_CORE_LOCK(_sc)              mtx_lock(&(_sc)->core_mtx)
-#define        IGB_CORE_UNLOCK(_sc)            mtx_unlock(&(_sc)->core_mtx)
-#define        IGB_CORE_LOCK_ASSERT(_sc)       mtx_assert(&(_sc)->core_mtx, MA_OWNED)
-
-#define        IGB_TX_LOCK_DESTROY(_sc)        mtx_destroy(&(_sc)->tx_mtx)
-#define        IGB_TX_LOCK(_sc)                mtx_lock(&(_sc)->tx_mtx)
-#define        IGB_TX_UNLOCK(_sc)              mtx_unlock(&(_sc)->tx_mtx)
-#define        IGB_TX_TRYLOCK(_sc)             mtx_trylock(&(_sc)->tx_mtx)
-#define        IGB_TX_LOCK_ASSERT(_sc)         mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
-
-#define        IGB_RX_LOCK_DESTROY(_sc)        mtx_destroy(&(_sc)->rx_mtx)
-#define        IGB_RX_LOCK(_sc)                mtx_lock(&(_sc)->rx_mtx)
-#define        IGB_RX_UNLOCK(_sc)              mtx_unlock(&(_sc)->rx_mtx)
-#define        IGB_RX_LOCK_ASSERT(_sc)         mtx_assert(&(_sc)->rx_mtx, MA_OWNED)
-
-#define UPDATE_VF_REG(reg, last, cur)          \
-{                                              \
-       u32 new = E1000_READ_REG(hw, reg);      \
-       if (new < last)                         \
-               cur += 0x100000000LL;           \
-       last = new;                             \
-       cur &= 0xFFFFFFFF00000000LL;            \
-       cur |= new;                             \
-}
-
-#if __FreeBSD_version < 800504
-static __inline int
-drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
-{
-#ifdef ALTQ
-       if (ALTQ_IS_ENABLED(&ifp->if_snd))
-               return (1);
-#endif
-       return (!buf_ring_empty(br));
-}
-#endif
-
-#endif /* _IGB_H_DEFINED_ */
-
-