ig_hal: Merge Intel igb-2.2.3 HAL w/ em-7.2.4 HAL
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 19 Apr 2012 14:11:00 +0000 (22:11 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 20 May 2012 13:42:02 +0000 (21:42 +0800)
20 files changed:
sys/conf/files
sys/dev/netif/ig_hal/Makefile
sys/dev/netif/ig_hal/e1000_82575.c [new file with mode: 0644]
sys/dev/netif/ig_hal/e1000_82575.h [new file with mode: 0644]
sys/dev/netif/ig_hal/e1000_api.c
sys/dev/netif/ig_hal/e1000_api.h
sys/dev/netif/ig_hal/e1000_defines.h
sys/dev/netif/ig_hal/e1000_hw.h
sys/dev/netif/ig_hal/e1000_mac.c
sys/dev/netif/ig_hal/e1000_mac.h
sys/dev/netif/ig_hal/e1000_manage.c
sys/dev/netif/ig_hal/e1000_manage.h
sys/dev/netif/ig_hal/e1000_mbx.c [new file with mode: 0644]
sys/dev/netif/ig_hal/e1000_mbx.h [new file with mode: 0644]
sys/dev/netif/ig_hal/e1000_osdep.c
sys/dev/netif/ig_hal/e1000_phy.c
sys/dev/netif/ig_hal/e1000_phy.h
sys/dev/netif/ig_hal/e1000_regs.h
sys/dev/netif/ig_hal/e1000_vf.c [new file with mode: 0644]
sys/dev/netif/ig_hal/e1000_vf.h [new file with mode: 0644]

index 6e7d1a2..a7d6d3a 100644 (file)
@@ -306,13 +306,16 @@ dev/netif/ig_hal/e1000_82541.c    optional ig_hal
 dev/netif/ig_hal/e1000_82542.c optional ig_hal
 dev/netif/ig_hal/e1000_82543.c optional ig_hal
 dev/netif/ig_hal/e1000_82571.c optional ig_hal
+dev/netif/ig_hal/e1000_82575.c optional ig_hal
 dev/netif/ig_hal/e1000_api.c   optional ig_hal
 dev/netif/ig_hal/e1000_ich8lan.c       optional ig_hal
 dev/netif/ig_hal/e1000_mac.c   optional ig_hal
 dev/netif/ig_hal/e1000_manage.c        optional ig_hal
+dev/netif/ig_hal/e1000_mbx.c   optional ig_hal
 dev/netif/ig_hal/e1000_nvm.c   optional ig_hal
 dev/netif/ig_hal/e1000_osdep.c optional ig_hal
 dev/netif/ig_hal/e1000_phy.c   optional ig_hal
+dev/netif/ig_hal/e1000_vf.c    optional ig_hal
 dev/atm/en/midway.c            optional en
 dev/netif/et/if_et.c           optional et
 dev/netif/ex/if_ex.c           optional ex
index 4007230..29a4f5b 100644 (file)
@@ -1,8 +1,9 @@
 KMOD   = ig_hal
 SRCS   = device_if.h pci_if.h bus_if.h
 SRCS   += e1000_osdep.c
-SRCS   += e1000_api.c e1000_mac.c e1000_manage.c e1000_nvm.c e1000_phy.c
+SRCS   += e1000_api.c e1000_mac.c e1000_manage.c e1000_nvm.c e1000_phy.c \
+          e1000_mbx.c
 SRCS   += e1000_80003es2lan.c e1000_82540.c e1000_82541.c e1000_82542.c \
-          e1000_82543.c e1000_82571.c e1000_ich8lan.c
+          e1000_82543.c e1000_82571.c e1000_ich8lan.c e1000_82575.c e1000_vf.c
 
 .include <bsd.kmod.mk>
diff --git a/sys/dev/netif/ig_hal/e1000_82575.c b/sys/dev/netif/ig_hal/e1000_82575.c
new file mode 100644 (file)
index 0000000..b2f1fca
--- /dev/null
@@ -0,0 +1,2429 @@
+/******************************************************************************
+
+  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$*/
+
+/*
+ * 82575EB Gigabit Network Connection
+ * 82575EB Gigabit Backplane Connection
+ * 82575GB Gigabit Network Connection
+ * 82576 Gigabit Network Connection
+ * 82576 Quad Port Gigabit Mezzanine Adapter
+ */
+
+#include "e1000_api.h"
+
+static s32  e1000_init_phy_params_82575(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82575(struct e1000_hw *hw);
+static s32  e1000_acquire_phy_82575(struct e1000_hw *hw);
+static void e1000_release_phy_82575(struct e1000_hw *hw);
+static s32  e1000_acquire_nvm_82575(struct e1000_hw *hw);
+static void e1000_release_nvm_82575(struct e1000_hw *hw);
+static s32  e1000_check_for_link_82575(struct e1000_hw *hw);
+static s32  e1000_get_cfg_done_82575(struct e1000_hw *hw);
+static s32  e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
+                                         u16 *duplex);
+static s32  e1000_init_hw_82575(struct e1000_hw *hw);
+static s32  e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw);
+static s32  e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
+                                           u16 *data);
+static s32  e1000_reset_hw_82575(struct e1000_hw *hw);
+static s32  e1000_reset_hw_82580(struct e1000_hw *hw);
+static s32  e1000_read_phy_reg_82580(struct e1000_hw *hw,
+                                    u32 offset, u16 *data);
+static s32  e1000_write_phy_reg_82580(struct e1000_hw *hw,
+                                     u32 offset, u16 data);
+static s32  e1000_set_d0_lplu_state_82580(struct e1000_hw *hw,
+                                          bool active);
+static s32  e1000_set_d3_lplu_state_82580(struct e1000_hw *hw,
+                                          bool active);
+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_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);
+static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw);
+static s32  e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
+static s32  e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
+                                                 u16 *speed, u16 *duplex);
+static s32  e1000_get_phy_id_82575(struct e1000_hw *hw);
+static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
+static bool e1000_sgmii_active_82575(struct e1000_hw *hw);
+static s32  e1000_reset_init_script_82575(struct e1000_hw *hw);
+static s32  e1000_read_mac_addr_82575(struct e1000_hw *hw);
+static void e1000_config_collision_dist_82575(struct e1000_hw *hw);
+static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw);
+static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw);
+static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw);
+static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw);
+static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw);
+static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw,
+                                               u16 offset);
+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 };
+#define E1000_82580_RXPBS_TABLE_SIZE \
+       (sizeof(e1000_82580_rxpbs_table)/sizeof(u16))
+
+
+/**
+ *  e1000_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to determine if the I2C pins are being used for I2C or as an
+ *  external MDIO interface since the two options are mutually exclusive.
+ **/
+static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw)
+{
+       u32 reg = 0;
+       bool ext_mdio = FALSE;
+
+       DEBUGFUNC("e1000_sgmii_uses_mdio_82575");
+
+       switch (hw->mac.type) {
+       case e1000_82575:
+       case e1000_82576:
+               reg = E1000_READ_REG(hw, E1000_MDIC);
+               ext_mdio = !!(reg & E1000_MDIC_DEST);
+               break;
+       case e1000_82580:
+       case e1000_i350:
+               reg = E1000_READ_REG(hw, E1000_MDICNFG);
+               ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
+               break;
+       default:
+               break;
+       }
+       return ext_mdio;
+}
+
+/**
+ *  e1000_init_phy_params_82575 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = E1000_SUCCESS;
+       u32 ctrl_ext;
+
+       DEBUGFUNC("e1000_init_phy_params_82575");
+
+       if (hw->phy.media_type != e1000_media_type_copper) {
+               phy->type = e1000_phy_none;
+               goto out;
+       }
+
+       phy->ops.power_up   = e1000_power_up_phy_copper;
+       phy->ops.power_down = e1000_power_down_phy_copper_82575;
+
+       phy->autoneg_mask           = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us         = 100;
+
+       phy->ops.acquire            = e1000_acquire_phy_82575;
+       phy->ops.check_reset_block  = e1000_check_reset_block_generic;
+       phy->ops.commit             = e1000_phy_sw_reset_generic;
+       phy->ops.get_cfg_done       = e1000_get_cfg_done_82575;
+       phy->ops.release            = e1000_release_phy_82575;
+
+       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+
+       if (e1000_sgmii_active_82575(hw)) {
+               phy->ops.reset      = e1000_phy_hw_reset_sgmii_82575;
+               ctrl_ext |= E1000_CTRL_I2C_ENA;
+       } else {
+               phy->ops.reset      = e1000_phy_hw_reset_generic;
+               ctrl_ext &= ~E1000_CTRL_I2C_ENA;
+       }
+
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       e1000_reset_mdicnfg_82580(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) {
+               phy->ops.read_reg   = e1000_read_phy_reg_82580;
+               phy->ops.write_reg  = e1000_write_phy_reg_82580;
+       } else {
+               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);
+
+       /* Verify phy id and set remaining function pointers */
+       switch (phy->id) {
+       case I347AT4_E_PHY_ID:
+       case M88E1112_E_PHY_ID:
+       case M88E1340M_E_PHY_ID:
+       case M88E1111_I_PHY_ID:
+               phy->type                   = e1000_phy_m88;
+               phy->ops.check_polarity     = e1000_check_polarity_m88;
+               phy->ops.get_info           = e1000_get_phy_info_m88;
+               if (phy->id == I347AT4_E_PHY_ID ||
+                   phy->id == M88E1112_E_PHY_ID ||
+                   phy->id == M88E1340M_E_PHY_ID)
+                       phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2;
+               else
+                       phy->ops.get_cable_length = e1000_get_cable_length_m88;
+               phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
+               break;
+       case IGP03E1000_E_PHY_ID:
+       case IGP04E1000_E_PHY_ID:
+               phy->type                   = e1000_phy_igp_3;
+               phy->ops.check_polarity     = e1000_check_polarity_igp;
+               phy->ops.get_info           = e1000_get_phy_info_igp;
+               phy->ops.get_cable_length   = e1000_get_cable_length_igp_2;
+               phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
+               phy->ops.set_d0_lplu_state  = e1000_set_d0_lplu_state_82575;
+               phy->ops.set_d3_lplu_state  = e1000_set_d3_lplu_state_generic;
+               break;
+       case I82580_I_PHY_ID:
+       case I350_I_PHY_ID:
+               phy->type                   = e1000_phy_82580;
+               phy->ops.check_polarity     = e1000_check_polarity_82577;
+               phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82577;
+               phy->ops.get_cable_length   = e1000_get_cable_length_82577;
+               phy->ops.get_info           = e1000_get_phy_info_82577;
+               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;
+       default:
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_nvm_params_82575 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
+{
+       struct e1000_nvm_info *nvm = &hw->nvm;
+       u32 eecd = E1000_READ_REG(hw, E1000_EECD);
+       u16 size;
+
+       DEBUGFUNC("e1000_init_nvm_params_82575");
+
+       size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+                    E1000_EECD_SIZE_EX_SHIFT);
+       /*
+        * Added to a constant, "size" becomes the left-shift value
+        * for setting word_size.
+        */
+       size += NVM_WORD_SIZE_BASE_SHIFT;
+
+       nvm->word_size = 1 << size;
+       nvm->opcode_bits        = 8;
+       nvm->delay_usec         = 1;
+       switch (nvm->override) {
+       case e1000_nvm_override_spi_large:
+               nvm->page_size    = 32;
+               nvm->address_bits = 16;
+               break;
+       case e1000_nvm_override_spi_small:
+               nvm->page_size    = 8;
+               nvm->address_bits = 8;
+               break;
+       default:
+               nvm->page_size    = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
+               nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
+               break;
+       }
+
+       nvm->type = e1000_nvm_eeprom_spi;
+
+       if (nvm->word_size == (1 << 15))
+               nvm->page_size = 128;
+
+       /* Function Pointers */
+       nvm->ops.acquire    = e1000_acquire_nvm_82575;
+       nvm->ops.release    = e1000_release_nvm_82575;
+       if (nvm->word_size < (1 << 15))
+               nvm->ops.read    = e1000_read_nvm_eerd;
+       else
+               nvm->ops.read    = e1000_read_nvm_spi;
+
+       nvm->ops.write              = e1000_write_nvm_spi;
+       nvm->ops.validate           = e1000_validate_nvm_checksum_generic;
+       nvm->ops.update             = e1000_update_nvm_checksum_generic;
+       nvm->ops.valid_led_default  = e1000_valid_led_default_82575;
+
+       /* override genric family function pointers for specific descendants */
+       switch (hw->mac.type) {
+       case e1000_82580:
+               nvm->ops.validate = e1000_validate_nvm_checksum_82580;
+               nvm->ops.update = e1000_update_nvm_checksum_82580;
+               break;
+       case e1000_i350:
+               nvm->ops.validate = e1000_validate_nvm_checksum_i350;
+               nvm->ops.update = e1000_update_nvm_checksum_i350;
+               break;
+       default:
+               break;
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_mac_params_82575 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+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;
+       }
+
+       /* Set mta register count */
+       mac->mta_reg_count = 128;
+       /* Set uta register count */
+       mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128;
+       /* Set rar entry count */
+       mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
+       if (mac->type == e1000_82576)
+               mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
+       if (mac->type == e1000_82580)
+               mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
+       if (mac->type == e1000_i350) {
+               mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
+               /* Enable EEE default settings for i350 */
+               dev_spec->eee_disable = FALSE;
+       }
+
+       /* Set if part includes ASF firmware */
+       mac->asf_firmware_present = TRUE;
+       /* FWSM register */
+       mac->has_fwsm = TRUE;
+       /* ARC supported; valid only if manageability features are enabled. */
+       mac->arc_subsystem_valid =
+               (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK)
+                       ? TRUE : FALSE;
+
+       /* Function pointers */
+
+       /* bus type/speed/width */
+       mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
+       /* reset */
+       if (mac->type >= e1000_82580)
+               mac->ops.reset_hw = e1000_reset_hw_82580;
+       else
+       mac->ops.reset_hw = e1000_reset_hw_82575;
+       /* hw initialization */
+       mac->ops.init_hw = e1000_init_hw_82575;
+       /* link setup */
+       mac->ops.setup_link = e1000_setup_link_generic;
+       /* physical interface link setup */
+       mac->ops.setup_physical_interface =
+               (hw->phy.media_type == e1000_media_type_copper)
+                       ? e1000_setup_copper_link_82575
+                       : e1000_setup_serdes_link_82575;
+       /* physical interface shutdown */
+       mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575;
+       /* physical interface power up */
+       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;
+       /* writing VFTA */
+       mac->ops.write_vfta = e1000_write_vfta_generic;
+       /* clearing VFTA */
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
+       /* ID LED init */
+       mac->ops.id_led_init = e1000_id_led_init_generic;
+       /* blink LED */
+       mac->ops.blink_led = e1000_blink_led_generic;
+       /* setup LED */
+       mac->ops.setup_led = e1000_setup_led_generic;
+       /* cleanup LED */
+       mac->ops.cleanup_led = e1000_cleanup_led_generic;
+       /* turn on/off LED */
+       mac->ops.led_on = e1000_led_on_generic;
+       mac->ops.led_off = e1000_led_off_generic;
+       /* clear hardware counters */
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575;
+       /* link info */
+       mac->ops.get_link_up_info = e1000_get_link_up_info_82575;
+
+       /* set lan id for port to determine which phy lock to use */
+       hw->mac.ops.set_lan_id(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_function_pointers_82575 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void e1000_init_function_pointers_82575(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_function_pointers_82575");
+
+       hw->mac.ops.init_params = e1000_init_mac_params_82575;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82575;
+       hw->phy.ops.init_params = e1000_init_phy_params_82575;
+       hw->mbx.ops.init_params = e1000_init_mbx_params_pf;
+}
+
+/**
+ *  e1000_acquire_phy_82575 - Acquire rights to access PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire access rights to the correct PHY.
+ **/
+static s32 e1000_acquire_phy_82575(struct e1000_hw *hw)
+{
+       u16 mask = E1000_SWFW_PHY0_SM;
+
+       DEBUGFUNC("e1000_acquire_phy_82575");
+
+       if (hw->bus.func == E1000_FUNC_1)
+               mask = E1000_SWFW_PHY1_SM;
+       else if (hw->bus.func == E1000_FUNC_2)
+               mask = E1000_SWFW_PHY2_SM;
+       else if (hw->bus.func == E1000_FUNC_3)
+               mask = E1000_SWFW_PHY3_SM;
+
+       return e1000_acquire_swfw_sync_82575(hw, mask);
+}
+
+/**
+ *  e1000_release_phy_82575 - Release rights to access PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  A wrapper to release access rights to the correct PHY.
+ **/
+static void e1000_release_phy_82575(struct e1000_hw *hw)
+{
+       u16 mask = E1000_SWFW_PHY0_SM;
+
+       DEBUGFUNC("e1000_release_phy_82575");
+
+       if (hw->bus.func == E1000_FUNC_1)
+               mask = E1000_SWFW_PHY1_SM;
+       else if (hw->bus.func == E1000_FUNC_2)
+               mask = E1000_SWFW_PHY2_SM;
+       else if (hw->bus.func == E1000_FUNC_3)
+               mask = E1000_SWFW_PHY3_SM;
+
+       e1000_release_swfw_sync_82575(hw, mask);
+}
+
+/**
+ *  e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY register at offset using the serial gigabit media independent
+ *  interface and stores the retrieved information in data.
+ **/
+static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
+                                          u16 *data)
+{
+       s32 ret_val = -E1000_ERR_PARAM;
+
+       DEBUGFUNC("e1000_read_phy_reg_sgmii_82575");
+
+       if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
+               DEBUGOUT1("PHY Address %u is out of range\n", offset);
+               goto out;
+       }
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               goto out;
+
+       ret_val = e1000_read_phy_reg_i2c(hw, offset, data);
+
+       hw->phy.ops.release(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii
+ *  @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 using the serial gigabit
+ *  media independent interface.
+ **/
+static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
+                                           u16 data)
+{
+       s32 ret_val = -E1000_ERR_PARAM;
+
+       DEBUGFUNC("e1000_write_phy_reg_sgmii_82575");
+
+       if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
+               DEBUGOUT1("PHY Address %d is out of range\n", offset);
+               goto out;
+       }
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               goto out;
+
+       ret_val = e1000_write_phy_reg_i2c(hw, offset, data);
+
+       hw->phy.ops.release(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_get_phy_id_82575 - Retrieve PHY addr and id
+ *  @hw: pointer to the HW structure
+ *
+ *  Retrieves the PHY address and ID for both PHY's which do and do not use
+ *  sgmi interface.
+ **/
+static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32  ret_val = E1000_SUCCESS;
+       u16 phy_id;
+       u32 ctrl_ext;
+       u32 mdic;
+
+       DEBUGFUNC("e1000_get_phy_id_82575");
+
+       /*
+        * For SGMII PHYs, we try the list of possible addresses until
+        * we find one that works.  For non-SGMII PHYs
+        * (e.g. integrated copper PHYs), an address of 1 should
+        * work.  The result of this function should mean phy->phy_addr
+        * and phy->id are set correctly.
+        */
+       if (!e1000_sgmii_active_82575(hw)) {
+               phy->addr = 1;
+               ret_val = e1000_get_phy_id(hw);
+               goto out;
+       }
+
+       if (e1000_sgmii_uses_mdio_82575(hw)) {
+               switch (hw->mac.type) {
+               case e1000_82575:
+               case e1000_82576:
+                       mdic = E1000_READ_REG(hw, E1000_MDIC);
+                       mdic &= E1000_MDIC_PHY_MASK;
+                       phy->addr = mdic >> E1000_MDIC_PHY_SHIFT;
+                       break;
+               case e1000_82580:
+               case e1000_i350:
+                       mdic = E1000_READ_REG(hw, E1000_MDICNFG);
+                       mdic &= E1000_MDICNFG_PHY_MASK;
+                       phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
+                       break;
+               default:
+                       ret_val = -E1000_ERR_PHY;
+                       goto out;
+                       break;
+               }
+               ret_val = e1000_get_phy_id(hw);
+               goto out;
+       }
+
+       /* Power on sgmii phy if it is disabled */
+       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT,
+                       ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA);
+       E1000_WRITE_FLUSH(hw);
+       msec_delay(300);
+
+       /*
+        * The address field in the I2CCMD register is 3 bits and 0 is invalid.
+        * Therefore, we need to test 1-7
+        */
+       for (phy->addr = 1; phy->addr < 8; phy->addr++) {
+               ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id);
+               if (ret_val == E1000_SUCCESS) {
+                       DEBUGOUT2("Vendor ID 0x%08X read at address %u\n",
+                                 phy_id,
+                                 phy->addr);
+                       /*
+                        * At the time of this writing, The M88 part is
+                        * the only supported SGMII PHY product.
+                        */
+                       if (phy_id == M88_VENDOR)
+                               break;
+               } else {
+                       DEBUGOUT1("PHY address %u was unreadable\n",
+                                 phy->addr);
+               }
+       }
+
+       /* A valid PHY type couldn't be found. */
+       if (phy->addr == 8) {
+               phy->addr = 0;
+               ret_val = -E1000_ERR_PHY;
+       } else {
+               ret_val = e1000_get_phy_id(hw);
+       }
+
+       /* restore previous sfp cage power state */
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Resets the PHY using the serial gigabit media independent interface.
+ **/
+static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575");
+
+       /*
+        * This isn't a TRUE "hard" reset, but is the only reset
+        * available to us at this time.
+        */
+
+       DEBUGOUT("Soft resetting SGMII attached PHY...\n");
+
+       if (!(hw->phy.ops.write_reg))
+               goto out;
+
+       /*
+        * SFP documentation requires the following to configure the SPF module
+        * to work on SGMII.  No further documentation is given.
+        */
+       ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084);
+       if (ret_val)
+               goto out;
+
+       ret_val = hw->phy.ops.commit(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state
+ *  @hw: pointer to the HW structure
+ *  @active: TRUE to enable LPLU, FALSE to disable
+ *
+ *  Sets the LPLU D0 state according to the active flag.  When
+ *  activating LPLU this function also disables smart speed
+ *  and vice versa.  LPLU will not be activated unless the
+ *  device autonegotiation advertisement meets standards of
+ *  either 10 or 10/100 or 10/100/1000 at all duplexes.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = E1000_SUCCESS;
+       u16 data;
+
+       DEBUGFUNC("e1000_set_d0_lplu_state_82575");
+
+       if (!(hw->phy.ops.read_reg))
+               goto out;
+
+       ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
+       if (ret_val)
+               goto out;
+
+       if (active) {
+               data |= IGP02E1000_PM_D0_LPLU;
+               ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
+                                            data);
+               if (ret_val)
+                       goto out;
+
+               /* When LPLU is enabled, we should disable SmartSpeed */
+               ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+                                           &data);
+               data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+               ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+                                            data);
+               if (ret_val)
+                       goto out;
+       } else {
+               data &= ~IGP02E1000_PM_D0_LPLU;
+               ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
+                                            data);
+               /*
+                * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+                * during Dx states where the power conservation is most
+                * important.  During driver activity we should enable
+                * SmartSpeed, so performance is maintained.
+                */
+               if (phy->smart_speed == e1000_smart_speed_on) {
+                       ret_val = phy->ops.read_reg(hw,
+                                                   IGP01E1000_PHY_PORT_CONFIG,
+                                                   &data);
+                       if (ret_val)
+                               goto out;
+
+                       data |= IGP01E1000_PSCFR_SMART_SPEED;
+                       ret_val = phy->ops.write_reg(hw,
+                                                    IGP01E1000_PHY_PORT_CONFIG,
+                                                    data);
+                       if (ret_val)
+                               goto out;
+               } 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;
+
+                       data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+                       ret_val = phy->ops.write_reg(hw,
+                                                    IGP01E1000_PHY_PORT_CONFIG,
+                                                    data);
+                       if (ret_val)
+                               goto out;
+               }
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state
+ *  @hw: pointer to the HW structure
+ *  @active: TRUE to enable LPLU, FALSE to disable
+ *
+ *  Sets the LPLU D0 state according to the active flag.  When
+ *  activating LPLU this function also disables smart speed
+ *  and vice versa.  LPLU will not be activated unless the
+ *  device autonegotiation advertisement meets standards of
+ *  either 10 or 10/100 or 10/100/1000 at all duplexes.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+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;
+
+       DEBUGFUNC("e1000_set_d0_lplu_state_82580");
+
+       data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+
+       if (active) {
+               data |= E1000_82580_PM_D0_LPLU;
+
+               /* When LPLU is enabled, we should disable SmartSpeed */
+               data &= ~E1000_82580_PM_SPD;
+       } else {
+               data &= ~E1000_82580_PM_D0_LPLU;
+
+               /*
+                * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+                * during Dx states where the power conservation is most
+                * important.  During driver activity we should enable
+                * SmartSpeed, so performance is maintained.
+                */
+               if (phy->smart_speed == e1000_smart_speed_on) {
+                       data |= E1000_82580_PM_SPD;
+               } else if (phy->smart_speed == e1000_smart_speed_off) {
+                       data &= ~E1000_82580_PM_SPD;
+               }
+       }
+
+       E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
+       return ret_val;
+}
+
+/**
+ *  e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  Success returns 0, Failure returns 1
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
+ *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.
+ **/
+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;
+
+       DEBUGFUNC("e1000_set_d3_lplu_state_82580");
+
+       data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+
+       if (!active) {
+               data &= ~E1000_82580_PM_D3_LPLU;
+               /*
+                * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+                * during Dx states where the power conservation is most
+                * important.  During driver activity we should enable
+                * SmartSpeed, so performance is maintained.
+                */
+               if (phy->smart_speed == e1000_smart_speed_on) {
+                       data |= E1000_82580_PM_SPD;
+               } else if (phy->smart_speed == e1000_smart_speed_off) {
+                       data &= ~E1000_82580_PM_SPD;
+               }
+       } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+                  (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
+                  (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
+               data |= E1000_82580_PM_D3_LPLU;
+               /* When LPLU is enabled, we should disable SmartSpeed */
+               data &= ~E1000_82580_PM_SPD;
+       }
+
+       E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
+       return ret_val;
+}
+
+/**
+ *  e1000_acquire_nvm_82575 - Request for access to EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the necessary semaphores for exclusive access to the EEPROM.
+ *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
+ *  Return successful if access grant bit set, else clear the request for
+ *  EEPROM access and return -E1000_ERR_NVM (-1).
+ **/
+static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw)
+{
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_acquire_nvm_82575");
+
+       ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
+       if (ret_val)
+               goto out;
+
+       /*
+        * Check if there is some access
+        * error this access may hook on
+        */
+       if (hw->mac.type == e1000_i350) {
+               u32 eecd = E1000_READ_REG(hw, E1000_EECD);
+               if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT |
+                   E1000_EECD_TIMEOUT)) {
+                       /* Clear all access error flags */
+                       E1000_WRITE_REG(hw, E1000_EECD, eecd |
+                                       E1000_EECD_ERROR_CLR);
+                       DEBUGOUT("Nvm bit banging access error"
+                               " detected and cleared.\n");
+               }
+       }
+       if (hw->mac.type == e1000_82580) {
+               u32 eecd = E1000_READ_REG(hw, E1000_EECD);
+               if (eecd & E1000_EECD_BLOCKED) {
+                       /* Clear access error flag */
+                       E1000_WRITE_REG(hw, E1000_EECD, eecd |
+                                       E1000_EECD_BLOCKED);
+                       DEBUGOUT("Nvm bit banging access"
+                               " error detected and cleared.\n");
+               }
+       }
+
+       ret_val = e1000_acquire_nvm_generic(hw);
+       if (ret_val)
+               e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_release_nvm_82575 - Release exclusive access to EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
+ *  then release the semaphores acquired.
+ **/
+static void e1000_release_nvm_82575(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_release_nvm_82575");
+
+       e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
+}
+
+/**
+ *  e1000_acquire_swfw_sync_82575 - Acquire SW/FW semaphore
+ *  @hw: pointer to the HW structure
+ *  @mask: specifies which semaphore to acquire
+ *
+ *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
+ *  will also specify which port we're acquiring the lock for.
+ **/
+static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
+{
+       u32 swfw_sync;
+       u32 swmask = mask;
+       u32 fwmask = mask << 16;
+       s32 ret_val = E1000_SUCCESS;
+       s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
+
+       DEBUGFUNC("e1000_acquire_swfw_sync_82575");
+
+       while (i < timeout) {
+               if (e1000_get_hw_semaphore_generic(hw)) {
+                       ret_val = -E1000_ERR_SWFW_SYNC;
+                       goto out;
+               }
+
+               swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
+               if (!(swfw_sync & (fwmask | swmask)))
+                       break;
+
+               /*
+                * Firmware currently using resource (fwmask)
+                * or other software thread using resource (swmask)
+                */
+               e1000_put_hw_semaphore_generic(hw);
+               msec_delay_irq(5);
+               i++;
+       }
+
+       if (i == timeout) {
+               DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
+               ret_val = -E1000_ERR_SWFW_SYNC;
+               goto out;
+       }
+
+       swfw_sync |= swmask;
+       E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
+
+       e1000_put_hw_semaphore_generic(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_release_swfw_sync_82575 - Release SW/FW semaphore
+ *  @hw: pointer to the HW structure
+ *  @mask: specifies which semaphore to acquire
+ *
+ *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
+ *  will also specify which port we're releasing the lock for.
+ **/
+static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
+{
+       u32 swfw_sync;
+
+       DEBUGFUNC("e1000_release_swfw_sync_82575");
+
+       while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS);
+       /* Empty */
+
+       swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
+       swfw_sync &= ~mask;
+       E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
+
+       e1000_put_hw_semaphore_generic(hw);
+}
+
+/**
+ *  e1000_get_cfg_done_82575 - Read config done bit
+ *  @hw: pointer to the HW structure
+ *
+ *  Read the management control register for the config done bit for
+ *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
+ *  to read the config done bit, so an error is *ONLY* logged and returns
+ *  E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
+ *  would not be able to be reset or change link.
+ **/
+static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw)
+{
+       s32 timeout = PHY_CFG_TIMEOUT;
+       s32 ret_val = E1000_SUCCESS;
+       u32 mask = E1000_NVM_CFG_DONE_PORT_0;
+
+       DEBUGFUNC("e1000_get_cfg_done_82575");
+
+       if (hw->bus.func == E1000_FUNC_1)
+               mask = E1000_NVM_CFG_DONE_PORT_1;
+       else if (hw->bus.func == E1000_FUNC_2)
+               mask = E1000_NVM_CFG_DONE_PORT_2;
+       else if (hw->bus.func == E1000_FUNC_3)
+               mask = E1000_NVM_CFG_DONE_PORT_3;
+       while (timeout) {
+               if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
+                       break;
+               msec_delay(1);
+               timeout--;
+       }
+       if (!timeout)
+               DEBUGOUT("MNG configuration cycle has not completed.\n");
+
+       /* If EEPROM is not marked present, init the PHY manually */
+       if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) &&
+           (hw->phy.type == e1000_phy_igp_3))
+               e1000_phy_init_script_igp3(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_get_link_up_info_82575 - Get link speed/duplex info
+ *  @hw: pointer to the HW structure
+ *  @speed: stores the current speed
+ *  @duplex: stores the current duplex
+ *
+ *  This is a wrapper function, if using the serial gigabit media independent
+ *  interface, use PCS to retrieve the link speed and duplex information.
+ *  Otherwise, use the generic function to get the link speed and duplex info.
+ **/
+static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
+                                        u16 *duplex)
+{
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_get_link_up_info_82575");
+
+       if (hw->phy.media_type != e1000_media_type_copper)
+               ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed,
+                                                              duplex);
+       else
+               ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
+                                                                   duplex);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_link_82575 - Check for link
+ *  @hw: pointer to the HW structure
+ *
+ *  If sgmii is enabled, then use the pcs register to determine link, otherwise
+ *  use the generic interface for determining link.
+ **/
+static s32 e1000_check_for_link_82575(struct e1000_hw *hw)
+{
+       s32 ret_val;
+       u16 speed, duplex;
+
+       DEBUGFUNC("e1000_check_for_link_82575");
+
+       if (hw->phy.media_type != e1000_media_type_copper) {
+               ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,
+                                                              &duplex);
+               /*
+                * Use this flag to determine if link needs to be checked or
+                * not.  If we have link clear the flag so that we do not
+                * continue to check for link.
+                */
+               hw->mac.get_link_status = !hw->mac.serdes_has_link;
+       } else {
+               ret_val = e1000_check_for_copper_link_generic(hw);
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown
+ *  @hw: pointer to the HW structure
+ **/
+static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw)
+{
+       u32 reg;
+
+       DEBUGFUNC("e1000_power_up_serdes_link_82575");
+
+       if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
+           !e1000_sgmii_active_82575(hw))
+               return;
+
+       /* Enable PCS to turn on link */
+       reg = E1000_READ_REG(hw, E1000_PCS_CFG0);
+       reg |= E1000_PCS_CFG_PCS_EN;
+       E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg);
+
+       /* Power up the laser */
+       reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+       reg &= ~E1000_CTRL_EXT_SDP3_DATA;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
+
+       /* flush the write to verify completion */
+       E1000_WRITE_FLUSH(hw);
+       msec_delay(1);
+}
+
+/**
+ *  e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
+ *  @hw: pointer to the HW structure
+ *  @speed: stores the current speed
+ *  @duplex: stores the current duplex
+ *
+ *  Using the physical coding sub-layer (PCS), retrieve the current speed and
+ *  duplex, then store the values in the pointers provided.
+ **/
+static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
+                                                u16 *speed, u16 *duplex)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       u32 pcs;
+
+       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
+        * used instead.
+        */
+       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
+        */
+       if ((pcs & E1000_PCS_LSTS_LINK_OK) && (pcs & E1000_PCS_LSTS_SYNK_OK)) {
+               mac->serdes_has_link = TRUE;
+
+               /* Detect and store PCS speed */
+               if (pcs & E1000_PCS_LSTS_SPEED_1000) {
+                       *speed = SPEED_1000;
+               } else if (pcs & E1000_PCS_LSTS_SPEED_100) {
+                       *speed = SPEED_100;
+               } else {
+                       *speed = SPEED_10;
+               }
+
+               /* Detect and store PCS duplex */
+               if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) {
+                       *duplex = FULL_DUPLEX;
+               } else {
+                       *duplex = HALF_DUPLEX;
+               }
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_shutdown_serdes_link_82575 - Remove link during power down
+ *  @hw: pointer to the HW structure
+ *
+ *  In the case of serdes shut down sfp and PCS on driver unload
+ *  when management pass thru is not enabled.
+ **/
+void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw)
+{
+       u32 reg;
+
+       DEBUGFUNC("e1000_shutdown_serdes_link_82575");
+
+       if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
+           !e1000_sgmii_active_82575(hw))
+               return;
+
+       if (!e1000_enable_mng_pass_thru(hw)) {
+               /* Disable PCS to turn off link */
+               reg = E1000_READ_REG(hw, E1000_PCS_CFG0);
+               reg &= ~E1000_PCS_CFG_PCS_EN;
+               E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg);
+
+               /* shutdown the laser */
+               reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+               reg |= E1000_CTRL_EXT_SDP3_DATA;
+               E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
+
+               /* flush the write to verify completion */
+               E1000_WRITE_FLUSH(hw);
+               msec_delay(1);
+       }
+
+       return;
+}
+
+/**
+ *  e1000_reset_hw_82575 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_reset_hw_82575");
+
+       /*
+        * Prevent the PCI-E bus from sticking if there is no TLP connection
+        * on the last TLP read/write transaction when MAC is reset.
+        */
+       ret_val = e1000_disable_pcie_master_generic(hw);
+       if (ret_val) {
+               DEBUGOUT("PCI-E Master disable polling has failed.\n");
+       }
+
+       /* set the completion timeout for interface */
+       ret_val = e1000_set_pcie_completion_timeout(hw);
+       if (ret_val) {
+               DEBUGOUT("PCI-E Set completion timeout has failed.\n");
+       }
+
+       DEBUGOUT("Masking off all interrupts\n");
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+
+       E1000_WRITE_REG(hw, E1000_RCTL, 0);
+       E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+       E1000_WRITE_FLUSH(hw);
+
+       msec_delay(10);
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       DEBUGOUT("Issuing a global reset to MAC\n");
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+
+       ret_val = e1000_get_auto_rd_done_generic(hw);
+       if (ret_val) {
+               /*
+                * When auto config read does not complete, do not
+                * return with an error. This can happen in situations
+                * where there is no eeprom and prevents getting link.
+                */
+               DEBUGOUT("Auto Read Done did not complete\n");
+       }
+
+       /* If EEPROM is not present, run manual init scripts */
+       if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0)
+               e1000_reset_init_script_82575(hw);
+
+       /* Clear any pending interrupt events. */
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+       E1000_READ_REG(hw, E1000_ICR);
+
+       /* Install any alternate MAC address into RAR0 */
+       ret_val = e1000_check_alt_mac_addr_generic(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_init_hw_82575 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+static s32 e1000_init_hw_82575(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val;
+       u16 i, rar_count = mac->rar_entry_count;
+
+       DEBUGFUNC("e1000_init_hw_82575");
+
+       /* Initialize identification LED */
+       ret_val = mac->ops.id_led_init(hw);
+       if (ret_val) {
+               DEBUGOUT("Error initializing identification LED\n");
+               /* This is not fatal and we should not stop init due to this */
+       }
+
+       /* Disabling VLAN filtering */
+       DEBUGOUT("Initializing the IEEE VLAN\n");
+       mac->ops.clear_vfta(hw);
+
+       /* Setup the receive address */
+       e1000_init_rx_addrs_generic(hw, rar_count);
+
+       /* Zero out the Multicast HASH table */
+       DEBUGOUT("Zeroing the MTA\n");
+       for (i = 0; i < mac->mta_reg_count; i++)
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
+
+       /* Zero out the Unicast HASH table */
+       DEBUGOUT("Zeroing the UTA\n");
+       for (i = 0; i < mac->uta_reg_count; i++)
+               E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0);
+
+       /* Setup link and flow control */
+       ret_val = mac->ops.setup_link(hw);
+
+       /*
+        * Clear all of the statistics registers (clear on read).  It is
+        * important that we do this after we have tried to establish link
+        * because the symbol error count will increment wildly if there
+        * is no link.
+        */
+       e1000_clear_hw_cntrs_82575(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_copper_link_82575 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the link for auto-neg or forced speed and duplex.  Then we check
+ *  for link, once link is established calls to configure collision distance
+ *  and flow control are called.
+ **/
+static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32  ret_val;
+
+       DEBUGFUNC("e1000_setup_copper_link_82575");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+       ctrl |= E1000_CTRL_SLU;
+       ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+       ret_val = e1000_setup_serdes_link_82575(hw);
+       if (ret_val)
+               goto out;
+
+       if (e1000_sgmii_active_82575(hw) && !hw->phy.reset_disable) {
+               /* allow time for SFP cage time to power up phy */
+               msec_delay(300);
+
+               ret_val = hw->phy.ops.reset(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error resetting the PHY.\n");
+                       goto out;
+               }
+       }
+       switch (hw->phy.type) {
+       case e1000_phy_m88:
+               if (hw->phy.id == I347AT4_E_PHY_ID ||
+                   hw->phy.id == M88E1112_E_PHY_ID ||
+                   hw->phy.id == M88E1340M_E_PHY_ID)
+                       ret_val = e1000_copper_link_setup_m88_gen2(hw);
+               else
+                       ret_val = e1000_copper_link_setup_m88(hw);
+               break;
+       case e1000_phy_igp_3:
+               ret_val = e1000_copper_link_setup_igp(hw);
+               break;
+       case e1000_phy_82580:
+               ret_val = e1000_copper_link_setup_82577(hw);
+               break;
+       default:
+               ret_val = -E1000_ERR_PHY;
+               break;
+       }
+
+       if (ret_val)
+               goto out;
+
+       ret_val = e1000_setup_copper_link_generic(hw);
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_serdes_link_82575 - Setup link for serdes
+ *  @hw: pointer to the HW structure
+ *
+ *  Configure the physical coding sub-layer (PCS) link.  The PCS link is
+ *  used on copper connections where the serialized gigabit media independent
+ *  interface (sgmii), or serdes fiber is being used.  Configures the link
+ *  for auto-negotiation or forces speed/duplex.
+ **/
+static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
+{
+       u32 ctrl_ext, ctrl_reg, reg;
+       bool pcs_autoneg;
+
+       DEBUGFUNC("e1000_setup_serdes_link_82575");
+
+       if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
+           !e1000_sgmii_active_82575(hw))
+               return E1000_SUCCESS;
+
+       /*
+        * On the 82575, SerDes loopback mode persists until it is
+        * explicitly turned off or a power cycle is performed.  A read to
+        * the register does not indicate its status.  Therefore, we ensure
+        * loopback mode is disabled during initialization.
+        */
+       E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
+
+       /* power on the sfp cage if present */
+       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);
+
+       ctrl_reg = E1000_READ_REG(hw, E1000_CTRL);
+       ctrl_reg |= E1000_CTRL_SLU;
+
+       /* set both sw defined pins on 82575/82576*/
+       if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576)
+               ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1;
+
+       reg = E1000_READ_REG(hw, E1000_PCS_LCTL);
+
+       /* default pcs_autoneg to the same setting as mac autoneg */
+       pcs_autoneg = hw->mac.autoneg;
+
+       switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
+       case E1000_CTRL_EXT_LINK_MODE_SGMII:
+               /* sgmii mode lets the phy handle forcing speed/duplex */
+               pcs_autoneg = TRUE;
+               /* autoneg time out should be disabled for SGMII mode */
+               reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT);
+               break;
+       case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
+               /* disable PCS autoneg and support parallel detect only */
+               pcs_autoneg = FALSE;
+               /* fall through to default case */
+       default:
+               /*
+                * 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
+                * link either autoneg or be forced to 1000/Full
+                */
+               ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD |
+                           E1000_CTRL_FD | E1000_CTRL_FRCDPX;
+
+               /* set speed of 1000/Full if speed/duplex is forced */
+               reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL;
+               break;
+       }
+
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg);
+
+       /*
+        * New SerDes mode allows for forcing speed or autonegotiating speed
+        * at 1gb. Autoneg should be default set by most drivers. This is the
+        * mode that will be compatible with older link partners and switches.
+        * However, both are supported by the hardware and some drivers/tools.
+        */
+       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 */
+               DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
+       } else {
+               /* Set PCS register for forced link */
+               reg |= E1000_PCS_LCTL_FSD;        /* Force Speed */
+               DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
+       }
+
+       E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg);
+
+       if (!e1000_sgmii_active_82575(hw))
+               e1000_force_mac_fc_generic(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_valid_led_default_82575 - Verify a valid default LED config
+ *  @hw: pointer to the HW structure
+ *  @data: pointer to the NVM (EEPROM)
+ *
+ *  Read the EEPROM for the current default LED configuration.  If the
+ *  LED configuration is not valid, set to a valid LED configuration.
+ **/
+static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data)
+{
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_valid_led_default_82575");
+
+       ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
+       if (ret_val) {
+               DEBUGOUT("NVM Read Error\n");
+               goto out;
+       }
+
+       if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
+               switch(hw->phy.media_type) {
+               case e1000_media_type_internal_serdes:
+                       *data = ID_LED_DEFAULT_82575_SERDES;
+                       break;
+               case e1000_media_type_copper:
+               default:
+                       *data = ID_LED_DEFAULT;
+                       break;
+               }
+       }
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_sgmii_active_82575 - Return sgmii state
+ *  @hw: pointer to the HW structure
+ *
+ *  82575 silicon has a serialized gigabit media independent interface (sgmii)
+ *  which can be enabled for use in the embedded applications.  Simply
+ *  return the current state of the sgmii interface.
+ **/
+static bool e1000_sgmii_active_82575(struct e1000_hw *hw)
+{
+       struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+       return dev_spec->sgmii_active;
+}
+
+/**
+ *  e1000_reset_init_script_82575 - Inits HW defaults after reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Inits recommended HW defaults after a reset when there is no EEPROM
+ *  detected. This is only for the 82575.
+ **/
+static s32 e1000_reset_init_script_82575(struct e1000_hw* hw)
+{
+       DEBUGFUNC("e1000_reset_init_script_82575");
+
+       if (hw->mac.type == e1000_82575) {
+               DEBUGOUT("Running reset init script for 82575\n");
+               /* SerDes configuration via SERDESCTRL */
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C);
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78);
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23);
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15);
+
+               /* CCM configuration via CCMCTL register */
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00);
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00);
+
+               /* PCIe lanes configuration */
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC);
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF);
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05);
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81);
+
+               /* PCIe PLL Configuration */
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47);
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00);
+               e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00);
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_read_mac_addr_82575 - Read device MAC address
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_read_mac_addr_82575");
+
+       /*
+        * If there's an alternate MAC address place it in RAR0
+        * so that it will override the Si installed default perm
+        * address.
+        */
+       ret_val = e1000_check_alt_mac_addr_generic(hw);
+       if (ret_val)
+               goto out;
+
+       ret_val = e1000_read_mac_addr_generic(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_config_collision_dist_82575 - Configure collision distance
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the collision distance to the default value and is used
+ *  during link setup.
+ **/
+static void e1000_config_collision_dist_82575(struct e1000_hw *hw)
+{
+       u32 tctl_ext;
+
+       DEBUGFUNC("e1000_config_collision_dist_82575");
+
+       tctl_ext = E1000_READ_REG(hw, E1000_TCTL_EXT);
+
+       tctl_ext &= ~E1000_TCTL_EXT_COLD;
+       tctl_ext |= E1000_COLLISION_DISTANCE << E1000_TCTL_EXT_COLD_SHIFT;
+
+       E1000_WRITE_REG(hw, E1000_TCTL_EXT, tctl_ext);
+       E1000_WRITE_FLUSH(hw);
+}
+
+/**
+ * e1000_power_down_phy_copper_82575 - Remove link during 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, remove the link.
+ **/
+static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+
+       if (!(phy->ops.check_reset_block))
+               return;
+
+       /* If the management interface is not enabled, then power down */
+       if (!(e1000_enable_mng_pass_thru(hw) || phy->ops.check_reset_block(hw)))
+               e1000_power_down_phy_copper(hw);
+
+       return;
+}
+
+/**
+ *  e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_clear_hw_cntrs_82575");
+
+       e1000_clear_hw_cntrs_base_generic(hw);
+
+       E1000_READ_REG(hw, E1000_PRC64);
+       E1000_READ_REG(hw, E1000_PRC127);
+       E1000_READ_REG(hw, E1000_PRC255);
+       E1000_READ_REG(hw, E1000_PRC511);
+       E1000_READ_REG(hw, E1000_PRC1023);
+       E1000_READ_REG(hw, E1000_PRC1522);
+       E1000_READ_REG(hw, E1000_PTC64);
+       E1000_READ_REG(hw, E1000_PTC127);
+       E1000_READ_REG(hw, E1000_PTC255);
+       E1000_READ_REG(hw, E1000_PTC511);
+       E1000_READ_REG(hw, E1000_PTC1023);
+       E1000_READ_REG(hw, E1000_PTC1522);
+
+       E1000_READ_REG(hw, E1000_ALGNERRC);
+       E1000_READ_REG(hw, E1000_RXERRC);
+       E1000_READ_REG(hw, E1000_TNCRS);
+       E1000_READ_REG(hw, E1000_CEXTERR);
+       E1000_READ_REG(hw, E1000_TSCTC);
+       E1000_READ_REG(hw, E1000_TSCTFC);
+
+       E1000_READ_REG(hw, E1000_MGTPRC);
+       E1000_READ_REG(hw, E1000_MGTPDC);
+       E1000_READ_REG(hw, E1000_MGTPTC);
+
+       E1000_READ_REG(hw, E1000_IAC);
+       E1000_READ_REG(hw, E1000_ICRXOC);
+
+       E1000_READ_REG(hw, E1000_ICRXPTC);
+       E1000_READ_REG(hw, E1000_ICRXATC);
+       E1000_READ_REG(hw, E1000_ICTXPTC);
+       E1000_READ_REG(hw, E1000_ICTXATC);
+       E1000_READ_REG(hw, E1000_ICTXQEC);
+       E1000_READ_REG(hw, E1000_ICTXQMTC);
+       E1000_READ_REG(hw, E1000_ICRXDMTC);
+
+       E1000_READ_REG(hw, E1000_CBTMPC);
+       E1000_READ_REG(hw, E1000_HTDPMC);
+       E1000_READ_REG(hw, E1000_CBRMPC);
+       E1000_READ_REG(hw, E1000_RPTHC);
+       E1000_READ_REG(hw, E1000_HGPTC);
+       E1000_READ_REG(hw, E1000_HTCBDPC);
+       E1000_READ_REG(hw, E1000_HGORCL);
+       E1000_READ_REG(hw, E1000_HGORCH);
+       E1000_READ_REG(hw, E1000_HGOTCL);
+       E1000_READ_REG(hw, E1000_HGOTCH);
+       E1000_READ_REG(hw, E1000_LENERRS);
+
+       /* This register should not be read in copper configurations */
+       if ((hw->phy.media_type == e1000_media_type_internal_serdes) ||
+           e1000_sgmii_active_82575(hw))
+               E1000_READ_REG(hw, E1000_SCVPC);
+}
+
+/**
+ *  e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable
+ *  @hw: pointer to the HW structure
+ *
+ *  After rx enable if managability is enabled then there is likely some
+ *  bad data at the start of the fifo and possibly in the DMA fifo.  This
+ *  function clears the fifos and flushes any packets that came in as rx was
+ *  being enabled.
+ **/
+void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
+{
+       u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
+       int i, ms_wait;
+
+       DEBUGFUNC("e1000_rx_fifo_workaround_82575");
+       if (hw->mac.type != e1000_82575 ||
+           !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN))
+               return;
+
+       /* Disable all Rx queues */
+       for (i = 0; i < 4; i++) {
+               rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i));
+               E1000_WRITE_REG(hw, E1000_RXDCTL(i),
+                               rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
+       }
+       /* Poll all queues to verify they have shut down */
+       for (ms_wait = 0; ms_wait < 10; ms_wait++) {
+               msec_delay(1);
+               rx_enabled = 0;
+               for (i = 0; i < 4; i++)
+                       rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i));
+               if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE))
+                       break;
+       }
+
+       if (ms_wait == 10)
+               DEBUGOUT("Queue disable timed out after 10ms\n");
+
+       /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
+        * incoming packets are rejected.  Set enable and wait 2ms so that
+        * any packet that was coming in as RCTL.EN was set is flushed
+        */
+       rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+       E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
+
+       rlpml = E1000_READ_REG(hw, E1000_RLPML);
+       E1000_WRITE_REG(hw, E1000_RLPML, 0);
+
+       rctl = E1000_READ_REG(hw, E1000_RCTL);
+       temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP);
+       temp_rctl |= E1000_RCTL_LPE;
+
+       E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl);
+       E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN);
+       E1000_WRITE_FLUSH(hw);
+       msec_delay(2);
+
+       /* Enable Rx queues that were previously enabled and restore our
+        * previous state
+        */
+       for (i = 0; i < 4; i++)
+               E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]);
+       E1000_WRITE_REG(hw, E1000_RCTL, rctl);
+       E1000_WRITE_FLUSH(hw);
+
+       E1000_WRITE_REG(hw, E1000_RLPML, rlpml);
+       E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
+
+       /* Flush receive errors generated by workaround */
+       E1000_READ_REG(hw, E1000_ROC);
+       E1000_READ_REG(hw, E1000_RNBC);
+       E1000_READ_REG(hw, E1000_MPC);
+}
+
+/**
+ *  e1000_set_pcie_completion_timeout - set pci-e completion timeout
+ *  @hw: pointer to the HW structure
+ *
+ *  The defaults for 82575 and 82576 should be in the range of 50us to 50ms,
+ *  however the hardware default for these parts is 500us to 1ms which is less
+ *  than the 10ms recommended by the pci-e spec.  To address this we need to
+ *  increase the value to either 10ms to 200ms for capability version 1 config,
+ *  or 16ms to 55ms for version 2.
+ **/
+static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw)
+{
+       u32 gcr = E1000_READ_REG(hw, E1000_GCR);
+       s32 ret_val = E1000_SUCCESS;
+       u16 pcie_devctl2;
+
+       /* only take action if timeout value is defaulted to 0 */
+       if (gcr & E1000_GCR_CMPL_TMOUT_MASK)
+               goto out;
+
+       /*
+        * if capababilities version is type 1 we can write the
+        * timeout of 10ms to 200ms through the GCR register
+        */
+       if (!(gcr & E1000_GCR_CAP_VER2)) {
+               gcr |= E1000_GCR_CMPL_TMOUT_10ms;
+               goto out;
+       }
+
+       /*
+        * for version 2 capabilities we need to write the config space
+        * directly in order to set the completion timeout value for
+        * 16ms to 55ms
+        */
+       ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
+                                         &pcie_devctl2);
+       if (ret_val)
+               goto out;
+
+       pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
+
+       ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
+                                          &pcie_devctl2);
+out:
+       /* disable completion timeout resend */
+       gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND;
+
+       E1000_WRITE_REG(hw, E1000_GCR, gcr);
+       return ret_val;
+}
+
+/**
+ *  e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing
+ *  @hw: pointer to the hardware struct
+ *  @enable: state to enter, either enabled or disabled
+ *  @pf: Physical Function pool - do not set anti-spoofing for the PF
+ *
+ *  enables/disables L2 switch anti-spoofing functionality.
+ **/
+void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
+{
+       u32 dtxswc;
+
+       switch (hw->mac.type) {
+       case e1000_82576:
+               dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
+               if (enable) {
+                       dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
+                                  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));
+               } else {
+                       dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
+                                   E1000_DTXSWC_VLAN_SPOOF_MASK);
+               }
+               E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
+               break;
+       case e1000_i350:
+               dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
+               if (enable) {
+                       dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
+                                  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));
+               } else {
+                       dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
+                                   E1000_DTXSWC_VLAN_SPOOF_MASK);
+               }
+               E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
+       default:
+               break;
+       }
+}
+
+/**
+ *  e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback
+ *  @hw: pointer to the hardware struct
+ *  @enable: state to enter, either enabled or disabled
+ *
+ *  enables/disables L2 switch loopback functionality.
+ **/
+void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
+{
+       u32 dtxswc;
+
+       switch (hw->mac.type) {
+       case e1000_82576:
+               dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
+               if (enable)
+                       dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+               else
+                       dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+               E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
+               break;
+       case e1000_i350:
+               dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
+               if (enable)
+                       dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+               else
+                       dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+               E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
+               break;
+       default:
+               /* Currently no other hardware supports loopback */
+               break;
+       }
+
+
+}
+
+/**
+ *  e1000_vmdq_set_replication_pf - enable or disable vmdq replication
+ *  @hw: pointer to the hardware struct
+ *  @enable: state to enter, either enabled or disabled
+ *
+ *  enables/disables replication of packets across multiple pools.
+ **/
+void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable)
+{
+       u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL);
+
+       if (enable)
+               vt_ctl |= E1000_VT_CTL_VM_REPL_EN;
+       else
+               vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN;
+
+       E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl);
+}
+
+/**
+ *  e1000_read_phy_reg_82580 - Read 82580 MDI control register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the MDI control register in the PHY at offset and stores the
+ *  information read to data.
+ **/
+static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_read_phy_reg_82580");
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               goto out;
+
+       ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
+
+       hw->phy.ops.release(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_write_phy_reg_82580 - Write 82580 MDI control register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write to register at offset
+ *
+ *  Writes data to MDI control register in the PHY at offset.
+ **/
+static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_write_phy_reg_82580");
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               goto out;
+
+       ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
+
+       hw->phy.ops.release(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on
+ *  the values found in the EEPROM.  This addresses an issue in which these
+ *  bits are not restored from EEPROM after reset.
+ **/
+static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u32 mdicnfg;
+       u16 nvm_data = 0;
+
+       DEBUGFUNC("e1000_reset_mdicnfg_82580");
+
+       if (hw->mac.type != e1000_82580)
+               goto out;
+       if (!e1000_sgmii_active_82575(hw))
+               goto out;
+
+       ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
+                                  NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
+                                  &nvm_data);
+       if (ret_val) {
+               DEBUGOUT("NVM Read Error\n");
+               goto out;
+       }
+
+       mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG);
+       if (nvm_data & NVM_WORD24_EXT_MDIO)
+               mdicnfg |= E1000_MDICNFG_EXT_MDIO;
+       if (nvm_data & NVM_WORD24_COM_MDIO)
+               mdicnfg |= E1000_MDICNFG_COM_MDIO;
+       E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_reset_hw_82580 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets function or entire device (all ports, etc.)
+ *  to a known state.
+ **/
+static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       /* BH SW mailbox bit in SW_FW_SYNC */
+       u16 swmbsw_mask = E1000_SW_SYNCH_MB;
+       u32 ctrl;
+       bool global_device_reset = hw->dev_spec._82575.global_device_reset;
+
+       DEBUGFUNC("e1000_reset_hw_82580");
+
+       hw->dev_spec._82575.global_device_reset = FALSE;
+
+       /* Get current control state. */
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /*
+        * Prevent the PCI-E bus from sticking if there is no TLP connection
+        * on the last TLP read/write transaction when MAC is reset.
+        */
+       ret_val = e1000_disable_pcie_master_generic(hw);
+       if (ret_val)
+               DEBUGOUT("PCI-E Master disable polling has failed.\n");
+
+       DEBUGOUT("Masking off all interrupts\n");
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+       E1000_WRITE_REG(hw, E1000_RCTL, 0);
+       E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+       E1000_WRITE_FLUSH(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 &&
+               !(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);
+
+       /* Add delay to insure DEV_RST has time to complete */
+       if (global_device_reset)
+               msec_delay(5);
+
+       ret_val = e1000_get_auto_rd_done_generic(hw);
+       if (ret_val) {
+               /*
+                * When auto config read does not complete, do not
+                * return with an error. This can happen in situations
+                * where there is no eeprom and prevents getting link.
+                */
+               DEBUGOUT("Auto Read Done did not complete\n");
+       }
+
+       /* If EEPROM is not present, run manual init scripts */
+       if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0)
+               e1000_reset_init_script_82575(hw);
+
+       /* clear global device reset status bit */
+       E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET);
+
+       /* Clear any pending interrupt events. */
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+       E1000_READ_REG(hw, E1000_ICR);
+
+       ret_val = e1000_reset_mdicnfg_82580(hw);
+       if (ret_val)
+               DEBUGOUT("Could not reset MDICNFG based on EEPROM\n");
+
+       /* Install any alternate MAC address into RAR0 */
+       ret_val = e1000_check_alt_mac_addr_generic(hw);
+
+       /* Release semaphore */
+       if (global_device_reset)
+               e1000_release_swfw_sync_82575(hw, swmbsw_mask);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size
+ *  @data: data received by reading RXPBS register
+ *
+ *  The 82580 uses a table based approach for packet buffer allocation sizes.
+ *  This function converts the retrieved value into the correct table value
+ *     0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
+ *  0x0 36  72 144   1   2   4   8  16
+ *  0x8 35  70 140 rsv rsv rsv rsv rsv
+ */
+u16 e1000_rxpbs_adjust_82580(u32 data)
+{
+       u16 ret_val = 0;
+
+       if (data < E1000_82580_RXPBS_TABLE_SIZE)
+               ret_val = e1000_82580_rxpbs_table[data];
+
+       return ret_val;
+}
+
+/**
+ *  e1000_validate_nvm_checksum_with_offset - Validate EEPROM
+ *  checksum
+ *  @hw: pointer to the HW structure
+ *  @offset: offset in words of the checksum protected region
+ *
+ *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 checksum = 0;
+       u16 i, nvm_data;
+
+       DEBUGFUNC("e1000_validate_nvm_checksum_with_offset");
+
+       for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
+               ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+               if (ret_val) {
+                       DEBUGOUT("NVM Read Error\n");
+                       goto out;
+               }
+               checksum += nvm_data;
+       }
+
+       if (checksum != (u16) NVM_SUM) {
+               DEBUGOUT("NVM Checksum Invalid\n");
+               ret_val = -E1000_ERR_NVM;
+               goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_update_nvm_checksum_with_offset - Update EEPROM
+ *  checksum
+ *  @hw: pointer to the HW structure
+ *  @offset: offset in words of the checksum protected region
+ *
+ *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  up to the checksum.  Then calculates the EEPROM checksum and writes the
+ *  value to the EEPROM.
+ **/
+s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+       s32 ret_val;
+       u16 checksum = 0;
+       u16 i, nvm_data;
+
+       DEBUGFUNC("e1000_update_nvm_checksum_with_offset");
+
+       for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
+               ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+               if (ret_val) {
+                       DEBUGOUT("NVM Read Error while updating checksum.\n");
+                       goto out;
+               }
+               checksum += nvm_data;
+       }
+       checksum = (u16) NVM_SUM - checksum;
+       ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
+                               &checksum);
+       if (ret_val)
+               DEBUGOUT("NVM Write Error while updating checksum.\n");
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM section checksum by reading/adding each word of
+ *  the EEPROM and then verifies that the sum of the EEPROM is
+ *  equal to 0xBABA.
+ **/
+static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 eeprom_regions_count = 1;
+       u16 j, nvm_data;
+       u16 nvm_offset;
+
+       DEBUGFUNC("e1000_validate_nvm_checksum_82580");
+
+       ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+       if (ret_val) {
+               DEBUGOUT("NVM Read Error\n");
+               goto out;
+       }
+
+       if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
+               /* if chekcsums compatibility bit is set validate checksums
+                * for all 4 ports. */
+               eeprom_regions_count = 4;
+       }
+
+       for (j = 0; j < eeprom_regions_count; j++) {
+               nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+               ret_val = e1000_validate_nvm_checksum_with_offset(hw,
+                                                               nvm_offset);
+               if (ret_val != E1000_SUCCESS)
+                       goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_update_nvm_checksum_82580 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM section checksums for all 4 ports by reading/adding
+ *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
+ *  checksum and writes the value to the EEPROM.
+ **/
+static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw)
+{
+       s32 ret_val;
+       u16 j, nvm_data;
+       u16 nvm_offset;
+
+       DEBUGFUNC("e1000_update_nvm_checksum_82580");
+
+       ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+       if (ret_val) {
+               DEBUGOUT("NVM Read Error while updating checksum"
+                       " compatibility bit.\n");
+               goto out;
+       }
+
+       if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) {
+               /* set compatibility bit to validate checksums appropriately */
+               nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
+               ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
+                                       &nvm_data);
+               if (ret_val) {
+                       DEBUGOUT("NVM Write Error while updating checksum"
+                               " compatibility bit.\n");
+                       goto out;
+               }
+       }
+
+       for (j = 0; j < 4; j++) {
+               nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+               ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
+               if (ret_val) {
+                       goto out;
+               }
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM section checksum by reading/adding each word of
+ *  the EEPROM and then verifies that the sum of the EEPROM is
+ *  equal to 0xBABA.
+ **/
+static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 j;
+       u16 nvm_offset;
+
+       DEBUGFUNC("e1000_validate_nvm_checksum_i350");
+
+       for (j = 0; j < 4; j++) {
+               nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+               ret_val = e1000_validate_nvm_checksum_with_offset(hw,
+                                                               nvm_offset);
+               if (ret_val != E1000_SUCCESS)
+                       goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_update_nvm_checksum_i350 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM section checksums for all 4 ports by reading/adding
+ *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
+ *  checksum and writes the value to the EEPROM.
+ **/
+static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 j;
+       u16 nvm_offset;
+
+       DEBUGFUNC("e1000_update_nvm_checksum_i350");
+
+       for (j = 0; j < 4; j++) {
+               nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+               ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
+               if (ret_val != E1000_SUCCESS)
+                       goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_set_eee_i350 - Enable/disable EEE support
+ *  @hw: pointer to the HW structure
+ *
+ *  Enable/disable EEE based on setting in dev_spec structure.
+ *
+ **/
+s32 e1000_set_eee_i350(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u32 ipcnfg, eeer, ctrl_ext;
+
+       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))
+               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)) {
+               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);
+
+       } else {
+               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);
+       }
+       E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg);
+       E1000_WRITE_REG(hw, E1000_EEER, eeer);
+                       E1000_READ_REG(hw, E1000_IPCNFG);
+                       E1000_READ_REG(hw, E1000_EEER);
+out:
+
+       return ret_val;
+}
diff --git a/sys/dev/netif/ig_hal/e1000_82575.h b/sys/dev/netif/ig_hal/e1000_82575.h
new file mode 100644 (file)
index 0000000..415756e
--- /dev/null
@@ -0,0 +1,487 @@
+/******************************************************************************
+
+  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 _E1000_82575_H_
+#define _E1000_82575_H_
+
+#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
+                                     (ID_LED_DEF1_DEF2 <<  8) | \
+                                     (ID_LED_DEF1_DEF2 <<  4) | \
+                                     (ID_LED_OFF1_ON2))
+/*
+ * Receive Address Register Count
+ * Number of high/low register pairs in the RAR.  The RAR (Receive Address
+ * Registers) holds the directed and multicast addresses that we monitor.
+ * These entries are also used for MAC-based filtering.
+ */
+/*
+ * For 82576, there are an additional set of RARs that begin at an offset
+ * separate from the first set of RARs.
+ */
+#define E1000_RAR_ENTRIES_82575        16
+#define E1000_RAR_ENTRIES_82576        24
+#define E1000_RAR_ENTRIES_82580        24
+#define E1000_RAR_ENTRIES_I350         32
+#define E1000_SW_SYNCH_MB              0x00000100
+#define E1000_STAT_DEV_RST_SET         0x00100000
+#define E1000_CTRL_DEV_RST             0x20000000
+
+#ifdef E1000_BIT_FIELDS
+struct e1000_adv_data_desc {
+       __le64 buffer_addr;    /* Address of the descriptor's data buffer */
+       union {
+               u32 data;
+               struct {
+                       u32 datalen :16; /* Data buffer length */
+                       u32 rsvd    :4;
+                       u32 dtyp    :4;  /* Descriptor type */
+                       u32 dcmd    :8;  /* Descriptor command */
+               } config;
+       } lower;
+       union {
+               u32 data;
+               struct {
+                       u32 status  :4;  /* Descriptor status */
+                       u32 idx     :4;
+                       u32 popts   :6;  /* Packet Options */
+                       u32 paylen  :18; /* Payload length */
+               } options;
+       } upper;
+};
+
+#define E1000_TXD_DTYP_ADV_C    0x2  /* Advanced Context Descriptor */
+#define E1000_TXD_DTYP_ADV_D    0x3  /* Advanced Data Descriptor */
+#define E1000_ADV_TXD_CMD_DEXT  0x20 /* Descriptor extension (0 = legacy) */
+#define E1000_ADV_TUCMD_IPV4    0x2  /* IP Packet Type: 1=IPv4 */
+#define E1000_ADV_TUCMD_IPV6    0x0  /* IP Packet Type: 0=IPv6 */
+#define E1000_ADV_TUCMD_L4T_UDP 0x0  /* L4 Packet TYPE of UDP */
+#define E1000_ADV_TUCMD_L4T_TCP 0x4  /* L4 Packet TYPE of TCP */
+#define E1000_ADV_TUCMD_MKRREQ  0x10 /* Indicates markers are required */
+#define E1000_ADV_DCMD_EOP      0x1  /* End of Packet */
+#define E1000_ADV_DCMD_IFCS     0x2  /* Insert FCS (Ethernet CRC) */
+#define E1000_ADV_DCMD_RS       0x8  /* Report Status */
+#define E1000_ADV_DCMD_VLE      0x40 /* Add VLAN tag */
+#define E1000_ADV_DCMD_TSE      0x80 /* TCP Seg enable */
+/* Extended Device Control */
+#define E1000_CTRL_EXT_NSICR    0x00000001 /* Disable Intr Clear all on read */
+
+struct e1000_adv_context_desc {
+       union {
+               u32 ip_config;
+               struct {
+                       u32 iplen    :9;
+                       u32 maclen   :7;
+                       u32 vlan_tag :16;
+               } fields;
+       } ip_setup;
+       u32 seq_num;
+       union {
+               u64 l4_config;
+               struct {
+                       u32 mkrloc :9;
+                       u32 tucmd  :11;
+                       u32 dtyp   :4;
+                       u32 adv    :8;
+                       u32 rsvd   :4;
+                       u32 idx    :4;
+                       u32 l4len  :8;
+                       u32 mss    :16;
+               } fields;
+       } l4_setup;
+};
+#endif
+
+/* SRRCTL bit definitions */
+#define E1000_SRRCTL_BSIZEPKT_SHIFT                     10 /* Shift _right_ */
+#define E1000_SRRCTL_BSIZEHDRSIZE_MASK                  0x00000F00
+#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT                 2  /* Shift _left_ */
+#define E1000_SRRCTL_DESCTYPE_LEGACY                    0x00000000
+#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF                0x02000000
+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT                 0x04000000
+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS          0x0A000000
+#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION           0x06000000
+#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
+#define E1000_SRRCTL_DESCTYPE_MASK                      0x0E000000
+#define E1000_SRRCTL_TIMESTAMP                          0x40000000
+#define E1000_SRRCTL_DROP_EN                            0x80000000
+
+#define E1000_SRRCTL_BSIZEPKT_MASK      0x0000007F
+#define E1000_SRRCTL_BSIZEHDR_MASK      0x00003F00
+
+#define E1000_TX_HEAD_WB_ENABLE   0x1
+#define E1000_TX_SEQNUM_WB_ENABLE 0x2
+
+#define E1000_MRQC_ENABLE_RSS_4Q            0x00000002
+#define E1000_MRQC_ENABLE_VMDQ              0x00000003
+#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q       0x00000005
+#define E1000_MRQC_RSS_FIELD_IPV4_UDP       0x00400000
+#define E1000_MRQC_RSS_FIELD_IPV6_UDP       0x00800000
+#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX    0x01000000
+#define E1000_MRQC_ENABLE_RSS_8Q            0x00000002
+
+#define E1000_VMRCTL_MIRROR_PORT_SHIFT      8
+#define E1000_VMRCTL_MIRROR_DSTPORT_MASK    (7 << E1000_VMRCTL_MIRROR_PORT_SHIFT)
+#define E1000_VMRCTL_POOL_MIRROR_ENABLE     (1 << 0)
+#define E1000_VMRCTL_UPLINK_MIRROR_ENABLE   (1 << 1)
+#define E1000_VMRCTL_DOWNLINK_MIRROR_ENABLE (1 << 2)
+
+#define E1000_EICR_TX_QUEUE ( \
+    E1000_EICR_TX_QUEUE0 |    \
+    E1000_EICR_TX_QUEUE1 |    \
+    E1000_EICR_TX_QUEUE2 |    \
+    E1000_EICR_TX_QUEUE3)
+
+#define E1000_EICR_RX_QUEUE ( \
+    E1000_EICR_RX_QUEUE0 |    \
+    E1000_EICR_RX_QUEUE1 |    \
+    E1000_EICR_RX_QUEUE2 |    \
+    E1000_EICR_RX_QUEUE3)
+
+#define E1000_EIMS_RX_QUEUE E1000_EICR_RX_QUEUE
+#define E1000_EIMS_TX_QUEUE E1000_EICR_TX_QUEUE
+
+#define EIMS_ENABLE_MASK ( \
+    E1000_EIMS_RX_QUEUE  | \
+    E1000_EIMS_TX_QUEUE  | \
+    E1000_EIMS_TCP_TIMER | \
+    E1000_EIMS_OTHER)
+
+/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
+#define E1000_IMIR_PORT_IM_EN     0x00010000  /* TCP port enable */
+#define E1000_IMIR_PORT_BP        0x00020000  /* TCP port check bypass */
+#define E1000_IMIREXT_SIZE_BP     0x00001000  /* Packet size bypass */
+#define E1000_IMIREXT_CTRL_URG    0x00002000  /* Check URG bit in header */
+#define E1000_IMIREXT_CTRL_ACK    0x00004000  /* Check ACK bit in header */
+#define E1000_IMIREXT_CTRL_PSH    0x00008000  /* Check PSH bit in header */
+#define E1000_IMIREXT_CTRL_RST    0x00010000  /* Check RST bit in header */
+#define E1000_IMIREXT_CTRL_SYN    0x00020000  /* Check SYN bit in header */
+#define E1000_IMIREXT_CTRL_FIN    0x00040000  /* Check FIN bit in header */
+#define E1000_IMIREXT_CTRL_BP     0x00080000  /* Bypass check of ctrl bits */
+
+/* Receive Descriptor - Advanced */
+union e1000_adv_rx_desc {
+       struct {
+               __le64 pkt_addr;             /* Packet buffer address */
+               __le64 hdr_addr;             /* Header buffer address */
+       } read;
+       struct {
+               struct {
+                       union {
+                               __le32 data;
+                               struct {
+                                       __le16 pkt_info; /*RSS type, Pkt type*/
+                                       /* Split Header, header buffer len */
+                                       __le16 hdr_info;
+                               } hs_rss;
+                       } lo_dword;
+                       union {
+                               __le32 rss;          /* RSS Hash */
+                               struct {
+                                       __le16 ip_id;    /* IP id */
+                                       __le16 csum;     /* Packet Checksum */
+                               } csum_ip;
+                       } hi_dword;
+               } lower;
+               struct {
+                       __le32 status_error;     /* ext status/error */
+                       __le16 length;           /* Packet length */
+                       __le16 vlan;             /* VLAN tag */
+               } upper;
+       } wb;  /* writeback */
+};
+
+#define E1000_RXDADV_RSSTYPE_MASK        0x0000000F
+#define E1000_RXDADV_RSSTYPE_SHIFT       12
+#define E1000_RXDADV_HDRBUFLEN_MASK      0x7FE0
+#define E1000_RXDADV_HDRBUFLEN_SHIFT     5
+#define E1000_RXDADV_SPLITHEADER_EN      0x00001000
+#define E1000_RXDADV_SPH                 0x8000
+#define E1000_RXDADV_STAT_TS             0x10000 /* Pkt was time stamped */
+#define E1000_RXDADV_STAT_TSIP           0x08000 /* timestamp in packet */
+#define E1000_RXDADV_ERR_HBO             0x00800000
+
+/* RSS Hash results */
+#define E1000_RXDADV_RSSTYPE_NONE        0x00000000
+#define E1000_RXDADV_RSSTYPE_IPV4_TCP    0x00000001
+#define E1000_RXDADV_RSSTYPE_IPV4        0x00000002
+#define E1000_RXDADV_RSSTYPE_IPV6_TCP    0x00000003
+#define E1000_RXDADV_RSSTYPE_IPV6_EX     0x00000004
+#define E1000_RXDADV_RSSTYPE_IPV6        0x00000005
+#define E1000_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006
+#define E1000_RXDADV_RSSTYPE_IPV4_UDP    0x00000007
+#define E1000_RXDADV_RSSTYPE_IPV6_UDP    0x00000008
+#define E1000_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009
+
+/* RSS Packet Types as indicated in the receive descriptor */
+#define E1000_RXDADV_PKTTYPE_NONE        0x00000000
+#define E1000_RXDADV_PKTTYPE_IPV4        0x00000010 /* IPV4 hdr present */
+#define E1000_RXDADV_PKTTYPE_IPV4_EX     0x00000020 /* IPV4 hdr + extensions */
+#define E1000_RXDADV_PKTTYPE_IPV6        0x00000040 /* IPV6 hdr present */
+#define E1000_RXDADV_PKTTYPE_IPV6_EX     0x00000080 /* IPV6 hdr + extensions */
+#define E1000_RXDADV_PKTTYPE_TCP         0x00000100 /* TCP hdr present */
+#define E1000_RXDADV_PKTTYPE_UDP         0x00000200 /* UDP hdr present */
+#define E1000_RXDADV_PKTTYPE_SCTP        0x00000400 /* SCTP hdr present */
+#define E1000_RXDADV_PKTTYPE_NFS         0x00000800 /* NFS hdr present */
+
+#define E1000_RXDADV_PKTTYPE_IPSEC_ESP   0x00001000 /* IPSec ESP */
+#define E1000_RXDADV_PKTTYPE_IPSEC_AH    0x00002000 /* IPSec AH */
+#define E1000_RXDADV_PKTTYPE_LINKSEC     0x00004000 /* LinkSec Encap */
+#define E1000_RXDADV_PKTTYPE_ETQF        0x00008000 /* PKTTYPE is ETQF index */
+#define E1000_RXDADV_PKTTYPE_ETQF_MASK   0x00000070 /* ETQF has 8 indices */
+#define E1000_RXDADV_PKTTYPE_ETQF_SHIFT  4          /* Right-shift 4 bits */
+
+/* LinkSec results */
+/* Security Processing bit Indication */
+#define E1000_RXDADV_LNKSEC_STATUS_SECP         0x00020000
+#define E1000_RXDADV_LNKSEC_ERROR_BIT_MASK      0x18000000
+#define E1000_RXDADV_LNKSEC_ERROR_NO_SA_MATCH   0x08000000
+#define E1000_RXDADV_LNKSEC_ERROR_REPLAY_ERROR  0x10000000
+#define E1000_RXDADV_LNKSEC_ERROR_BAD_SIG       0x18000000
+
+#define E1000_RXDADV_IPSEC_STATUS_SECP          0x00020000
+#define E1000_RXDADV_IPSEC_ERROR_BIT_MASK       0x18000000
+#define E1000_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL       0x08000000
+#define E1000_RXDADV_IPSEC_ERROR_INVALID_LENGTH         0x10000000
+#define E1000_RXDADV_IPSEC_ERROR_AUTHENTICATION_FAILED  0x18000000
+
+/* Transmit Descriptor - Advanced */
+union e1000_adv_tx_desc {
+       struct {
+               __le64 buffer_addr;    /* Address of descriptor's data buf */
+               __le32 cmd_type_len;
+               __le32 olinfo_status;
+       } read;
+       struct {
+               __le64 rsvd;       /* Reserved */
+               __le32 nxtseq_seed;
+               __le32 status;
+       } wb;
+};
+
+/* Adv Transmit Descriptor Config Masks */
+#define E1000_ADVTXD_DTYP_CTXT    0x00200000 /* Advanced Context Descriptor */
+#define E1000_ADVTXD_DTYP_DATA    0x00300000 /* Advanced Data Descriptor */
+#define E1000_ADVTXD_DCMD_EOP     0x01000000 /* End of Packet */
+#define E1000_ADVTXD_DCMD_IFCS    0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_ADVTXD_DCMD_RS      0x08000000 /* Report Status */
+#define E1000_ADVTXD_DCMD_DDTYP_ISCSI  0x10000000 /* DDP hdr type or iSCSI */
+#define E1000_ADVTXD_DCMD_DEXT    0x20000000 /* Descriptor extension (1=Adv) */
+#define E1000_ADVTXD_DCMD_VLE     0x40000000 /* VLAN pkt enable */
+#define E1000_ADVTXD_DCMD_TSE     0x80000000 /* TCP Seg enable */
+#define E1000_ADVTXD_MAC_LINKSEC  0x00040000 /* Apply LinkSec on packet */
+#define E1000_ADVTXD_MAC_TSTAMP   0x00080000 /* IEEE1588 Timestamp packet */
+#define E1000_ADVTXD_STAT_SN_CRC  0x00000002 /* NXTSEQ/SEED present in WB */
+#define E1000_ADVTXD_IDX_SHIFT    4  /* Adv desc Index shift */
+#define E1000_ADVTXD_POPTS_ISCO_1ST  0x00000000 /* 1st TSO of iSCSI PDU */
+#define E1000_ADVTXD_POPTS_ISCO_MDL  0x00000800 /* Middle TSO of iSCSI PDU */
+#define E1000_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */
+#define E1000_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU*/
+#define E1000_ADVTXD_POPTS_IPSEC     0x00000400 /* IPSec offload request */
+#define E1000_ADVTXD_PAYLEN_SHIFT    14 /* Adv desc PAYLEN shift */
+
+/* Context descriptors */
+struct e1000_adv_tx_context_desc {
+       __le32 vlan_macip_lens;
+       __le32 seqnum_seed;
+       __le32 type_tucmd_mlhl;
+       __le32 mss_l4len_idx;
+};
+
+#define E1000_ADVTXD_MACLEN_SHIFT    9  /* Adv ctxt desc mac len shift */
+#define E1000_ADVTXD_VLAN_SHIFT     16  /* Adv ctxt vlan tag shift */
+#define E1000_ADVTXD_TUCMD_IPV4    0x00000400  /* IP Packet Type: 1=IPv4 */
+#define E1000_ADVTXD_TUCMD_IPV6    0x00000000  /* IP Packet Type: 0=IPv6 */
+#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000  /* L4 Packet TYPE of UDP */
+#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800  /* L4 Packet TYPE of TCP */
+#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000  /* L4 Packet TYPE of SCTP */
+#define E1000_ADVTXD_TUCMD_IPSEC_TYPE_ESP    0x00002000 /* IPSec Type ESP */
+/* IPSec Encrypt Enable for ESP */
+#define E1000_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN  0x00004000
+#define E1000_ADVTXD_TUCMD_MKRREQ  0x00002000 /* Req requires Markers and CRC */
+#define E1000_ADVTXD_L4LEN_SHIFT     8  /* Adv ctxt L4LEN shift */
+#define E1000_ADVTXD_MSS_SHIFT      16  /* Adv ctxt MSS shift */
+/* Adv ctxt IPSec SA IDX mask */
+#define E1000_ADVTXD_IPSEC_SA_INDEX_MASK     0x000000FF
+/* Adv ctxt IPSec ESP len mask */
+#define E1000_ADVTXD_IPSEC_ESP_LEN_MASK      0x000000FF
+
+/* Additional Transmit Descriptor Control definitions */
+#define E1000_TXDCTL_QUEUE_ENABLE  0x02000000 /* Enable specific Tx Queue */
+#define E1000_TXDCTL_SWFLSH        0x04000000 /* Tx Desc. write-back flushing */
+/* Tx Queue Arbitration Priority 0=low, 1=high */
+#define E1000_TXDCTL_PRIORITY      0x08000000
+
+/* Additional Receive Descriptor Control definitions */
+#define E1000_RXDCTL_QUEUE_ENABLE  0x02000000 /* Enable specific Rx Queue */
+#define E1000_RXDCTL_SWFLSH        0x04000000 /* Rx Desc. write-back flushing */
+
+/* Direct Cache Access (DCA) definitions */
+#define E1000_DCA_CTRL_DCA_ENABLE  0x00000000 /* DCA Enable */
+#define E1000_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */
+
+#define E1000_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */
+#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */
+
+#define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */
+#define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
+#define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */
+#define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */
+
+#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
+#define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
+#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
+
+#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
+#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */
+#define E1000_DCA_TXCTRL_CPUID_SHIFT_82576 24 /* Tx CPUID */
+#define E1000_DCA_RXCTRL_CPUID_SHIFT_82576 24 /* Rx CPUID */
+
+/* Additional interrupt register bit definitions */
+#define E1000_ICR_LSECPNS       0x00000020          /* PN threshold - server */
+#define E1000_IMS_LSECPNS       E1000_ICR_LSECPNS   /* PN threshold - server */
+#define E1000_ICS_LSECPNS       E1000_ICR_LSECPNS   /* PN threshold - server */
+
+/* ETQF register bit definitions */
+#define E1000_ETQF_FILTER_ENABLE   (1 << 26)
+#define E1000_ETQF_IMM_INT         (1 << 29)
+#define E1000_ETQF_1588            (1 << 30)
+#define E1000_ETQF_QUEUE_ENABLE    (1 << 31)
+/*
+ * ETQF filter list: one static filter per filter consumer. This is
+ *                   to avoid filter collisions later. Add new filters
+ *                   here!!
+ *
+ * Current filters:
+ *    EAPOL 802.1x (0x888e): Filter 0
+ */
+#define E1000_ETQF_FILTER_EAPOL          0
+
+#define E1000_FTQF_VF_BP               0x00008000
+#define E1000_FTQF_1588_TIME_STAMP     0x08000000
+#define E1000_FTQF_MASK                0xF0000000
+#define E1000_FTQF_MASK_PROTO_BP       0x10000000
+#define E1000_FTQF_MASK_SOURCE_ADDR_BP 0x20000000
+#define E1000_FTQF_MASK_DEST_ADDR_BP   0x40000000
+#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000
+
+#define E1000_NVM_APME_82575          0x0400
+#define MAX_NUM_VFS                   8
+
+#define E1000_DTXSWC_MAC_SPOOF_MASK   0x000000FF /* Per VF MAC spoof control */
+#define E1000_DTXSWC_VLAN_SPOOF_MASK  0x0000FF00 /* Per VF VLAN spoof control */
+#define E1000_DTXSWC_LLE_MASK         0x00FF0000 /* Per VF Local LB enables */
+#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
+#define E1000_DTXSWC_LLE_SHIFT        16
+#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31)  /* global VF LB enable */
+
+/* Easy defines for setting default pool, would normally be left a zero */
+#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
+#define E1000_VT_CTL_DEFAULT_POOL_MASK  (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
+
+/* Other useful VMD_CTL register defines */
+#define E1000_VT_CTL_IGNORE_MAC         (1 << 28)
+#define E1000_VT_CTL_DISABLE_DEF_POOL   (1 << 29)
+#define E1000_VT_CTL_VM_REPL_EN         (1 << 30)
+
+/* Per VM Offload register setup */
+#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */
+#define E1000_VMOLR_LPE        0x00010000 /* Accept Long packet */
+#define E1000_VMOLR_RSSE       0x00020000 /* Enable RSS */
+#define E1000_VMOLR_AUPE       0x01000000 /* Accept untagged packets */
+#define E1000_VMOLR_ROMPE      0x02000000 /* Accept overflow multicast */
+#define E1000_VMOLR_ROPE       0x04000000 /* Accept overflow unicast */
+#define E1000_VMOLR_BAM        0x08000000 /* Accept Broadcast packets */
+#define E1000_VMOLR_MPME       0x10000000 /* Multicast promiscuous mode */
+#define E1000_VMOLR_STRVLAN    0x40000000 /* Vlan stripping enable */
+#define E1000_VMOLR_STRCRC     0x80000000 /* CRC stripping enable */
+
+#define E1000_VMOLR_VPE        0x00800000 /* VLAN promiscuous enable */
+#define E1000_VMOLR_UPE        0x20000000 /* Unicast promisuous enable */
+#define E1000_DVMOLR_HIDVLAN   0x20000000 /* Vlan hiding enable */
+#define E1000_DVMOLR_STRVLAN   0x40000000 /* Vlan stripping enable */
+#define E1000_DVMOLR_STRCRC    0x80000000 /* CRC stripping enable */
+
+#define E1000_PBRWAC_WALPB     0x00000007 /* Wrap around event on LAN Rx PB */
+#define E1000_PBRWAC_PBE       0x00000008 /* Rx packet buffer empty */
+
+#define E1000_VLVF_ARRAY_SIZE     32
+#define E1000_VLVF_VLANID_MASK    0x00000FFF
+#define E1000_VLVF_POOLSEL_SHIFT  12
+#define E1000_VLVF_POOLSEL_MASK   (0xFF << E1000_VLVF_POOLSEL_SHIFT)
+#define E1000_VLVF_LVLAN          0x00100000
+#define E1000_VLVF_VLANID_ENABLE  0x80000000
+
+#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
+#define E1000_VMVIR_VLANA_NEVER   0x80000000 /* Never insert VLAN tag */
+
+#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
+
+#define E1000_IOVCTL 0x05BBC
+#define E1000_IOVCTL_REUSE_VFQ 0x00000001
+
+#define E1000_RPLOLR_STRVLAN   0x40000000
+#define E1000_RPLOLR_STRCRC    0x80000000
+
+#define E1000_TCTL_EXT_COLD       0x000FFC00
+#define E1000_TCTL_EXT_COLD_SHIFT 10
+
+#define E1000_DTXCTL_8023LL     0x0004
+#define E1000_DTXCTL_VLAN_ADDED 0x0008
+#define E1000_DTXCTL_OOS_ENABLE 0x0010
+#define E1000_DTXCTL_MDP_EN     0x0020
+#define E1000_DTXCTL_SPOOF_INT  0x0040
+
+#define ALL_QUEUES   0xFFFF
+
+/* Rx packet buffer size defines */
+#define E1000_RXPBS_SIZE_MASK_82576  0x0000007F
+void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable);
+void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf);
+void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable);
+s32 e1000_init_nvm_params_82575(struct e1000_hw *hw);
+
+enum e1000_promisc_type {
+       e1000_promisc_disabled = 0,   /* all promisc modes disabled */
+       e1000_promisc_unicast = 1,    /* unicast promiscuous enabled */
+       e1000_promisc_multicast = 2,  /* multicast promiscuous enabled */
+       e1000_promisc_enabled = 3,    /* both uni and multicast promisc */
+       e1000_num_promisc_types
+};
+
+void e1000_vfta_set_vf(struct e1000_hw *, u16, bool);
+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 *);
+#endif /* _E1000_82575_H_ */
index 3dae75d..f2d5494 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD$*/
+/*$FreeBSD$*/
 
 #include "e1000_api.h"
 
@@ -113,6 +113,32 @@ out:
 }
 
 /**
+ *  e1000_init_mbx_params - Initialize mailbox function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function initializes the function pointers for the PHY
+ *  set of functions.  Called by drivers or by e1000_setup_init_funcs.
+ **/
+s32 e1000_init_mbx_params(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       if (hw->mbx.ops.init_params) {
+               ret_val = hw->mbx.ops.init_params(hw);
+               if (ret_val) {
+                       DEBUGOUT("Mailbox Initialization Error\n");
+                       goto out;
+               }
+       } else {
+               DEBUGOUT("mbx.init_mbx_params was NULL\n");
+               ret_val =  -E1000_ERR_CONFIG;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
  *  e1000_set_mac_type - Sets MAC type
  *  @hw: pointer to the HW structure
  *
@@ -265,6 +291,46 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
        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:
+               mac->type = e1000_82575;
+               break;
+       case E1000_DEV_ID_82576:
+       case E1000_DEV_ID_82576_FIBER:
+       case E1000_DEV_ID_82576_SERDES:
+       case E1000_DEV_ID_82576_QUAD_COPPER:
+       case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
+       case E1000_DEV_ID_82576_NS:
+       case E1000_DEV_ID_82576_NS_SERDES:
+       case E1000_DEV_ID_82576_SERDES_QUAD:
+               mac->type = e1000_82576;
+               break;
+       case E1000_DEV_ID_82580_COPPER:
+       case E1000_DEV_ID_82580_FIBER:
+       case E1000_DEV_ID_82580_SERDES:
+       case E1000_DEV_ID_82580_SGMII:
+       case E1000_DEV_ID_82580_COPPER_DUAL:
+       case E1000_DEV_ID_82580_QUAD_FIBER:
+       case E1000_DEV_ID_DH89XXCC_SGMII:
+       case E1000_DEV_ID_DH89XXCC_SERDES:
+       case E1000_DEV_ID_DH89XXCC_BACKPLANE:
+       case E1000_DEV_ID_DH89XXCC_SFP:
+               mac->type = e1000_82580;
+               break;
+       case E1000_DEV_ID_I350_COPPER:
+       case E1000_DEV_ID_I350_FIBER:
+       case E1000_DEV_ID_I350_SERDES:
+       case E1000_DEV_ID_I350_SGMII:
+       case E1000_DEV_ID_I350_DA4:
+               mac->type = e1000_i350;
+               break;
+       case E1000_DEV_ID_82576_VF:
+               mac->type = e1000_vfadapt;
+               break;
+       case E1000_DEV_ID_I350_VF:
+               mac->type = e1000_vfadapt_i350;
+               break;
        default:
                /* Should never have loaded on this device */
                ret_val = -E1000_ERR_MAC_INIT;
@@ -310,6 +376,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
        e1000_init_mac_ops_generic(hw);
        e1000_init_phy_ops_generic(hw);
        e1000_init_nvm_ops_generic(hw);
+       e1000_init_mbx_ops_generic(hw);
 
        /*
         * Set up the init function pointers. These are functions within the
@@ -356,6 +423,18 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
        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_vfadapt:
+               e1000_init_function_pointers_vf(hw);
+               break;
+       case e1000_vfadapt_i350:
+               e1000_init_function_pointers_vf(hw);
+               break;
        default:
                DEBUGOUT("Hardware not supported\n");
                ret_val = -E1000_ERR_CONFIG;
@@ -378,6 +457,10 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
                ret_val = e1000_init_phy_params(hw);
                if (ret_val)
                        goto out;
+
+               ret_val = e1000_init_mbx_params(hw);
+               if (ret_val)
+                       goto out;
        }
 
 out:
@@ -1202,6 +1285,22 @@ s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 }
 
 /**
+ *  e1000_write_8bit_ctrl_reg - Writes 8bit Control register
+ *  @hw: pointer to the HW structure
+ *  @reg: 32bit register offset
+ *  @offset: the register to write
+ *  @data: the value to write.
+ *
+ *  Writes the PHY register at offset with the value in data.
+ *  This is a function pointer entry point called by drivers.
+ **/
+s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset,
+                              u8 data)
+{
+       return e1000_write_8bit_ctrl_reg_generic(hw, reg, offset, data);
+}
+
+/**
  * e1000_power_up_phy - Restores link in case of PHY power down
  * @hw: pointer to the HW structure
  *
@@ -1229,3 +1328,27 @@ void e1000_power_down_phy(struct e1000_hw *hw)
                hw->phy.ops.power_down(hw);
 }
 
+/**
+ *  e1000_power_up_fiber_serdes_link - Power up serdes link
+ *  @hw: pointer to the HW structure
+ *
+ *  Power on the optics and PCS.
+ **/
+void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.power_up_serdes)
+               hw->mac.ops.power_up_serdes(hw);
+}
+
+/**
+ *  e1000_shutdown_fiber_serdes_link - Remove link during power down
+ *  @hw: pointer to the HW structure
+ *
+ *  Shutdown the optics and PCS on driver unload.
+ **/
+void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.shutdown_serdes)
+               hw->mac.ops.shutdown_serdes(hw);
+}
+
index 94cbde9..2dfec0d 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: $*/
+/*$FreeBSD*/
 
 #ifndef _E1000_API_H_
 #define _E1000_API_H_
@@ -46,12 +46,18 @@ 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);
 
 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);
 s32  e1000_init_nvm_params(struct e1000_hw *hw);
 s32  e1000_init_phy_params(struct e1000_hw *hw);
+s32  e1000_init_mbx_params(struct e1000_hw *hw);
 s32  e1000_get_bus_info(struct e1000_hw *hw);
 void e1000_clear_vfta(struct e1000_hw *hw);
 void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
@@ -81,6 +87,8 @@ s32  e1000_get_cable_length(struct e1000_hw *hw);
 s32  e1000_validate_mdi_setting(struct e1000_hw *hw);
 s32  e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
+                               u32 offset, u8 data);
 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);
index eb2072e..50c7b3c 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD$*/
+/*$FreeBSD$*/
 
 #ifndef _E1000_DEFINES_H_
 #define _E1000_DEFINES_H_
 #define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
 #define E1000_WUC_APMPME     0x00000008 /* Assert PME on APM Wakeup */
 #define E1000_WUC_LSCWE      0x00000010 /* Link Status wake up enable */
+#define E1000_WUC_PPROXYE    0x00000010 /* Protocol Proxy Enable */
 #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 */
 #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_ALL_FILTERS_PHY_4 0x0000F0FF /*Mask for all wakeup filters*/
-#define E1000_WUFC_FLX_OFFSET_PHY 12 /* Offset to the Flexible Filters bits */
-#define E1000_WUFC_FLX_FILTERS_PHY_4 0x0000F000 /*Mask for 4 flexible filters*/
-#define E1000_WUFC_ALL_FILTERS_PHY_6 0x0000F6FF /*Mask for 6 wakeup filters */
-#define E1000_WUFC_FLX_FILTERS_PHY_6 0x0000F600 /*Mask for 6 flexible filters*/
+#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_ALL_FILTERS_6  0x003F00FF /* Mask for all 6 wakeup filters*/
-#define E1000_WUFC_ALL_FILTERS_8  0x00FF00FF /* Mask for all 8 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_FLX_FILTERS_6  0x003F0000 /* Mask for 6 flexible filters */
-#define E1000_WUFC_FLX_FILTERS_8  0x00FF0000 /* Mask for 8 flexible filters */
+/*
+ * For 82576 to utilize Extended filter masks in addition to
+ * existing (filter) masks
+ */
+#define E1000_WUFC_EXT_FLX_FILTERS      0x00300000 /* Ext. FLX filter mask */
 
 /* Wake Up Status */
 #define E1000_WUS_LNKC         E1000_WUFC_LNKC
 #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 */
+#define E1000_FHFT_LENGTH_MASK          0x0FF /* Length in lower byte */
 
 /* Each Flexible Filter is at most 128 (0x80) bytes in length */
 #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
 
 #define E1000_CTRL_EXT_ASDCHK    0x00001000 /* Initiate an ASD sequence */
 #define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
 #define E1000_CTRL_EXT_IPS       0x00004000 /* Invert Power State */
+/* Physical Func Reset Done Indication */
+#define E1000_CTRL_EXT_PFRSTD    0x00004000
 #define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
 #define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
 #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
-#define E1000_CTRL_EXT_LINK_MODE_OFFSET 22  /* Offset of the link mode field
-                                             * in Ctrl Ext register */
 #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
 #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
+#define E1000_GPIE_NSICR        0x00000001
+#define E1000_GPIE_MSIX_MODE    0x00000010
+#define E1000_GPIE_EIAME        0x40000000
+#define E1000_GPIE_PBA          0x80000000
 
 /* Receive Descriptor bit definitions */
 #define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
 #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  |                \
 #define E1000_MANC_SMB_DATA_IN   0x08000000 /* SMBus Data In */
 #define E1000_MANC_SMB_DATA_OUT  0x10000000 /* SMBus Data Out */
 #define E1000_MANC_SMB_CLK_OUT   0x20000000 /* SMBus Clock Out */
+#define E1000_MANC_MPROXYE       0x40000000 /* Mngment Proxy Enable */
+#define E1000_MANC_EN_BMC2OS     0x10000000 /* OS2BMC is enabled or not */
 
 #define E1000_MANC_SMB_DATA_OUT_SHIFT  28 /* SMBus Data Out Shift */
 #define E1000_MANC_SMB_CLK_OUT_SHIFT   29 /* SMBus Clock Out Shift */
 #define E1000_SWFW_CSR_SM   0x08
 #define E1000_SWFW_PHY2_SM  0x20
 #define E1000_SWFW_PHY3_SM  0x40
+#define E1000_SWFW_SW_MNG_SM 0x400
 
 /* FACTPS Definitions */
 #define E1000_FACTPS_LFS    0x40000000  /* LAN Function Select */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
 #define E1000_CTRL_SWDPIN2  0x00100000  /* SWDPIN 2 value */
+#define E1000_CTRL_ADVD3WUC 0x00100000  /* D3 WUC */
 #define E1000_CTRL_SWDPIN3  0x00200000  /* SWDPIN 3 value */
 #define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */
 #define E1000_CTRL_SWDPIO1  0x00800000  /* SWDPIN 1 input or output */
 #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 */
                                             * an interrupt */
 #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 */
+
 /* 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_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 */
+#define E1000_EICR_RX_QUEUE2    0x00000004 /* Rx Queue 2 Interrupt */
+#define E1000_EICR_RX_QUEUE3    0x00000008 /* Rx Queue 3 Interrupt */
+#define E1000_EICR_TX_QUEUE0    0x00000100 /* Tx Queue 0 Interrupt */
+#define E1000_EICR_TX_QUEUE1    0x00000200 /* Tx Queue 1 Interrupt */
+#define E1000_EICR_TX_QUEUE2    0x00000400 /* Tx Queue 2 Interrupt */
+#define E1000_EICR_TX_QUEUE3    0x00000800 /* Tx Queue 3 Interrupt */
+#define E1000_EICR_TCP_TIMER    0x40000000 /* TCP Timer */
+#define E1000_EICR_OTHER        0x80000000 /* Interrupt Cause Active */
+/* TCP Timer */
+#define E1000_TCPTIMER_KS       0x00000100 /* KickStart */
+#define E1000_TCPTIMER_COUNT_ENABLE       0x00000200 /* Count Enable */
+#define E1000_TCPTIMER_COUNT_FINISH       0x00000400 /* Count finish */
+#define E1000_TCPTIMER_LOOP     0x00000800 /* Loop */
+
 /*
  * This defines the bits that are set in the Interrupt Mask
  * Set/Read Register.  Each bit is documented below:
 #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*/
+#define E1000_IMS_MDDET         E1000_ICR_MDDET /* Malicious Driver Detect */
+/* Extended Interrupt Mask Set */
+#define E1000_EIMS_RX_QUEUE0    E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
+#define E1000_EIMS_RX_QUEUE1    E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */
+#define E1000_EIMS_RX_QUEUE2    E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */
+#define E1000_EIMS_RX_QUEUE3    E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */
+#define E1000_EIMS_TX_QUEUE0    E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */
+#define E1000_EIMS_TX_QUEUE1    E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */
+#define E1000_EIMS_TX_QUEUE2    E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */
+#define E1000_EIMS_TX_QUEUE3    E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */
+#define E1000_EIMS_TCP_TIMER    E1000_EICR_TCP_TIMER /* TCP Timer */
+#define E1000_EIMS_OTHER        E1000_EICR_OTHER   /* Interrupt Cause Active */
+
 /* Interrupt Cause Set */
 #define E1000_ICS_TXDW      E1000_ICR_TXDW      /* Tx desc written back */
 #define E1000_ICS_TXQE      E1000_ICR_TXQE      /* Transmit Queue empty */
 #define E1000_ICS_PHYINT    E1000_ICR_PHYINT
 #define E1000_ICS_EPRST     E1000_ICR_EPRST
 
+/* Extended Interrupt Cause Set */
+#define E1000_EICS_RX_QUEUE0    E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
+#define E1000_EICS_RX_QUEUE1    E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */
+#define E1000_EICS_RX_QUEUE2    E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */
+#define E1000_EICS_RX_QUEUE3    E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */
+#define E1000_EICS_TX_QUEUE0    E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */
+#define E1000_EICS_TX_QUEUE1    E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */
+#define E1000_EICS_TX_QUEUE2    E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */
+#define E1000_EICS_TX_QUEUE3    E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */
+#define E1000_EICS_TCP_TIMER    E1000_EICR_TCP_TIMER /* TCP Timer */
+#define E1000_EICS_OTHER        E1000_EICR_OTHER   /* Interrupt Cause Active */
+
+#define E1000_EITR_ITR_INT_MASK 0x0000FFFF
+/* E1000_EITR_CNT_IGNR is only for 82576 and newer */
+#define E1000_EITR_CNT_IGNR     0x80000000 /* Don't reset counters on write */
+
 /* Transmit Descriptor Control */
 #define E1000_TXDCTL_PTHRESH    0x0000003F /* TXDCTL Prefetch Threshold */
 #define E1000_TXDCTL_HTHRESH    0x00003F00 /* TXDCTL Host Threshold */
 #define E1000_RAH_AV  0x80000000        /* Receive descriptor valid */
 #define E1000_RAL_MAC_ADDR_LEN 4
 #define E1000_RAH_MAC_ADDR_LEN 2
+#define E1000_RAH_QUEUE_MASK_82575 0x000C0000
 #define E1000_RAH_POOL_MASK     0x03FC0000
 #define E1000_RAH_POOL_SHIFT    18
 #define E1000_RAH_POOL_1        0x00040000
 #define E1000_MDICNFG_PHY_MASK    0x03E00000
 #define E1000_MDICNFG_PHY_SHIFT   21
 
+#define E1000_THSTAT_LOW_EVENT      0x20000000  /* Low thermal threshold */
+#define E1000_THSTAT_MID_EVENT      0x00200000  /* Mid thermal threshold */
+#define E1000_THSTAT_HIGH_EVENT     0x00002000  /* High thermal threshold */
+#define E1000_THSTAT_PWR_DOWN       0x00000001  /* Power Down Event */
+#define E1000_THSTAT_LINK_THROTTLE  0x00000002  /* Link Speed Throttle Event */
+
+/* Powerville EEE defines */
+#define E1000_IPCNFG_EEE_1G_AN      0x00000008  /* IPCNFG EEE Enable 1G AN */
+#define E1000_IPCNFG_EEE_100M_AN    0x00000004  /* IPCNFG EEE Enable 100M AN */
+#define E1000_EEER_TX_LPI_EN        0x00010000  /* EEER Tx LPI Enable */
+#define E1000_EEER_RX_LPI_EN        0x00020000  /* EEER Rx LPI Enable */
+#define E1000_EEER_LPI_FC           0x00040000  /* EEER Enable on Flow Control*/
+/* EEE status */
+#define E1000_EEER_EEE_NEG          0x20000000  /* EEE capability negotiated */
+#define E1000_EEER_RX_LPI_STATUS    0x40000000  /* Rx in LPI state */
+#define E1000_EEER_TX_LPI_STATUS    0x80000000  /* Tx in LPI state */
+
 /* PCI Express Control */
 #define E1000_GCR_RXD_NO_SNOOP          0x00000001
 #define E1000_GCR_RXDSCW_NO_SNOOP       0x00000002
 /* 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 external */
-#define NVM_WORD24_LNK_MODE_OFFSET         8 /* Offset of Link Mode bits
-                                              * for 82575 up to Kawela */
-#define NVM_WORD24_82580_LNK_MODE_OFFSET   4 /* Offset of Link Mode bits
-                                              * Link Mode bits for 82580 up */
-
 
 /* Mask bits for fields in Word 0x0f of the NVM */
 #define NVM_WORD0F_PAUSE_MASK       0x3000
 #define IGP01E1000_I_PHY_ID  0x02A80380
 #define M88E1011_I_REV_4     0x04
 #define M88E1111_I_PHY_ID    0x01410CC0
+#define M88E1112_E_PHY_ID    0x01410C90
+#define I347AT4_E_PHY_ID     0x01410DC0
+#define M88E1340M_E_PHY_ID   0x01410DF0
 #define GG82563_E_PHY_ID     0x01410CA0
 #define IGP03E1000_E_PHY_ID  0x02A80390
 #define IFE_E_PHY_ID         0x02A80330
 #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 I82577_E_PHY_ID      0x01540050
+#define I82578_E_PHY_ID      0x004DD040
+#define I82579_E_PHY_ID      0x01540090
 #define I82580_I_PHY_ID      0x015403A0
+#define I350_I_PHY_ID        0x015403B0
+#define IGP04E1000_E_PHY_ID  0x02A80391
 #define M88_VENDOR           0x0141
 
 /* M88E1000 Specific Registers */
 #define M88E1111_PHY_PAGE_SELECT_MASK1  0xFF
 #define M88E1111_PHY_PAGE_SELECT_MASK2  0x3F
 
+/* Intel I347AT4 Registers */
+
+#define I347AT4_PCDL            0x10 /* PHY Cable Diagnostics Length */
+#define I347AT4_PCDC            0x15 /* PHY Cable Diagnostics Control */
+#define I347AT4_PAGE_SELECT     0x16
+
+/* I347AT4 Extended PHY Specific Control Register */
+
+/*
+ * Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master
+ */
+#define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800
+#define I347AT4_PSCR_DOWNSHIFT_MASK   0x7000
+#define I347AT4_PSCR_DOWNSHIFT_1X     0x0000
+#define I347AT4_PSCR_DOWNSHIFT_2X     0x1000
+#define I347AT4_PSCR_DOWNSHIFT_3X     0x2000
+#define I347AT4_PSCR_DOWNSHIFT_4X     0x3000
+#define I347AT4_PSCR_DOWNSHIFT_5X     0x4000
+#define I347AT4_PSCR_DOWNSHIFT_6X     0x5000
+#define I347AT4_PSCR_DOWNSHIFT_7X     0x6000
+#define I347AT4_PSCR_DOWNSHIFT_8X     0x7000
+
+/* I347AT4 PHY Cable Diagnostics Control */
+#define I347AT4_PCDC_CABLE_LENGTH_UNIT  0x0400 /* 0=cm 1=meters */
+
+/* M88E1112 only registers */
+#define M88E1112_VCT_DSP_DISTANCE       0x001A
 
 /* M88EC018 Rev 2 specific DownShift settings */
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK  0x0E00
 /* BME1000 PHY Specific Control Register */
 #define BME1000_PSCR_ENABLE_DOWNSHIFT   0x0800 /* 1 = enable downshift */
 
+
 /*
  * Bits...
  * 15-5: page
 #define E1000_GEN_CTL_ADDRESS_SHIFT     8
 #define E1000_GEN_POLL_TIMEOUT          640
 
+/* LinkSec register fields */
+#define E1000_LSECTXCAP_SUM_MASK        0x00FF0000
+#define E1000_LSECTXCAP_SUM_SHIFT       16
+#define E1000_LSECRXCAP_SUM_MASK        0x00FF0000
+#define E1000_LSECRXCAP_SUM_SHIFT       16
+
+#define E1000_LSECTXCTRL_EN_MASK        0x00000003
+#define E1000_LSECTXCTRL_DISABLE        0x0
+#define E1000_LSECTXCTRL_AUTH           0x1
+#define E1000_LSECTXCTRL_AUTH_ENCRYPT   0x2
+#define E1000_LSECTXCTRL_AISCI          0x00000020
+#define E1000_LSECTXCTRL_PNTHRSH_MASK   0xFFFFFF00
+#define E1000_LSECTXCTRL_RSV_MASK       0x000000D8
+
+#define E1000_LSECRXCTRL_EN_MASK        0x0000000C
+#define E1000_LSECRXCTRL_EN_SHIFT       2
+#define E1000_LSECRXCTRL_DISABLE        0x0
+#define E1000_LSECRXCTRL_CHECK          0x1
+#define E1000_LSECRXCTRL_STRICT         0x2
+#define E1000_LSECRXCTRL_DROP           0x3
+#define E1000_LSECRXCTRL_PLSH           0x00000040
+#define E1000_LSECRXCTRL_RP             0x00000080
+#define E1000_LSECRXCTRL_RSV_MASK       0xFFFFFF33
+
+/* Tx Rate-Scheduler Config fields */
+#define E1000_RTTBCNRC_RS_ENA          0x80000000
+#define E1000_RTTBCNRC_RF_DEC_MASK     0x00003FFF
+#define E1000_RTTBCNRC_RF_INT_SHIFT     14
+#define E1000_RTTBCNRC_RF_INT_MASK     \
+       (E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT)
+
 /* DMA Coalescing register fields */
 #define E1000_DMACR_DMACWT_MASK         0x00003FFF /* DMA Coalescing
                                                     * Watchdog Timer */
 #define E1000_PCIEMISC_LX_DECISION      0x00000080 /* Lx power decision based
                                                       on DMA coal */
 
+/* Proxy Filer Control */
+#define E1000_PROXYFC_D0               0x00000001  /* Enable offload in D0 */
+#define E1000_PROXYFC_EX               0x00000004  /* Directed exact proxy */
+#define E1000_PROXYFC_MC               0x00000008  /* Directed Multicast
+                                                    * Proxy */
+#define E1000_PROXYFC_BC               0x00000010  /* Broadcast Proxy Enable */
+#define E1000_PROXYFC_ARP_DIRECTED     0x00000020  /* Directed ARP Proxy
+                                                    * Enable */
+#define E1000_PROXYFC_IPV4             0x00000040  /* Directed IPv4 Enable */
+#define E1000_PROXYFC_IPV6             0x00000080  /* Directed IPv6 Enable */
+#define E1000_PROXYFC_NS               0x00000200  /* IPv4 Neighborhood
+                                                    * Solicitation */
+#define E1000_PROXYFC_ARP              0x00000800  /* ARP Request Proxy
+                                                    * Enable */
+/* Proxy Status */
+#define E1000_PROXYS_CLEAR             0xFFFFFFFF  /* Clear */
+
+/* Firmware Status */
+#define E1000_FWSTS_FWRI               0x80000000 /* Firmware Reset
+                                                   * Indication */
+
+
 #endif /* _E1000_DEFINES_H_ */
index 8595667..ea9b1e5 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: $*/
+/*$FreeBSD:$*/
 
 #ifndef _E1000_HW_H_
 #define _E1000_HW_H_
@@ -126,19 +126,40 @@ struct e1000_hw;
 #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
+#define E1000_DEV_ID_82576_QUAD_COPPER        0x10E8
+#define E1000_DEV_ID_82576_QUAD_COPPER_ET2    0x1526
+#define E1000_DEV_ID_82576_NS                 0x150A
+#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_I350_VF                  0x1520
+#define E1000_DEV_ID_82575EB_COPPER           0x10A7
+#define E1000_DEV_ID_82575EB_FIBER_SERDES     0x10A9
+#define E1000_DEV_ID_82575GB_QUAD_COPPER      0x10D6
 #define E1000_DEV_ID_82580_COPPER             0x150E
 #define E1000_DEV_ID_82580_FIBER              0x150F
 #define E1000_DEV_ID_82580_SERDES             0x1510
 #define E1000_DEV_ID_82580_SGMII              0x1511
 #define E1000_DEV_ID_82580_COPPER_DUAL        0x1516
 #define E1000_DEV_ID_82580_QUAD_FIBER         0x1527
+#define E1000_DEV_ID_I350_COPPER              0x1521
+#define E1000_DEV_ID_I350_FIBER               0x1522
+#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_DH89XXCC_SGMII           0x0438
+#define E1000_DEV_ID_DH89XXCC_SERDES          0x043A
+#define E1000_DEV_ID_DH89XXCC_BACKPLANE       0x043C
+#define E1000_DEV_ID_DH89XXCC_SFP             0x0440
 #define E1000_REVISION_0 0
 #define E1000_REVISION_1 1
 #define E1000_REVISION_2 2
@@ -182,6 +203,12 @@ enum e1000_mac_type {
        e1000_ich10lan,
        e1000_pchlan,
        e1000_pch2lan,
+       e1000_82575,
+       e1000_82576,
+       e1000_82580,
+       e1000_i350,
+       e1000_vfadapt,
+       e1000_vfadapt_i350,
        e1000_num_macs  /* List is 1-based, so subtract 1 for TRUE count. */
 };
 
@@ -224,6 +251,7 @@ enum e1000_phy_type {
        e1000_phy_82577,
        e1000_phy_82579,
        e1000_phy_82580,
+       e1000_phy_vf,
 };
 
 enum e1000_bus_type {
@@ -530,6 +558,37 @@ struct e1000_hw_stats {
        u64 doosync;
 };
 
+struct e1000_vf_stats {
+       u64 base_gprc;
+       u64 base_gptc;
+       u64 base_gorc;
+       u64 base_gotc;
+       u64 base_mprc;
+       u64 base_gotlbc;
+       u64 base_gptlbc;
+       u64 base_gorlbc;
+       u64 base_gprlbc;
+
+       u32 last_gprc;
+       u32 last_gptc;
+       u32 last_gorc;
+       u32 last_gotc;
+       u32 last_mprc;
+       u32 last_gotlbc;
+       u32 last_gptlbc;
+       u32 last_gorlbc;
+       u32 last_gprlbc;
+
+       u64 gprc;
+       u64 gptc;
+       u64 gorc;
+       u64 gotc;
+       u64 mprc;
+       u64 gotlbc;
+       u64 gptlbc;
+       u64 gorlbc;
+       u64 gprlbc;
+};
 
 struct e1000_phy_stats {
        u32 idle_errors;
@@ -580,6 +639,7 @@ struct e1000_host_mng_command_info {
 #include "e1000_phy.h"
 #include "e1000_nvm.h"
 #include "e1000_manage.h"
+#include "e1000_mbx.h"
 
 struct e1000_mac_operations {
        /* Function pointers for the MAC. */
@@ -599,6 +659,8 @@ struct e1000_mac_operations {
        void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
        s32  (*reset_hw)(struct e1000_hw *);
        s32  (*init_hw)(struct e1000_hw *);
+       void (*shutdown_serdes)(struct e1000_hw *);
+       void (*power_up_serdes)(struct e1000_hw *);
        s32  (*setup_link)(struct e1000_hw *);
        s32  (*setup_physical_interface)(struct e1000_hw *);
        s32  (*setup_led)(struct e1000_hw *);
@@ -688,6 +750,7 @@ struct e1000_mac_info {
        u16 ifs_ratio;
        u16 ifs_step_size;
        u16 mta_reg_count;
+       u16 uta_reg_count;
 
        /* Maximum size of the MTA register table in all supported adapters */
        #define MAX_MTA_REG 128
@@ -781,6 +844,34 @@ struct e1000_fc_info {
        enum e1000_fc_mode requested_mode; /* FC mode requested by caller */
 };
 
+struct e1000_mbx_operations {
+       s32 (*init_params)(struct e1000_hw *hw);
+       s32 (*read)(struct e1000_hw *, u32 *, u16,  u16);
+       s32 (*write)(struct e1000_hw *, u32 *, u16, u16);
+       s32 (*read_posted)(struct e1000_hw *, u32 *, u16,  u16);
+       s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16);
+       s32 (*check_for_msg)(struct e1000_hw *, u16);
+       s32 (*check_for_ack)(struct e1000_hw *, u16);
+       s32 (*check_for_rst)(struct e1000_hw *, u16);
+};
+
+struct e1000_mbx_stats {
+       u32 msgs_tx;
+       u32 msgs_rx;
+
+       u32 acks;
+       u32 reqs;
+       u32 rsts;
+};
+
+struct e1000_mbx_info {
+       struct e1000_mbx_operations ops;
+       struct e1000_mbx_stats stats;
+       u32 timeout;
+       u32 usec_delay;
+       u16 size;
+};
+
 struct e1000_dev_spec_82541 {
        enum e1000_dsp_config dsp_config;
        enum e1000_ffe_config ffe_config;
@@ -823,6 +914,17 @@ struct e1000_dev_spec_ich8lan {
        bool eee_disable;
 };
 
+struct e1000_dev_spec_82575 {
+       bool sgmii_active;
+       bool global_device_reset;
+       bool eee_disable;
+};
+
+struct e1000_dev_spec_vf {
+       u32 vf_number;
+       u32 v2p_mailbox;
+};
+
 struct e1000_hw {
        void *back;
 
@@ -835,6 +937,7 @@ struct e1000_hw {
        struct e1000_phy_info  phy;
        struct e1000_nvm_info  nvm;
        struct e1000_bus_info  bus;
+       struct e1000_mbx_info mbx;
        struct e1000_host_mng_dhcp_cookie mng_cookie;
 
        union {
@@ -846,6 +949,8 @@ struct e1000_hw {
                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;
 
        u16 device_id;
@@ -861,6 +966,7 @@ struct e1000_hw {
 #include "e1000_82571.h"
 #include "e1000_80003es2lan.h"
 #include "e1000_ich8lan.h"
+#include "e1000_82575.h"
 
 /* These functions must be implemented by drivers */
 #ifndef NO_82542_SUPPORT
index 4606dd3..995ecfd 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD$*/
+/*$FreeBSD$*/
 
 #include "e1000_api.h"
 
@@ -2135,3 +2135,43 @@ static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
 out:
        return ret_val;
 }
+
+/**
+ *  e1000_write_8bit_ctrl_reg_generic - Write a 8bit CTRL register
+ *  @hw: pointer to the HW structure
+ *  @reg: 32bit register offset such as E1000_SCTL
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Writes an address/data control type register.  There are several of these
+ *  and they all have the format address << 8 | data and bit 31 is polled for
+ *  completion.
+ **/
+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");
+
+       /* Set up the address and data */
+       regvalue = ((u32)data) | (offset << E1000_GEN_CTL_ADDRESS_SHIFT);
+       E1000_WRITE_REG(hw, reg, regvalue);
+
+       /* Poll the ready bit to see if the MDI read completed */
+       for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) {
+               usec_delay(5);
+               regvalue = E1000_READ_REG(hw, reg);
+               if (regvalue & E1000_GEN_CTL_READY)
+                       break;
+       }
+       if (!(regvalue & E1000_GEN_CTL_READY)) {
+               DEBUGOUT1("Reg %08x did not indicate ready\n", reg);
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+       }
+
+out:
+       return ret_val;
+}
index e952335..515a8b5 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD$*/
+/*$FreeBSD$*/
 
 #ifndef _E1000_MAC_H_
 #define _E1000_MAC_H_
@@ -79,6 +79,8 @@ 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_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
+                                       u32 offset, u8 data);
 
 u32  e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr);
 
index 16a88b5..5cfcf64 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: $*/
+/*$FreeBSD:$*/
 
 #include "e1000_api.h"
 
@@ -42,7 +42,7 @@
  *  Calculates the checksum for some buffer on a specified length.  The
  *  checksum calculated is returned.
  **/
-static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
+u8 e1000_calculate_checksum(u8 *buffer, u32 length)
 {
        u32 i;
        u8 sum = 0;
@@ -402,3 +402,84 @@ out:
        return ret_val;
 }
 
+/**
+ *  e1000_host_interface_command - Writes buffer to host interface
+ *  @hw: pointer to the HW structure
+ *  @buffer: contains a command to write
+ *  @length: the byte length of the buffer, must be multiple of 4 bytes
+ *
+ *  Writes a buffer to the Host Interface.  Upon success, returns E1000_SUCCESS
+ *  else returns E1000_ERR_HOST_INTERFACE_COMMAND.
+ **/
+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;
+       }
+
+       if (!hw->mac.asf_firmware_present) {
+               DEBUGOUT("Firmware is not present.\n");
+               goto out;
+       }
+
+       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;
+       }
+
+       /* Check that the host interface is enabled. */
+       hicr = E1000_READ_REG(hw, E1000_HICR);
+       if ((hicr & E1000_HICR_EN) == 0) {
+               DEBUGOUT("E1000_HOST_EN bit disabled.\n");
+               ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
+               goto out;
+       }
+
+       /* Calculate length in DWORDs */
+       length >>= 2;
+
+       /*
+        * The device driver writes the relevant command block
+        * into the ram area.
+        */
+       for (i = 0; i < length; i++)
+               E1000_WRITE_REG_ARRAY_DWORD(hw,
+                                           E1000_HOST_IF,
+                                           i,
+                                           *((u32 *)buffer + i));
+
+       /* Setting this bit tells the ARC that a new command is pending. */
+       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 command successful completion. */
+       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;
+       }
+
+       for (i = 0; i < length; i++)
+               *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
+                                                                 E1000_HOST_IF,
+                                                                 i);
+
+out:
+       return ret_val;
+}
+
index 3a61ac1..9a8d756 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD$*/
+/*$FreeBSD$*/
 
 #ifndef _E1000_MANAGE_H_
 #define _E1000_MANAGE_H_
@@ -45,6 +45,8 @@ s32  e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
 s32  e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw,
                                        u8 *buffer, u16 length);
 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);
 
 enum e1000_mng_mode {
        e1000_mng_mode_none = 0,
diff --git a/sys/dev/netif/ig_hal/e1000_mbx.c b/sys/dev/netif/ig_hal/e1000_mbx.c
new file mode 100644 (file)
index 0000000..67dbc64
--- /dev/null
@@ -0,0 +1,764 @@
+/******************************************************************************
+
+  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$*/
+
+#include "e1000_mbx.h"
+
+/**
+ *  e1000_null_mbx_check_for_flag - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_null_mbx_check_for_flag(struct e1000_hw *hw, u16 mbx_id)
+{
+       DEBUGFUNC("e1000_null_mbx_check_flag");
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_null_mbx_transact - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_null_mbx_transact(struct e1000_hw *hw, u32 *msg, u16 size,
+                            u16 mbx_id)
+{
+       DEBUGFUNC("e1000_null_mbx_rw_msg");
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_read_mbx - Reads a message from the mailbox
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to read
+ *
+ *  returns SUCCESS if it successfuly read message from buffer
+ **/
+s32 e1000_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_read_mbx");
+
+       /* limit read to size of mailbox */
+       if (size > mbx->size)
+               size = mbx->size;
+
+       if (mbx->ops.read)
+               ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_write_mbx - Write a message to the mailbox
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully copied message into the buffer
+ **/
+s32 e1000_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_write_mbx");
+
+       if (size > mbx->size)
+               ret_val = -E1000_ERR_MBX;
+
+       else if (mbx->ops.write)
+               ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_msg - checks to see if someone sent us mail
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to check
+ *
+ *  returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+s32 e1000_check_for_msg(struct e1000_hw *hw, u16 mbx_id)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_check_for_msg");
+
+       if (mbx->ops.check_for_msg)
+               ret_val = mbx->ops.check_for_msg(hw, mbx_id);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_ack - checks to see if someone sent us ACK
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to check
+ *
+ *  returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+s32 e1000_check_for_ack(struct e1000_hw *hw, u16 mbx_id)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_check_for_ack");
+
+       if (mbx->ops.check_for_ack)
+               ret_val = mbx->ops.check_for_ack(hw, mbx_id);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_rst - checks to see if other side has reset
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to check
+ *
+ *  returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+s32 e1000_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_check_for_rst");
+
+       if (mbx->ops.check_for_rst)
+               ret_val = mbx->ops.check_for_rst(hw, mbx_id);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_poll_for_msg - Wait for message notification
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully received a message notification
+ **/
+static s32 e1000_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       int countdown = mbx->timeout;
+
+       DEBUGFUNC("e1000_poll_for_msg");
+
+       if (!countdown || !mbx->ops.check_for_msg)
+               goto out;
+
+       while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
+               countdown--;
+               if (!countdown)
+                       break;
+               usec_delay(mbx->usec_delay);
+       }
+
+       /* if we failed, all future posted messages fail until reset */
+       if (!countdown)
+               mbx->timeout = 0;
+out:
+       return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
+}
+
+/**
+ *  e1000_poll_for_ack - Wait for message acknowledgement
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully received a message acknowledgement
+ **/
+static s32 e1000_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       int countdown = mbx->timeout;
+
+       DEBUGFUNC("e1000_poll_for_ack");
+
+       if (!countdown || !mbx->ops.check_for_ack)
+               goto out;
+
+       while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
+               countdown--;
+               if (!countdown)
+                       break;
+               usec_delay(mbx->usec_delay);
+       }
+
+       /* if we failed, all future posted messages fail until reset */
+       if (!countdown)
+               mbx->timeout = 0;
+out:
+       return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
+}
+
+/**
+ *  e1000_read_posted_mbx - Wait for message notification and receive message
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully received a message notification and
+ *  copied it into the receive buffer.
+ **/
+s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_read_posted_mbx");
+
+       if (!mbx->ops.read)
+               goto out;
+
+       ret_val = e1000_poll_for_msg(hw, mbx_id);
+
+       /* if ack received read message, otherwise we timed out */
+       if (!ret_val)
+               ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_write_posted_mbx - Write a message to the mailbox, wait for ack
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully copied message into the buffer and
+ *  received an ack to that message within delay * timeout period
+ **/
+s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_write_posted_mbx");
+
+       /* exit if either we can't write or there isn't a defined timeout */
+       if (!mbx->ops.write || !mbx->timeout)
+               goto out;
+
+       /* send msg */
+       ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+
+       /* if msg sent wait until we receive an ack */
+       if (!ret_val)
+               ret_val = e1000_poll_for_ack(hw, mbx_id);
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_mbx_ops_generic - Initialize mbx function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets the function pointers to no-op functions
+ **/
+void e1000_init_mbx_ops_generic(struct e1000_hw *hw)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       mbx->ops.init_params = e1000_null_ops_generic;
+       mbx->ops.read = e1000_null_mbx_transact;
+       mbx->ops.write = e1000_null_mbx_transact;
+       mbx->ops.check_for_msg = e1000_null_mbx_check_for_flag;
+       mbx->ops.check_for_ack = e1000_null_mbx_check_for_flag;
+       mbx->ops.check_for_rst = e1000_null_mbx_check_for_flag;
+       mbx->ops.read_posted = e1000_read_posted_mbx;
+       mbx->ops.write_posted = e1000_write_posted_mbx;
+}
+
+/**
+ *  e1000_read_v2p_mailbox - read v2p mailbox
+ *  @hw: pointer to the HW structure
+ *
+ *  This function is used to read the v2p mailbox without losing the read to
+ *  clear status bits.
+ **/
+static u32 e1000_read_v2p_mailbox(struct e1000_hw *hw)
+{
+       u32 v2p_mailbox = E1000_READ_REG(hw, E1000_V2PMAILBOX(0));
+
+       v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
+       hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
+
+       return v2p_mailbox;
+}
+
+/**
+ *  e1000_check_for_bit_vf - Determine if a status bit was set
+ *  @hw: pointer to the HW structure
+ *  @mask: bitmask for bits to be tested and cleared
+ *
+ *  This function is used to check for the read to clear bits within
+ *  the V2P mailbox.
+ **/
+static s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
+{
+       u32 v2p_mailbox = e1000_read_v2p_mailbox(hw);
+       s32 ret_val = -E1000_ERR_MBX;
+
+       if (v2p_mailbox & mask)
+               ret_val = E1000_SUCCESS;
+
+       hw->dev_spec.vf.v2p_mailbox &= ~mask;
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_msg_vf - checks to see if the PF has sent mail
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to check
+ *
+ *  returns SUCCESS if the PF has set the Status bit or else ERR_MBX
+ **/
+static s32 e1000_check_for_msg_vf(struct e1000_hw *hw, u16 mbx_id)
+{
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_check_for_msg_vf");
+
+       if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
+               ret_val = E1000_SUCCESS;
+               hw->mbx.stats.reqs++;
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_ack_vf - checks to see if the PF has ACK'd
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to check
+ *
+ *  returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
+ **/
+static s32 e1000_check_for_ack_vf(struct e1000_hw *hw, u16 mbx_id)
+{
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_check_for_ack_vf");
+
+       if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
+               ret_val = E1000_SUCCESS;
+               hw->mbx.stats.acks++;
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_rst_vf - checks to see if the PF has reset
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to check
+ *
+ *  returns TRUE if the PF has set the reset done bit or else FALSE
+ **/
+static s32 e1000_check_for_rst_vf(struct e1000_hw *hw, u16 mbx_id)
+{
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_check_for_rst_vf");
+
+       if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
+                                        E1000_V2PMAILBOX_RSTI))) {
+               ret_val = E1000_SUCCESS;
+               hw->mbx.stats.rsts++;
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_obtain_mbx_lock_vf - obtain mailbox lock
+ *  @hw: pointer to the HW structure
+ *
+ *  return SUCCESS if we obtained the mailbox lock
+ **/
+static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
+{
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_obtain_mbx_lock_vf");
+
+       /* Take ownership of the buffer */
+       E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
+
+       /* reserve mailbox for vf use */
+       if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU)
+               ret_val = E1000_SUCCESS;
+
+       return ret_val;
+}
+
+/**
+ *  e1000_write_mbx_vf - Write a message to the mailbox
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully copied message into the buffer
+ **/
+static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
+                              u16 mbx_id)
+{
+       s32 ret_val;
+       u16 i;
+
+
+       DEBUGFUNC("e1000_write_mbx_vf");
+
+       /* lock the mailbox to prevent pf/vf race condition */
+       ret_val = e1000_obtain_mbx_lock_vf(hw);
+       if (ret_val)
+               goto out_no_write;
+
+       /* flush msg and acks as we are overwriting the message buffer */
+       e1000_check_for_msg_vf(hw, 0);
+       e1000_check_for_ack_vf(hw, 0);
+
+       /* copy the caller specified message to the mailbox memory buffer */
+       for (i = 0; i < size; i++)
+               E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(0), i, msg[i]);
+
+       /* update stats */
+       hw->mbx.stats.msgs_tx++;
+
+       /* Drop VFU and interrupt the PF to tell it a message has been sent */
+       E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
+
+out_no_write:
+       return ret_val;
+}
+
+/**
+ *  e1000_read_mbx_vf - Reads a message from the inbox intended for vf
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to read
+ *
+ *  returns SUCCESS if it successfuly read message from buffer
+ **/
+static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
+                             u16 mbx_id)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 i;
+
+       DEBUGFUNC("e1000_read_mbx_vf");
+
+       /* lock the mailbox to prevent pf/vf race condition */
+       ret_val = e1000_obtain_mbx_lock_vf(hw);
+       if (ret_val)
+               goto out_no_read;
+
+       /* copy the message from the mailbox memory buffer */
+       for (i = 0; i < size; i++)
+               msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(0), i);
+
+       /* Acknowledge receipt and release mailbox, then we're done */
+       E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
+
+       /* update stats */
+       hw->mbx.stats.msgs_rx++;
+
+out_no_read:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_mbx_params_vf - set initial values for vf mailbox
+ *  @hw: pointer to the HW structure
+ *
+ *  Initializes the hw->mbx struct to correct values for vf mailbox
+ */
+s32 e1000_init_mbx_params_vf(struct e1000_hw *hw)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+
+       /* start mailbox as timed out and let the reset_hw call set the timeout
+        * value to begin communications */
+       mbx->timeout = 0;
+       mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
+
+       mbx->size = E1000_VFMAILBOX_SIZE;
+
+       mbx->ops.read = e1000_read_mbx_vf;
+       mbx->ops.write = e1000_write_mbx_vf;
+       mbx->ops.read_posted = e1000_read_posted_mbx;
+       mbx->ops.write_posted = e1000_write_posted_mbx;
+       mbx->ops.check_for_msg = e1000_check_for_msg_vf;
+       mbx->ops.check_for_ack = e1000_check_for_ack_vf;
+       mbx->ops.check_for_rst = e1000_check_for_rst_vf;
+
+       mbx->stats.msgs_tx = 0;
+       mbx->stats.msgs_rx = 0;
+       mbx->stats.reqs = 0;
+       mbx->stats.acks = 0;
+       mbx->stats.rsts = 0;
+
+       return E1000_SUCCESS;
+}
+
+static s32 e1000_check_for_bit_pf(struct e1000_hw *hw, u32 mask)
+{
+       u32 mbvficr = E1000_READ_REG(hw, E1000_MBVFICR);
+       s32 ret_val = -E1000_ERR_MBX;
+
+       if (mbvficr & mask) {
+               ret_val = E1000_SUCCESS;
+               E1000_WRITE_REG(hw, E1000_MBVFICR, mask);
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_msg_pf - checks to see if the VF has sent mail
+ *  @hw: pointer to the HW structure
+ *  @vf_number: the VF index
+ *
+ *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+static s32 e1000_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number)
+{
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_check_for_msg_pf");
+
+       if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) {
+               ret_val = E1000_SUCCESS;
+               hw->mbx.stats.reqs++;
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_ack_pf - checks to see if the VF has ACKed
+ *  @hw: pointer to the HW structure
+ *  @vf_number: the VF index
+ *
+ *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+static s32 e1000_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number)
+{
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_check_for_ack_pf");
+
+       if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) {
+               ret_val = E1000_SUCCESS;
+               hw->mbx.stats.acks++;
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_rst_pf - checks to see if the VF has reset
+ *  @hw: pointer to the HW structure
+ *  @vf_number: the VF index
+ *
+ *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+static s32 e1000_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number)
+{
+       u32 vflre = E1000_READ_REG(hw, E1000_VFLRE);
+       s32 ret_val = -E1000_ERR_MBX;
+
+       DEBUGFUNC("e1000_check_for_rst_pf");
+
+       if (vflre & (1 << vf_number)) {
+               ret_val = E1000_SUCCESS;
+               E1000_WRITE_REG(hw, E1000_VFLRE, (1 << vf_number));
+               hw->mbx.stats.rsts++;
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_obtain_mbx_lock_pf - obtain mailbox lock
+ *  @hw: pointer to the HW structure
+ *  @vf_number: the VF index
+ *
+ *  return SUCCESS if we obtained the mailbox lock
+ **/
+static s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
+{
+       s32 ret_val = -E1000_ERR_MBX;
+       u32 p2v_mailbox;
+
+       DEBUGFUNC("e1000_obtain_mbx_lock_pf");
+
+       /* Take ownership of the buffer */
+       E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
+
+       /* reserve mailbox for vf use */
+       p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number));
+       if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
+               ret_val = E1000_SUCCESS;
+
+       return ret_val;
+}
+
+/**
+ *  e1000_write_mbx_pf - Places a message in the mailbox
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @vf_number: the VF index
+ *
+ *  returns SUCCESS if it successfully copied message into the buffer
+ **/
+static s32 e1000_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
+                              u16 vf_number)
+{
+       s32 ret_val;
+       u16 i;
+
+       DEBUGFUNC("e1000_write_mbx_pf");
+
+       /* lock the mailbox to prevent pf/vf race condition */
+       ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number);
+       if (ret_val)
+               goto out_no_write;
+
+       /* flush msg and acks as we are overwriting the message buffer */
+       e1000_check_for_msg_pf(hw, vf_number);
+       e1000_check_for_ack_pf(hw, vf_number);
+
+       /* copy the caller specified message to the mailbox memory buffer */
+       for (i = 0; i < size; i++)
+               E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i, msg[i]);
+
+       /* Interrupt VF to tell it a message has been sent and release buffer*/
+       E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS);
+
+       /* update stats */
+       hw->mbx.stats.msgs_tx++;
+
+out_no_write:
+       return ret_val;
+
+}
+
+/**
+ *  e1000_read_mbx_pf - Read a message from the mailbox
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @vf_number: the VF index
+ *
+ *  This function copies a message from the mailbox buffer to the caller's
+ *  memory buffer.  The presumption is that the caller knows that there was
+ *  a message due to a VF request so no polling for message is needed.
+ **/
+static s32 e1000_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
+                             u16 vf_number)
+{
+       s32 ret_val;
+       u16 i;
+
+       DEBUGFUNC("e1000_read_mbx_pf");
+
+       /* lock the mailbox to prevent pf/vf race condition */
+       ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number);
+       if (ret_val)
+               goto out_no_read;
+
+       /* copy the message to the mailbox memory buffer */
+       for (i = 0; i < size; i++)
+               msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i);
+
+       /* Acknowledge the message and release buffer */
+       E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
+
+       /* update stats */
+       hw->mbx.stats.msgs_rx++;
+
+out_no_read:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_mbx_params_pf - set initial values for pf mailbox
+ *  @hw: pointer to the HW structure
+ *
+ *  Initializes the hw->mbx struct to correct values for pf mailbox
+ */
+s32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+
+       switch (hw->mac.type) {
+       case e1000_82576:
+       case e1000_i350:
+               mbx->timeout = 0;
+               mbx->usec_delay = 0;
+
+               mbx->size = E1000_VFMAILBOX_SIZE;
+
+               mbx->ops.read = e1000_read_mbx_pf;
+               mbx->ops.write = e1000_write_mbx_pf;
+               mbx->ops.read_posted = e1000_read_posted_mbx;
+               mbx->ops.write_posted = e1000_write_posted_mbx;
+               mbx->ops.check_for_msg = e1000_check_for_msg_pf;
+               mbx->ops.check_for_ack = e1000_check_for_ack_pf;
+               mbx->ops.check_for_rst = e1000_check_for_rst_pf;
+
+               mbx->stats.msgs_tx = 0;
+               mbx->stats.msgs_rx = 0;
+               mbx->stats.reqs = 0;
+               mbx->stats.acks = 0;
+               mbx->stats.rsts = 0;
+       default:
+               return E1000_SUCCESS;
+       }
+}
+
diff --git a/sys/dev/netif/ig_hal/e1000_mbx.h b/sys/dev/netif/ig_hal/e1000_mbx.h
new file mode 100644 (file)
index 0000000..6e9d538
--- /dev/null
@@ -0,0 +1,106 @@
+/******************************************************************************
+
+  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 _E1000_MBX_H_
+#define _E1000_MBX_H_
+
+#include "e1000_api.h"
+
+/* Define mailbox register bits */
+#define E1000_V2PMAILBOX_REQ   0x00000001 /* Request for PF Ready bit */
+#define E1000_V2PMAILBOX_ACK   0x00000002 /* Ack PF message received */
+#define E1000_V2PMAILBOX_VFU   0x00000004 /* VF owns the mailbox buffer */
+#define E1000_V2PMAILBOX_PFU   0x00000008 /* PF owns the mailbox buffer */
+#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
+#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
+#define E1000_V2PMAILBOX_RSTI  0x00000040 /* PF has reset indication */
+#define E1000_V2PMAILBOX_RSTD  0x00000080 /* PF has indicated reset done */
+#define E1000_V2PMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */
+
+#define E1000_P2VMAILBOX_STS   0x00000001 /* Initiate message send to VF */
+#define E1000_P2VMAILBOX_ACK   0x00000002 /* Ack message recv'd from VF */
+#define E1000_P2VMAILBOX_VFU   0x00000004 /* VF owns the mailbox buffer */
+#define E1000_P2VMAILBOX_PFU   0x00000008 /* PF owns the mailbox buffer */
+#define E1000_P2VMAILBOX_RVFU  0x00000010 /* Reset VFU - used when VF stuck */
+
+#define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */
+#define E1000_MBVFICR_VFREQ_VF1  0x00000001 /* bit for VF 1 message */
+#define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */
+#define E1000_MBVFICR_VFACK_VF1  0x00010000 /* bit for VF 1 ack */
+
+#define E1000_VFMAILBOX_SIZE   16 /* 16 32 bit words - 64 bytes */
+
+/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
+ * PF.  The reverse is TRUE if it is E1000_PF_*.
+ * Message ACK's are the value or'd with 0xF0000000
+ */
+#define E1000_VT_MSGTYPE_ACK      0x80000000  /* Messages below or'd with
+                                               * this are the ACK */
+#define E1000_VT_MSGTYPE_NACK     0x40000000  /* Messages below or'd with
+                                               * this are the NACK */
+#define E1000_VT_MSGTYPE_CTS      0x20000000  /* Indicates that VF is still
+                                                 clear to send requests */
+#define E1000_VT_MSGINFO_SHIFT    16
+/* bits 23:16 are used for exra info for certain messages */
+#define E1000_VT_MSGINFO_MASK     (0xFF << E1000_VT_MSGINFO_SHIFT)
+
+#define E1000_VF_RESET            0x01 /* VF requests reset */
+#define E1000_VF_SET_MAC_ADDR     0x02 /* VF requests to set MAC addr */
+#define E1000_VF_SET_MULTICAST    0x03 /* VF requests to set MC addr */
+#define E1000_VF_SET_MULTICAST_COUNT_MASK (0x1F << E1000_VT_MSGINFO_SHIFT)
+#define E1000_VF_SET_MULTICAST_OVERFLOW   (0x80 << E1000_VT_MSGINFO_SHIFT)
+#define E1000_VF_SET_VLAN         0x04 /* VF requests to set VLAN */
+#define E1000_VF_SET_VLAN_ADD             (0x01 << E1000_VT_MSGINFO_SHIFT)
+#define E1000_VF_SET_LPE          0x05 /* VF requests to set VMOLR.LPE */
+#define E1000_VF_SET_PROMISC      0x06 /*VF requests to clear VMOLR.ROPE/MPME*/
+#define E1000_VF_SET_PROMISC_UNICAST      (0x01 << E1000_VT_MSGINFO_SHIFT)
+#define E1000_VF_SET_PROMISC_MULTICAST    (0x02 << E1000_VT_MSGINFO_SHIFT)
+
+#define E1000_PF_CONTROL_MSG      0x0100 /* PF control message */
+
+#define E1000_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */
+#define E1000_VF_MBX_INIT_DELAY   500  /* microseconds between retries */
+
+s32 e1000_read_mbx(struct e1000_hw *, u32 *, u16, u16);
+s32 e1000_write_mbx(struct e1000_hw *, u32 *, u16, u16);
+s32 e1000_read_posted_mbx(struct e1000_hw *, u32 *, u16, u16);
+s32 e1000_write_posted_mbx(struct e1000_hw *, u32 *, u16, u16);
+s32 e1000_check_for_msg(struct e1000_hw *, u16);
+s32 e1000_check_for_ack(struct e1000_hw *, u16);
+s32 e1000_check_for_rst(struct e1000_hw *, u16);
+void e1000_init_mbx_ops_generic(struct e1000_hw *hw);
+s32 e1000_init_mbx_params_vf(struct e1000_hw *);
+s32 e1000_init_mbx_params_pf(struct e1000_hw *);
+
+#endif /* _E1000_MBX_H_ */
index 92f95e4..9ba579f 100644 (file)
@@ -82,6 +82,20 @@ e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
        return E1000_SUCCESS;
 }
 
+int32_t
+e1000_write_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
+{
+       device_t dev = ((struct e1000_osdep *)hw->back)->dev;
+       uint8_t pcie_ptr;
+
+       pcie_ptr = pci_get_pciecap_ptr(dev);
+       if (pcie_ptr == 0)
+               return E1000_NOT_IMPLEMENTED;
+
+       pci_write_config(dev, pcie_ptr + reg, *value, 2);
+       return E1000_SUCCESS;
+}
+
 /* Module glue */
 static moduledata_t ig_hal_mod = { "ig_hal" };
 DECLARE_MODULE(ig_hal, ig_hal_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
index 7d377e1..bdccb71 100644 (file)
@@ -369,6 +369,105 @@ out:
 }
 
 /**
+ *  e1000_read_phy_reg_i2c - Read PHY register using i2c
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY register at offset using the i2c interface and stores the
+ *  retrieved information in data.
+ **/
+s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       u32 i, i2ccmd = 0;
+
+       DEBUGFUNC("e1000_read_phy_reg_i2c");
+
+       /*
+        * Set up Op-code, Phy Address, and register address in the I2CCMD
+        * register.  The MAC will take care of interfacing with the
+        * PHY to retrieve the desired data.
+        */
+       i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+                 (phy->addr << E1000_I2CCMD_PHY_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);
+               i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
+               if (i2ccmd & E1000_I2CCMD_READY)
+                       break;
+       }
+       if (!(i2ccmd & E1000_I2CCMD_READY)) {
+               DEBUGOUT("I2CCMD Read did not complete\n");
+               return -E1000_ERR_PHY;
+       }
+       if (i2ccmd & E1000_I2CCMD_ERROR) {
+               DEBUGOUT("I2CCMD Error bit set\n");
+               return -E1000_ERR_PHY;
+       }
+
+       /* Need to byte-swap the 16-bit value. */
+       *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_write_phy_reg_i2c - Write PHY register using i2c
+ *  @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 using the i2c interface.
+ **/
+s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       u32 i, i2ccmd = 0;
+       u16 phy_data_swapped;
+
+       DEBUGFUNC("e1000_write_phy_reg_i2c");
+
+       /* Swap the data bytes for the I2C interface */
+       phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
+
+       /*
+        * Set up Op-code, Phy Address, and register address in the I2CCMD
+        * register.  The MAC will take care of interfacing with the
+        * PHY to retrieve the desired data.
+        */
+       i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+                 (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
+                 E1000_I2CCMD_OPCODE_WRITE |
+                 phy_data_swapped);
+
+       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);
+               i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
+               if (i2ccmd & E1000_I2CCMD_READY)
+                       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
  *  @offset: register offset to be read
@@ -928,6 +1027,91 @@ out:
 }
 
 /**
+ *  e1000_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's.
+ *  Also enables and sets the downshift parameters.
+ **/
+s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 phy_data;
+
+       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;
+
+       /*
+        * Options:
+        *   MDI/MDI-X = 0 (default)
+        *   0 - Auto for all speeds
+        *   1 - MDI mode
+        *   2 - MDI-X mode
+        *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+        */
+       phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+
+       switch (phy->mdix) {
+       case 1:
+               phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+               break;
+       case 2:
+               phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+               break;
+       case 3:
+               /* M88E1112 does not support this mode) */
+               if (phy->id != M88E1112_E_PHY_ID) {
+                       phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+                       break;
+               }
+       case 0:
+       default:
+               phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+               break;
+       }
+
+       /*
+        * Options:
+        *   disable_polarity_correction = 0 (default)
+        *       Automatic Correction for Reversed Cable Polarity
+        *   0 - Disabled
+        *   1 - Enabled
+        */
+       phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+       if (phy->disable_polarity_correction == 1)
+               phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+
+       /* Enable downshift and setting it to X6 */
+       phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
+       phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
+       phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
+
+       ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+       if (ret_val)
+               goto out;
+
+       /* Commit the changes. */
+       ret_val = phy->ops.commit(hw);
+       if (ret_val) {
+               DEBUGOUT("Error committing the PHY changes\n");
+               goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
  *  e1000_copper_link_setup_igp - Setup igp PHY's for copper link
  *  @hw: pointer to the HW structure
  *
@@ -1495,7 +1679,10 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                        goto out;
 
                if (!link) {
-                       if (hw->phy.type != e1000_phy_m88) {
+                       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) {
                                DEBUGOUT("Link taking longer than expected.\n");
                        } else {
                                /*
@@ -1520,7 +1707,10 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                        goto out;
        }
 
-       if (hw->phy.type != e1000_phy_m88)
+       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)
                goto out;
 
        ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
@@ -2061,6 +2251,96 @@ out:
        return ret_val;
 }
 
+s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 phy_data, phy_data2, index, default_page, is_cm;
+
+       DEBUGFUNC("e1000_get_cable_length_m88_gen2");
+
+       switch (hw->phy.id) {
+       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;
+
+               ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
+               if (ret_val)
+                       goto out;
+
+               /* 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;
+
+               /* 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;
+
+               is_cm = !(phy_data & 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);
+
+               /* Reset the page selec to its original value */
+               ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+                                            default_page);
+               if (ret_val)
+                       goto out;
+               break;
+       case M88E1112_E_PHY_ID:
+               /* Remember the original page select and set it to 5 */
+               ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
+                                           &default_page);
+               if (ret_val)
+                       goto out;
+
+               ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
+               if (ret_val)
+                       goto out;
+
+               ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
+                                           &phy_data);
+               if (ret_val)
+                       goto out;
+
+               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;
+               }
+
+               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;
+
+               /* Reset the page select to its original value */
+               ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+                                            default_page);
+               if (ret_val)
+                       goto out;
+
+               break;
+       default:
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+       }
+
+out:
+       return ret_val;
+}
+
 /**
  *  e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY
  *  @hw: pointer to the HW structure
@@ -2533,6 +2813,9 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
        case M88E1000_E_PHY_ID:
        case M88E1111_I_PHY_ID:
        case M88E1011_I_PHY_ID:
+       case I347AT4_E_PHY_ID:
+       case M88E1112_E_PHY_ID:
+       case M88E1340M_E_PHY_ID:
                phy_type = e1000_phy_m88;
                break;
        case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */
index 1e1e847..478c82f 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: $*/
+/*$FreeBSD:$*/
 
 #ifndef _E1000_PHY_H_
 #define _E1000_PHY_H_
@@ -50,10 +50,12 @@ 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);
 s32  e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw);
 s32  e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw);
 s32  e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
 s32  e1000_get_cable_length_m88(struct e1000_hw *hw);
+s32  e1000_get_cable_length_m88_gen2(struct e1000_hw *hw);
 s32  e1000_get_cable_length_igp_2(struct e1000_hw *hw);
 s32  e1000_get_cfg_done_generic(struct e1000_hw *hw);
 s32  e1000_get_phy_id(struct e1000_hw *hw);
@@ -101,6 +103,8 @@ 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_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_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);
index 400358b..2e9055c 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2011, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD$*/
+/*$FreeBSD$*/
 
 #ifndef _E1000_REGS_H_
 #define _E1000_REGS_H_
 #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_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 */
+#define E1000_EIMS     0x01524  /* Ext. Interrupt Mask Set/Read - RW */
+#define E1000_EIMC     0x01528  /* Ext. Interrupt Mask Clear - WO */
+#define E1000_EIAC     0x0152C  /* Ext. Interrupt Auto Clear - RW */
+#define E1000_EIAM     0x01530  /* Ext. Interrupt Ack Auto Clear Mask - RW */
+#define E1000_GPIE     0x01514  /* General Purpose Interrupt Enable - RW */
+#define E1000_IVAR0    0x01700  /* Interrupt Vector Allocation (array) - RW */
+#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
 #define E1000_TCTL     0x00400  /* Tx Control - RW */
 #define E1000_TCTL_EXT 0x00404  /* Extended Tx Control - RW */
 #define E1000_TIPG     0x00410  /* Tx Inter-packet gap -RW */
 #define E1000_WDSTP    0x01040  /* Watchdog Setup - RW */
 #define E1000_SWDSTS   0x01044  /* SW Device Status - RW */
 #define E1000_FRTIMER  0x01048  /* Free Running Timer - RW */
+#define E1000_TCPTIMER 0x0104C  /* TCP Timer - RW */
+#define E1000_VPDDIAG  0x01060  /* VPD Diagnostic - RO */
+#define E1000_ICR_V2   0x01500  /* Interrupt Cause - new location - RC */
+#define E1000_ICS_V2   0x01504  /* Interrupt Cause Set - new location - WO */
+#define E1000_IMS_V2   0x01508  /* Interrupt Mask Set/Read - new location - RW */
+#define E1000_IMC_V2   0x0150C  /* Interrupt Mask Clear - new location - WO */
+#define E1000_IAM_V2   0x01510  /* Interrupt Ack Auto Mask - new location - RW */
 #define E1000_ERT      0x02008  /* Early Rx Threshold - RW */
 #define E1000_FCRTL    0x02160  /* Flow Control Receive Threshold Low - RW */
 #define E1000_FCRTH    0x02168  /* Flow Control Receive Threshold High - RW */
 #define E1000_RDPUWD   0x025D4  /* DMA Rx Descriptor uC Data Write - RW */
 #define E1000_RDPURD   0x025D8  /* DMA Rx Descriptor uC Data Read - RW */
 #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_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_FFMT_REG(_i)      (0x09000 + ((_i) * 8))
 #define E1000_FFVT_REG(_i)      (0x09800 + ((_i) * 8))
 #define E1000_FFLT_REG(_i)      (0x05F00 + ((_i) * 8))
+#define E1000_PBSLAC   0x03100  /* Packet Buffer Slave Access Control */
+#define E1000_PBSLAD(_n)  (0x03110 + (0x4 * (_n)))  /* Packet Buffer DWORD (_n) */
+#define E1000_TXPBS    0x03404  /* Tx Packet Buffer Size - RW */
 #define E1000_ITPBS   0x03404   /* Same as TXPBS, renamed for newer adpaters - RW */
 #define E1000_TDFH     0x03410  /* Tx Data FIFO Head - RW */
 #define E1000_TDFT     0x03418  /* Tx Data FIFO Tail - RW */
 #define E1000_TDPURD   0x03588  /* DMA Tx Descriptor uC Data  Read  - RW */
 #define E1000_TDPUCTL  0x0358C  /* DMA Tx Descriptor uC Control - RW */
 #define E1000_DTXCTL   0x03590  /* DMA Tx Control - RW */
+#define E1000_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */
+#define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */
+#define E1000_DTXMXSZRQ  0x03540 /* DMA Tx Max Total Allow Size Requests - RW */
 #define E1000_TIDV     0x03820  /* Tx Interrupt Delay Value - RW */
 #define E1000_TADV     0x0382C  /* Tx Interrupt Absolute Delay Val - RW */
 #define E1000_TSPMT    0x03830  /* TCP Segmentation PAD & Min Threshold - RW */
 #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
+#define E1000_VFMPRC   0x00F3C
+#define E1000_VFGPTC   0x00F14
+#define E1000_VFGOTC   0x00F34
+#define E1000_VFGOTLBC 0x00F50
+#define E1000_VFGPTLBC 0x00F44
+#define E1000_VFGORLBC 0x00F48
+#define E1000_VFGPRLBC 0x00F40
+/* Virtualization statistical counters */
+#define E1000_PFVFGPRC(_n)   (0x010010 + (0x100 * (_n)))
+#define E1000_PFVFGPTC(_n)   (0x010014 + (0x100 * (_n)))
+#define E1000_PFVFGORC(_n)   (0x010018 + (0x100 * (_n)))
+#define E1000_PFVFGOTC(_n)   (0x010034 + (0x100 * (_n)))
+#define E1000_PFVFMPRC(_n)   (0x010038 + (0x100 * (_n)))
+#define E1000_PFVFGPRLBC(_n) (0x010040 + (0x100 * (_n)))
+#define E1000_PFVFGPTLBC(_n) (0x010044 + (0x100 * (_n)))
+#define E1000_PFVFGORLBC(_n) (0x010048 + (0x100 * (_n)))
+#define E1000_PFVFGOTLBC(_n) (0x010050 + (0x100 * (_n)))
+
+#define E1000_LSECTXUT        0x04300  /* LinkSec Tx Untagged Packet Count - OutPktsUntagged */
+#define E1000_LSECTXPKTE      0x04304  /* LinkSec Encrypted Tx Packets Count - OutPktsEncrypted */
+#define E1000_LSECTXPKTP      0x04308  /* LinkSec Protected Tx Packet Count - OutPktsProtected */
+#define E1000_LSECTXOCTE      0x0430C  /* LinkSec Encrypted Tx Octets Count - OutOctetsEncrypted */
+#define E1000_LSECTXOCTP      0x04310  /* LinkSec Protected Tx Octets Count - OutOctetsProtected */
+#define E1000_LSECRXUT        0x04314  /* LinkSec Untagged non-Strict Rx Packet Count - InPktsUntagged/InPktsNoTag */
+#define E1000_LSECRXOCTD      0x0431C  /* LinkSec Rx Octets Decrypted Count - InOctetsDecrypted */
+#define E1000_LSECRXOCTV      0x04320  /* LinkSec Rx Octets Validated - InOctetsValidated */
+#define E1000_LSECRXBAD       0x04324  /* LinkSec Rx Bad Tag - InPktsBadTag */
+#define E1000_LSECRXNOSCI     0x04328  /* LinkSec Rx Packet No SCI Count - InPktsNoSci */
+#define E1000_LSECRXUNSCI     0x0432C  /* LinkSec Rx Packet Unknown SCI Count - InPktsUnknownSci */
+#define E1000_LSECRXUNCH      0x04330  /* LinkSec Rx Unchecked Packets Count - InPktsUnchecked */
+#define E1000_LSECRXDELAY     0x04340  /* LinkSec Rx Delayed Packet Count - InPktsDelayed */
+#define E1000_LSECRXLATE      0x04350  /* LinkSec Rx Late Packets Count - InPktsLate */
+#define E1000_LSECRXOK(_n)    (0x04360 + (0x04 * (_n))) /* LinkSec Rx Packet OK Count - InPktsOk */
+#define E1000_LSECRXINV(_n)   (0x04380 + (0x04 * (_n))) /* LinkSec Rx Invalid Count - InPktsInvalid */
+#define E1000_LSECRXNV(_n)    (0x043A0 + (0x04 * (_n))) /* LinkSec Rx Not Valid Count - InPktsNotValid */
+#define E1000_LSECRXUNSA      0x043C0  /* LinkSec Rx Unused SA Count - InPktsUnusedSa */
+#define E1000_LSECRXNUSA      0x043D0  /* LinkSec Rx Not Using SA Count - InPktsNotUsingSa */
+#define E1000_LSECTXCAP       0x0B000  /* LinkSec Tx Capabilities Register - RO */
+#define E1000_LSECRXCAP       0x0B300  /* LinkSec Rx Capabilities Register - RO */
+#define E1000_LSECTXCTRL      0x0B004  /* LinkSec Tx Control - RW */
+#define E1000_LSECRXCTRL      0x0B304  /* LinkSec Rx Control - RW */
+#define E1000_LSECTXSCL       0x0B008  /* LinkSec Tx SCI Low - RW */
+#define E1000_LSECTXSCH       0x0B00C  /* LinkSec Tx SCI High - RW */
+#define E1000_LSECTXSA        0x0B010  /* LinkSec Tx SA0 - RW */
+#define E1000_LSECTXPN0       0x0B018  /* LinkSec Tx SA PN 0 - RW */
+#define E1000_LSECTXPN1       0x0B01C  /* LinkSec Tx SA PN 1 - RW */
+#define E1000_LSECRXSCL       0x0B3D0  /* LinkSec Rx SCI Low - RW */
+#define E1000_LSECRXSCH       0x0B3E0  /* LinkSec Rx SCI High - RW */
+#define E1000_LSECTXKEY0(_n)  (0x0B020 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 0 - WO */
+#define E1000_LSECTXKEY1(_n)  (0x0B030 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 1 - WO */
+#define E1000_LSECRXSA(_n)    (0x0B310 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */
+#define E1000_LSECRXPN(_n)    (0x0B330 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */
+/*
+ * LinkSec Rx Keys  - where _n is the SA no. and _m the 4 dwords of the 128 bit
+ * key - RW.
+ */
+#define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m)))
+
+#define E1000_SSVPC             0x041A0  /* Switch Security Violation Packet Count */
+#define E1000_IPSCTRL           0xB430   /* IpSec Control Register */
+#define E1000_IPSRXCMD          0x0B408  /* IPSec Rx Command Register - RW */
+#define E1000_IPSRXIDX          0x0B400  /* IPSec Rx Index - RW */
+#define E1000_IPSRXIPADDR(_n)   (0x0B420+ (0x04 * (_n)))  /* IPSec Rx IPv4/v6 Address - RW */
+#define E1000_IPSRXKEY(_n)      (0x0B410 + (0x04 * (_n))) /* IPSec Rx 128-bit Key - RW */
+#define E1000_IPSRXSALT         0x0B404  /* IPSec Rx Salt - RW */
+#define E1000_IPSRXSPI          0x0B40C  /* IPSec Rx SPI - RW */
+#define E1000_IPSTXKEY(_n)      (0x0B460 + (0x04 * (_n))) /* IPSec Tx 128-bit Key - RW */
+#define E1000_IPSTXSALT         0x0B454  /* IPSec Tx Salt - RW */
+#define E1000_IPSTXIDX          0x0B450  /* IPSec Tx SA IDX - RW */
 #define E1000_PCS_CFG0    0x04200  /* PCS Configuration 0 - RW */
 #define E1000_PCS_LCTL    0x04208  /* PCS Link Control - RW */
 #define E1000_PCS_LSTAT   0x0420C  /* PCS Link Status - RO */
 #define E1000_RFCTL    0x05008  /* Receive Filter Control*/
 #define E1000_MTA      0x05200  /* Multicast Table Array - RW Array */
 #define E1000_RA       0x05400  /* Receive Address - RW Array */
+#define E1000_RA2      0x054E0  /* 2nd half of receive address array - RW Array */
 #define E1000_VFTA     0x05600  /* VLAN Filter Table Array - RW Array */
 #define E1000_VT_CTL   0x0581C  /* VMDq Control - RW */
 #define E1000_VFQA0    0x0B000  /* VLAN Filter Queue Array 0 - RW Array */
 #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_FHFT(_n)  (0x09000 + (_n * 0x100)) /* Flexible Host Filter Table */
+#define E1000_FHFT_EXT(_n) (0x09A00 + (_n * 0x100)) /* Ext Flexible Host Filter Table */
+
 
 #define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
 #define E1000_MDPHYA      0x0003C /* PHY address - RW */
 #define E1000_UFUSE     0x05B78 /* UFUSE - RO */
 #define E1000_FFLT_DBG  0x05F04 /* Debug Register */
 #define E1000_HICR      0x08F00 /* Host Interface Control */
+#define E1000_FWSTS     0x08F0C /* FW Status */
 
 /* RSS registers */
 #define E1000_CPUVEC    0x02C10 /* CPU Vector Register - RW */
 #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */
 #define E1000_RSSIM     0x05864 /* RSS Interrupt Mask */
 #define E1000_RSSIR     0x05868 /* RSS Interrupt Request */
+/* VT Registers */
+#define E1000_SWPBS     0x03004 /* Switch Packet Buffer Size - RW */
+#define E1000_MBVFICR   0x00C80 /* Mailbox VF Cause - RWC */
+#define E1000_MBVFIMR   0x00C84 /* Mailbox VF int Mask - RW */
+#define E1000_VFLRE     0x00C88 /* VF Register Events - RWC */
+#define E1000_VFRE      0x00C8C /* VF Receive Enables */
+#define E1000_VFTE      0x00C90 /* VF Transmit Enables */
+#define E1000_QDE       0x02408 /* Queue Drop Enable - RW */
+#define E1000_DTXSWC    0x03500 /* DMA Tx Switch Control - RW */
+#define E1000_WVBR      0x03554 /* VM Wrong Behavior - RWS */
+#define E1000_RPLOLR    0x05AF0 /* Replication Offload - RW */
+#define E1000_UTA       0x0A000 /* Unicast Table Array - RW */
+#define E1000_IOVTCL    0x05BBC /* IOV Control Register */
+#define E1000_VMRCTL    0X05D80 /* Virtual Mirror Rule Control */
+#define E1000_VMRVLAN   0x05D90 /* Virtual Mirror Rule VLAN */
+#define E1000_VMRVM     0x05DA0 /* Virtual Mirror Rule VM */
+#define E1000_MDFB      0x03558 /* Malicious Driver free block */
+#define E1000_LVMMC     0x03548 /* Last VM Misbehavior cause */
+#define E1000_TXSWC     0x05ACC /* Tx Switch Control */
+#define E1000_SCCRL     0x05DB0 /* Storm Control Control */
+#define E1000_BSCTRH    0x05DB8 /* Broadcast Storm Control Threshold */
+#define E1000_MSCTRH    0x05DBC /* Multicast Storm Control Threshold */
+/* These act per VF so an array friendly macro is used */
+#define E1000_V2PMAILBOX(_n)   (0x00C40 + (4 * (_n)))
+#define E1000_P2VMAILBOX(_n)   (0x00C00 + (4 * (_n)))
+#define E1000_VMBMEM(_n)       (0x00800 + (64 * (_n)))
+#define E1000_VFVMBMEM(_n)     (0x00800 + (_n))
+#define E1000_VMOLR(_n)        (0x05AD0 + (4 * (_n)))
+#define E1000_VLVF(_n)         (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine
+                                                       * Filter - RW */
+#define E1000_VMVIR(_n)        (0x03700 + (4 * (_n)))
+#define E1000_DVMOLR(_n)       (0x0C038 + (0x40 * (_n))) /* DMA VM offload */
 /* Time Sync */
 #define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
 #define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
 #define E1000_TIMINCA    0x0B608 /* Increment attributes register - RW */
 #define E1000_TSAUXC     0x0B640 /* Timesync Auxiliary Control register */
 #define E1000_SYSTIMR    0x0B6F8 /* System time register Residue */
-#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 */
+#define E1000_DAQF(_n)  (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */
+#define E1000_SPQF(_n)  (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */
+#define E1000_FTQF(_n)  (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */
+#define E1000_TTQF(_n)  (0x059E0 + (4 * (_n))) /* 2-tuple Queue Fltr */
+#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */
+#define E1000_ETQF(_n)  (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
+
+#define E1000_RTTDCS            0x3600  /* Reedtown Tx Desc plane control and status */
+#define E1000_RTTPCS            0x3474  /* Reedtown Tx Packet Plane control and status */
+#define E1000_RTRPCS            0x2474  /* Rx packet plane control and status */
+#define E1000_RTRUP2TC          0x05AC4 /* Rx User Priority to Traffic Class */
+#define E1000_RTTUP2TC          0x0418  /* Transmit User Priority to Traffic Class */
+#define E1000_RTTDTCRC(_n)      (0x3610 + ((_n) * 4)) /* Tx Desc plane TC Rate-scheduler config */
+#define E1000_RTTPTCRC(_n)      (0x3480 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Config */
+#define E1000_RTRPTCRC(_n)      (0x2480 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Config */
+#define E1000_RTTDTCRS(_n)      (0x3630 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler Status */
+#define E1000_RTTDTCRM(_n)      (0x3650 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler MMW */
+#define E1000_RTTPTCRS(_n)      (0x34A0 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Status */
+#define E1000_RTTPTCRM(_n)      (0x34C0 + ((_n) * 4)) /* Tx Packet plane TC Rate-scheduler MMW */
+#define E1000_RTRPTCRS(_n)      (0x24A0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Status */
+#define E1000_RTRPTCRM(_n)      (0x24C0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler MMW */
+#define E1000_RTTDVMRM(_n)      (0x3670 + ((_n) * 4)) /* Tx Desc plane VM Rate-Scheduler MMW*/
+#define E1000_RTTBCNRM(_n)      (0x3690 + ((_n) * 4)) /* Tx BCN Rate-Scheduler MMW */
+#define E1000_RTTDQSEL          0x3604  /* Tx Desc Plane Queue Select */
+#define E1000_RTTDVMRC          0x3608  /* Tx Desc Plane VM Rate-Scheduler Config */
+#define E1000_RTTDVMRS          0x360C  /* Tx Desc Plane VM Rate-Scheduler Status */
+#define E1000_RTTBCNRC          0x36B0  /* Tx BCN Rate-Scheduler Config */
+#define E1000_RTTBCNRS          0x36B4  /* Tx BCN Rate-Scheduler Status */
+#define E1000_RTTBCNCR          0xB200  /* Tx BCN Control Register */
+#define E1000_RTTBCNTG          0x35A4  /* Tx BCN Tagging */
+#define E1000_RTTBCNCP          0xB208  /* Tx BCN Congestion point */
+#define E1000_RTRBCNCR          0xB20C  /* Rx BCN Control Register */
+#define E1000_RTTBCNRD          0x36B8  /* Tx BCN Rate Drift */
+#define E1000_PFCTOP            0x1080  /* Priority Flow Control Type and Opcode */
+#define E1000_RTTBCNIDX         0xB204  /* Tx BCN Congestion Point */
+#define E1000_RTTBCNACH         0x0B214 /* Tx BCN Control High */
+#define E1000_RTTBCNACL         0x0B210 /* Tx BCN Control Low */
 
 /* DMA Coalescing registers */
 #define E1000_DMACR             0x02508 /* Control Register */
 /* PCIe Parity Status Register */
 #define E1000_PCIEERRSTS        0x05BA8
 
+#define E1000_PROXYS            0x5F64 /* Proxying Status */
+#define E1000_PROXYFC           0x5F60 /* Proxying Filter Control */
+/* Thermal sensor configuration and status registers */
+#define E1000_THMJT             0x08100 /* Junction Temperature */
+#define E1000_THLOWTC           0x08104 /* Low Threshold Control */
+#define E1000_THMIDTC           0x08108 /* Mid Threshold Control */
+#define E1000_THHIGHTC          0x0810C /* High Threshold Control */
+#define E1000_THSTAT            0x08110 /* Thermal Sensor Status */
+
+/*Energy Efficient Ethernet "EEE" registers */
+#define E1000_IPCNFG            0x0E38 /* Internal PHY Configuration */
+#define E1000_LTRC              0x01A0 /* Latency Tolerance Reporting Control */
+#define E1000_EEER              0x0E30 /* Energy Efficient Ethernet "EEE"*/
+#define E1000_EEE_SU            0x0E34 /* EEE Setup */
+#define E1000_TLPIC             0x4148 /* EEE Tx LPI Count - TLPIC */
+#define E1000_RLPIC             0x414C /* EEE Rx LPI Count - RLPIC */
+
+/* OS2BMC Registers */
+#define E1000_B2OSPC            0x08FE0 /* BMC2OS packets sent by BMC */
+#define E1000_B2OGPRC           0x04158 /* BMC2OS packets received by host */
+#define E1000_O2BGPTC           0x08FE4 /* OS2BMC packets received by BMC */
+#define E1000_O2BSPC            0x0415C /* OS2BMC packets transmitted by host */
 
 #endif
diff --git a/sys/dev/netif/ig_hal/e1000_vf.c b/sys/dev/netif/ig_hal/e1000_vf.c
new file mode 100644 (file)
index 0000000..8b81e4b
--- /dev/null
@@ -0,0 +1,574 @@
+/******************************************************************************
+
+  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$*/
+
+
+#include "e1000_api.h"
+
+
+static s32       e1000_init_phy_params_vf(struct e1000_hw *hw);
+static s32       e1000_init_nvm_params_vf(struct e1000_hw *hw);
+static void      e1000_release_vf(struct e1000_hw *hw);
+static s32       e1000_acquire_vf(struct e1000_hw *hw);
+static s32       e1000_setup_link_vf(struct e1000_hw *hw);
+static s32       e1000_get_bus_info_pcie_vf(struct e1000_hw *hw);
+static s32       e1000_init_mac_params_vf(struct e1000_hw *hw);
+static s32       e1000_check_for_link_vf(struct e1000_hw *hw);
+static s32       e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
+                                              u16 *duplex);
+static s32       e1000_init_hw_vf(struct e1000_hw *hw);
+static s32       e1000_reset_hw_vf(struct e1000_hw *hw);
+static void      e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *, u32);
+static void      e1000_rar_set_vf(struct e1000_hw *, u8 *, u32);
+static s32       e1000_read_mac_addr_vf(struct e1000_hw *);
+
+/**
+ *  e1000_init_phy_params_vf - Inits PHY params
+ *  @hw: pointer to the HW structure
+ *
+ *  Doesn't do much - there's no PHY available to the VF.
+ **/
+static s32 e1000_init_phy_params_vf(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_phy_params_vf");
+       hw->phy.type = e1000_phy_vf;
+       hw->phy.ops.acquire = e1000_acquire_vf;
+       hw->phy.ops.release = e1000_release_vf;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_nvm_params_vf - Inits NVM params
+ *  @hw: pointer to the HW structure
+ *
+ *  Doesn't do much - there's no NVM available to the VF.
+ **/
+static s32 e1000_init_nvm_params_vf(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_nvm_params_vf");
+       hw->nvm.type = e1000_nvm_none;
+       hw->nvm.ops.acquire = e1000_acquire_vf;
+       hw->nvm.ops.release = e1000_release_vf;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_mac_params_vf - Inits MAC params
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_mac_params_vf(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+
+       DEBUGFUNC("e1000_init_mac_params_vf");
+
+       /* Set media type */
+       /*
+        * Virtual functions don't care what they're media type is as they
+        * have no direct access to the PHY, or the media.  That is handled
+        * by the physical function driver.
+        */
+       hw->phy.media_type = e1000_media_type_unknown;
+
+       /* No ASF features for the VF driver */
+       mac->asf_firmware_present = FALSE;
+       /* ARC subsystem not supported */
+       mac->arc_subsystem_valid = FALSE;
+       /* Disable adaptive IFS mode so the generic funcs don't do anything */
+       mac->adaptive_ifs = FALSE;
+       /* VF's have no MTA Registers - PF feature only */
+       mac->mta_reg_count = 128;
+       /* VF's have no access to RAR entries  */
+       mac->rar_entry_count = 1;
+
+       /* Function pointers */
+       /* link setup */
+       mac->ops.setup_link = e1000_setup_link_vf;
+       /* bus type/speed/width */
+       mac->ops.get_bus_info = e1000_get_bus_info_pcie_vf;
+       /* reset */
+       mac->ops.reset_hw = e1000_reset_hw_vf;
+       /* hw initialization */
+       mac->ops.init_hw = e1000_init_hw_vf;
+       /* check for link */
+       mac->ops.check_for_link = e1000_check_for_link_vf;
+       /* link info */
+       mac->ops.get_link_up_info = e1000_get_link_up_info_vf;
+       /* multicast address update */
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_vf;
+       /* set mac address */
+       mac->ops.rar_set = e1000_rar_set_vf;
+       /* read mac address */
+       mac->ops.read_mac_addr = e1000_read_mac_addr_vf;
+
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_function_pointers_vf - Inits function pointers
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_init_function_pointers_vf(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_function_pointers_vf");
+
+       hw->mac.ops.init_params = e1000_init_mac_params_vf;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_vf;
+       hw->phy.ops.init_params = e1000_init_phy_params_vf;
+       hw->mbx.ops.init_params = e1000_init_mbx_params_vf;
+}
+
+/**
+ *  e1000_acquire_vf - Acquire rights to access PHY or NVM.
+ *  @hw: pointer to the HW structure
+ *
+ *  There is no PHY or NVM so we want all attempts to acquire these to fail.
+ *  In addition, the MAC registers to access PHY/NVM don't exist so we don't
+ *  even want any SW to attempt to use them.
+ **/
+static s32 e1000_acquire_vf(struct e1000_hw *hw)
+{
+       return -E1000_ERR_PHY;
+}
+
+/**
+ *  e1000_release_vf - Release PHY or NVM
+ *  @hw: pointer to the HW structure
+ *
+ *  There is no PHY or NVM so we want all attempts to acquire these to fail.
+ *  In addition, the MAC registers to access PHY/NVM don't exist so we don't
+ *  even want any SW to attempt to use them.
+ **/
+static void e1000_release_vf(struct e1000_hw *hw)
+{
+       return;
+}
+
+/**
+ *  e1000_setup_link_vf - Sets up link.
+ *  @hw: pointer to the HW structure
+ *
+ *  Virtual functions cannot change link.
+ **/
+static s32 e1000_setup_link_vf(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_setup_link_vf");
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_get_bus_info_pcie_vf - Gets the bus info.
+ *  @hw: pointer to the HW structure
+ *
+ *  Virtual functions are not really on their own bus.
+ **/
+static s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+
+       DEBUGFUNC("e1000_get_bus_info_pcie_vf");
+
+       /* Do not set type PCI-E because we don't want disable master to run */
+       bus->type = e1000_bus_type_reserved;
+       bus->speed = e1000_bus_speed_2500;
+
+       return 0;
+}
+
+/**
+ *  e1000_get_link_up_info_vf - Gets link info.
+ *  @hw: pointer to the HW structure
+ *  @speed: pointer to 16 bit value to store link speed.
+ *  @duplex: pointer to 16 bit value to store duplex.
+ *
+ *  Since we cannot read the PHY and get accurate link info, we must rely upon
+ *  the status register's data which is often stale and inaccurate.
+ **/
+static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
+                                     u16 *duplex)
+{
+       s32 status;
+
+       DEBUGFUNC("e1000_get_link_up_info_vf");
+
+       status = E1000_READ_REG(hw, E1000_STATUS);
+       if (status & E1000_STATUS_SPEED_1000) {
+               *speed = SPEED_1000;
+               DEBUGOUT("1000 Mbs, ");
+       } else if (status & E1000_STATUS_SPEED_100) {
+               *speed = SPEED_100;
+               DEBUGOUT("100 Mbs, ");
+       } else {
+               *speed = SPEED_10;
+               DEBUGOUT("10 Mbs, ");
+       }
+
+       if (status & E1000_STATUS_FD) {
+               *duplex = FULL_DUPLEX;
+               DEBUGOUT("Full Duplex\n");
+       } else {
+               *duplex = HALF_DUPLEX;
+               DEBUGOUT("Half Duplex\n");
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_reset_hw_vf - Resets the HW
+ *  @hw: pointer to the HW structure
+ *
+ *  VF's provide a function level reset. This is done using bit 26 of ctrl_reg.
+ *  This is all the reset we can perform on a VF.
+ **/
+static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       u32 timeout = E1000_VF_INIT_TIMEOUT;
+       s32 ret_val = -E1000_ERR_MAC_INIT;
+       u32 ctrl, msgbuf[3];
+       u8 *addr = (u8 *)(&msgbuf[1]);
+
+       DEBUGFUNC("e1000_reset_hw_vf");
+
+       DEBUGOUT("Issuing a function level reset to MAC\n");
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+
+       /* we cannot reset while the RSTI / RSTD bits are asserted */
+       while (!mbx->ops.check_for_rst(hw, 0) && timeout) {
+               timeout--;
+               usec_delay(5);
+       }
+
+       if (timeout) {
+               /* mailbox timeout can now become active */
+               mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT;
+
+               msgbuf[0] = E1000_VF_RESET;
+               mbx->ops.write_posted(hw, msgbuf, 1, 0);
+
+               msec_delay(10);
+
+               /* set our "perm_addr" based on info provided by PF */
+               ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
+               if (!ret_val) {
+                       if (msgbuf[0] == (E1000_VF_RESET |
+                                               E1000_VT_MSGTYPE_ACK))
+                               memcpy(hw->mac.perm_addr, addr, 6);
+                       else
+                               ret_val = -E1000_ERR_MAC_INIT;
+               }
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_init_hw_vf - Inits the HW
+ *  @hw: pointer to the HW structure
+ *
+ *  Not much to do here except clear the PF Reset indication if there is one.
+ **/
+static s32 e1000_init_hw_vf(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_hw_vf");
+
+       /* attempt to set and restore our mac address */
+       e1000_rar_set_vf(hw, hw->mac.addr, 0);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_rar_set_vf - set device MAC address
+ *  @hw: pointer to the HW structure
+ *  @addr: pointer to the receive address
+ *  @index receive address array register
+ **/
+static void e1000_rar_set_vf(struct e1000_hw *hw, u8 * addr, u32 index)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       u32 msgbuf[3];
+       u8 *msg_addr = (u8 *)(&msgbuf[1]);
+       s32 ret_val;
+
+       memset(msgbuf, 0, 12);
+       msgbuf[0] = E1000_VF_SET_MAC_ADDR;
+       memcpy(msg_addr, addr, 6);
+       ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0);
+
+       if (!ret_val)
+               ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
+
+       msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
+
+       /* if nacked the address was rejected, use "perm_addr" */
+       if (!ret_val &&
+           (msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK)))
+               e1000_read_mac_addr_vf(hw);
+}
+
+/**
+ *  e1000_hash_mc_addr_vf - Generate a multicast hash value
+ *  @hw: pointer to the HW structure
+ *  @mc_addr: pointer to a multicast address
+ *
+ *  Generates a multicast address hash value which is used to determine
+ *  the multicast filter table array address and new table value.
+ **/
+static u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
+{
+       u32 hash_value, hash_mask;
+       u8 bit_shift = 0;
+
+       DEBUGFUNC("e1000_hash_mc_addr_generic");
+
+       /* Register count multiplied by bits per register */
+       hash_mask = (hw->mac.mta_reg_count * 32) - 1;
+
+       /*
+        * The bit_shift is the number of left-shifts
+        * where 0xFF would still fall within the hash mask.
+        */
+       while (hash_mask >> bit_shift != 0xFF)
+               bit_shift++;
+
+       hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
+                                 (((u16) mc_addr[5]) << bit_shift)));
+
+       return hash_value;
+}
+
+/**
+ *  e1000_update_mc_addr_list_vf - 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 the Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+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;
+       u32 i;
+
+       DEBUGFUNC("e1000_update_mc_addr_list_vf");
+
+       /* Each entry in the list uses 1 16 bit word.  We have 30
+        * 16 bit words available in our HW msg buffer (minus 1 for the
+        * msg type).  That's 30 hash values if we pack 'em right.  If
+        * there are more than 30 MC addresses to add then punt the
+        * extras for now and then add code to handle more than 30 later.
+        * It would be unusual for a server to request that many multi-cast
+        * addresses except for in large enterprise network environments.
+        */
+
+       DEBUGOUT1("MC Addr Count = %d\n", mc_addr_count);
+
+       if (mc_addr_count > 30) {
+               msgbuf[0] |= E1000_VF_SET_MULTICAST_OVERFLOW;
+               mc_addr_count = 30;
+       }
+
+       msgbuf[0] = E1000_VF_SET_MULTICAST;
+       msgbuf[0] |= mc_addr_count << E1000_VT_MSGINFO_SHIFT;
+
+       for (i = 0; i < mc_addr_count; i++) {
+               hash_value = e1000_hash_mc_addr_vf(hw, mc_addr_list);
+               DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
+               hash_list[i] = hash_value & 0x0FFF;
+               mc_addr_list += ETH_ADDR_LEN;
+       }
+
+       mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE, 0);
+}
+
+/**
+ *  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
+ **/
+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;
+       msgbuf[1] = vid;
+       /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */
+       if (set)
+               msgbuf[0] |= E1000_VF_SET_VLAN_ADD;
+
+       mbx->ops.write_posted(hw, msgbuf, 2, 0);
+}
+
+/** e1000_rlpml_set_vf - Set the maximum receive packet length
+ *  @hw: pointer to the HW structure
+ *  @max_size: value to assign to max frame size
+ **/
+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_promisc_set_vf - Set flags for Unicast or Multicast promisc
+ *  @hw: pointer to the HW structure
+ *  @uni: boolean indicating unicast promisc status
+ *  @multi: boolean indicating multicast promisc status
+ **/
+s32 e1000_promisc_set_vf(struct e1000_hw *hw, enum e1000_promisc_type type)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       u32 msgbuf = E1000_VF_SET_PROMISC;
+       s32 ret_val;
+
+       switch (type) {
+       case e1000_promisc_multicast:
+               msgbuf |= E1000_VF_SET_PROMISC_MULTICAST;
+               break;
+       case e1000_promisc_enabled:
+               msgbuf |= E1000_VF_SET_PROMISC_MULTICAST;
+       case e1000_promisc_unicast:
+               msgbuf |= E1000_VF_SET_PROMISC_UNICAST;
+       case e1000_promisc_disabled:
+               break;
+       default:
+               return -E1000_ERR_MAC_INIT;
+       }
+
+        ret_val = mbx->ops.write_posted(hw, &msgbuf, 1, 0);
+
+       if (!ret_val)
+               ret_val = mbx->ops.read_posted(hw, &msgbuf, 1, 0);
+
+       if (!ret_val && !(msgbuf & E1000_VT_MSGTYPE_ACK))
+               ret_val = -E1000_ERR_MAC_INIT;
+
+       return ret_val;
+}
+
+/**
+ *  e1000_read_mac_addr_vf - Read device MAC address
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_read_mac_addr_vf(struct e1000_hw *hw)
+{
+       int i;
+
+       for (i = 0; i < ETH_ADDR_LEN; i++)
+               hw->mac.addr[i] = hw->mac.perm_addr[i];
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_check_for_link_vf - Check for link for a virtual interface
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks to see if the underlying PF is still talking to the VF and
+ *  if it is then it reports the link state to the hardware, otherwise
+ *  it reports link down and returns an error.
+ **/
+static s32 e1000_check_for_link_vf(struct e1000_hw *hw)
+{
+       struct e1000_mbx_info *mbx = &hw->mbx;
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val = E1000_SUCCESS;
+       u32 in_msg = 0;
+
+       DEBUGFUNC("e1000_check_for_link_vf");
+
+       /*
+        * We only want to run this if there has been a rst asserted.
+        * in this case that could mean a link change, device reset,
+        * or a virtual function reset
+        */
+
+       /* If we were hit with a reset or timeout drop the link */
+       if (!mbx->ops.check_for_rst(hw, 0) || !mbx->timeout)
+               mac->get_link_status = TRUE;
+
+       if (!mac->get_link_status)
+               goto out;
+
+       /* if link status is down no point in checking to see if pf is up */
+       if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU))
+               goto out;
+
+       /* if the read failed it could just be a mailbox collision, best wait
+        * until we are called again and don't report an error */
+       if (mbx->ops.read(hw, &in_msg, 1, 0))
+               goto out;
+
+       /* if incoming message isn't clear to send we are waiting on response */
+       if (!(in_msg & E1000_VT_MSGTYPE_CTS)) {
+               /* message is not CTS and is NACK we have lost CTS status */
+               if (in_msg & E1000_VT_MSGTYPE_NACK)
+                       ret_val = -E1000_ERR_MAC_INIT;
+               goto out;
+       }
+
+       /* at this point we know the PF is talking to us, check and see if
+        * we are still accepting timeout or if we had a timeout failure.
+        * if we failed then we will need to reinit */
+       if (!mbx->timeout) {
+               ret_val = -E1000_ERR_MAC_INIT;
+               goto out;
+       }
+
+       /* if we passed all the tests above then the link is up and we no
+        * longer need to check for link */
+       mac->get_link_status = FALSE;
+
+out:
+       return ret_val;
+}
+
diff --git a/sys/dev/netif/ig_hal/e1000_vf.h b/sys/dev/netif/ig_hal/e1000_vf.h
new file mode 100644 (file)
index 0000000..b2fd8a1
--- /dev/null
@@ -0,0 +1,294 @@
+/******************************************************************************
+
+  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 _E1000_VF_H_
+#define _E1000_VF_H_
+
+#include "e1000_osdep.h"
+#include "e1000_regs.h"
+#include "e1000_defines.h"
+
+struct e1000_hw;
+
+#define E1000_DEV_ID_82576_VF                 0x10CA
+#define E1000_DEV_ID_I350_VF                  0x1520
+
+#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
+
+/* Additional Descriptor Control definitions */
+#define E1000_TXDCTL_QUEUE_ENABLE  0x02000000 /* Enable specific Tx Queue */
+#define E1000_RXDCTL_QUEUE_ENABLE  0x02000000 /* Enable specific Rx Queue */
+
+/* SRRCTL bit definitions */
+#define E1000_SRRCTL_BSIZEPKT_SHIFT                     10 /* Shift _right_ */
+#define E1000_SRRCTL_BSIZEHDRSIZE_MASK                  0x00000F00
+#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT                 2  /* Shift _left_ */
+#define E1000_SRRCTL_DESCTYPE_LEGACY                    0x00000000
+#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF                0x02000000
+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT                 0x04000000
+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS          0x0A000000
+#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION           0x06000000
+#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
+#define E1000_SRRCTL_DESCTYPE_MASK                      0x0E000000
+#define E1000_SRRCTL_DROP_EN                            0x80000000
+
+#define E1000_SRRCTL_BSIZEPKT_MASK      0x0000007F
+#define E1000_SRRCTL_BSIZEHDR_MASK      0x00003F00
+
+/* Interrupt Defines */
+#define E1000_EICR     0x01580  /* Ext. Interrupt Cause Read - R/clr */
+#define E1000_EITR(_n) (0x01680 + ((_n) << 2))
+#define E1000_EICS     0x01520  /* Ext. Interrupt Cause Set - W0 */
+#define E1000_EIMS     0x01524  /* Ext. Interrupt Mask Set/Read - RW */
+#define E1000_EIMC     0x01528  /* Ext. Interrupt Mask Clear - WO */
+#define E1000_EIAC     0x0152C  /* Ext. Interrupt Auto Clear - RW */
+#define E1000_EIAM     0x01530  /* Ext. Interrupt Ack Auto Clear Mask - RW */
+#define E1000_IVAR0    0x01700  /* Interrupt Vector Allocation (array) - RW */
+#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
+#define E1000_IVAR_VALID        0x80
+
+/* Receive Descriptor - Advanced */
+union e1000_adv_rx_desc {
+       struct {
+               u64 pkt_addr;             /* Packet buffer address */
+               u64 hdr_addr;             /* Header buffer address */
+       } read;
+       struct {
+               struct {
+                       union {
+                               u32 data;
+                               struct {
+                                       /* RSS type, Packet type */
+                                       u16 pkt_info;
+                                       /* Split Header, header buffer len */
+                                       u16 hdr_info;
+                               } hs_rss;
+                       } lo_dword;
+                       union {
+                               u32 rss;          /* RSS Hash */
+                               struct {
+                                       u16 ip_id;    /* IP id */
+                                       u16 csum;     /* Packet Checksum */
+                               } csum_ip;
+                       } hi_dword;
+               } lower;
+               struct {
+                       u32 status_error;     /* ext status/error */
+                       u16 length;           /* Packet length */
+                       u16 vlan;             /* VLAN tag */
+               } upper;
+       } wb;  /* writeback */
+};
+
+#define E1000_RXDADV_HDRBUFLEN_MASK      0x7FE0
+#define E1000_RXDADV_HDRBUFLEN_SHIFT     5
+
+/* Transmit Descriptor - Advanced */
+union e1000_adv_tx_desc {
+       struct {
+               u64 buffer_addr;    /* Address of descriptor's data buf */
+               u32 cmd_type_len;
+               u32 olinfo_status;
+       } read;
+       struct {
+               u64 rsvd;       /* Reserved */
+               u32 nxtseq_seed;
+               u32 status;
+       } wb;
+};
+
+/* Adv Transmit Descriptor Config Masks */
+#define E1000_ADVTXD_DTYP_CTXT    0x00200000 /* Advanced Context Descriptor */
+#define E1000_ADVTXD_DTYP_DATA    0x00300000 /* Advanced Data Descriptor */
+#define E1000_ADVTXD_DCMD_EOP     0x01000000 /* End of Packet */
+#define E1000_ADVTXD_DCMD_IFCS    0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_ADVTXD_DCMD_RS      0x08000000 /* Report Status */
+#define E1000_ADVTXD_DCMD_DEXT    0x20000000 /* Descriptor extension (1=Adv) */
+#define E1000_ADVTXD_DCMD_VLE     0x40000000 /* VLAN pkt enable */
+#define E1000_ADVTXD_DCMD_TSE     0x80000000 /* TCP Seg enable */
+#define E1000_ADVTXD_PAYLEN_SHIFT    14 /* Adv desc PAYLEN shift */
+
+/* Context descriptors */
+struct e1000_adv_tx_context_desc {
+       u32 vlan_macip_lens;
+       u32 seqnum_seed;
+       u32 type_tucmd_mlhl;
+       u32 mss_l4len_idx;
+};
+
+#define E1000_ADVTXD_MACLEN_SHIFT    9  /* Adv ctxt desc mac len shift */
+#define E1000_ADVTXD_TUCMD_IPV4    0x00000400  /* IP Packet Type: 1=IPv4 */
+#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800  /* L4 Packet TYPE of TCP */
+#define E1000_ADVTXD_L4LEN_SHIFT     8  /* Adv ctxt L4LEN shift */
+#define E1000_ADVTXD_MSS_SHIFT      16  /* Adv ctxt MSS shift */
+
+enum e1000_mac_type {
+       e1000_undefined = 0,
+       e1000_vfadapt,
+       e1000_vfadapt_i350,
+       e1000_num_macs  /* List is 1-based, so subtract 1 for TRUE count. */
+};
+
+struct e1000_vf_stats {
+       u64 base_gprc;
+       u64 base_gptc;
+       u64 base_gorc;
+       u64 base_gotc;
+       u64 base_mprc;
+       u64 base_gotlbc;
+       u64 base_gptlbc;
+       u64 base_gorlbc;
+       u64 base_gprlbc;
+
+       u32 last_gprc;
+       u32 last_gptc;
+       u32 last_gorc;
+       u32 last_gotc;
+       u32 last_mprc;
+       u32 last_gotlbc;
+       u32 last_gptlbc;
+       u32 last_gorlbc;
+       u32 last_gprlbc;
+
+       u64 gprc;
+       u64 gptc;
+       u64 gorc;
+       u64 gotc;
+       u64 mprc;
+       u64 gotlbc;
+       u64 gptlbc;
+       u64 gorlbc;
+       u64 gprlbc;
+};
+
+#include "e1000_mbx.h"
+
+struct e1000_mac_operations {
+       /* Function pointers for the MAC. */
+       s32  (*init_params)(struct e1000_hw *);
+       s32  (*check_for_link)(struct e1000_hw *);
+       void (*clear_vfta)(struct e1000_hw *);
+       s32  (*get_bus_info)(struct e1000_hw *);
+       s32  (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+       void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
+       s32  (*reset_hw)(struct e1000_hw *);
+       s32  (*init_hw)(struct e1000_hw *);
+       s32  (*setup_link)(struct e1000_hw *);
+       void (*write_vfta)(struct e1000_hw *, u32, u32);
+       void (*rar_set)(struct e1000_hw *, u8*, u32);
+       s32  (*read_mac_addr)(struct e1000_hw *);
+};
+
+struct e1000_mac_info {
+       struct e1000_mac_operations ops;
+       u8 addr[6];
+       u8 perm_addr[6];
+
+       enum e1000_mac_type type;
+
+       u16 mta_reg_count;
+       u16 rar_entry_count;
+
+       bool get_link_status;
+};
+
+struct e1000_mbx_operations {
+       s32 (*init_params)(struct e1000_hw *hw);
+       s32 (*read)(struct e1000_hw *, u32 *, u16,  u16);
+       s32 (*write)(struct e1000_hw *, u32 *, u16, u16);
+       s32 (*read_posted)(struct e1000_hw *, u32 *, u16,  u16);
+       s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16);
+       s32 (*check_for_msg)(struct e1000_hw *, u16);
+       s32 (*check_for_ack)(struct e1000_hw *, u16);
+       s32 (*check_for_rst)(struct e1000_hw *, u16);
+};
+
+struct e1000_mbx_stats {
+       u32 msgs_tx;
+       u32 msgs_rx;
+
+       u32 acks;
+       u32 reqs;
+       u32 rsts;
+};
+
+struct e1000_mbx_info {
+       struct e1000_mbx_operations ops;
+       struct e1000_mbx_stats stats;
+       u32 timeout;
+       u32 usec_delay;
+       u16 size;
+};
+
+struct e1000_dev_spec_vf {
+       u32 vf_number;
+       u32 v2p_mailbox;
+};
+
+struct e1000_hw {
+       void *back;
+
+       u8 *hw_addr;
+       u8 *flash_address;
+       unsigned long io_base;
+
+       struct e1000_mac_info  mac;
+       struct e1000_mbx_info mbx;
+
+       union {
+               struct e1000_dev_spec_vf vf;
+       } dev_spec;
+
+       u16 device_id;
+       u16 subsystem_vendor_id;
+       u16 subsystem_device_id;
+       u16 vendor_id;
+
+       u8  revision_id;
+};
+
+enum e1000_promisc_type {
+       e1000_promisc_disabled = 0,   /* all promisc modes disabled */
+       e1000_promisc_unicast = 1,    /* unicast promiscuous enabled */
+       e1000_promisc_multicast = 2,  /* multicast promiscuous enabled */
+       e1000_promisc_enabled = 3,    /* both uni and multicast promisc */
+       e1000_num_promisc_types
+};
+
+/* These functions must be implemented by drivers */
+s32  e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+void e1000_vfta_set_vf(struct e1000_hw *, u16, bool);
+void e1000_rlpml_set_vf(struct e1000_hw *, u16);
+s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type);
+#endif /* _E1000_VF_H_ */