[haiku-development] Updated freebsd-compat and ipro1000 driver

  • From: "Michael Weirauch" <dev@xxxxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Mon, 12 Jan 2009 18:54:00 +0100

Hello everybody,

please find attached two patches for the freebsd-compat-lib and the
ipro1000/dev/em source
based on RELENG_7.

This patch enables the "Intel Corporation 82567LM Gigabit Network
Connection [8086:10f5] (rev 03)" in
my ThinkPad (and other new supported models, too). DHCP, replugging
and Haiku svn co work.

haiku-freebsd-compat.diff:
* Updated struct ifnet and a stubbed eventhandler.c necessary for the
updated ipro1000/dev/em source

haiku-updated-ipro1000.diff:
* Updated dev/em source to RELENG_7 excluding the merged dev/bge source

Both patches should be applied together as otherwise the old dev/em
source won't compile. Just
splitted them for better distinction.

It would be kind if people already using this driver could check the
patch and see if things are still
working after applying it.

Thanks,
Michael

PS: For RELENG_7 the dev/em and dev/bge drivers have been merged into
dev/e1000. Perhaps we
might wan't to reflect this in the tree, too, in the future and build
the two drivers from it.
If desired, I can also check the 7_1 tree, but beforehand somebody
should get 7_1 into the vendor
branch.
Index: src/libs/compat/freebsd_network/compat/net/if.h
===================================================================
--- src/libs/compat/freebsd_network/compat/net/if.h     (Revision 28889)
+++ src/libs/compat/freebsd_network/compat/net/if.h     (Arbeitskopie)
@@ -26,6 +26,7 @@
 #define        IFCAP_POLLING           0x0040  /* driver supports polling */
 #define        IFCAP_VLAN_HWCSUM       0x0080
 #define        IFCAP_TSO4                      0x0100  /* supports TCP 
segmentation offload */
+#define        IFCAP_VLAN_HWFILTER     0x10000 /* interface hw can filter vlan 
tag */
 
 #define IFCAP_HWCSUM           (IFCAP_RXCSUM | IFCAP_TXCSUM)
 
Index: src/libs/compat/freebsd_network/compat/net/if_var.h
===================================================================
--- src/libs/compat/freebsd_network/compat/net/if_var.h (Revision 28889)
+++ src/libs/compat/freebsd_network/compat/net/if_var.h (Arbeitskopie)
@@ -137,7 +137,7 @@
        struct  bpf_if *if_bpf;         /* packet filter structure */
        u_short if_index;               /* numeric abbreviation for this if  */
        short   if_timer;               /* time 'til if_watchdog called */
-       u_short if_nvlans;              /* number of active vlans */
+       struct  ifvlantrunk *if_vlantrunk; /* pointer to 802.1q data */
        int     if_flags;               /* up/down, broadcast, etc. */
        int     if_capabilities;        /* interface capabilities */
        int     if_capenable;           /* enabled features */
Index: src/libs/compat/freebsd_network/eventhandler.c
===================================================================
--- src/libs/compat/freebsd_network/eventhandler.c      (Revision 0)
+++ src/libs/compat/freebsd_network/eventhandler.c      (Revision 0)
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2009, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *      Michael Weirauch, dev@xxxxxxxxxxx
+ */
+
+#include <compat/sys/types.h>
+
+#include <compat/sys/eventhandler.h>
+
+eventhandler_tag
+eventhandler_register(struct eventhandler_list *list, 
+           const char *name, void *func, void *arg, int priority)
+{
+       return NULL;
+};
+
+
+void
+eventhandler_deregister(struct eventhandler_list *list,
+           eventhandler_tag tag)
+{
+       //
+};
+
+
+struct eventhandler_list *
+eventhandler_find_list(const char *name)
+{
+       return NULL;
+};
+
+
+void
+eventhandler_prune_list(struct eventhandler_list *list)
+{
+       //
+};
Index: src/libs/compat/freebsd_network/Jamfile
===================================================================
--- src/libs/compat/freebsd_network/Jamfile     (Revision 28889)
+++ src/libs/compat/freebsd_network/Jamfile     (Arbeitskopie)
@@ -14,6 +14,7 @@
        compat.c
        device.c
        driver.c
+       eventhandler.c
        fbsd_busdma_x86.c
        fbsd_ether.c
        fbsd_if_media.c
Index: dev/em/e1000_82575.c
===================================================================
--- dev/em/e1000_82575.c        (Revision 28889)
+++ dev/em/e1000_82575.c        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,92 +29,95 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82575.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82575.c,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
-
-/* e1000_82575
+/*
+ * 82575EB Gigabit Network Connection
+ * 82575EB Gigabit Backplane Connection
+ * 82575GB Gigabit Network Connection
+ * 82576 Gigabit Network Connection
  */
 
 #include "e1000_api.h"
-#include "e1000_82575.h"
 
-void e1000_init_function_pointers_82575(struct e1000_hw *hw);
+static s32  e1000_init_phy_params_82575(struct e1000_hw *hw);
+static s32  e1000_init_nvm_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_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_fiber_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_configure_pcs_link_82575(struct e1000_hw *hw);
+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_power_down_phy_copper_82575(struct e1000_hw *hw);
 
-STATIC s32       e1000_init_phy_params_82575(struct e1000_hw *hw);
-STATIC s32       e1000_init_nvm_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 void      e1000_rar_set_82575(struct e1000_hw *hw, u8 *addr, u32 index);
-STATIC s32       e1000_reset_hw_82575(struct e1000_hw *hw);
-STATIC s32       e1000_set_d0_lplu_state_82575(struct e1000_hw *hw,
-                                               boolean_t active);
-STATIC s32       e1000_setup_copper_link_82575(struct e1000_hw *hw);
-STATIC s32       e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw);
-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_configure_pcs_link_82575(struct e1000_hw *hw);
-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 boolean_t e1000_sgmii_active_82575(struct e1000_hw *hw);
-STATIC s32       e1000_reset_init_script_82575(struct e1000_hw* hw);
+static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count);
+static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw,
+                                           u8 *mc_addr_list, u32 mc_addr_count,
+                                           u32 rar_used_count, u32 rar_count);
+void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw);
 
-struct e1000_dev_spec_82575 {
-       boolean_t sgmii_active;
-};
-
 /**
  *  e1000_init_phy_params_82575 - Init PHY func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_phy_params_82575(struct e1000_hw *hw)
+static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_phy_params_82575");
 
-       if (hw->media_type != e1000_media_type_copper) {
-               phy->type                = e1000_phy_none;
+       if (hw->phy.media_type != e1000_media_type_copper) {
+               phy->type = e1000_phy_none;
                goto out;
+       } else {
+               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->autoneg_mask           = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us         = 100;
 
-       func->acquire_phy        = e1000_acquire_phy_82575;
-       func->check_reset_block  = e1000_check_reset_block_generic;
-       func->commit_phy         = e1000_phy_sw_reset_generic;
-       func->get_cfg_done       = e1000_get_cfg_done_82575;
-       func->release_phy        = e1000_release_phy_82575;
+       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;
 
-       if (e1000_sgmii_active_82575(hw) == TRUE) {
-               func->reset_phy          = e1000_phy_hw_reset_sgmii_82575;
-               func->read_phy_reg       = e1000_read_phy_reg_sgmii_82575;
-               func->write_phy_reg      = e1000_write_phy_reg_sgmii_82575;
+       if (e1000_sgmii_active_82575(hw)) {
+               phy->ops.reset      = e1000_phy_hw_reset_sgmii_82575;
+               phy->ops.read_reg   = e1000_read_phy_reg_sgmii_82575;
+               phy->ops.write_reg  = e1000_write_phy_reg_sgmii_82575;
        } else {
-               func->reset_phy          = e1000_phy_hw_reset_generic;
-               func->read_phy_reg       = e1000_read_phy_reg_igp;
-               func->write_phy_reg      = e1000_write_phy_reg_igp;
+               phy->ops.reset      = e1000_phy_hw_reset_generic;
+               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. */
@@ -123,20 +126,21 @@
        /* Verify phy id and set remaining function pointers */
        switch (phy->id) {
        case M88E1111_I_PHY_ID:
-               phy->type                = e1000_phy_m88;
-               func->check_polarity     = e1000_check_polarity_m88;
-               func->get_phy_info       = e1000_get_phy_info_m88;
-               func->get_cable_length   = e1000_get_cable_length_m88;
-               func->force_speed_duplex = e1000_phy_force_speed_duplex_m88;
+               phy->type                   = e1000_phy_m88;
+               phy->ops.check_polarity     = e1000_check_polarity_m88;
+               phy->ops.get_info           = e1000_get_phy_info_m88;
+               phy->ops.get_cable_length   = e1000_get_cable_length_m88;
+               phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
                break;
        case IGP03E1000_E_PHY_ID:
-               phy->type                = e1000_phy_igp_3;
-               func->check_polarity     = e1000_check_polarity_igp;
-               func->get_phy_info       = e1000_get_phy_info_igp;
-               func->get_cable_length   = e1000_get_cable_length_igp_2;
-               func->force_speed_duplex = e1000_phy_force_speed_duplex_igp;
-               func->set_d0_lplu_state  = e1000_set_d0_lplu_state_82575;
-               func->set_d3_lplu_state  = e1000_set_d3_lplu_state_generic;
+       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;
        default:
                ret_val = -E1000_ERR_PHY;
@@ -150,14 +154,10 @@
 /**
  *  e1000_init_nvm_params_82575 - Init NVM func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_nvm_params_82575(struct e1000_hw *hw)
+static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_functions *func = &hw->func;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
        u16 size;
 
@@ -180,25 +180,30 @@
                break;
        }
 
-       nvm->type               = e1000_nvm_eeprom_spi;
+       nvm->type              = e1000_nvm_eeprom_spi;
 
        size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
                          E1000_EECD_SIZE_EX_SHIFT);
 
-       /* Added to a constant, "size" becomes the left-shift value
+       /*
+        * Added to a constant, "size" becomes the left-shift value
         * for setting word_size.
         */
        size += NVM_WORD_SIZE_BASE_SHIFT;
+
+       /* EEPROM access above 16k is unsupported */
+       if (size > 14)
+               size = 14;
        nvm->word_size  = 1 << size;
 
        /* Function Pointers */
-       func->acquire_nvm       = e1000_acquire_nvm_82575;
-       func->read_nvm          = e1000_read_nvm_eerd;
-       func->release_nvm       = e1000_release_nvm_82575;
-       func->update_nvm        = e1000_update_nvm_checksum_generic;
-       func->valid_led_default = e1000_valid_led_default_generic;
-       func->validate_nvm      = e1000_validate_nvm_checksum_generic;
-       func->write_nvm         = e1000_write_nvm_spi;
+       nvm->ops.acquire       = e1000_acquire_nvm_82575;
+       nvm->ops.read          = e1000_read_nvm_eerd;
+       nvm->ops.release       = e1000_release_nvm_82575;
+       nvm->ops.update        = e1000_update_nvm_checksum_generic;
+       nvm->ops.valid_led_default = e1000_valid_led_default_82575;
+       nvm->ops.validate      = e1000_validate_nvm_checksum_generic;
+       nvm->ops.write         = e1000_write_nvm_spi;
 
        return E1000_SUCCESS;
 }
@@ -206,53 +211,45 @@
 /**
  *  e1000_init_mac_params_82575 - Init MAC func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_mac_params_82575(struct e1000_hw *hw)
+static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
-       struct e1000_dev_spec_82575 *dev_spec;
-       u32 ctrl, ctrl_ext;
-       s32 ret_val = E1000_SUCCESS;
+       struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+       u32 ctrl_ext = 0;
 
        DEBUGFUNC("e1000_init_mac_params_82575");
 
-       hw->dev_spec_size = sizeof(struct e1000_dev_spec_82575);
-
-       /* Device-specific structure allocation */
-       ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size);
-       if (ret_val)
-               goto out;
-
-       dev_spec = (struct e1000_dev_spec_82575 *)hw->dev_spec;
-
        /* Set media type */
-        /* The 82575 uses bits 22:23 for link mode. The mode can be changed
+        /*
+        * 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->media_type = e1000_media_type_copper;
+       hw->phy.media_type = e1000_media_type_copper;
        dev_spec->sgmii_active = FALSE;
 
        ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
        if ((ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) ==
            E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES) {
-               hw->media_type = e1000_media_type_internal_serdes;
+               hw->phy.media_type = e1000_media_type_internal_serdes;
+               ctrl_ext |= E1000_CTRL_I2C_ENA;
        } else if (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII) {
                dev_spec->sgmii_active = TRUE;
-               ctrl = E1000_READ_REG(hw, E1000_CTRL);
-               E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_I2C_ENA));
+               ctrl_ext |= E1000_CTRL_I2C_ENA;
+       } else {
+               ctrl_ext &= ~E1000_CTRL_I2C_ENA;
        }
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
 
        /* Set mta register count */
        mac->mta_reg_count = 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;
        /* Set if part includes ASF firmware */
        mac->asf_firmware_present = TRUE;
        /* Set if manageability features are enabled. */
@@ -263,76 +260,73 @@
        /* Function pointers */
 
        /* bus type/speed/width */
-       func->get_bus_info = e1000_get_bus_info_pcie_generic;
+       mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
        /* reset */
-       func->reset_hw = e1000_reset_hw_82575;
+       mac->ops.reset_hw = e1000_reset_hw_82575;
        /* hw initialization */
-       func->init_hw = e1000_init_hw_82575;
+       mac->ops.init_hw = e1000_init_hw_82575;
        /* link setup */
-       func->setup_link = e1000_setup_link_generic;
+       mac->ops.setup_link = e1000_setup_link_generic;
        /* physical interface link setup */
-       func->setup_physical_interface =
-               (hw->media_type == e1000_media_type_copper)
+       mac->ops.setup_physical_interface =
+               (hw->phy.media_type == e1000_media_type_copper)
                        ? e1000_setup_copper_link_82575
                        : e1000_setup_fiber_serdes_link_82575;
+       /* physical interface shutdown */
+       mac->ops.shutdown_serdes = e1000_shutdown_fiber_serdes_link_82575;
        /* check for link */
-       func->check_for_link = e1000_check_for_link_82575;
+       mac->ops.check_for_link = e1000_check_for_link_82575;
        /* receive address register setting */
-       func->rar_set = e1000_rar_set_82575;
+       mac->ops.rar_set = e1000_rar_set_generic;
+       /* read mac address */
+       mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
        /* multicast address update */
-       func->mc_addr_list_update = e1000_mc_addr_list_update_generic;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82575;
        /* writing VFTA */
-       func->write_vfta = e1000_write_vfta_generic;
+       mac->ops.write_vfta = e1000_write_vfta_generic;
        /* clearing VFTA */
-       func->clear_vfta = e1000_clear_vfta_generic;
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
        /* setting MTA */
-       func->mta_set = e1000_mta_set_generic;
+       mac->ops.mta_set = e1000_mta_set_generic;
        /* blink LED */
-       func->blink_led = e1000_blink_led_generic;
+       mac->ops.blink_led = e1000_blink_led_generic;
        /* setup LED */
-       func->setup_led = e1000_setup_led_generic;
+       mac->ops.setup_led = e1000_setup_led_generic;
        /* cleanup LED */
-       func->cleanup_led = e1000_cleanup_led_generic;
+       mac->ops.cleanup_led = e1000_cleanup_led_generic;
        /* turn on/off LED */
-       func->led_on = e1000_led_on_generic;
-       func->led_off = e1000_led_off_generic;
-       /* remove device */
-       func->remove_device = e1000_remove_device_generic;
+       mac->ops.led_on = e1000_led_on_generic;
+       mac->ops.led_off = e1000_led_off_generic;
        /* clear hardware counters */
-       func->clear_hw_cntrs = e1000_clear_hw_cntrs_82575;
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575;
        /* link info */
-       func->get_link_up_info = e1000_get_link_up_info_82575;
+       mac->ops.get_link_up_info = e1000_get_link_up_info_82575;
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
  *  e1000_init_function_pointers_82575 - Init func ptrs.
  *  @hw: pointer to the HW structure
  *
- *  The only function explicitly called by the api module to initialize
- *  all function pointers and parameters.
+ *  Called to initialize all function pointers and parameters.
  **/
-void
-e1000_init_function_pointers_82575(struct e1000_hw *hw)
+void e1000_init_function_pointers_82575(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_init_function_pointers_82575");
 
-       hw->func.init_mac_params = e1000_init_mac_params_82575;
-       hw->func.init_nvm_params = e1000_init_nvm_params_82575;
-       hw->func.init_phy_params = e1000_init_phy_params_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;
 }
 
 /**
  *  e1000_acquire_phy_82575 - Acquire rights to access PHY
  *  @hw: pointer to the HW structure
  *
- *  Acquire access rights to the correct PHY.  This is a
- *  function pointer entry point called by the api module.
+ *  Acquire access rights to the correct PHY.
  **/
-STATIC s32
-e1000_acquire_phy_82575(struct e1000_hw *hw)
+static s32 e1000_acquire_phy_82575(struct e1000_hw *hw)
 {
        u16 mask;
 
@@ -347,11 +341,9 @@
  *  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.  This is a
- *  function pointer entry point called by the api module.
+ *  A wrapper to release access rights to the correct PHY.
  **/
-STATIC void
-e1000_release_phy_82575(struct e1000_hw *hw)
+static void e1000_release_phy_82575(struct e1000_hw *hw)
 {
        u16 mask;
 
@@ -370,8 +362,8 @@
  *  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)
+static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
+                                          u16 *data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, i2ccmd = 0;
@@ -383,7 +375,8 @@
                return -E1000_ERR_PARAM;
        }
 
-       /* Set up Op-code, Phy Address, and register address in the I2CCMD
+       /*
+        * 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.
         */
@@ -424,8 +417,8 @@
  *  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)
+static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
+                                           u16 data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, i2ccmd = 0;
@@ -441,7 +434,8 @@
        /* 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
+       /*
+        * 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.
         */
@@ -472,14 +466,13 @@
 }
 
 /**
- *  e1000_get_phy_id_82575 - Retreive PHY addr and id
+ *  e1000_get_phy_id_82575 - Retrieve PHY addr and id
  *  @hw: pointer to the HW structure
  *
- *  Retreives the PHY address and ID for both PHY's which do and do not use
+ *  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)
+static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32  ret_val = E1000_SUCCESS;
@@ -487,19 +480,21 @@
 
        DEBUGFUNC("e1000_get_phy_id_82575");
 
-       /* For SGMII PHYs, we try the list of possible addresses until
+       /*
+        * 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) == FALSE) {
+       if (!(e1000_sgmii_active_82575(hw))) {
                phy->addr = 1;
                ret_val = e1000_get_phy_id(hw);
                goto out;
        }
 
-       /* The address field in the I2CCMD register is 3 bits and 0 is invalid.
+       /*
+        * 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++) {
@@ -508,8 +503,10 @@
                        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. */
+                       /*
+                        * At the time of this writing, The M88 part is
+                        * the only supported SGMII PHY product.
+                        */
                        if (phy_id == M88_VENDOR)
                                break;
                } else {
@@ -537,27 +534,31 @@
  *
  *  Resets the PHY using the serial gigabit media independent interface.
  **/
-STATIC s32
-e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw)
+static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw)
 {
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575");
 
-       /* This isn't a true "hard" reset, but is the only reset
+       /*
+        * 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");
 
-       /* SFP documentation requires the following to configure the SPF module
+       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 = e1000_write_phy_reg(hw, 0x1B, 0x8084);
+       ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_phy_commit(hw);
+       ret_val = hw->phy.ops.commit(hw);
 
 out:
        return ret_val;
@@ -576,68 +577,68 @@
  *  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, boolean_t active)
+static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u16 data;
 
        DEBUGFUNC("e1000_set_d0_lplu_state_82575");
 
-       ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
+       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 = e1000_write_phy_reg(hw,
-                                             IGP02E1000_PHY_POWER_MGMT,
-                                             data);
+               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 = e1000_read_phy_reg(hw,
-                                            IGP01E1000_PHY_PORT_CONFIG,
-                                            &data);
+               ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+                                           &data);
                data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-               ret_val = e1000_write_phy_reg(hw,
-                                             IGP01E1000_PHY_PORT_CONFIG,
-                                             data);
+               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 = e1000_write_phy_reg(hw,
-                                             IGP02E1000_PHY_POWER_MGMT,
-                                             data);
-               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               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. */
+                * SmartSpeed, so performance is maintained.
+                */
                if (phy->smart_speed == e1000_smart_speed_on) {
-                       ret_val = e1000_read_phy_reg(hw,
-                                                    IGP01E1000_PHY_PORT_CONFIG,
-                                                    &data);
+                       ret_val = phy->ops.read_reg(hw,
+                                                   IGP01E1000_PHY_PORT_CONFIG,
+                                                   &data);
                        if (ret_val)
                                goto out;
 
                        data |= IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       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 = e1000_read_phy_reg(hw,
-                                                    IGP01E1000_PHY_PORT_CONFIG,
-                                                    &data);
+                       ret_val = phy->ops.read_reg(hw,
+                                                   IGP01E1000_PHY_PORT_CONFIG,
+                                                   &data);
                        if (ret_val)
                                goto out;
 
                        data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
@@ -653,13 +654,12 @@
  *  e1000_acquire_nvm_82575 - Request for access to EEPROM
  *  @hw: pointer to the HW structure
  *
- *  Acquire the necessary semaphores for exclussive access to the EEPROM.
+ *  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)
+static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw)
 {
        s32 ret_val;
 
@@ -685,8 +685,7 @@
  *  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)
+static void e1000_release_nvm_82575(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_release_nvm_82575");
 
@@ -702,8 +701,7 @@
  *  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)
+static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
 {
        u32 swfw_sync;
        u32 swmask = mask;
@@ -723,8 +721,10 @@
                if (!(swfw_sync & (fwmask | swmask)))
                        break;
 
-               /* Firmware currently using resource (fwmask)
-                * or other software thread using resource (swmask) */
+               /*
+                * Firmware currently using resource (fwmask)
+                * or other software thread using resource (swmask)
+                */
                e1000_put_hw_semaphore_generic(hw);
                msec_delay_irq(5);
                i++;
@@ -753,8 +753,7 @@
  *  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)
+static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
 {
        u32 swfw_sync;
 
@@ -780,8 +779,7 @@
  *  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)
+static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw)
 {
        s32 timeout = PHY_CFG_TIMEOUT;
        s32 ret_val = E1000_SUCCESS;
@@ -818,23 +816,24 @@
  *  @duplex: stores the current duplex
  *
  *  This is a wrapper function, if using the serial gigabit media independent
- *  interface, use pcs to retreive the link speed and duplex information.
+ *  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)
+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->media_type != e1000_media_type_copper ||
-           e1000_sgmii_active_82575(hw) == TRUE) {
+       if (hw->phy.media_type != e1000_media_type_copper ||
+           e1000_sgmii_active_82575(hw)) {
                ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed,
                                                               duplex);
-       } else
+       } else {
                ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
                                                                    duplex);
+       }
 
        return ret_val;
 }
@@ -846,8 +845,7 @@
  *  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)
+static s32 e1000_check_for_link_82575(struct e1000_hw *hw)
 {
        s32 ret_val;
        u16 speed, duplex;
@@ -855,8 +853,8 @@
        DEBUGFUNC("e1000_check_for_link_82575");
 
        /* SGMII link check is done through the PCS register. */
-       if ((hw->media_type != e1000_media_type_copper) ||
-           (e1000_sgmii_active_82575(hw) == TRUE))
+       if ((hw->phy.media_type != e1000_media_type_copper) ||
+           (e1000_sgmii_active_82575(hw)))
                ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,
                                                               &duplex);
        else
@@ -871,12 +869,11 @@
  *  @speed: stores the current speed
  *  @duplex: stores the current duplex
  *
- *  Using the physical coding sub-layer (PCS), retreive the current speed and
+ *  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)
+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;
@@ -888,12 +885,15 @@
        *speed = 0;
        *duplex = 0;
 
-       /* Read the PCS Status register for link state. For non-copper mode,
+       /*
+        * 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. */
+        * used instead.
+        */
        pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT);
 
-       /* The link up bit determines when link is up on autoneg. The sync ok
+       /*
+        * 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
         */
@@ -921,25 +921,141 @@
 }
 
 /**
- *  e1000_rar_set_82575 - Set receive address register
+ *  e1000_init_rx_addrs_82575 - Initialize receive address's
  *  @hw: pointer to the HW structure
- *  @addr: pointer to the receive address
- *  @index: receive address array register
+ *  @rar_count: receive address registers
  *
- *  Sets the receive address array register at index to the address passed
- *  in by addr.
+ *  Setups the receive address registers by setting the base receive address
+ *  register to the devices MAC address and clearing all the other receive
+ *  address registers to 0.
  **/
-void
-e1000_rar_set_82575(struct e1000_hw *hw, u8 *addr, u32 index)
+static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count)
 {
-       DEBUGFUNC("e1000_rar_set_82575");
+       u32 i;
+       u8 addr[6] = {0,0,0,0,0,0};
+       /*
+        * This function is essentially the same as that of
+        * e1000_init_rx_addrs_generic. However it also takes care
+        * of the special case where the register offset of the
+        * second set of RARs begins elsewhere. This is implicitly taken care by
+        * function e1000_rar_set_generic.
+        */
 
-       if (index < E1000_RAR_ENTRIES_82575) {
-               e1000_rar_set_generic(hw, addr, index);
-               goto out;
+       DEBUGFUNC("e1000_init_rx_addrs_82575");
+
+       /* Setup the receive address */
+       DEBUGOUT("Programming MAC Address into RAR[0]\n");
+       hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
+
+       /* Zero out the other (rar_entry_count - 1) receive addresses */
+       DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1);
+       for (i = 1; i < rar_count; i++) {
+           hw->mac.ops.rar_set(hw, addr, i);
        }
+}
 
-out:
+/**
+ *  e1000_update_mc_addr_list_82575 - 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
+ *  @rar_used_count: the first RAR register free to program
+ *  @rar_count: total number of supported Receive Address Registers
+ *
+ *  Updates the Receive Address Registers and Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ *  The parameter rar_count will usually be hw->mac.rar_entry_count
+ *  unless there are workarounds that change this.
+ **/
+static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw,
+                                     u8 *mc_addr_list, u32 mc_addr_count,
+                                     u32 rar_used_count, u32 rar_count)
+{
+       u32 hash_value;
+       u32 i;
+       u8 addr[6] = {0,0,0,0,0,0};
+       /*
+        * This function is essentially the same as that of 
+        * e1000_update_mc_addr_list_generic. However it also takes care 
+        * of the special case where the register offset of the 
+        * second set of RARs begins elsewhere. This is implicitly taken care 
by 
+        * function e1000_rar_set_generic.
+        */
+
+       DEBUGFUNC("e1000_update_mc_addr_list_82575");
+
+       /*
+        * Load the first set of multicast addresses into the exact
+        * filters (RAR).  If there are not enough to fill the RAR
+        * array, clear the filters.
+        */
+       for (i = rar_used_count; i < rar_count; i++) {
+               if (mc_addr_count) {
+                       e1000_rar_set_generic(hw, mc_addr_list, i);
+                       mc_addr_count--;
+                       mc_addr_list += ETH_ADDR_LEN;
+               } else {
+                       e1000_rar_set_generic(hw, addr, i);
+               }
+       }
+
+       /* Clear the old settings from the MTA */
+       DEBUGOUT("Clearing MTA\n");
+       for (i = 0; i < hw->mac.mta_reg_count; i++) {
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
+               E1000_WRITE_FLUSH(hw);
+       }
+
+       /* Load any remaining multicast addresses into the hash table. */
+       for (; mc_addr_count > 0; mc_addr_count--) {
+               hash_value = e1000_hash_mc_addr(hw, mc_addr_list);
+               DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
+               hw->mac.ops.mta_set(hw, hash_value);
+               mc_addr_list += ETH_ADDR_LEN;
+       }
+}
+
+/**
+ *  e1000_shutdown_fiber_serdes_link_82575 - Remove link during power down
+ *  @hw: pointer to the HW structure
+ *
+ *  In the case of fiber serdes shut down optics and PCS on driver unload
+ *  when management pass thru is not enabled.
+ **/
+void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw)
+{
+       u32 reg;
+       u16 eeprom_data = 0;
+
+       if (hw->mac.type != e1000_82576 ||
+          (hw->phy.media_type != e1000_media_type_fiber &&
+           hw->phy.media_type != e1000_media_type_internal_serdes))
+               return;
+
+       if (hw->bus.func == 0)
+               hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
+
+       /*
+        * If APM is not enabled in the EEPROM and management interface is
+        * not enabled, then power down.
+        */
+       if (!(eeprom_data & E1000_NVM_APME_82575) &&
+           !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_SDP7_DATA;
+               E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
+
+               /* flush the write to verfiy completion */
+               E1000_WRITE_FLUSH(hw);
+               msec_delay(1);
+       }
+
        return;
 }
 
@@ -947,18 +1063,17 @@
  *  e1000_reset_hw_82575 - Reset hardware
  *  @hw: pointer to the HW structure
  *
- *  This resets the hardware into a known state.  This is a
- *  function pointer entry point called by the api module.
+ *  This resets the hardware into a known state.
  **/
-STATIC s32
-e1000_reset_hw_82575(struct e1000_hw *hw)
+static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
 {
        u32 ctrl, icr;
        s32 ret_val;
 
        DEBUGFUNC("e1000_reset_hw_82575");
 
-       /* Prevent the PCI-E bus from sticking if there is no TLP connection
+       /*
+        * 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);
@@ -982,7 +1097,8 @@
 
        ret_val = e1000_get_auto_rd_done_generic(hw);
        if (ret_val) {
-               /* When auto config read does not complete, do not
+               /*
+                * 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.
                 */
@@ -997,6 +1113,8 @@
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
        icr = E1000_READ_REG(hw, E1000_ICR);
 
+       e1000_check_alt_mac_addr_generic(hw);
+
        return ret_val;
 }
 
@@ -1006,8 +1124,7 @@
  *
  *  This inits the hardware readying it for operation.
  **/
-STATIC s32
-e1000_init_hw_82575(struct e1000_hw *hw)
+static s32 e1000_init_hw_82575(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val;
@@ -1019,32 +1136,31 @@
        ret_val = e1000_id_led_init_generic(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
-               goto out;
+               /* This is not fatal and we should not stop init due to this */
        }
 
        /* Disabling VLAN filtering */
        DEBUGOUT("Initializing the IEEE VLAN\n");
-       e1000_clear_vfta(hw);
+       mac->ops.clear_vfta(hw);
 
-       /* Setup the receive address. */
-       e1000_init_rx_addrs_generic(hw, rar_count);
-
+       /* Setup the receive address */
+       e1000_init_rx_addrs_82575(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);
 
        /* Setup link and flow control */
-       ret_val = e1000_setup_link(hw);
+       ret_val = mac->ops.setup_link(hw);
 
-       /* Clear all of the statistics registers (clear on read).  It is
+       /*
+        * 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);
 
-out:
        return ret_val;
 }
 
@@ -1056,12 +1172,11 @@
  *  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)
+static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
 {
        u32 ctrl, led_ctrl;
        s32  ret_val;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_setup_copper_link_82575");
 
@@ -1091,16 +1206,20 @@
                goto out;
 
        if (hw->mac.autoneg) {
-               /* Setup autoneg and flow control advertisement
-                * and perform autonegotiation. */
+               /*
+                * Setup autoneg and flow control advertisement
+                * and perform autonegotiation.
+                */
                ret_val = e1000_copper_link_autoneg(hw);
                if (ret_val)
                        goto out;
        } else {
-               /* PHY will be set to 10H, 10F, 100H or 100F
-                * depending on user settings. */
+               /*
+                * PHY will be set to 10H, 10F, 100H or 100F
+                * depending on user settings.
+                */
                DEBUGOUT("Forcing Speed and Duplex\n");
-               ret_val = e1000_phy_force_speed_duplex(hw);
+               ret_val = hw->phy.ops.force_speed_duplex(hw);
                if (ret_val) {
                        DEBUGOUT("Error Forcing Speed and Duplex\n");
                        goto out;
@@ -1111,7 +1230,8 @@
        if (ret_val)
                goto out;
 
-       /* Check link status. Wait up to 100 microseconds for link to become
+       /*
+        * Check link status. Wait up to 100 microseconds for link to become
         * valid.
         */
        ret_val = e1000_phy_has_link_generic(hw,
@@ -1140,14 +1260,14 @@
  *
  *  Configures speed and duplex for fiber and serdes links.
  **/
-STATIC s32
-e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
+static s32 e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
 {
        u32 reg;
 
        DEBUGFUNC("e1000_setup_fiber_serdes_link_82575");
 
-       /* On the 82575, SerDes loopback mode persists until it is
+       /*
+        * 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.
@@ -1163,17 +1283,29 @@
               E1000_CTRL_SWDPIN1;
        E1000_WRITE_REG(hw, E1000_CTRL, reg);
 
+       /* Power on phy for 82576 fiber adapters */
+       if (hw->mac.type == e1000_82576) {
+               reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+               reg &= ~E1000_CTRL_EXT_SDP7_DATA;
+               E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
+       }
+
        /* Set switch control to serdes energy detect */
        reg = E1000_READ_REG(hw, E1000_CONNSW);
        reg |= E1000_CONNSW_ENRGSRC;
        E1000_WRITE_REG(hw, E1000_CONNSW, reg);
 
-       /* New SerDes mode allows for forcing speed or autonegotiating speed
+       /*
+        * 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_READ_REG(hw, E1000_PCS_LCTL);
+
+       reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
+               E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
+
        if (hw->mac.autoneg) {
                /* Set PCS register for autoneg */
                reg |= E1000_PCS_LCTL_FSV_1000 |      /* Force 1000    */
@@ -1190,12 +1322,54 @@
                       E1000_PCS_LCTL_FORCE_LINK;     /* Force Link */
                DEBUGOUT1("Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg);
        }
+
+       if (hw->mac.type == e1000_82576) {
+               reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+               e1000_force_mac_fc_generic(hw);
+       }
+
        E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg);
 
        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_fiber:
+               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_configure_pcs_link_82575 - Configure PCS link
  *  @hw: pointer to the HW structure
  *
@@ -1204,16 +1378,15 @@
  *  independent interface (sgmii) is being used.  Configures the link
  *  for auto-negotiation or forces speed/duplex.
  **/
-static s32
-e1000_configure_pcs_link_82575(struct e1000_hw *hw)
+static s32 e1000_configure_pcs_link_82575(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 reg = 0;
 
        DEBUGFUNC("e1000_configure_pcs_link_82575");
 
-       if (hw->media_type != e1000_media_type_copper ||
-           e1000_sgmii_active_82575(hw) == FALSE)
+       if (hw->phy.media_type != e1000_media_type_copper ||
+           !(e1000_sgmii_active_82575(hw)))
                goto out;
 
        /* For SGMII, we need to issue a PCS autoneg restart */
@@ -1226,12 +1399,13 @@
                /* Make sure forced speed and force link are not set */
                reg &= ~(E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
 
-               /* The PHY should be setup prior to calling this function.
+               /*
+                * The PHY should be setup prior to calling this function.
                 * All we need to do is restart autoneg and enable autoneg.
                 */
                reg |= E1000_PCS_LCTL_AN_RESTART | E1000_PCS_LCTL_AN_ENABLE;
        } else {
-               /* Set PCS regiseter for forced speed */
+               /* Set PCS register for forced speed */
 
                /* Turn off bits for full duplex, speed, and autoneg */
                reg &= ~(E1000_PCS_LCTL_FSV_1000 |
@@ -1269,25 +1443,16 @@
  *  which can be enabled for use in the embedded applications.  Simply
  *  return the current state of the sgmii interface.
  **/
-static boolean_t
-e1000_sgmii_active_82575(struct e1000_hw *hw)
+static bool e1000_sgmii_active_82575(struct e1000_hw *hw)
 {
-       struct e1000_dev_spec_82575 *dev_spec;
-       boolean_t ret_val;
+       struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
 
        DEBUGFUNC("e1000_sgmii_active_82575");
 
-       if (hw->mac.type != e1000_82575) {
-               ret_val = FALSE;
-               goto out;
-       }
+       if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576)
+               return FALSE;
 
-       dev_spec = (struct e1000_dev_spec_82575 *)hw->dev_spec;
-
-       ret_val = dev_spec->sgmii_active;
-
-out:
-       return ret_val;
+       return dev_spec->sgmii_active;
 }
 
 /**
@@ -1297,101 +1462,208 @@
  *  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)
+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(hw, E1000_SCTL, 0x00, 0x0C);
-               e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x01, 0x78);
-               e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x1B, 0x23);
-               e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x23, 0x15);
+               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(hw, E1000_CCMCTL, 0x14, 0x00);
-               e1000_write_8bit_ctrl_reg(hw, E1000_CCMCTL, 0x10, 0x00);
+               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(hw, E1000_GIOCTL, 0x00, 0xEC);
-               e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x61, 0xDF);
-               e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x34, 0x05);
-               e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x2F, 0x81);
+               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(hw, E1000_SCCTL, 0x02, 0x47);
-               e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x14, 0x00);
-               e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x10, 0x00);
+               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 (e1000_check_alt_mac_addr_generic(hw))
+               ret_val = e1000_read_mac_addr_generic(hw);
+
+       return ret_val;
+}
+
+/**
+ * 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;
+       struct e1000_mac_info *mac = &hw->mac;
+
+       if (!(phy->ops.check_reset_block))
+               return;
+
+       /* If the management interface is not enabled, then power down */
+       if (!(mac->ops.check_mng_mode(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)
+static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw)
 {
-       volatile u32 temp;
-
        DEBUGFUNC("e1000_clear_hw_cntrs_82575");
 
        e1000_clear_hw_cntrs_base_generic(hw);
 
-       temp = E1000_READ_REG(hw, E1000_PRC64);
-       temp = E1000_READ_REG(hw, E1000_PRC127);
-       temp = E1000_READ_REG(hw, E1000_PRC255);
-       temp = E1000_READ_REG(hw, E1000_PRC511);
-       temp = E1000_READ_REG(hw, E1000_PRC1023);
-       temp = E1000_READ_REG(hw, E1000_PRC1522);
-       temp = E1000_READ_REG(hw, E1000_PTC64);
-       temp = E1000_READ_REG(hw, E1000_PTC127);
-       temp = E1000_READ_REG(hw, E1000_PTC255);
-       temp = E1000_READ_REG(hw, E1000_PTC511);
-       temp = E1000_READ_REG(hw, E1000_PTC1023);
-       temp = E1000_READ_REG(hw, E1000_PTC1522);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_ALGNERRC);
-       temp = E1000_READ_REG(hw, E1000_RXERRC);
-       temp = E1000_READ_REG(hw, E1000_TNCRS);
-       temp = E1000_READ_REG(hw, E1000_CEXTERR);
-       temp = E1000_READ_REG(hw, E1000_TSCTC);
-       temp = E1000_READ_REG(hw, E1000_TSCTFC);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_MGTPRC);
-       temp = E1000_READ_REG(hw, E1000_MGTPDC);
-       temp = E1000_READ_REG(hw, E1000_MGTPTC);
+       E1000_READ_REG(hw, E1000_MGTPRC);
+       E1000_READ_REG(hw, E1000_MGTPDC);
+       E1000_READ_REG(hw, E1000_MGTPTC);
 
-       temp = E1000_READ_REG(hw, E1000_IAC);
-       temp = E1000_READ_REG(hw, E1000_ICRXOC);
+       E1000_READ_REG(hw, E1000_IAC);
+       E1000_READ_REG(hw, E1000_ICRXOC);
 
-       temp = E1000_READ_REG(hw, E1000_ICRXPTC);
-       temp = E1000_READ_REG(hw, E1000_ICRXATC);
-       temp = E1000_READ_REG(hw, E1000_ICTXPTC);
-       temp = E1000_READ_REG(hw, E1000_ICTXATC);
-       temp = E1000_READ_REG(hw, E1000_ICTXQEC);
-       temp = E1000_READ_REG(hw, E1000_ICTXQMTC);
-       temp = E1000_READ_REG(hw, E1000_ICRXDMTC);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_CBTMPC);
-       temp = E1000_READ_REG(hw, E1000_HTDPMC);
-       temp = E1000_READ_REG(hw, E1000_CBRMPC);
-       temp = E1000_READ_REG(hw, E1000_RPTHC);
-       temp = E1000_READ_REG(hw, E1000_HGPTC);
-       temp = E1000_READ_REG(hw, E1000_HTCBDPC);
-       temp = E1000_READ_REG(hw, E1000_HGORCL);
-       temp = E1000_READ_REG(hw, E1000_HGORCH);
-       temp = E1000_READ_REG(hw, E1000_HGOTCL);
-       temp = E1000_READ_REG(hw, E1000_HGOTCH);
-       temp = E1000_READ_REG(hw, E1000_LENERRS);
+       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->media_type == e1000_media_type_internal_serdes)
-               temp = E1000_READ_REG(hw, E1000_SCVPC);
+       if (hw->phy.media_type == e1000_media_type_internal_serdes)
+               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);
+}
+
Index: dev/em/e1000_ich8lan.h
===================================================================
--- dev/em/e1000_ich8lan.h      (Revision 28889)
+++ dev/em/e1000_ich8lan.h      (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,10 +29,9 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_ich8lan.h,v 1.3 2007/05/16 00:14:23 jfv Exp 
$*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_ich8lan.h,v 1.2 2008/11/26 23:57:23 jfv 
Exp $*/
 
-
 #ifndef _E1000_ICH8LAN_H_
 #define _E1000_ICH8LAN_H_
 
@@ -55,8 +54,6 @@
 #define FLASH_GFPREG_BASE_MASK           0x1FFF
 #define FLASH_SECTOR_ADDR_SHIFT          12
 
-#define E1000_SHADOW_RAM_WORDS           2048
-
 #define ICH_FLASH_SEG_SIZE_256           256
 #define ICH_FLASH_SEG_SIZE_4K            4096
 #define ICH_FLASH_SEG_SIZE_8K            8192
@@ -67,9 +64,8 @@
 
 #define E1000_ICH_FWSM_RSPCIPHY          0x00000040 /* Reset PHY on PCI Reset 
*/
 #define E1000_ICH_FWSM_DISSW             0x10000000 /* FW Disables SW Writes */
-#define E1000_ICH_FWSM_FW_VALID          0x00008000 /* FW established a valid
-                                                     * mode.
-                                                     */
+/* FW established a valid mode */
+#define E1000_ICH_FWSM_FW_VALID          0x00008000
 
 #define E1000_ICH_MNG_IAMT_MODE          0x2
 
@@ -84,7 +80,7 @@
 #define E1000_ICH8_LAN_INIT_TIMEOUT      1500
 
 #define E1000_FEXTNVM_SW_CONFIG        1
-#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ 
*/
+#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M */
 
 #define PCIE_ICH8_SNOOP_ALL   PCIE_NO_SNOOP_ALL
 
@@ -103,13 +99,34 @@
 #define IGP3_VR_CTRL_MODE_SHUTDOWN           0x0200
 #define IGP3_PM_CTRL_FORCE_PWR_DOWN          0x0020
 
-/* Additional interrupts need to be handled for ICH family:
-    DSW = The FW changed the status of the DISSW bit in FWSM
-    PHYINT = The LAN connected device generates an interrupt
-    EPRST = Manageability reset event */
+/*
+ * Additional interrupts need to be handled for ICH family:
+ *  DSW = The FW changed the status of the DISSW bit in FWSM
+ *  PHYINT = The LAN connected device generates an interrupt
+ *  EPRST = Manageability reset event
+ */
 #define IMS_ICH_ENABLE_MASK (\
     E1000_IMS_DSW   | \
     E1000_IMS_PHYINT | \
     E1000_IMS_EPRST)
 
+/* Additional interrupt register bit definitions */
+#define E1000_ICR_LSECPNC       0x00004000          /* PN threshold - client */
+#define E1000_IMS_LSECPNC       E1000_ICR_LSECPNC   /* PN threshold - client */
+#define E1000_ICS_LSECPNC       E1000_ICR_LSECPNC   /* PN threshold - client */
+
+/* Security Processing bit Indication */
+#define E1000_RXDEXT_LINKSEC_STATUS_LSECH       0x01000000
+#define E1000_RXDEXT_LINKSEC_ERROR_BIT_MASK     0x60000000
+#define E1000_RXDEXT_LINKSEC_ERROR_NO_SA_MATCH  0x20000000
+#define E1000_RXDEXT_LINKSEC_ERROR_REPLAY_ERROR 0x40000000
+#define E1000_RXDEXT_LINKSEC_ERROR_BAD_SIG      0x60000000
+
+
+void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
+                                                 bool state);
+void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
+void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
+void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw);
+
 #endif
Index: dev/em/e1000_82571.h
===================================================================
--- dev/em/e1000_82571.h        (Revision 28889)
+++ dev/em/e1000_82571.h        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,10 +29,9 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82571.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82571.h,v 1.1 2008/07/30 21:56:53 jfv Exp 
$*/
 
-
 #ifndef _E1000_82571_H_
 #define _E1000_82571_H_
 
@@ -44,4 +43,17 @@
 
 #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
 
+/* Intr Throttling - RW */
+#define E1000_EITR_82574(_n)    (0x000E8 + (0x4 * (_n)))
+
+#define E1000_EIAC_82574        0x000DC /* Ext. Interrupt Auto Clear - RW */
+#define E1000_EIAC_MASK_82574   0x01F00000
+
+#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask 
*/
+
+#define E1000_RXCFGL    0x0B634 /* TimeSync Rx EtherType & Msg Type Reg - RW */
+
+bool e1000_get_laa_state_82571(struct e1000_hw *hw);
+void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state);
+
 #endif
Index: dev/em/e1000_82575.h
===================================================================
--- dev/em/e1000_82575.h        (Revision 28889)
+++ dev/em/e1000_82575.h        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,19 +29,28 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82575.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82575.h,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
-
 #ifndef _E1000_82575_H_
 #define _E1000_82575_H_
 
-/* Receive Address Register Count
+#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
 
 #ifdef E1000_BIT_FIELDS
 struct e1000_adv_data_desc {
@@ -79,6 +88,8 @@
 #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 {
@@ -116,15 +127,26 @@
 #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_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_RSS_FIELD_IPV4_UDP       0x00400000
 #define E1000_MRQC_RSS_FIELD_IPV6_UDP       0x00800000
 #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX    0x01000000
 
+#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 |    \
@@ -146,7 +168,7 @@
     E1000_EIMS_TCP_TIMER | \
     E1000_EIMS_OTHER)
 
-/* Immediate Interrupt RX (A.K.A. Low Latency Interrupt) */
+/* 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 */
@@ -156,7 +178,7 @@
 #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 control bits 
*/
+#define E1000_IMIREXT_CTRL_BP     0x00080000  /* Bypass check of ctrl bits */
 
 /* Receive Descriptor - Advanced */
 union e1000_adv_rx_desc {
@@ -166,10 +188,13 @@
        } read;
        struct {
                struct {
-                       struct {
-                               u16 pkt_info;   /* RSS type, Packet type */
-                               u16 hdr_info;   /* Split Header,
-                                                     * header buffer length */
+                       union {
+                               u32 data;
+                               struct {
+                                       u16 pkt_info; /* RSS type, Packet type 
*/
+                                       u16 hdr_info; /* Split Header,
+                                                      * header buffer length */
+                               } hs_rss;
                        } lo_dword;
                        union {
                                u32 rss;          /* RSS Hash */
@@ -193,7 +218,7 @@
 #define E1000_RXDADV_HDRBUFLEN_SHIFT     5
 #define E1000_RXDADV_SPLITHEADER_EN      0x00001000
 #define E1000_RXDADV_SPH                 0x8000
-#define E1000_RXDADV_HBO                 0x00800000
+#define E1000_RXDADV_ERR_HBO             0x00800000
 
 /* RSS Hash results */
 #define E1000_RXDADV_RSSTYPE_NONE        0x00000000
@@ -207,6 +232,38 @@
 #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 {
@@ -226,7 +283,6 @@
 #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_RDMA    0x04000000 /* RDMA */
 #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) */
@@ -236,7 +292,6 @@
 #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_EOM    0x00000400 /* Enable L bit in RDMA DDP hdr */
 #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 */
@@ -272,8 +327,8 @@
 /* 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 
*/
-#define E1000_TXDCTL_PRIORITY      0x08000000 /* Tx Queue Arbitration Priority
-                                                 0=low, 1=high */
+/* 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 */
@@ -293,6 +348,127 @@
 
 #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_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_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_LPE        0x00010000 /* Accept Long packet */
+#define E1000_VMOLR_AUPE       0x01000000 /* Accept untagged packets */
+#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_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_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_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      0xF0000000  /* Messages below or'd with
+                                               * this are the ACK */
+#define E1000_VT_MSGTYPE_NACK     0xFF000000  /* Messages below or'd with
+                                               * this are the NACK */
+#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_MSGTYPE_REQ_MAC  1 /* VF needs to know its MAC */
+#define E1000_VF_MSGTYPE_VFLR     2 /* VF notifies VFLR to PF */
+#define E1000_VF_SET_MULTICAST    3 /* VF requests PF to set MC addr */
+#define E1000_VF_SET_VLAN         4 /* VF requests PF to set VLAN */
+
+/* Add 100h to all PF msgs, leaves room for up to 255 discrete message types
+ * from VF to PF - way more than we'll ever need */
+#define E1000_PF_MSGTYPE_RESET    (1 + 0x100) /* PF notifies global reset
+                                               * imminent to VF */
+#define E1000_PF_MSGTYPE_LSC      (2 + 0x100) /* PF notifies VF of LSC... VF
+                                               * will see extra msg info for
+                                               * status */
+
+#define E1000_PF_MSG_LSCDOWN      (1 << E1000_VT_MSGINFO_SHIFT)
+#define E1000_PF_MSG_LSCUP        (2 << E1000_VT_MSGINFO_SHIFT)
+
+#define ALL_QUEUES   0xFFFF
+
+s32  e1000_send_mail_to_pf_vf(struct e1000_hw *hw, u32 *msg,
+                              s16 size);
+s32  e1000_receive_mail_from_pf_vf(struct e1000_hw *hw,
+                                   u32 *msg, s16 size);
+s32  e1000_send_mail_to_vf(struct e1000_hw *hw, u32 *msg,
+                           u32 vf_number, s16 size);
+s32  e1000_receive_mail_from_vf(struct e1000_hw *hw, u32 *msg,
+                                u32 vf_number, s16 size);
+void e1000_vmdq_loopback_enable_vf(struct e1000_hw *hw);
+void e1000_vmdq_loopback_disable_vf(struct e1000_hw *hw);
+void e1000_vmdq_replication_enable_vf(struct e1000_hw *hw, u32 enables);
+void e1000_vmdq_replication_disable_vf(struct e1000_hw *hw);
+void e1000_vmdq_enable_replication_mode_vf(struct e1000_hw *hw);
+void e1000_vmdq_broadcast_replication_enable_vf(struct e1000_hw *hw,
+                                               u32 enables);
+void e1000_vmdq_multicast_replication_enable_vf(struct e1000_hw *hw,
+                                               u32 enables);
+void e1000_vmdq_broadcast_replication_disable_vf(struct e1000_hw *hw,
+                                               u32 disables);
+void e1000_vmdq_multicast_replication_disable_vf(struct e1000_hw *hw,
+                                               u32 disables);
+bool e1000_check_for_pf_ack_vf(struct e1000_hw *hw);
+
+bool e1000_check_for_pf_mail_vf(struct e1000_hw *hw, u32*);
+
+
 #endif
Index: dev/em/e1000_regs.h
===================================================================
--- dev/em/e1000_regs.h (Revision 28889)
+++ dev/em/e1000_regs.h (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,10 +29,9 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_regs.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_regs.h,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
-
 #ifndef _E1000_REGS_H_
 #define _E1000_REGS_H_
 
@@ -47,6 +46,7 @@
 #define E1000_SCTL     0x00024  /* SerDes Control - RW */
 #define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
 #define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
+#define E1000_FEXT     0x0002C  /* Future Extended - RW */
 #define E1000_FEXTNVM  0x00028  /* Future Extended NVM - RW */
 #define E1000_FCT      0x00030  /* Flow Control Type - RW */
 #define E1000_CONNSW   0x00034  /* Copper/Fiber switch control - RW */
@@ -57,36 +57,25 @@
 #define E1000_IMS      0x000D0  /* Interrupt Mask Set - RW */
 #define E1000_IMC      0x000D8  /* Interrupt Mask Clear - WO */
 #define E1000_IAM      0x000E0  /* Interrupt Acknowledge Auto Mask */
-#define E1000_RCTL     0x00100  /* RX Control - RW */
-#define E1000_RDTR1    0x02820  /* RX Delay Timer (1) - RW */
-#define E1000_RDBAL1   0x02900  /* RX Descriptor Base Address Low (1) - RW */
-#define E1000_RDBAH1   0x02904  /* RX Descriptor Base Address High (1) - RW */
-#define E1000_RDLEN1   0x02908  /* RX Descriptor Length (1) - RW */
-#define E1000_RDH1     0x02910  /* RX Descriptor Head (1) - RW */
-#define E1000_RDT1     0x02918  /* RX Descriptor Tail (1) - RW */
+#define E1000_IVAR     0x000E4  /* Interrupt Vector Allocation Register - RW */
+#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_TXCW     0x00178  /* Tx Configuration Word - RW */
+#define E1000_RXCW     0x00180  /* Rx Configuration Word - RO */
 #define E1000_EICR     0x01580  /* Ext. Interrupt Cause Read - R/clr */
-#define E1000_EITR0    0x01680  /* Ext. Int. Throttling Rate Vector 0 - RW */
-#define E1000_EITR1    0x01684  /* Ext. Int. Throttling Rate Vector 1 - RW */
-#define E1000_EITR2    0x01688  /* Ext. Int. Throttling Rate Vector 2 - RW */
-#define E1000_EITR3    0x0168C  /* Ext. Int. Throttling Rate Vector 3 - RW */
-#define E1000_EITR4    0x01690  /* Ext. Int. Throttling Rate Vector 4 - RW */
-#define E1000_EITR5    0x01694  /* Ext. Int. Throttling Rate Vector 5 - RW */
-#define E1000_EITR6    0x01698  /* Ext. Int. Throttling Rate Vector 6 - RW */
-#define E1000_EITR7    0x0169C  /* Ext. Int. Throttling Rate Vector 7 - RW */
-#define E1000_EITR8    0x016A0  /* Ext. Int. Throttling Rate Vector 8 - RW */
-#define E1000_EITR9    0x016A4  /* Ext. Int. Throttling Rate Vector 9 - RW */
+#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_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_TBT      0x00448  /* TX Burst Timer - 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_TBT      0x00448  /* Tx Burst Timer - RW */
 #define E1000_AIT      0x00458  /* Adaptive Interframe Spacing Throttle - RW */
 #define E1000_LEDCTL   0x00E00  /* LED Control - RW */
 #define E1000_EXTCNF_CTRL  0x00F00  /* Extended Configuration Control */
@@ -108,141 +97,110 @@
 #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_PSRCTL   0x02170  /* Packet Split Receive Control - RW */
-#define E1000_RDFPCQ0  0x02430
-#define E1000_RDFPCQ1  0x02434
-#define E1000_RDFPCQ2  0x02438
-#define E1000_RDFPCQ3  0x0243C
-#define E1000_PBRTH    0x02458  /* PB RX Arbitration Threshold - RW */
+#define E1000_RDFPCQ(_n)  (0x02430 + (0x4 * (_n)))
+#define E1000_PBRTH    0x02458  /* PB Rx Arbitration Threshold - RW */
 #define E1000_FCRTV    0x02460  /* Flow Control Refresh Timer Value - RW */
-#define E1000_SRRCTL0  0x0280C
-#define E1000_SRRCTL(_n) (0x280C + (_n << 8)) /* Split and Replication
-                                               * RX Control - RW */
-#define E1000_RDPUMB   0x025CC  /* DMA RX Descriptor uC Mailbox - RW */
-#define E1000_RDPUAD   0x025D0  /* DMA RX Descriptor uC Addr Command - 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_RDBAL    0x02800  /* RX Descriptor Base Address Low - RW */
-#define E1000_RDBAH    0x02804  /* RX Descriptor Base Address High - RW */
-#define E1000_RDLEN    0x02808  /* RX Descriptor Length - RW */
-#define E1000_RDH      0x02810  /* RX Descriptor Head - RW */
-#define E1000_RDT      0x02818  /* RX Descriptor Tail - RW */
-#define E1000_RDTR     0x02820  /* RX Delay Timer - RW */
-#define E1000_RDBAL0   E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
-#define E1000_RDBAH0   E1000_RDBAH /* RX Desc Base Address High (0) - RW */
-#define E1000_RDLEN0   E1000_RDLEN /* RX Desc Length (0) - RW */
-#define E1000_RDH0     E1000_RDH   /* RX Desc Head (0) - RW */
-#define E1000_RDT0     E1000_RDT   /* RX Desc Tail (0) - RW */
-#define E1000_RDTR0    E1000_RDTR  /* RX Delay Timer (0) - RW */
-#define E1000_RXDCTL   0x02828  /* RX Descriptor Control queue 0 - RW */
-#define E1000_RXDCTL1  0x02928  /* RX Descriptor Control queue 1 - RW */
-#define E1000_RADV     0x0282C  /* RX Interrupt Absolute Delay Timer - RW */
-/* Convenience macros
+/* Split and Replication Rx Control - RW */
+#define E1000_RDPUMB   0x025CC  /* DMA Rx Descriptor uC Mailbox - RW */
+#define E1000_RDPUAD   0x025D0  /* DMA Rx Descriptor uC Addr Command - 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_RXCTL(_n)   (0x0C014 + (0x40 * (_n)))
+#define E1000_RQDPC(_n)   (0x0C030 + (0x40 * (_n)))
+#define E1000_TXCTL(_n)   (0x0E014 + (0x40 * (_n)))
+#define E1000_RXCTL(_n)   (0x0C014 + (0x40 * (_n)))
+#define E1000_RQDPC(_n)   (0x0C030 + (0x40 * (_n)))
+#define E1000_RDTR     0x02820  /* Rx Delay Timer - RW */
+#define E1000_RADV     0x0282C  /* Rx Interrupt Absolute Delay Timer - RW */
+/*
+ * Convenience macros
  *
  * Note: "_n" is the queue number of the register to be written to.
  *
  * Example usage:
  * E1000_RDBAL_REG(current_rx_queue)
- *
  */
-#define E1000_RDBAL_REG(_n)   (E1000_RDBAL + (_n << 8))
-#define E1000_RDBAH_REG(_n)   (E1000_RDBAH + (_n << 8))
-#define E1000_RDLEN_REG(_n)   (E1000_RDLEN + (_n << 8))
-#define E1000_RDH_REG(_n)     (E1000_RDH + (_n << 8))
-#define E1000_RDT_REG(_n)     (E1000_RDT + (_n << 8))
-#define E1000_RXDCTL_REG(_n)  (E1000_RXDCTL + (_n << 8))
-#define E1000_TDBAL_REG(_n)   (E1000_TDBAL + (_n << 8))
-#define E1000_TDBAH_REG(_n)   (E1000_TDBAH + (_n << 8))
-#define E1000_TDLEN_REG(_n)   (E1000_TDLEN + (_n << 8))
-#define E1000_TDH_REG(_n)     (E1000_TDH + (_n << 8))
-#define E1000_TDT_REG(_n)     (E1000_TDT + (_n << 8))
-#define E1000_TXDCTL_REG(_n)  (E1000_TXDCTL + (_n << 8))
-#define E1000_TARC_REG(_n)    (E1000_TARC0 + (_n << 8))
+#define E1000_RDBAL(_n)      ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
+                                         (0x0C000 + ((_n) * 0x40)))
+#define E1000_RDBAH(_n)      ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
+                                         (0x0C004 + ((_n) * 0x40)))
+#define E1000_RDLEN(_n)      ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
+                                         (0x0C008 + ((_n) * 0x40)))
+#define E1000_SRRCTL(_n)     ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
+                                         (0x0C00C + ((_n) * 0x40)))
+#define E1000_RDH(_n)        ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
+                                         (0x0C010 + ((_n) * 0x40)))
+#define E1000_RDT(_n)        ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
+                                         (0x0C018 + ((_n) * 0x40)))
+#define E1000_RXDCTL(_n)     ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
+                                         (0x0C028 + ((_n) * 0x40)))
+#define E1000_TDBAL(_n)      ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
+                                         (0x0E000 + ((_n) * 0x40)))
+#define E1000_TDBAH(_n)      ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
+                                         (0x0E004 + ((_n) * 0x40)))
+#define E1000_TDLEN(_n)      ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
+                                         (0x0E008 + ((_n) * 0x40)))
+#define E1000_TDH(_n)        ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
+                                         (0x0E010 + ((_n) * 0x40)))
+#define E1000_TDT(_n)        ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
+                                         (0x0E018 + ((_n) * 0x40)))
+#define E1000_TXDCTL(_n)     ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
+                                         (0x0E028 + ((_n) * 0x40)))
+#define E1000_TARC(_n)       (0x03840 + (_n << 8))
+#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8))
 #define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8))
-#define E1000_DCA_RXCTRL0    0x02814 /* RX Queue 0 DCA CTRL - RW */
-#define E1000_DCA_RXCTRL1    0x02914 /* RX Queue 1 DCA CTRL - RW */
-#define E1000_RDBAL2         0x02A00 /* RX Descriptor Base Low Queue 2 - RW */
-#define E1000_RDBAH2         0x02A04 /* RX Descriptor Base High Queue 2 - RW */
-#define E1000_RDLEN2         0x02A08 /* RX Descriptor Length Queue 2 - RW */
-#define E1000_RDH2           0x02A10 /* RX Descriptor Head Queue 2 - RW */
-#define E1000_DCA_RXCTRL2    0x02A14 /* RX Queue 2 DCA CTRL - RW */
-#define E1000_RDT2           0x02A18 /* RX Descriptor Tail Queue 2 - RW */
-#define E1000_RXDCTL2        0x02A28 /* RX Descriptor Control queue 2 - RW */
-#define E1000_RDBAL3         0x02B00 /* RX Descriptor Base Low Queue 3 - RW */
-#define E1000_RDBAH3         0x02B04 /* RX Descriptor Base High Queue 3 - RW */
-#define E1000_RDLEN3         0x02B08 /* RX Descriptor Length Queue 3 - RW */
-#define E1000_RDH3           0x02B10 /* RX Descriptor Head Queue 3 - RW */
-#define E1000_DCA_RXCTRL3    0x02B14 /* RX Queue 3 DCA Control - RW */
-#define E1000_RDT3           0x02B18 /* RX Descriptor Tail Queue 3 - RW */
-#define E1000_RXDCTL3        0x02B28 /* RX Descriptor Control Queue 3 - RW */
-#define E1000_RSRPD    0x02C00  /* RX Small Packet Detect - RW */
+#define E1000_TDWBAL(_n)     ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \
+                                         (0x0E038 + ((_n) * 0x40)))
+#define E1000_TDWBAH(_n)     ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \
+                                         (0x0E03C + ((_n) * 0x40)))
+#define E1000_RSRPD    0x02C00  /* Rx Small Packet Detect - RW */
 #define E1000_RAID     0x02C08  /* Receive Ack Interrupt Delay - RW */
-#define E1000_TXDMAC   0x03000  /* TX DMA Control - RW */
+#define E1000_TXDMAC   0x03000  /* Tx DMA Control - RW */
 #define E1000_KABGTXD  0x03004  /* AFE Band Gap Transmit Ref Data */
-#define E1000_TDFH     0x03410  /* TX Data FIFO Head - RW */
-#define E1000_TDFT     0x03418  /* TX Data FIFO Tail - RW */
-#define E1000_TDFHS    0x03420  /* TX Data FIFO Head Saved - RW */
-#define E1000_TDFTS    0x03428  /* TX Data FIFO Tail Saved - RW */
-#define E1000_TDFPC    0x03430  /* TX Data FIFO Packet Count - RW */
-#define E1000_TDPUMB   0x0357C  /* DMA TX Descriptor uC Mail Box - RW */
-#define E1000_TDPUAD   0x03580  /* DMA TX Descriptor uC Addr Command - RW */
-#define E1000_TDPUWD   0x03584  /* DMA TX Descriptor uC Data Write - 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_TDBAL    0x03800  /* TX Descriptor Base Address Low - RW */
-#define E1000_TDBAH    0x03804  /* TX Descriptor Base Address High - RW */
-#define E1000_TDLEN    0x03808  /* TX Descriptor Length - RW */
-#define E1000_TDH      0x03810  /* TX Descriptor Head - RW */
-#define E1000_TDT      0x03818  /* TX Descriptor Tail - RW */
-#define E1000_TDBAL0   E1000_TDBAL /* TX Descriptor Base Address Low - RW */
-#define E1000_TDBAH0   E1000_TDBAH /* TX Descriptor Base Address High - RW */
-#define E1000_TDLEN0   E1000_TDLEN /* TX Descriptor Length - RW */
-#define E1000_TDH0     E1000_TDH   /* TX Descriptor Head - RW */
-#define E1000_TDT0     E1000_TDT   /* TX Descriptor Tail - RW */
-#define E1000_TIDV     0x03820  /* TX Interrupt Delay Value - RW */
-#define E1000_TXDCTL   0x03828  /* TX Descriptor Control - RW */
-#define E1000_TADV     0x0382C  /* TX Interrupt Absolute Delay Val - RW */
+#define E1000_PSRTYPE(_i)       (0x05480 + ((_i) * 4))
+#define E1000_RAL(_i)  (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
+                                       (0x054E0 + ((_i - 16) * 8)))
+#define E1000_RAH(_i)  (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
+                                       (0x054E4 + ((_i - 16) * 8)))
+#define E1000_IP4AT_REG(_i)     (0x05840 + ((_i) * 8))
+#define E1000_IP6AT_REG(_i)     (0x05880 + ((_i) * 4))
+#define E1000_WUPM_REG(_i)      (0x05A00 + ((_i) * 4))
+#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_TDFH     0x03410  /* Tx Data FIFO Head - RW */
+#define E1000_TDFT     0x03418  /* Tx Data FIFO Tail - RW */
+#define E1000_TDFHS    0x03420  /* Tx Data FIFO Head Saved - RW */
+#define E1000_TDFTS    0x03428  /* Tx Data FIFO Tail Saved - RW */
+#define E1000_TDFPC    0x03430  /* Tx Data FIFO Packet Count - RW */
+#define E1000_TDPUMB   0x0357C  /* DMA Tx Descriptor uC Mail Box - RW */
+#define E1000_TDPUAD   0x03580  /* DMA Tx Descriptor uC Addr Command - RW */
+#define E1000_TDPUWD   0x03584  /* DMA Tx Descriptor uC Data Write - 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_TARC0    0x03840  /* TX Arbitration Count (0) */
-#define E1000_DCA_TXCTRL0     0x03814 /* TX Queue 0 DCA CTRL - RW */
-#define E1000_TDWBAL0         0x03838 /* TX Desc. WB Addr Low Queue 0 - RW */
-#define E1000_TDWBAH0         0x0383C /* TX Desc. WB Addr High Queue 0 - RW */
-#define E1000_DCA_TXCTRL(_n) (E1000_DCA_TXCTRL0 + (_n << 8))
-#define E1000_TDWBAL_REG(_n) (E1000_TDWBAL0 + (_n << 8))
-#define E1000_TDWBAH_REG(_n) (E1000_TDWBAH0 + (_n << 8))
-#define E1000_TDBAL1   0x03900  /* TX Desc Base Address Low (1) - RW */
-#define E1000_TDBAH1   0x03904  /* TX Desc Base Address High (1) - RW */
-#define E1000_TDLEN1   0x03908  /* TX Desc Length (1) - RW */
-#define E1000_TDH1     0x03910  /* TX Desc Head (1) - RW */
-#define E1000_TDT1     0x03918  /* TX Desc Tail (1) - RW */
-#define E1000_TXDCTL1  0x03928  /* TX Descriptor Control (1) - RW */
-#define E1000_TARC1    0x03940  /* TX Arbitration Count (1) */
-#define E1000_DCA_TXCTRL1 0x03914  /* TX Queue 0 DCA CTRL - RW */
-#define E1000_TDWBAL1     0x03938  /* TX Descriptor WB Addr Low Queue 1 - RW */
-#define E1000_TDWBAH1     0x0393C  /* TX Descriptor WB Addr High Queue 1 - RW 
*/
-#define E1000_TDBAL2      0x03A00  /* TX Descriptor Base Low Queue 2 - RW */
-#define E1000_TDBAH2      0x03A04  /* TX Descriptor Base High Queue 2 - RW */
-#define E1000_TDLEN2      0x03A08  /* TX Descriptor Length Queue 2 - RW */
-#define E1000_TDH2        0x03A10  /* TX Descriptor Head Queue 2 - RW */
-#define E1000_DCA_TXCTRL2 0x03A14  /* TX Queue 2 DCA Control - RW */
-#define E1000_TDT2        0x03A18  /* TX Descriptor Tail Queue 2 - RW */
-#define E1000_TXDCTL2     0x03A28  /* TX Descriptor Control 2 - RW */
-#define E1000_TDWBAL2     0x03A38  /* TX Descriptor WB Addr Low Queue 2 - RW */
-#define E1000_TDWBAH2     0x03A3C  /* TX Descriptor WB Addr High Queue 2 - RW 
*/
-#define E1000_TDBAL3      0x03B00  /* TX Descriptor Base Low Queue 3 - RW */
-#define E1000_TDBAH3      0x03B04  /* TX Descriptor Base High Queue 3 - RW */
-#define E1000_TDLEN3      0x03B08  /* TX Descriptor Length Queue 3 - RW */
-#define E1000_TDH3        0x03B10  /* TX Descriptor Head Queue 3 - RW */
-#define E1000_DCA_TXCTRL3 0x03B14  /* TX Queue 3 DCA Control - RW */
-#define E1000_TDT3        0x03B18  /* TX Descriptor Tail Queue 3 - RW */
-#define E1000_TXDCTL3     0x03B28  /* TX Descriptor Control 3 - RW */
-#define E1000_TDWBAL3     0x03B38  /* TX Descriptor WB Addr Low Queue 3 - RW */
-#define E1000_TDWBAH3     0x03B3C  /* TX Descriptor WB Addr High Queue 3 - RW 
*/
 #define E1000_CRCERRS  0x04000  /* CRC Error Count - R/clr */
 #define E1000_ALGNERRC 0x04004  /* Alignment Error Count - R/clr */
 #define E1000_SYMERRS  0x04008  /* Symbol Error Count - R/clr */
@@ -254,72 +212,133 @@
 #define E1000_LATECOL  0x04020  /* Late Collision Count - R/clr */
 #define E1000_COLC     0x04028  /* Collision Count - R/clr */
 #define E1000_DC       0x04030  /* Defer Count - R/clr */
-#define E1000_TNCRS    0x04034  /* TX-No CRS - R/clr */
+#define E1000_TNCRS    0x04034  /* Tx-No CRS - R/clr */
 #define E1000_SEC      0x04038  /* Sequence Error Count - R/clr */
 #define E1000_CEXTERR  0x0403C  /* Carrier Extension Error Count - R/clr */
 #define E1000_RLEC     0x04040  /* Receive Length Error Count - R/clr */
-#define E1000_XONRXC   0x04048  /* XON RX Count - R/clr */
-#define E1000_XONTXC   0x0404C  /* XON TX Count - R/clr */
-#define E1000_XOFFRXC  0x04050  /* XOFF RX Count - R/clr */
-#define E1000_XOFFTXC  0x04054  /* XOFF TX Count - R/clr */
-#define E1000_FCRUC    0x04058  /* Flow Control RX Unsupported Count- R/clr */
-#define E1000_PRC64    0x0405C  /* Packets RX (64 bytes) - R/clr */
-#define E1000_PRC127   0x04060  /* Packets RX (65-127 bytes) - R/clr */
-#define E1000_PRC255   0x04064  /* Packets RX (128-255 bytes) - R/clr */
-#define E1000_PRC511   0x04068  /* Packets RX (255-511 bytes) - R/clr */
-#define E1000_PRC1023  0x0406C  /* Packets RX (512-1023 bytes) - R/clr */
-#define E1000_PRC1522  0x04070  /* Packets RX (1024-1522 bytes) - R/clr */
-#define E1000_GPRC     0x04074  /* Good Packets RX Count - R/clr */
-#define E1000_BPRC     0x04078  /* Broadcast Packets RX Count - R/clr */
-#define E1000_MPRC     0x0407C  /* Multicast Packets RX Count - R/clr */
-#define E1000_GPTC     0x04080  /* Good Packets TX Count - R/clr */
-#define E1000_GORCL    0x04088  /* Good Octets RX Count Low - R/clr */
-#define E1000_GORCH    0x0408C  /* Good Octets RX Count High - R/clr */
-#define E1000_GOTCL    0x04090  /* Good Octets TX Count Low - R/clr */
-#define E1000_GOTCH    0x04094  /* Good Octets TX Count High - R/clr */
-#define E1000_RNBC     0x040A0  /* RX No Buffers Count - R/clr */
-#define E1000_RUC      0x040A4  /* RX Undersize Count - R/clr */
-#define E1000_RFC      0x040A8  /* RX Fragment Count - R/clr */
-#define E1000_ROC      0x040AC  /* RX Oversize Count - R/clr */
-#define E1000_RJC      0x040B0  /* RX Jabber Count - R/clr */
-#define E1000_MGTPRC   0x040B4  /* Management Packets RX Count - R/clr */
+#define E1000_XONRXC   0x04048  /* XON Rx Count - R/clr */
+#define E1000_XONTXC   0x0404C  /* XON Tx Count - R/clr */
+#define E1000_XOFFRXC  0x04050  /* XOFF Rx Count - R/clr */
+#define E1000_XOFFTXC  0x04054  /* XOFF Tx Count - R/clr */
+#define E1000_FCRUC    0x04058  /* Flow Control Rx Unsupported Count- R/clr */
+#define E1000_PRC64    0x0405C  /* Packets Rx (64 bytes) - R/clr */
+#define E1000_PRC127   0x04060  /* Packets Rx (65-127 bytes) - R/clr */
+#define E1000_PRC255   0x04064  /* Packets Rx (128-255 bytes) - R/clr */
+#define E1000_PRC511   0x04068  /* Packets Rx (255-511 bytes) - R/clr */
+#define E1000_PRC1023  0x0406C  /* Packets Rx (512-1023 bytes) - R/clr */
+#define E1000_PRC1522  0x04070  /* Packets Rx (1024-1522 bytes) - R/clr */
+#define E1000_GPRC     0x04074  /* Good Packets Rx Count - R/clr */
+#define E1000_BPRC     0x04078  /* Broadcast Packets Rx Count - R/clr */
+#define E1000_MPRC     0x0407C  /* Multicast Packets Rx Count - R/clr */
+#define E1000_GPTC     0x04080  /* Good Packets Tx Count - R/clr */
+#define E1000_GORCL    0x04088  /* Good Octets Rx Count Low - R/clr */
+#define E1000_GORCH    0x0408C  /* Good Octets Rx Count High - R/clr */
+#define E1000_GOTCL    0x04090  /* Good Octets Tx Count Low - R/clr */
+#define E1000_GOTCH    0x04094  /* Good Octets Tx Count High - R/clr */
+#define E1000_RNBC     0x040A0  /* Rx No Buffers Count - R/clr */
+#define E1000_RUC      0x040A4  /* Rx Undersize Count - R/clr */
+#define E1000_RFC      0x040A8  /* Rx Fragment Count - R/clr */
+#define E1000_ROC      0x040AC  /* Rx Oversize Count - R/clr */
+#define E1000_RJC      0x040B0  /* Rx Jabber Count - R/clr */
+#define E1000_MGTPRC   0x040B4  /* Management Packets Rx Count - R/clr */
 #define E1000_MGTPDC   0x040B8  /* Management Packets Dropped Count - R/clr */
-#define E1000_MGTPTC   0x040BC  /* Management Packets TX Count - R/clr */
-#define E1000_TORL     0x040C0  /* Total Octets RX Low - R/clr */
-#define E1000_TORH     0x040C4  /* Total Octets RX High - R/clr */
-#define E1000_TOTL     0x040C8  /* Total Octets TX Low - R/clr */
-#define E1000_TOTH     0x040CC  /* Total Octets TX High - R/clr */
-#define E1000_TPR      0x040D0  /* Total Packets RX - R/clr */
-#define E1000_TPT      0x040D4  /* Total Packets TX - R/clr */
-#define E1000_PTC64    0x040D8  /* Packets TX (64 bytes) - R/clr */
-#define E1000_PTC127   0x040DC  /* Packets TX (65-127 bytes) - R/clr */
-#define E1000_PTC255   0x040E0  /* Packets TX (128-255 bytes) - R/clr */
-#define E1000_PTC511   0x040E4  /* Packets TX (256-511 bytes) - R/clr */
-#define E1000_PTC1023  0x040E8  /* Packets TX (512-1023 bytes) - R/clr */
-#define E1000_PTC1522  0x040EC  /* Packets TX (1024-1522 Bytes) - R/clr */
-#define E1000_MPTC     0x040F0  /* Multicast Packets TX Count - R/clr */
-#define E1000_BPTC     0x040F4  /* Broadcast Packets TX Count - R/clr */
-#define E1000_TSCTC    0x040F8  /* TCP Segmentation Context TX - R/clr */
-#define E1000_TSCTFC   0x040FC  /* TCP Segmentation Context TX Fail - R/clr */
+#define E1000_MGTPTC   0x040BC  /* Management Packets Tx Count - R/clr */
+#define E1000_TORL     0x040C0  /* Total Octets Rx Low - R/clr */
+#define E1000_TORH     0x040C4  /* Total Octets Rx High - R/clr */
+#define E1000_TOTL     0x040C8  /* Total Octets Tx Low - R/clr */
+#define E1000_TOTH     0x040CC  /* Total Octets Tx High - R/clr */
+#define E1000_TPR      0x040D0  /* Total Packets Rx - R/clr */
+#define E1000_TPT      0x040D4  /* Total Packets Tx - R/clr */
+#define E1000_PTC64    0x040D8  /* Packets Tx (64 bytes) - R/clr */
+#define E1000_PTC127   0x040DC  /* Packets Tx (65-127 bytes) - R/clr */
+#define E1000_PTC255   0x040E0  /* Packets Tx (128-255 bytes) - R/clr */
+#define E1000_PTC511   0x040E4  /* Packets Tx (256-511 bytes) - R/clr */
+#define E1000_PTC1023  0x040E8  /* Packets Tx (512-1023 bytes) - R/clr */
+#define E1000_PTC1522  0x040EC  /* Packets Tx (1024-1522 Bytes) - R/clr */
+#define E1000_MPTC     0x040F0  /* Multicast Packets Tx Count - R/clr */
+#define E1000_BPTC     0x040F4  /* Broadcast Packets Tx Count - R/clr */
+#define E1000_TSCTC    0x040F8  /* TCP Segmentation Context Tx - R/clr */
+#define E1000_TSCTFC   0x040FC  /* TCP Segmentation Context Tx Fail - R/clr */
 #define E1000_IAC      0x04100  /* Interrupt Assertion Count */
-#define E1000_ICRXPTC  0x04104  /* Interrupt Cause Rx Packet Timer Expire 
Count */
-#define E1000_ICRXATC  0x04108  /* Interrupt Cause Rx Absolute Timer Expire 
Count */
-#define E1000_ICTXPTC  0x0410C  /* Interrupt Cause Tx Packet Timer Expire 
Count */
-#define E1000_ICTXATC  0x04110  /* Interrupt Cause Tx Absolute Timer Expire 
Count */
+#define E1000_ICRXPTC  0x04104  /* Interrupt Cause Rx Pkt Timer Expire Count */
+#define E1000_ICRXATC  0x04108  /* Interrupt Cause Rx Abs Timer Expire Count */
+#define E1000_ICTXPTC  0x0410C  /* Interrupt Cause Tx Pkt Timer Expire Count */
+#define E1000_ICTXATC  0x04110  /* Interrupt Cause Tx Abs Timer Expire Count */
 #define E1000_ICTXQEC  0x04118  /* Interrupt Cause Tx Queue Empty Count */
-#define E1000_ICTXQMTC 0x0411C  /* Interrupt Cause Tx Queue Minimum Threshold 
Count */
-#define E1000_ICRXDMTC 0x04120  /* Interrupt Cause Rx Descriptor Minimum 
Threshold Count */
+#define E1000_ICTXQMTC 0x0411C  /* Interrupt Cause Tx Queue Min Thresh Count */
+#define E1000_ICRXDMTC 0x04120  /* Interrupt Cause Rx Desc Min Thresh Count */
 #define E1000_ICRXOC   0x04124  /* Interrupt Cause Receiver Overrun Count */
+
+#define E1000_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
+#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_CBTMPC      0x0402C  /* Circuit Breaker TX Packet Count */
+#define E1000_CBTMPC      0x0402C  /* Circuit Breaker Tx Packet Count */
 #define E1000_HTDPMC      0x0403C  /* Host Transmit Discarded Packets */
-#define E1000_CBRDPC      0x04044  /* Circuit Breaker RX Dropped Count */
-#define E1000_CBRMPC      0x040FC  /* Circuit Breaker RX Packet Count */
+#define E1000_CBRDPC      0x04044  /* Circuit Breaker Rx Dropped Count */
+#define E1000_CBRMPC      0x040FC  /* Circuit Breaker Rx Packet Count */
 #define E1000_RPTHC       0x04104  /* Rx Packets To Host */
-#define E1000_HGPTC       0x04118  /* Host Good Packets TX Count */
-#define E1000_HTCBDPC     0x04124  /* Host TX Circuit Breaker Dropped Count */
+#define E1000_HGPTC       0x04118  /* Host Good Packets Tx Count */
+#define E1000_HTCBDPC     0x04124  /* Host Tx Circuit Breaker Dropped Count */
 #define E1000_HGORCL      0x04128  /* Host Good Octets Received Count Low */
 #define E1000_HGORCH      0x0412C  /* Host Good Octets Received Count High */
 #define E1000_HGOTCL      0x04130  /* Host Good Octets Transmit Count Low */
@@ -332,14 +351,14 @@
 #define E1000_PCS_NPTX    0x04220  /* AN Next Page Transmit - RW */
 #define E1000_PCS_LPABNP  0x04224  /* Link Partner Ability Next Page - RW */
 #define E1000_1GSTAT_RCV  0x04228  /* 1GSTAT Code Violation Packet Count - RW 
*/
-#define E1000_RXCSUM   0x05000  /* RX Checksum Control - RW */
-#define E1000_RLPML    0x05004  /* RX Long Packet Max Length */
+#define E1000_RXCSUM   0x05000  /* Rx Checksum Control - RW */
+#define E1000_RLPML    0x05004  /* Rx Long Packet Max Length */
 #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_PSRTYPE  0x05480  /* Packet Split Receive Type - RW */
+#define E1000_RA2      0x054E0  /* 2nd half of receive address array - RW 
Array */
 #define E1000_VFTA     0x05600  /* VLAN Filter Table Array - RW Array */
-#define E1000_VMD_CTL  0x0581C  /* VMDq Control - RW */
+#define E1000_VT_CTL   0x0581C  /* VMDq Control - RW */
 #define E1000_VFQA0    0x0B000  /* VLAN Filter Queue Array 0 - RW Array */
 #define E1000_VFQA1    0x0B200  /* VLAN Filter Queue Array 1 - RW Array */
 #define E1000_WUC      0x05800  /* Wakeup Control - RW */
@@ -351,11 +370,15 @@
 #define E1000_IP6AT    0x05880  /* IPv6 Address Table - RW Array */
 #define E1000_WUPL     0x05900  /* Wakeup Packet Length - RW */
 #define E1000_WUPM     0x05A00  /* Wakeup Packet Memory - RO A */
+#define E1000_PBACL    0x05B68  /* MSIx PBA Clear - Read/Write 1's to clear */
 #define E1000_FFLT     0x05F00  /* Flexible Filter Length Table - 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_MANC2H      0x05860 /* Management Control To Host - RW */
@@ -374,68 +397,102 @@
 #define E1000_DCA_ID    0x05B70 /* DCA Requester ID Information - RO */
 #define E1000_DCA_CTRL  0x05B74 /* DCA Control - RW */
 #define E1000_FFLT_DBG  0x05F04 /* Debug Register */
-#define E1000_HICR      0x08F00 /* Host Inteface Control */
+#define E1000_HICR      0x08F00 /* Host Interface Control */
 
 /* RSS registers */
 #define E1000_CPUVEC    0x02C10 /* CPU Vector Register - RW */
 #define E1000_MRQC      0x05818 /* Multiple Receive Control - RW */
 #define E1000_IMIR(_i)      (0x05A80 + ((_i) * 4))  /* Immediate Interrupt */
 #define E1000_IMIREXT(_i)   (0x05AA0 + ((_i) * 4))  /* Immediate Interrupt 
Ext*/
-#define E1000_IMIRVP    0x05AC0 /* Immediate Interrupt RX VLAN Priority - RW */
-#define E1000_MSIXBM0   0x01600 /* MSI-X Allocation Register 0 - RW */
-#define E1000_MSIXBM1   0x01604 /* MSI-X Allocation Register 1 - RW */
-#define E1000_MSIXBM2   0x01608 /* MSI-X Allocation Register 2 - RW */
-#define E1000_MSIXBM3   0x0160C /* MSI-X Allocation Register 3 - RW */
-#define E1000_MSIXBM4   0x01610 /* MSI-X Allocation Register 4 - RW */
-#define E1000_MSIXBM5   0x01614 /* MSI-X Allocation Register 5 - RW */
-#define E1000_MSIXBM6   0x01618 /* MSI-X Allocation Register 6 - RW */
-#define E1000_MSIXBM7   0x0161C /* MSI-X Allocation Register 7 - RW */
-#define E1000_MSIXBM8   0x01620 /* MSI-X Allocation Register 8 - RW */
-#define E1000_MSIXBM9   0x01624 /* MSI-X Allocation Register 9 - RW */
-#define E1000_MSIXTADD0 0x0C000 /* MSI-X Table entry addr low reg 0 - RW */
-#define E1000_MSIXTADD1 0x0C010 /* MSI-X Table entry addr low reg 1 - RW */
-#define E1000_MSIXTADD2 0x0C020 /* MSI-X Table entry addr low reg 2 - RW */
-#define E1000_MSIXTADD3 0x0C030 /* MSI-X Table entry addr low reg 3 - RW */
-#define E1000_MSIXTADD4 0x0C040 /* MSI-X Table entry addr low reg 4 - RW */
-#define E1000_MSIXTADD5 0x0C050 /* MSI-X Table entry addr low reg 5 - RW */
-#define E1000_MSIXTADD6 0x0C060 /* MSI-X Table entry addr low reg 6 - RW */
-#define E1000_MSIXTADD7 0x0C070 /* MSI-X Table entry addr low reg 7 - RW */
-#define E1000_MSIXTADD8 0x0C080 /* MSI-X Table entry addr low reg 8 - RW */
-#define E1000_MSIXTADD9 0x0C090 /* MSI-X Table entry addr low reg 9 - RW */
-#define E1000_MSIXTUADD0 0x0C004 /* MSI-X Table entry addr upper reg 0 - RW */
-#define E1000_MSIXTUADD1 0x0C014 /* MSI-X Table entry addr upper reg 1 - RW */
-#define E1000_MSIXTUADD2 0x0C024 /* MSI-X Table entry addr upper reg 2 - RW */
-#define E1000_MSIXTUADD3 0x0C034 /* MSI-X Table entry addr upper reg 3 - RW */
-#define E1000_MSIXTUADD4 0x0C044 /* MSI-X Table entry addr upper reg 4 - RW */
-#define E1000_MSIXTUADD5 0x0C054 /* MSI-X Table entry addr upper reg 5 - RW */
-#define E1000_MSIXTUADD6 0x0C064 /* MSI-X Table entry addr upper reg 6 - RW */
-#define E1000_MSIXTUADD7 0x0C074 /* MSI-X Table entry addr upper reg 7 - RW */
-#define E1000_MSIXTUADD8 0x0C084 /* MSI-X Table entry addr upper reg 8 - RW */
-#define E1000_MSIXTUADD9 0x0C094 /* MSI-X Table entry addr upper reg 9 - RW */
-#define E1000_MSIXTMSG0 0x0C008 /* MSI-X Table entry message reg 0 - RW */
-#define E1000_MSIXTMSG1 0x0C018 /* MSI-X Table entry message reg 1 - RW */
-#define E1000_MSIXTMSG2 0x0C028 /* MSI-X Table entry message reg 2 - RW */
-#define E1000_MSIXTMSG3 0x0C038 /* MSI-X Table entry message reg 3 - RW */
-#define E1000_MSIXTMSG4 0x0C048 /* MSI-X Table entry message reg 4 - RW */
-#define E1000_MSIXTMSG5 0x0C058 /* MSI-X Table entry message reg 5 - RW */
-#define E1000_MSIXTMSG6 0x0C068 /* MSI-X Table entry message reg 6 - RW */
-#define E1000_MSIXTMSG7 0x0C078 /* MSI-X Table entry message reg 7 - RW */
-#define E1000_MSIXTMSG8 0x0C088 /* MSI-X Table entry message reg 8 - RW */
-#define E1000_MSIXTMSG9 0x0C098 /* MSI-X Table entry message reg 9 - RW */
-#define E1000_MSIXVCTRL0 0x0C00C /* MSI-X Table entry vector ctrl reg 0 - RW */
-#define E1000_MSIXVCTRL1 0x0C01C /* MSI-X Table entry vector ctrl reg 1 - RW */
-#define E1000_MSIXVCTRL2 0x0C02C /* MSI-X Table entry vector ctrl reg 2 - RW */
-#define E1000_MSIXVCTRL3 0x0C03C /* MSI-X Table entry vector ctrl reg 3 - RW */
-#define E1000_MSIXVCTRL4 0x0C04C /* MSI-X Table entry vector ctrl reg 4 - RW */
-#define E1000_MSIXVCTRL5 0x0C05C /* MSI-X Table entry vector ctrl reg 5 - RW */
-#define E1000_MSIXVCTRL6 0x0C06C /* MSI-X Table entry vector ctrl reg 6 - RW */
-#define E1000_MSIXVCTRL7 0x0C07C /* MSI-X Table entry vector ctrl reg 7 - RW */
-#define E1000_MSIXVCTRL8 0x0C08C /* MSI-X Table entry vector ctrl reg 8 - RW */
-#define E1000_MSIXVCTRL9 0x0C09C /* MSI-X Table entry vector ctrl reg 9 - RW */
+#define E1000_IMIRVP    0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */
+#define E1000_MSIXBM(_i)    (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register
+                                                    * (_i) - RW */
+#define E1000_MSIXTADD(_i)  (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr
+                                                       * low reg - RW */
+#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr
+                                                       * upper reg - RW */
+#define E1000_MSIXTMSG(_i)  (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry
+                                                       * message reg - RW */
+#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry
+                                                       * vector ctrl reg - RW 
*/
 #define E1000_MSIXPBA    0x0E000 /* MSI-X Pending bit array */
-#define E1000_RETA      0x05C00 /* Redirection Table - RW Array */
-#define E1000_RSSRK     0x05C80 /* RSS Random Key - RW Array */
+#define E1000_RETA(_i)  (0x05C00 + ((_i) * 4)) /* Redirection Table - 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_VLVF      0x05D00 /* VLAN Virtual Machine Filter - RW */
+#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 */
+/* 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)))
+/* Time Sync */
+#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
+#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
+#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
+#define E1000_RXSTMPL    0x0B624 /* Rx timestamp Low - RO */
+#define E1000_RXSTMPH    0x0B628 /* Rx timestamp High - RO */
+#define E1000_RXSATRL    0x0B62C /* Rx timestamp attribute low - RO */
+#define E1000_RXSATRH    0x0B630 /* Rx timestamp attribute high - RO */
+#define E1000_TXSTMPL    0x0B618 /* Tx timestamp value Low - RO */
+#define E1000_TXSTMPH    0x0B61C /* Tx timestamp value High - RO */
+#define E1000_SYSTIML    0x0B600 /* System time register Low - RO */
+#define E1000_SYSTIMH    0x0B604 /* System time register High - RO */
+#define E1000_TIMINCA    0x0B608 /* Increment attributes register - RW */
+#define E1000_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_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 */
+
 #endif
Index: dev/em/e1000_api.c
===================================================================
--- dev/em/e1000_api.c  (Revision 28889)
+++ dev/em/e1000_api.c  (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,26 +29,11 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_api.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_api.c,v 1.2 2008/11/26 23:57:23 jfv Exp $*/
 
-
 #include "e1000_api.h"
-#include "e1000_mac.h"
-#include "e1000_nvm.h"
-#include "e1000_phy.h"
 
-#ifndef NO_82542_SUPPORT
-extern void    e1000_init_function_pointers_82542(struct e1000_hw *hw);
-#endif
-extern void    e1000_init_function_pointers_82543(struct e1000_hw *hw);
-extern void    e1000_init_function_pointers_82540(struct e1000_hw *hw);
-extern void    e1000_init_function_pointers_82571(struct e1000_hw *hw);
-extern void    e1000_init_function_pointers_82541(struct e1000_hw *hw);
-extern void    e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw);
-extern void    e1000_init_function_pointers_ich8lan(struct e1000_hw *hw);
-extern void    e1000_init_function_pointers_82575(struct e1000_hw *hw);
-
 /**
  *  e1000_init_mac_params - Initialize MAC function pointers
  *  @hw: pointer to the HW structure
@@ -56,13 +41,12 @@
  *  This function initializes the function pointers for the MAC
  *  set of functions.  Called by drivers or by e1000_setup_init_funcs.
  **/
-s32
-e1000_init_mac_params(struct e1000_hw *hw)
+s32 e1000_init_mac_params(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
 
-       if (hw->func.init_mac_params != NULL) {
-               ret_val = hw->func.init_mac_params(hw);
+       if (hw->mac.ops.init_params) {
+               ret_val = hw->mac.ops.init_params(hw);
                if (ret_val) {
                        DEBUGOUT("MAC Initialization Error\n");
                        goto out;
@@ -83,13 +67,12 @@
  *  This function initializes the function pointers for the NVM
  *  set of functions.  Called by drivers or by e1000_setup_init_funcs.
  **/
-s32
-e1000_init_nvm_params(struct e1000_hw *hw)
+s32 e1000_init_nvm_params(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
 
-       if (hw->func.init_nvm_params != NULL) {
-               ret_val = hw->func.init_nvm_params(hw);
+       if (hw->nvm.ops.init_params) {
+               ret_val = hw->nvm.ops.init_params(hw);
                if (ret_val) {
                        DEBUGOUT("NVM Initialization Error\n");
                        goto out;
@@ -110,13 +93,12 @@
  *  This function initializes the function pointers for the PHY
  *  set of functions.  Called by drivers or by e1000_setup_init_funcs.
  **/
-s32
-e1000_init_phy_params(struct e1000_hw *hw)
+s32 e1000_init_phy_params(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
 
-       if (hw->func.init_phy_params != NULL) {
-               ret_val = hw->func.init_phy_params(hw);
+       if (hw->phy.ops.init_params) {
+               ret_val = hw->phy.ops.init_params(hw);
                if (ret_val) {
                        DEBUGOUT("PHY Initialization Error\n");
                        goto out;
@@ -139,8 +121,7 @@
  *  MUST BE FIRST FUNCTION CALLED (explicitly or through
  *  e1000_setup_init_funcs()).
  **/
-s32
-e1000_set_mac_type(struct e1000_hw *hw)
+s32 e1000_set_mac_type(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val = E1000_SUCCESS;
@@ -148,11 +129,9 @@
        DEBUGFUNC("e1000_set_mac_type");
 
        switch (hw->device_id) {
-#ifndef NO_82542_SUPPORT
        case E1000_DEV_ID_82542:
                mac->type = e1000_82542;
                break;
-#endif
        case E1000_DEV_ID_82543GC_FIBER:
        case E1000_DEV_ID_82543GC_COPPER:
                mac->type = e1000_82543;
@@ -216,6 +195,7 @@
        case E1000_DEV_ID_82571EB_SERDES_DUAL:
        case E1000_DEV_ID_82571EB_SERDES_QUAD:
        case E1000_DEV_ID_82571EB_QUAD_COPPER:
+       case E1000_DEV_ID_82571PT_QUAD_COPPER:
        case E1000_DEV_ID_82571EB_QUAD_FIBER:
        case E1000_DEV_ID_82571EB_QUAD_COPPER_LP:
                mac->type = e1000_82571;
@@ -231,6 +211,9 @@
        case E1000_DEV_ID_82573L:
                mac->type = e1000_82573;
                break;
+       case E1000_DEV_ID_82574L:
+               mac->type = e1000_82574;
+               break;
        case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
        case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
        case E1000_DEV_ID_80003ES2LAN_COPPER_SPT:
@@ -249,17 +232,32 @@
        case E1000_DEV_ID_ICH9_IFE:
        case E1000_DEV_ID_ICH9_IFE_GT:
        case E1000_DEV_ID_ICH9_IFE_G:
+       case E1000_DEV_ID_ICH9_IGP_M:
+       case E1000_DEV_ID_ICH9_IGP_M_AMT:
+       case E1000_DEV_ID_ICH9_IGP_M_V:
        case E1000_DEV_ID_ICH9_IGP_AMT:
+       case E1000_DEV_ID_ICH9_BM:
        case E1000_DEV_ID_ICH9_IGP_C:
+       case E1000_DEV_ID_ICH10_R_BM_LM:
+       case E1000_DEV_ID_ICH10_R_BM_LF:
+       case E1000_DEV_ID_ICH10_R_BM_V:
                mac->type = e1000_ich9lan;
                break;
+       case E1000_DEV_ID_ICH10_D_BM_LM:
+       case E1000_DEV_ID_ICH10_D_BM_LF:
+               mac->type = e1000_ich10lan;
+               break;
        case E1000_DEV_ID_82575EB_COPPER:
        case E1000_DEV_ID_82575EB_FIBER_SERDES:
-       case E1000_DEV_ID_82575EM_COPPER:
-       case E1000_DEV_ID_82575EM_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:
+               mac->type = e1000_82576;
+               break;
        default:
                /* Should never have loaded on this device */
                ret_val = -E1000_ERR_MAC_INIT;
@@ -281,13 +279,11 @@
  *  This function must be called by a driver in order to use the rest
  *  of the 'shared' code files. Called by drivers only.
  **/
-s32
-e1000_setup_init_funcs(struct e1000_hw *hw, boolean_t init_device)
+s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
 {
        s32 ret_val;
 
-       /* Can't do much good without knowing the MAC type.
-        */
+       /* Can't do much good without knowing the MAC type. */
        ret_val = e1000_set_mac_type(hw);
        if (ret_val) {
                DEBUGOUT("ERROR: MAC type could not be set properly.\n");
@@ -300,29 +296,23 @@
                goto out;
        }
 
-       /* Init some generic function pointers that are currently all pointing
-        * to generic implementations. We do this first allowing a driver
-        * module to override it afterwards.
+       /*
+        * Init function pointers to generic implementations. We do this first
+        * allowing a driver module to override it afterward.
         */
-       hw->func.config_collision_dist = e1000_config_collision_dist_generic;
-       hw->func.rar_set = e1000_rar_set_generic;
-       hw->func.validate_mdi_setting = e1000_validate_mdi_setting_generic;
-       hw->func.mng_host_if_write = e1000_mng_host_if_write_generic;
-       hw->func.mng_write_cmd_header = e1000_mng_write_cmd_header_generic;
-       hw->func.mng_enable_host_if = e1000_mng_enable_host_if_generic;
-       hw->func.wait_autoneg = e1000_wait_autoneg_generic;
-       hw->func.reload_nvm = e1000_reload_nvm_generic;
+       e1000_init_mac_ops_generic(hw);
+       e1000_init_phy_ops_generic(hw);
+       e1000_init_nvm_ops_generic(hw);
 
-       /* Set up the init function pointers. These are functions within the
+       /*
+        * Set up the init function pointers. These are functions within the
         * adapter family file that sets up function pointers for the rest of
         * the functions in that family.
         */
        switch (hw->mac.type) {
-#ifndef NO_82542_SUPPORT
        case e1000_82542:
                e1000_init_function_pointers_82542(hw);
                break;
-#endif
        case e1000_82543:
        case e1000_82544:
                e1000_init_function_pointers_82543(hw);
@@ -343,6 +333,7 @@
        case e1000_82571:
        case e1000_82572:
        case e1000_82573:
+       case e1000_82574:
                e1000_init_function_pointers_82571(hw);
                break;
        case e1000_80003es2lan:
@@ -350,9 +341,11 @@
                break;
        case e1000_ich8lan:
        case e1000_ich9lan:
+       case e1000_ich10lan:
                e1000_init_function_pointers_ich8lan(hw);
                break;
        case e1000_82575:
+       case e1000_82576:
                e1000_init_function_pointers_82575(hw);
                break;
        default:
@@ -361,10 +354,11 @@
                break;
        }
 
-       /* Initialize the rest of the function pointers. These require some
+       /*
+        * Initialize the rest of the function pointers. These require some
         * register reads/writes in some cases.
         */
-       if ((ret_val == E1000_SUCCESS) && (init_device == TRUE)) {
+       if (!(ret_val) && init_device) {
                ret_val = e1000_init_mac_params(hw);
                if (ret_val)
                        goto out;
@@ -384,34 +378,19 @@
 }
 
 /**
- *  e1000_remove_device - Free device specific structure
- *  @hw: pointer to the HW structure
- *
- *  If a device specific structure was allocated, this function will
- *  free it. This is a function pointer entry point called by drivers.
- **/
-void
-e1000_remove_device(struct e1000_hw *hw)
-{
-       if (hw->func.remove_device != NULL)
-               hw->func.remove_device(hw);
-}
-
-/**
  *  e1000_get_bus_info - Obtain bus information for adapter
  *  @hw: pointer to the HW structure
  *
  *  This will obtain information about the HW bus for which the
- *  adaper is attached and stores it in the hw structure. This is a
+ *  adapter is attached and stores it in the hw structure. This is a
  *  function pointer entry point called by drivers.
  **/
-s32
-e1000_get_bus_info(struct e1000_hw *hw)
+s32 e1000_get_bus_info(struct e1000_hw *hw)
 {
-       if (hw->func.get_bus_info != NULL)
-               return hw->func.get_bus_info(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->mac.ops.get_bus_info)
+               return hw->mac.ops.get_bus_info(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -421,11 +400,10 @@
  *  This clears the VLAN filter table on the adapter. This is a function
  *  pointer entry point called by drivers.
  **/
-void
-e1000_clear_vfta(struct e1000_hw *hw)
+void e1000_clear_vfta(struct e1000_hw *hw)
 {
-       if (hw->func.clear_vfta != NULL)
-               hw->func.clear_vfta (hw);
+       if (hw->mac.ops.clear_vfta)
+               hw->mac.ops.clear_vfta(hw);
 }
 
 /**
@@ -437,15 +415,14 @@
  *  This writes a 32-bit value to a 32-bit offset in the VLAN filter
  *  table. This is a function pointer entry point called by drivers.
  **/
-void
-e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
+void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
 {
-       if (hw->func.write_vfta != NULL)
-               hw->func.write_vfta(hw, offset, value);
+       if (hw->mac.ops.write_vfta)
+               hw->mac.ops.write_vfta(hw, offset, value);
 }
 
 /**
- *  e1000_mc_addr_list_update - Update Multicast addresses
+ *  e1000_update_mc_addr_list - 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
@@ -459,19 +436,16 @@
  *  exists and all implementations are handled in the generic version of this
  *  function.
  **/
-void
-e1000_mc_addr_list_update(struct e1000_hw *hw,
-                          u8 *mc_addr_list,
-                          u32 mc_addr_count,
-                          u32 rar_used_count,
-                          u32 rar_count)
+void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
+                               u32 mc_addr_count, u32 rar_used_count,
+                               u32 rar_count)
 {
-       if (hw->func.mc_addr_list_update != NULL)
-               hw->func.mc_addr_list_update(hw,
-                                            mc_addr_list,
-                                            mc_addr_count,
-                                            rar_used_count,
-                                            rar_count);
+       if (hw->mac.ops.update_mc_addr_list)
+               hw->mac.ops.update_mc_addr_list(hw,
+                                               mc_addr_list,
+                                               mc_addr_count,
+                                               rar_used_count,
+                                               rar_count);
 }
 
 /**
@@ -482,8 +456,7 @@
  *  and all implementations are handled in the generic version of this
  *  function.
  **/
-s32
-e1000_force_mac_fc(struct e1000_hw *hw)
+s32 e1000_force_mac_fc(struct e1000_hw *hw)
 {
        return e1000_force_mac_fc_generic(hw);
 }
@@ -496,13 +469,12 @@
  *  results in the hw->mac structure. This is a function pointer entry
  *  point called by drivers.
  **/
-s32
-e1000_check_for_link(struct e1000_hw *hw)
+s32 e1000_check_for_link(struct e1000_hw *hw)
 {
-       if (hw->func.check_for_link != NULL)
-               return hw->func.check_for_link(hw);
-       else
-               return -E1000_ERR_CONFIG;
+       if (hw->mac.ops.check_for_link)
+               return hw->mac.ops.check_for_link(hw);
+
+       return -E1000_ERR_CONFIG;
 }
 
 /**
@@ -512,13 +484,12 @@
  *  This checks if the adapter has manageability enabled.
  *  This is a function pointer entry point called by drivers.
  **/
-boolean_t
-e1000_check_mng_mode(struct e1000_hw *hw)
+bool e1000_check_mng_mode(struct e1000_hw *hw)
 {
-       if (hw->func.check_mng_mode != NULL)
-               return hw->func.check_mng_mode(hw);
-       else
-               return FALSE;
+       if (hw->mac.ops.check_mng_mode)
+               return hw->mac.ops.check_mng_mode(hw);
+
+       return FALSE;
 }
 
 /**
@@ -529,8 +500,7 @@
  *
  *  Writes the DHCP information to the host interface.
  **/
-s32
-e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
+s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
 {
        return e1000_mng_write_dhcp_info_generic(hw, buffer, length);
 }
@@ -542,13 +512,12 @@
  *  This resets the hardware into a known state. This is a function pointer
  *  entry point called by drivers.
  **/
-s32
-e1000_reset_hw(struct e1000_hw *hw)
+s32 e1000_reset_hw(struct e1000_hw *hw)
 {
-       if (hw->func.reset_hw != NULL)
-               return hw->func.reset_hw(hw);
-       else
-               return -E1000_ERR_CONFIG;
+       if (hw->mac.ops.reset_hw)
+               return hw->mac.ops.reset_hw(hw);
+
+       return -E1000_ERR_CONFIG;
 }
 
 /**
@@ -558,13 +527,12 @@
  *  This inits the hardware readying it for operation. This is a function
  *  pointer entry point called by drivers.
  **/
-s32
-e1000_init_hw(struct e1000_hw *hw)
+s32 e1000_init_hw(struct e1000_hw *hw)
 {
-       if (hw->func.init_hw != NULL)
-               return hw->func.init_hw(hw);
-       else
-               return -E1000_ERR_CONFIG;
+       if (hw->mac.ops.init_hw)
+               return hw->mac.ops.init_hw(hw);
+
+       return -E1000_ERR_CONFIG;
 }
 
 /**
@@ -575,13 +543,12 @@
  *  is a function pointer entry point called by drivers. While modules can
  *  also call this, they probably call their own version of this function.
  **/
-s32
-e1000_setup_link(struct e1000_hw *hw)
+s32 e1000_setup_link(struct e1000_hw *hw)
 {
-       if (hw->func.setup_link != NULL)
-               return hw->func.setup_link(hw);
-       else
-               return -E1000_ERR_CONFIG;
+       if (hw->mac.ops.setup_link)
+               return hw->mac.ops.setup_link(hw);
+
+       return -E1000_ERR_CONFIG;
 }
 
 /**
@@ -594,13 +561,12 @@
  *  variables passed in. This is a function pointer entry point called
  *  by drivers.
  **/
-s32
-e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
 {
-       if (hw->func.get_link_up_info != NULL)
-               return hw->func.get_link_up_info(hw, speed, duplex);
-       else
-               return -E1000_ERR_CONFIG;
+       if (hw->mac.ops.get_link_up_info)
+               return hw->mac.ops.get_link_up_info(hw, speed, duplex);
+
+       return -E1000_ERR_CONFIG;
 }
 
 /**
@@ -611,13 +577,12 @@
  *  of the LED so it can be later restored. This is a function pointer entry
  *  point called by drivers.
  **/
-s32
-e1000_setup_led(struct e1000_hw *hw)
+s32 e1000_setup_led(struct e1000_hw *hw)
 {
-       if (hw->func.setup_led != NULL)
-               return hw->func.setup_led(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->mac.ops.setup_led)
+               return hw->mac.ops.setup_led(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -627,13 +592,12 @@
  *  This restores the SW controllable LED to the value saved off by
  *  e1000_setup_led. This is a function pointer entry point called by drivers.
  **/
-s32
-e1000_cleanup_led(struct e1000_hw *hw)
+s32 e1000_cleanup_led(struct e1000_hw *hw)
 {
-       if (hw->func.cleanup_led != NULL)
-               return hw->func.cleanup_led(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->mac.ops.cleanup_led)
+               return hw->mac.ops.cleanup_led(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -644,13 +608,12 @@
  *  and cleaned up after. This is a function pointer entry point called by
  *  drivers.
  **/
-s32
-e1000_blink_led(struct e1000_hw *hw)
+s32 e1000_blink_led(struct e1000_hw *hw)
 {
-       if (hw->func.blink_led != NULL)
-               return hw->func.blink_led(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->mac.ops.blink_led)
+               return hw->mac.ops.blink_led(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -660,13 +623,12 @@
  *  Turns the SW defined LED on. This is a function pointer entry point
  *  called by drivers.
  **/
-s32
-e1000_led_on(struct e1000_hw *hw)
+s32 e1000_led_on(struct e1000_hw *hw)
 {
-       if (hw->func.led_on != NULL)
-               return hw->func.led_on(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->mac.ops.led_on)
+               return hw->mac.ops.led_on(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -676,13 +638,12 @@
  *  Turns the SW defined LED off. This is a function pointer entry point
  *  called by drivers.
  **/
-s32
-e1000_led_off(struct e1000_hw *hw)
+s32 e1000_led_off(struct e1000_hw *hw)
 {
-       if (hw->func.led_off != NULL)
-               return hw->func.led_off(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->mac.ops.led_off)
+               return hw->mac.ops.led_off(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -692,8 +653,7 @@
  *  Resets the adaptive IFS. Currently no func pointer exists and all
  *  implementations are handled in the generic version of this function.
  **/
-void
-e1000_reset_adaptive(struct e1000_hw *hw)
+void e1000_reset_adaptive(struct e1000_hw *hw)
 {
        e1000_reset_adaptive_generic(hw);
 }
@@ -705,8 +665,7 @@
  *  Updates adapter IFS. Currently no func pointer exists and all
  *  implementations are handled in the generic version of this function.
  **/
-void
-e1000_update_adaptive(struct e1000_hw *hw)
+void e1000_update_adaptive(struct e1000_hw *hw)
 {
        e1000_update_adaptive_generic(hw);
 }
@@ -719,8 +678,7 @@
  *  requests. Currently no func pointer exists and all implementations are
  *  handled in the generic version of this function.
  **/
-s32
-e1000_disable_pcie_master(struct e1000_hw *hw)
+s32 e1000_disable_pcie_master(struct e1000_hw *hw)
 {
        return e1000_disable_pcie_master_generic(hw);
 }
@@ -732,11 +690,10 @@
  *  Configures the collision distance to the default value and is used
  *  during link setup.
  **/
-void
-e1000_config_collision_dist(struct e1000_hw *hw)
+void e1000_config_collision_dist(struct e1000_hw *hw)
 {
-       if (hw->func.config_collision_dist != NULL)
-               hw->func.config_collision_dist(hw);
+       if (hw->mac.ops.config_collision_dist)
+               hw->mac.ops.config_collision_dist(hw);
 }
 
 /**
@@ -747,11 +704,10 @@
  *
  *  Sets a Receive Address Register (RAR) to the specified address.
  **/
-void
-e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
+void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
 {
-       if (hw->func.rar_set != NULL)
-               hw->func.rar_set(hw, addr, index);
+       if (hw->mac.ops.rar_set)
+               hw->mac.ops.rar_set(hw, addr, index);
 }
 
 /**
@@ -760,13 +716,12 @@
  *
  *  Ensures that the MDI/MDIX SW state is valid.
  **/
-s32
-e1000_validate_mdi_setting(struct e1000_hw *hw)
+s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
 {
-       if (hw->func.validate_mdi_setting != NULL)
-               return hw->func.validate_mdi_setting(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->mac.ops.validate_mdi_setting)
+               return hw->mac.ops.validate_mdi_setting(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -777,11 +732,10 @@
  *  This sets the bit in the multicast table corresponding to the
  *  hash value.  This is a function pointer entry point called by drivers.
  **/
-void
-e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
+void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
 {
-       if (hw->func.mta_set != NULL)
-               hw->func.mta_set(hw, hash_value);
+       if (hw->mac.ops.mta_set)
+               hw->mac.ops.mta_set(hw, hash_value);
 }
 
 /**
@@ -793,8 +747,7 @@
  *  table. Currently no func pointer exists and all implementations
  *  are handled in the generic version of this function.
  **/
-u32
-e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
 {
        return e1000_hash_mc_addr_generic(hw, mc_addr);
 }
@@ -808,8 +761,7 @@
  *  Currently no func pointer exists and all implementations are handled in the
  *  generic version of this function.
  **/
-boolean_t
-e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
 {
        return e1000_enable_tx_pkt_filtering_generic(hw);
 }
@@ -826,15 +778,14 @@
  *  It also does alignment considerations to do the writes in most efficient
  *  way.  Also fills up the sum of the buffer in *buffer parameter.
  **/
-s32
-e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer, u16 length,
-                        u16 offset, u8 *sum)
+s32 e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer, u16 length,
+                            u16 offset, u8 *sum)
 {
-       if (hw->func.mng_host_if_write != NULL)
-               return hw->func.mng_host_if_write(hw, buffer, length, offset,
-                                                 sum);
-       else
-               return E1000_NOT_IMPLEMENTED;
+       if (hw->mac.ops.mng_host_if_write)
+               return hw->mac.ops.mng_host_if_write(hw, buffer, length,
+                                                    offset, sum);
+
+       return E1000_NOT_IMPLEMENTED;
 }
 
 /**
@@ -844,14 +795,13 @@
  *
  *  Writes the command header after does the checksum calculation.
  **/
-s32
-e1000_mng_write_cmd_header(struct e1000_hw *hw,
-                           struct e1000_host_mng_command_header *hdr)
+s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
+                               struct e1000_host_mng_command_header *hdr)
 {
-       if (hw->func.mng_write_cmd_header != NULL)
-               return hw->func.mng_write_cmd_header(hw, hdr);
-       else
-               return E1000_NOT_IMPLEMENTED;
+       if (hw->mac.ops.mng_write_cmd_header)
+               return hw->mac.ops.mng_write_cmd_header(hw, hdr);
+
+       return E1000_NOT_IMPLEMENTED;
 }
 
 /**
@@ -860,17 +810,16 @@
  *
  *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
  *
- *  This function checks whether the HOST IF is enabled for command operaton
+ *  This function checks whether the HOST IF is enabled for command operation
  *  and also checks whether the previous command is completed.  It busy waits
  *  in case of previous command is not completed.
  **/
-s32
-e1000_mng_enable_host_if(struct e1000_hw * hw)
+s32 e1000_mng_enable_host_if(struct e1000_hw * hw)
 {
-       if (hw->func.mng_enable_host_if != NULL)
-               return hw->func.mng_enable_host_if(hw);
-       else
-               return E1000_NOT_IMPLEMENTED;
+       if (hw->mac.ops.mng_enable_host_if)
+               return hw->mac.ops.mng_enable_host_if(hw);
+
+       return E1000_NOT_IMPLEMENTED;
 }
 
 /**
@@ -880,13 +829,12 @@
  *  Waits for autoneg to complete. Currently no func pointer exists and all
  *  implementations are handled in the generic version of this function.
  **/
-s32
-e1000_wait_autoneg(struct e1000_hw *hw)
+s32 e1000_wait_autoneg(struct e1000_hw *hw)
 {
-       if (hw->func.wait_autoneg != NULL)
-               return hw->func.wait_autoneg(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->mac.ops.wait_autoneg)
+               return hw->mac.ops.wait_autoneg(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -896,13 +844,12 @@
  *  Checks if the PHY is in a state that can be reset or if manageability
  *  has it tied up. This is a function pointer entry point called by drivers.
  **/
-s32
-e1000_check_reset_block(struct e1000_hw *hw)
+s32 e1000_check_reset_block(struct e1000_hw *hw)
 {
-       if (hw->func.check_reset_block != NULL)
-               return hw->func.check_reset_block(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->phy.ops.check_reset_block)
+               return hw->phy.ops.check_reset_block(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -914,13 +861,12 @@
  *  Reads the PHY register and returns the value in data.
  *  This is a function pointer entry point called by drivers.
  **/
-s32
-e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-       if (hw->func.read_phy_reg != NULL)
-               return hw->func.read_phy_reg(hw, offset, data);
-       else
-               return E1000_SUCCESS;
+       if (hw->phy.ops.read_reg)
+               return hw->phy.ops.read_reg(hw, offset, data);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -932,16 +878,55 @@
  *  Writes the PHY register at offset with the value in data.
  *  This is a function pointer entry point called by drivers.
  **/
-s32
-e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data)
 {
-       if (hw->func.write_phy_reg != NULL)
-               return hw->func.write_phy_reg(hw, offset, data);
-       else
-               return E1000_SUCCESS;
+       if (hw->phy.ops.write_reg)
+               return hw->phy.ops.write_reg(hw, offset, data);
+
+       return E1000_SUCCESS;
 }
 
 /**
+ *  e1000_release_phy - Generic release PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Return if silicon family does not require a semaphore when accessing the
+ *  PHY.
+ **/
+void e1000_release_phy(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.release)
+               hw->phy.ops.release(hw);
+}
+
+/**
+ *  e1000_acquire_phy - Generic acquire PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Return success if silicon family does not require a semaphore when
+ *  accessing the PHY.
+ **/
+s32 e1000_acquire_phy(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.acquire)
+               return hw->phy.ops.acquire(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_cfg_on_link_up - Configure PHY upon link up
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_cfg_on_link_up(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.cfg_on_link_up)
+               return hw->phy.ops.cfg_on_link_up(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
  *  e1000_read_kmrn_reg - Reads register using Kumeran interface
  *  @hw: pointer to the HW structure
  *  @offset: the register to read
@@ -951,8 +936,7 @@
  *  exists and all implementations are handled in the generic version of
  *  this function.
  **/
-s32
-e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
 {
        return e1000_read_kmrn_reg_generic(hw, offset, data);
 }
@@ -967,8 +951,7 @@
  *  exists and all implementations are handled in the generic version of
  *  this function.
  **/
-s32
-e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
 {
        return e1000_write_kmrn_reg_generic(hw, offset, data);
 }
@@ -981,13 +964,12 @@
  *  hw->phy.min_length and hw->phy.max_length. This is a function pointer
  *  entry point called by drivers.
  **/
-s32
-e1000_get_cable_length(struct e1000_hw *hw)
+s32 e1000_get_cable_length(struct e1000_hw *hw)
 {
-       if (hw->func.get_cable_length != NULL)
-               return hw->func.get_cable_length(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->phy.ops.get_cable_length)
+               return hw->phy.ops.get_cable_length(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -998,13 +980,12 @@
  *  populates hw->phy values with it. This is a function pointer entry
  *  point called by drivers.
  **/
-s32
-e1000_get_phy_info(struct e1000_hw *hw)
+s32 e1000_get_phy_info(struct e1000_hw *hw)
 {
-       if (hw->func.get_phy_info != NULL)
-               return hw->func.get_phy_info(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->phy.ops.get_info)
+               return hw->phy.ops.get_info(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1014,13 +995,12 @@
  *  Performs a hard PHY reset. This is a function pointer entry point called
  *  by drivers.
  **/
-s32
-e1000_phy_hw_reset(struct e1000_hw *hw)
+s32 e1000_phy_hw_reset(struct e1000_hw *hw)
 {
-       if (hw->func.reset_phy != NULL)
-               return hw->func.reset_phy(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->phy.ops.reset)
+               return hw->phy.ops.reset(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1030,36 +1010,34 @@
  *  Performs a soft PHY reset on those that apply. This is a function pointer
  *  entry point called by drivers.
  **/
-s32
-e1000_phy_commit(struct e1000_hw *hw)
+s32 e1000_phy_commit(struct e1000_hw *hw)
 {
-       if (hw->func.commit_phy != NULL)
-               return hw->func.commit_phy(hw);
-       else
-               return E1000_SUCCESS;
+       if (hw->phy.ops.commit)
+               return hw->phy.ops.commit(hw);
+
+       return E1000_SUCCESS;
 }
 
 /**
- *  e1000_set_d3_lplu_state - Sets low power link up state for D0
+ *  e1000_set_d0_lplu_state - Sets low power link up state for D0
  *  @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 D0
- *  and SmartSpeed is disabled when active is true, else clear lplu for D0
+ *  and SmartSpeed is disabled when active is TRUE, else clear lplu for D0
  *  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.  This is a function pointer entry point called by drivers.
  **/
-s32
-e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active)
+s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
 {
-       if (hw->func.set_d0_lplu_state != NULL)
-               return hw->func.set_d0_lplu_state(hw, active);
-       else
-               return E1000_SUCCESS;
+       if (hw->phy.ops.set_d0_lplu_state)
+               return hw->phy.ops.set_d0_lplu_state(hw, active);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1070,19 +1048,18 @@
  *  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 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.  This is a function pointer entry point called by drivers.
  **/
-s32
-e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active)
+s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
 {
-       if (hw->func.set_d3_lplu_state != NULL)
-               return hw->func.set_d3_lplu_state(hw, active);
-       else
-               return E1000_SUCCESS;
+       if (hw->phy.ops.set_d3_lplu_state)
+               return hw->phy.ops.set_d3_lplu_state(hw, active);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1093,26 +1070,27 @@
  *  Currently no func pointer exists and all implementations are handled in the
  *  generic version of this function.
  **/
-s32
-e1000_read_mac_addr(struct e1000_hw *hw)
+s32 e1000_read_mac_addr(struct e1000_hw *hw)
 {
+       if (hw->mac.ops.read_mac_addr)
+               return hw->mac.ops.read_mac_addr(hw);
+
        return e1000_read_mac_addr_generic(hw);
 }
 
 /**
- *  e1000_read_part_num - Read device part number
+ *  e1000_read_pba_num - Read device part number
  *  @hw: pointer to the HW structure
- *  @part_num: pointer to device part number
+ *  @pba_num: pointer to device part number
  *
  *  Reads the product board assembly (PBA) number from the EEPROM and stores
- *  the value in part_num.
+ *  the value in pba_num.
  *  Currently no func pointer exists and all implementations are handled in the
  *  generic version of this function.
  **/
-s32
-e1000_read_part_num(struct e1000_hw *hw, u32 *part_num)
+s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
 {
-       return e1000_read_part_num_generic(hw, part_num);
+       return e1000_read_pba_num_generic(hw, pba_num);
 }
 
 /**
@@ -1122,13 +1100,12 @@
  *  Validates the NVM checksum is correct. This is a function pointer entry
  *  point called by drivers.
  **/
-s32
-e1000_validate_nvm_checksum(struct e1000_hw *hw)
+s32 e1000_validate_nvm_checksum(struct e1000_hw *hw)
 {
-       if (hw->func.validate_nvm != NULL)
-               return hw->func.validate_nvm(hw);
-       else
-               return -E1000_ERR_CONFIG;
+       if (hw->nvm.ops.validate)
+               return hw->nvm.ops.validate(hw);
+
+       return -E1000_ERR_CONFIG;
 }
 
 /**
@@ -1138,13 +1115,12 @@
  *  Updates the NVM checksum. Currently no func pointer exists and all
  *  implementations are handled in the generic version of this function.
  **/
-s32
-e1000_update_nvm_checksum(struct e1000_hw *hw)
+s32 e1000_update_nvm_checksum(struct e1000_hw *hw)
 {
-       if (hw->func.update_nvm != NULL)
-               return hw->func.update_nvm(hw);
-       else
-               return -E1000_ERR_CONFIG;
+       if (hw->nvm.ops.update)
+               return hw->nvm.ops.update(hw);
+
+       return -E1000_ERR_CONFIG;
 }
 
 /**
@@ -1154,11 +1130,10 @@
  *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
  *  extended control register.
  **/
-void
-e1000_reload_nvm(struct e1000_hw *hw)
+void e1000_reload_nvm(struct e1000_hw *hw)
 {
-       if (hw->func.reload_nvm != NULL)
-               hw->func.reload_nvm(hw);
+       if (hw->nvm.ops.reload)
+               hw->nvm.ops.reload(hw);
 }
 
 /**
@@ -1171,13 +1146,12 @@
  *  Reads 16-bit chunks of data from the NVM (EEPROM). This is a function
  *  pointer entry point called by drivers.
  **/
-s32
-e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 {
-       if (hw->func.read_nvm != NULL)
-               return hw->func.read_nvm(hw, offset, words, data);
-       else
-               return -E1000_ERR_CONFIG;
+       if (hw->nvm.ops.read)
+               return hw->nvm.ops.read(hw, offset, words, data);
+
+       return -E1000_ERR_CONFIG;
 }
 
 /**
@@ -1190,13 +1164,12 @@
  *  Writes 16-bit chunks of data to the NVM (EEPROM). This is a function
  *  pointer entry point called by drivers.
  **/
-s32
-e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 {
-       if (hw->func.write_nvm != NULL)
-               return hw->func.write_nvm(hw, offset, words, data);
-       else
-               return E1000_SUCCESS;
+       if (hw->nvm.ops.write)
+               return hw->nvm.ops.write(hw, offset, words, data);
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1209,8 +1182,49 @@
  *  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)
+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
+ *
+ * The phy may be powered down to save power, to turn off link when the
+ * driver is unloaded, or wake on lan is not enabled (among others).
+ **/
+void e1000_power_up_phy(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.power_up)
+               hw->phy.ops.power_up(hw);
+
+       e1000_setup_link(hw);
+}
+
+/**
+ * e1000_power_down_phy - Power down PHY
+ * @hw: pointer to the HW structure
+ *
+ * The phy may be powered down to save power, to turn off link when the
+ * driver is unloaded, or wake on lan is not enabled (among others).
+ **/
+void e1000_power_down_phy(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.power_down)
+               hw->phy.ops.power_down(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: dev/em/e1000_api.h
===================================================================
--- dev/em/e1000_api.h  (Revision 28889)
+++ dev/em/e1000_api.h  (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,104 +29,103 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_api.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_api.h,v 1.2 2008/11/26 23:57:23 jfv Exp $*/
 
-
 #ifndef _E1000_API_H_
 #define _E1000_API_H_
 
 #include "e1000_hw.h"
 
-s32       e1000_set_mac_type(struct e1000_hw *hw);
-s32       e1000_setup_init_funcs(struct e1000_hw *hw, boolean_t 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);
-void      e1000_remove_device(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);
-s32       e1000_force_mac_fc(struct e1000_hw *hw);
-s32       e1000_check_for_link(struct e1000_hw *hw);
-s32       e1000_reset_hw(struct e1000_hw *hw);
-s32       e1000_init_hw(struct e1000_hw *hw);
-s32       e1000_setup_link(struct e1000_hw *hw);
-s32       e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed,
-                                     u16 *duplex);
-s32       e1000_disable_pcie_master(struct e1000_hw *hw);
-void      e1000_config_collision_dist(struct e1000_hw *hw);
-void      e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
-void      e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
-u32       e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
-void      e1000_mc_addr_list_update(struct e1000_hw *hw,
-                                    u8 *mc_addr_list, u32 mc_addr_count,
-                                    u32 rar_used_count, u32 rar_count);
-s32       e1000_setup_led(struct e1000_hw *hw);
-s32       e1000_cleanup_led(struct e1000_hw *hw);
-s32       e1000_check_reset_block(struct e1000_hw *hw);
-s32       e1000_blink_led(struct e1000_hw *hw);
-s32       e1000_led_on(struct e1000_hw *hw);
-s32       e1000_led_off(struct e1000_hw *hw);
-void      e1000_reset_adaptive(struct e1000_hw *hw);
-void      e1000_update_adaptive(struct e1000_hw *hw);
-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);
-s32       e1000_phy_hw_reset(struct e1000_hw *hw);
-s32       e1000_phy_commit(struct e1000_hw *hw);
-s32       e1000_read_mac_addr(struct e1000_hw *hw);
-s32       e1000_read_part_num(struct e1000_hw *hw, u32 *part_num);
-void      e1000_reload_nvm(struct e1000_hw *hw);
-s32       e1000_update_nvm_checksum(struct e1000_hw *hw);
-s32       e1000_validate_nvm_checksum(struct e1000_hw *hw);
-s32       e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 
*data);
-s32       e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
-s32       e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
-s32       e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words,
-                          u16 *data);
-s32       e1000_wait_autoneg(struct e1000_hw *hw);
-s32       e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
-s32       e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active);
-boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
-boolean_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
-boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
-s32       e1000_mng_enable_host_if(struct e1000_hw *hw);
-s32       e1000_mng_host_if_write(struct e1000_hw *hw,
-                                  u8 *buffer, u16 length, u16 offset, u8 *sum);
-s32       e1000_mng_write_cmd_header(struct e1000_hw *hw,
-                                     struct e1000_host_mng_command_header 
*hdr);
-s32       e1000_mng_write_dhcp_info(struct e1000_hw * hw,
+extern void    e1000_init_function_pointers_82542(struct e1000_hw *hw);
+extern void    e1000_init_function_pointers_82543(struct e1000_hw *hw);
+extern void    e1000_init_function_pointers_82540(struct e1000_hw *hw);
+extern void    e1000_init_function_pointers_82571(struct e1000_hw *hw);
+extern void    e1000_init_function_pointers_82541(struct e1000_hw *hw);
+extern void    e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw);
+extern void    e1000_init_function_pointers_ich8lan(struct e1000_hw *hw);
+extern void    e1000_init_function_pointers_82575(struct e1000_hw *hw);
+extern void    e1000_rx_fifo_flush_82575(struct e1000_hw *hw);
+extern void    e1000_init_function_pointers_vf(struct e1000_hw *hw);
+extern void    e1000_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_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);
+s32  e1000_force_mac_fc(struct e1000_hw *hw);
+s32  e1000_check_for_link(struct e1000_hw *hw);
+s32  e1000_reset_hw(struct e1000_hw *hw);
+s32  e1000_init_hw(struct e1000_hw *hw);
+s32  e1000_setup_link(struct e1000_hw *hw);
+s32  e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed,
+                                u16 *duplex);
+s32  e1000_disable_pcie_master(struct e1000_hw *hw);
+void e1000_config_collision_dist(struct e1000_hw *hw);
+void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
+void e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
+u32  e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
+void e1000_update_mc_addr_list(struct e1000_hw *hw,
+                               u8 *mc_addr_list, u32 mc_addr_count,
+                               u32 rar_used_count, u32 rar_count);
+s32  e1000_setup_led(struct e1000_hw *hw);
+s32  e1000_cleanup_led(struct e1000_hw *hw);
+s32  e1000_check_reset_block(struct e1000_hw *hw);
+s32  e1000_blink_led(struct e1000_hw *hw);
+s32  e1000_led_on(struct e1000_hw *hw);
+s32  e1000_led_off(struct e1000_hw *hw);
+void e1000_reset_adaptive(struct e1000_hw *hw);
+void e1000_update_adaptive(struct e1000_hw *hw);
+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);
+s32  e1000_cfg_on_link_up(struct e1000_hw *hw);
+s32  e1000_phy_hw_reset(struct e1000_hw *hw);
+s32  e1000_phy_commit(struct e1000_hw *hw);
+void e1000_power_up_phy(struct e1000_hw *hw);
+void e1000_power_down_phy(struct e1000_hw *hw);
+s32  e1000_read_mac_addr(struct e1000_hw *hw);
+s32  e1000_read_pba_num(struct e1000_hw *hw, u32 *part_num);
+void e1000_reload_nvm(struct e1000_hw *hw);
+s32  e1000_update_nvm_checksum(struct e1000_hw *hw);
+s32  e1000_validate_nvm_checksum(struct e1000_hw *hw);
+s32  e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+s32  e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words,
+                     u16 *data);
+s32  e1000_wait_autoneg(struct e1000_hw *hw);
+s32  e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
+s32  e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
+bool e1000_check_mng_mode(struct e1000_hw *hw);
+bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
+s32  e1000_mng_enable_host_if(struct e1000_hw *hw);
+s32  e1000_mng_host_if_write(struct e1000_hw *hw,
+                             u8 *buffer, u16 length, u16 offset, u8 *sum);
+s32  e1000_mng_write_cmd_header(struct e1000_hw *hw,
+                                struct e1000_host_mng_command_header *hdr);
+s32  e1000_mng_write_dhcp_info(struct e1000_hw * hw,
                                     u8 *buffer, u16 length);
-void      e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
-                                       struct e1000_hw_stats *stats,
-                                       u32 frame_len, u8 *mac_addr);
-void      e1000_set_tbi_compatibility_82543(struct e1000_hw *hw,
-                                            boolean_t state);
-boolean_t e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw);
-#ifndef NO_82542_SUPPORT
-u32       e1000_translate_register_82542(u32 reg);
-#endif
-void      e1000_init_script_state_82541(struct e1000_hw *hw, boolean_t state);
-boolean_t e1000_get_laa_state_82571(struct e1000_hw *hw);
-void      e1000_set_laa_state_82571(struct e1000_hw *hw, boolean_t state);
-void      e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
-                                                      boolean_t state);
-void      e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
-void      e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
+u32  e1000_translate_register_82542(u32 reg);
 
-
-/* TBI_ACCEPT macro definition:
+/*
+ * TBI_ACCEPT macro definition:
  *
  * This macro requires:
  *      adapter = a pointer to struct e1000_hw
- *      status = the 8 bit status field of the RX descriptor with EOP set
- *      error = the 8 bit error field of the RX descriptor with EOP set
- *      length = the sum of all the length fields of the RX descriptors that
+ *      status = the 8 bit status field of the Rx descriptor with EOP set
+ *      error = the 8 bit error field of the Rx descriptor with EOP set
+ *      length = the sum of all the length fields of the Rx descriptors that
  *               make up the current frame
  *      last_byte = the last byte of the frame DMAed by the hardware
  *      max_frame_length = the maximum frame length we want to accept.
@@ -150,14 +149,14 @@
 /* The carrier extension symbol, as received by the NIC. */
 #define CARRIER_EXTENSION   0x0F
 
-#define TBI_ACCEPT(a, status, errors, length, last_byte) \
+#define TBI_ACCEPT(a, status, errors, length, last_byte, min_frame_size, 
max_frame_size) \
     (e1000_tbi_sbp_enabled_82543(a) && \
      (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \
      ((last_byte) == CARRIER_EXTENSION) && \
      (((status) & E1000_RXD_STAT_VP) ? \
-          (((length) > ((a)->mac.min_frame_size - VLAN_TAG_SIZE)) && \
-           ((length) <= ((a)->mac.max_frame_size + 1))) : \
-          (((length) > (a)->mac.min_frame_size) && \
-           ((length) <= ((a)->mac.max_frame_size + VLAN_TAG_SIZE + 1)))))
+          (((length) > (min_frame_size - VLAN_TAG_SIZE)) && \
+           ((length) <= (max_frame_size + 1))) : \
+          (((length) > min_frame_size) && \
+           ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1)))))
 
 #endif
Index: dev/em/e1000_80003es2lan.c
===================================================================
--- dev/em/e1000_80003es2lan.c  (Revision 28889)
+++ dev/em/e1000_80003es2lan.c  (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,54 +29,62 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_80003es2lan.c,v 1.3 2007/05/16 00:14:23 jfv 
Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_80003es2lan.c,v 1.2 2008/11/26 23:57:23 
jfv Exp $*/
 
-/* e1000_80003es2lan
+/*
+ * 80003ES2LAN Gigabit Ethernet Controller (Copper)
+ * 80003ES2LAN Gigabit Ethernet Controller (Serdes)
  */
 
 #include "e1000_api.h"
-#include "e1000_80003es2lan.h"
 
-void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw);
-
-STATIC s32  e1000_init_phy_params_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_init_mac_params_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);
-STATIC void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
-STATIC void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
+static s32  e1000_init_phy_params_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw);
+static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
+static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
+static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
                                                    u32 offset,
                                                    u16 *data);
-STATIC s32  e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
+static s32  e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
                                                     u32 offset,
                                                     u16 data);
-STATIC s32  e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
+static s32  e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
                                         u16 words, u16 *data);
-STATIC s32  e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
+static s32  e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
                                                u16 *duplex);
-STATIC s32  e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_init_hw_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
-STATIC void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_init_hw_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
+static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);
 static s32  e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
 static s32  e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);
 static s32  e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);
+static s32  e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+                                            u16 *data);
+static s32  e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+                                             u16 data);
 static s32  e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw);
 static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
 static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
+static s32  e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw);
+static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
 
-/* A table for the GG82563 cable length where the range is defined
+/*
+ * A table for the GG82563 cable length where the range is defined
  * with a lower bound at "index" and the upper bound at
  * "index + 5".
  */
-static const
-u16 e1000_gg82563_cable_length_table[] =
+static const u16 e1000_gg82563_cable_length_table[] =
          { 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
 #define GG82563_CABLE_LENGTH_TABLE_SIZE \
                 (sizeof(e1000_gg82563_cable_length_table) / \
@@ -85,21 +93,20 @@
 /**
  *  e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_phy_params_80003es2lan");
 
-       if (hw->media_type != e1000_media_type_copper) {
+       if (hw->phy.media_type != e1000_media_type_copper) {
                phy->type        = e1000_phy_none;
                goto out;
+       } else {
+               phy->ops.power_up = e1000_power_up_phy_copper;
+               phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
        }
 
        phy->addr                = 1;
@@ -107,21 +114,23 @@
        phy->reset_delay_us      = 100;
        phy->type                = e1000_phy_gg82563;
 
-       func->acquire_phy        = e1000_acquire_phy_80003es2lan;
-       func->check_polarity     = e1000_check_polarity_m88;
-       func->check_reset_block  = e1000_check_reset_block_generic;
-       func->commit_phy         = e1000_phy_sw_reset_generic;
-       func->get_cfg_done       = e1000_get_cfg_done_80003es2lan;
-       func->get_phy_info       = e1000_get_phy_info_m88;
-       func->release_phy        = e1000_release_phy_80003es2lan;
-       func->reset_phy          = e1000_phy_hw_reset_generic;
-       func->set_d3_lplu_state  = e1000_set_d3_lplu_state_generic;
+       phy->ops.acquire            = e1000_acquire_phy_80003es2lan;
+       phy->ops.check_polarity     = e1000_check_polarity_m88;
+       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_80003es2lan;
+       phy->ops.get_info           = e1000_get_phy_info_m88;
+       phy->ops.release            = e1000_release_phy_80003es2lan;
+       phy->ops.reset              = e1000_phy_hw_reset_generic;
+       phy->ops.set_d3_lplu_state  = e1000_set_d3_lplu_state_generic;
 
-       func->force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan;
-       func->get_cable_length   = e1000_get_cable_length_80003es2lan;
-       func->read_phy_reg       = e1000_read_phy_reg_gg82563_80003es2lan;
-       func->write_phy_reg      = e1000_write_phy_reg_gg82563_80003es2lan;
+       phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan;
+       phy->ops.get_cable_length   = e1000_get_cable_length_80003es2lan;
+       phy->ops.read_reg           = e1000_read_phy_reg_gg82563_80003es2lan;
+       phy->ops.write_reg          = e1000_write_phy_reg_gg82563_80003es2lan;
 
+       phy->ops.cfg_on_link_up    = e1000_cfg_on_link_up_80003es2lan;
+
        /* This can only be done after all function pointers are setup. */
        ret_val = e1000_get_phy_id(hw);
 
@@ -138,14 +147,10 @@
 /**
  *  e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_functions *func = &hw->func;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
        u16 size;
 
@@ -173,20 +178,25 @@
        size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
                          E1000_EECD_SIZE_EX_SHIFT);
 
-       /* Added to a constant, "size" becomes the left-shift value
+       /*
+        * Added to a constant, "size" becomes the left-shift value
         * for setting word_size.
         */
        size += NVM_WORD_SIZE_BASE_SHIFT;
+
+       /* EEPROM access above 16k is unsupported */
+       if (size > 14)
+               size = 14;
        nvm->word_size  = 1 << size;
 
        /* Function Pointers */
-       func->acquire_nvm       = e1000_acquire_nvm_80003es2lan;
-       func->read_nvm          = e1000_read_nvm_eerd;
-       func->release_nvm       = e1000_release_nvm_80003es2lan;
-       func->update_nvm        = e1000_update_nvm_checksum_generic;
-       func->valid_led_default = e1000_valid_led_default_generic;
-       func->validate_nvm      = e1000_validate_nvm_checksum_generic;
-       func->write_nvm         = e1000_write_nvm_80003es2lan;
+       nvm->ops.acquire           = e1000_acquire_nvm_80003es2lan;
+       nvm->ops.read              = e1000_read_nvm_eerd;
+       nvm->ops.release           = e1000_release_nvm_80003es2lan;
+       nvm->ops.update            = e1000_update_nvm_checksum_generic;
+       nvm->ops.valid_led_default = e1000_valid_led_default_generic;
+       nvm->ops.validate          = e1000_validate_nvm_checksum_generic;
+       nvm->ops.write             = e1000_write_nvm_80003es2lan;
 
        return E1000_SUCCESS;
 }
@@ -194,14 +204,10 @@
 /**
  *  e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_mac_params_80003es2lan");
@@ -209,10 +215,10 @@
        /* Set media type */
        switch (hw->device_id) {
        case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
-               hw->media_type = e1000_media_type_internal_serdes;
+               hw->phy.media_type = e1000_media_type_internal_serdes;
                break;
        default:
-               hw->media_type = e1000_media_type_copper;
+               hw->phy.media_type = e1000_media_type_copper;
                break;
        }
 
@@ -230,28 +236,28 @@
        /* Function pointers */
 
        /* bus type/speed/width */
-       func->get_bus_info = e1000_get_bus_info_pcie_generic;
+       mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
        /* reset */
-       func->reset_hw = e1000_reset_hw_80003es2lan;
+       mac->ops.reset_hw = e1000_reset_hw_80003es2lan;
        /* hw initialization */
-       func->init_hw = e1000_init_hw_80003es2lan;
+       mac->ops.init_hw = e1000_init_hw_80003es2lan;
        /* link setup */
-       func->setup_link = e1000_setup_link_generic;
+       mac->ops.setup_link = e1000_setup_link_generic;
        /* physical interface link setup */
-       func->setup_physical_interface =
-               (hw->media_type == e1000_media_type_copper)
+       mac->ops.setup_physical_interface =
+               (hw->phy.media_type == e1000_media_type_copper)
                        ? e1000_setup_copper_link_80003es2lan
                        : e1000_setup_fiber_serdes_link_generic;
        /* check for link */
-       switch (hw->media_type) {
+       switch (hw->phy.media_type) {
        case e1000_media_type_copper:
-               func->check_for_link = e1000_check_for_copper_link_generic;
+               mac->ops.check_for_link = e1000_check_for_copper_link_generic;
                break;
        case e1000_media_type_fiber:
-               func->check_for_link = e1000_check_for_fiber_link_generic;
+               mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
                break;
        case e1000_media_type_internal_serdes:
-               func->check_for_link = e1000_check_for_serdes_link_generic;
+               mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
                break;
        default:
                ret_val = -E1000_ERR_CONFIG;
@@ -259,30 +265,30 @@
                break;
        }
        /* check management mode */
-       func->check_mng_mode = e1000_check_mng_mode_generic;
+       mac->ops.check_mng_mode = e1000_check_mng_mode_generic;
        /* multicast address update */
-       func->mc_addr_list_update = e1000_mc_addr_list_update_generic;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
        /* writing VFTA */
-       func->write_vfta = e1000_write_vfta_generic;
+       mac->ops.write_vfta = e1000_write_vfta_generic;
        /* clearing VFTA */
-       func->clear_vfta = e1000_clear_vfta_generic;
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
        /* setting MTA */
-       func->mta_set = e1000_mta_set_generic;
+       mac->ops.mta_set = e1000_mta_set_generic;
+       /* read mac address */
+       mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan;
        /* blink LED */
-       func->blink_led = e1000_blink_led_generic;
+       mac->ops.blink_led = e1000_blink_led_generic;
        /* setup LED */
-       func->setup_led = e1000_setup_led_generic;
+       mac->ops.setup_led = e1000_setup_led_generic;
        /* cleanup LED */
-       func->cleanup_led = e1000_cleanup_led_generic;
+       mac->ops.cleanup_led = e1000_cleanup_led_generic;
        /* turn on/off LED */
-       func->led_on = e1000_led_on_generic;
-       func->led_off = e1000_led_off_generic;
-       /* remove device */
-       func->remove_device = e1000_remove_device_generic;
+       mac->ops.led_on = e1000_led_on_generic;
+       mac->ops.led_off = e1000_led_off_generic;
        /* clear hardware counters */
-       func->clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan;
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan;
        /* link info */
-       func->get_link_up_info = e1000_get_link_up_info_80003es2lan;
+       mac->ops.get_link_up_info = e1000_get_link_up_info_80003es2lan;
 
 out:
        return ret_val;
@@ -292,35 +298,31 @@
  *  e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs.
  *  @hw: pointer to the HW structure
  *
- *  The only function explicitly called by the api module to initialize
- *  all function pointers and parameters.
+ *  Called to initialize all function pointers and parameters.
  **/
-void
-e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw)
+void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_init_function_pointers_80003es2lan");
 
-       hw->func.init_mac_params = e1000_init_mac_params_80003es2lan;
-       hw->func.init_nvm_params = e1000_init_nvm_params_80003es2lan;
-       hw->func.init_phy_params = e1000_init_phy_params_80003es2lan;
+       hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan;
+       hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan;
+       e1000_get_bus_info_pcie_generic(hw);
 }
 
 /**
  *  e1000_acquire_phy_80003es2lan - Acquire rights to access PHY
  *  @hw: pointer to the HW structure
  *
- *  A wrapper to acquire access rights to the correct PHY.  This is a
- *  function pointer entry point called by the api module.
+ *  A wrapper to acquire access rights to the correct PHY.
  **/
-STATIC s32
-e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
 {
        u16 mask;
 
        DEBUGFUNC("e1000_acquire_phy_80003es2lan");
 
        mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
-
        return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
 }
 
@@ -328,11 +330,9 @@
  *  e1000_release_phy_80003es2lan - Release rights to access PHY
  *  @hw: pointer to the HW structure
  *
- *  A wrapper to release access rights to the correct PHY.  This is a
- *  function pointer entry point called by the api module.
+ *  A wrapper to release access rights to the correct PHY.
  **/
-STATIC void
-e1000_release_phy_80003es2lan(struct e1000_hw *hw)
+static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
 {
        u16 mask;
 
@@ -342,15 +342,49 @@
        e1000_release_swfw_sync_80003es2lan(hw, mask);
 }
 
+
 /**
+ *  e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran 
register
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the semaphore to access the Kumeran interface.
+ *
+ **/
+static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
+{
+       u16 mask;
+
+       DEBUGFUNC("e1000_acquire_mac_csr_80003es2lan");
+
+       mask = E1000_SWFW_CSR_SM;
+
+       return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
+}
+
+/**
+ *  e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran 
Register
+ *  @hw: pointer to the HW structure
+ *
+ *  Release the semaphore used to access the Kumeran interface
+ **/
+static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw)
+{
+       u16 mask;
+
+       DEBUGFUNC("e1000_release_mac_csr_80003es2lan");
+
+       mask = E1000_SWFW_CSR_SM;
+
+       e1000_release_swfw_sync_80003es2lan(hw, mask);
+}
+
+/**
  *  e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM
  *  @hw: pointer to the HW structure
  *
- *  Acquire the semaphore to access the EEPROM.  This is a function
- *  pointer entry point called by the api module.
+ *  Acquire the semaphore to access the EEPROM.
  **/
-STATIC s32
-e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw)
 {
        s32 ret_val;
 
@@ -373,11 +407,9 @@
  *  e1000_release_nvm_80003es2lan - Relinquish rights to access NVM
  *  @hw: pointer to the HW structure
  *
- *  Release the semaphore used to access the EEPROM.  This is a
- *  function pointer entry point called by the api module.
+ *  Release the semaphore used to access the EEPROM.
  **/
-STATIC void
-e1000_release_nvm_80003es2lan(struct e1000_hw *hw)
+static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_release_nvm_80003es2lan");
 
@@ -393,14 +425,13 @@
  *  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_80003es2lan(struct e1000_hw *hw, u16 mask)
+static s32 e1000_acquire_swfw_sync_80003es2lan(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;
+       s32 i = 0, timeout = 50;
 
        DEBUGFUNC("e1000_acquire_swfw_sync_80003es2lan");
 
@@ -414,8 +445,10 @@
                if (!(swfw_sync & (fwmask | swmask)))
                        break;
 
-               /* Firmware currently using resource (fwmask)
-                * or other software thread using resource (swmask) */
+               /*
+                * Firmware currently using resource (fwmask)
+                * or other software thread using resource (swmask)
+                */
                e1000_put_hw_semaphore_generic(hw);
                msec_delay_irq(5);
                i++;
@@ -444,15 +477,14 @@
  *  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_80003es2lan(struct e1000_hw *hw, u16 mask)
+static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
 {
        u32 swfw_sync;
 
        DEBUGFUNC("e1000_release_swfw_sync_80003es2lan");
 
-       while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS);
-       /* Empty */
+       while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS)
+               ; /* Empty */
 
        swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
        swfw_sync &= ~mask;
@@ -467,12 +499,10 @@
  *  @offset: offset of the register to read
  *  @data: pointer to the data returned from the operation
  *
- *  Read the GG82563 PHY register.  This is a function pointer entry
- *  point called by the api module.
+ *  Read the GG82563 PHY register.
  **/
-STATIC s32
-e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset,
-                                       u16 *data)
+static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
+                                                  u32 offset, u16 *data)
 {
        s32 ret_val;
        u32 page_select;
@@ -480,42 +510,51 @@
 
        DEBUGFUNC("e1000_read_phy_reg_gg82563_80003es2lan");
 
+       ret_val = e1000_acquire_phy_80003es2lan(hw);
+       if (ret_val)
+               goto out;
+
        /* Select Configuration Page */
-       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
+       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
                page_select = GG82563_PHY_PAGE_SELECT;
-       else {
-               /* Use Alternative Page Select register to access
+       } else {
+               /*
+                * Use Alternative Page Select register to access
                 * registers 30 and 31
                 */
                page_select = GG82563_PHY_PAGE_SELECT_ALT;
        }
 
        temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
-       ret_val = e1000_write_phy_reg_m88(hw, page_select, temp);
-       if (ret_val)
+       ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
+       if (ret_val) {
+               e1000_release_phy_80003es2lan(hw);
                goto out;
+       }
 
-       /* The "ready" bit in the MDIC register may be incorrectly set
+       /*
+        * The "ready" bit in the MDIC register may be incorrectly set
         * before the device has completed the "Page Select" MDI
         * transaction.  So we wait 200us after each MDI command...
         */
        usec_delay(200);
 
        /* ...and verify the command was successful. */
-       ret_val = e1000_read_phy_reg_m88(hw, page_select, &temp);
+       ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
 
        if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
                ret_val = -E1000_ERR_PHY;
+               e1000_release_phy_80003es2lan(hw);
                goto out;
        }
 
        usec_delay(200);
 
-       ret_val = e1000_read_phy_reg_m88(hw,
-                                        MAX_PHY_REG_ADDRESS & offset,
-                                        data);
+       ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
 
        usec_delay(200);
+       e1000_release_phy_80003es2lan(hw);
 
 out:
        return ret_val;
@@ -527,12 +566,10 @@
  *  @offset: offset of the register to read
  *  @data: value to write to the register
  *
- *  Write to the GG82563 PHY register.  This is a function pointer entry
- *  point called by the api module.
+ *  Write to the GG82563 PHY register.
  **/
-STATIC s32
-e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset,
-                                        u16 data)
+static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
+                                                   u32 offset, u16 data)
 {
        s32 ret_val;
        u32 page_select;
@@ -540,43 +577,52 @@
 
        DEBUGFUNC("e1000_write_phy_reg_gg82563_80003es2lan");
 
+       ret_val = e1000_acquire_phy_80003es2lan(hw);
+       if (ret_val)
+               goto out;
+
        /* Select Configuration Page */
-       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
+       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
                page_select = GG82563_PHY_PAGE_SELECT;
-       else {
-               /* Use Alternative Page Select register to access
+       } else {
+               /*
+                * Use Alternative Page Select register to access
                 * registers 30 and 31
                 */
                page_select = GG82563_PHY_PAGE_SELECT_ALT;
        }
 
        temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
-       ret_val = e1000_write_phy_reg_m88(hw, page_select, temp);
-       if (ret_val)
+       ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
+       if (ret_val) {
+               e1000_release_phy_80003es2lan(hw);
                goto out;
+       }
 
 
-       /* The "ready" bit in the MDIC register may be incorrectly set
+       /*
+        * The "ready" bit in the MDIC register may be incorrectly set
         * before the device has completed the "Page Select" MDI
         * transaction.  So we wait 200us after each MDI command...
         */
        usec_delay(200);
 
        /* ...and verify the command was successful. */
-       ret_val = e1000_read_phy_reg_m88(hw, page_select, &temp);
+       ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
 
        if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
                ret_val = -E1000_ERR_PHY;
+               e1000_release_phy_80003es2lan(hw);
                goto out;
        }
 
        usec_delay(200);
 
-       ret_val = e1000_write_phy_reg_m88(hw,
-                                         MAX_PHY_REG_ADDRESS & offset,
+       ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                          data);
 
        usec_delay(200);
+       e1000_release_phy_80003es2lan(hw);
 
 out:
        return ret_val;
@@ -589,11 +635,9 @@
  *  @words: number of words to write
  *  @data: buffer of data to write to the NVM
  *
- *  Write "words" of data to the ESB2 NVM.  This is a function
- *  pointer entry point called by the api module.
+ *  Write "words" of data to the ESB2 NVM.
  **/
-STATIC s32
-e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
+static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
                             u16 words, u16 *data)
 {
        DEBUGFUNC("e1000_write_nvm_80003es2lan");
@@ -608,8 +652,7 @@
  *  Wait a specific amount of time for manageability processes to complete.
  *  This is a function pointer entry point called by the phy module.
  **/
-STATIC s32
-e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw)
 {
        s32 timeout = PHY_CFG_TIMEOUT;
        s32 ret_val = E1000_SUCCESS;
@@ -643,30 +686,33 @@
  *  Force the speed and duplex settings onto the PHY.  This is a
  *  function pointer entry point called by the phy module.
  **/
-STATIC s32
-e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
 {
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u16 phy_data;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_phy_force_speed_duplex_80003es2lan");
 
-       /* Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
+       if (!(hw->phy.ops.read_reg))
+               goto out;
+
+       /*
+        * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
         * forced whenever speed and duplex are forced.
         */
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+       ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
                goto out;
 
        phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO;
-       ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
+       ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
        if (ret_val)
                goto out;
 
        DEBUGOUT1("GG82563 PSCR: %X\n", phy_data);
 
-       ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &phy_data);
+       ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data);
        if (ret_val)
                goto out;
 
@@ -675,13 +721,13 @@
        /* Reset the phy to commit changes. */
        phy_data |= MII_CR_RESET;
 
-       ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, phy_data);
+       ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data);
        if (ret_val)
                goto out;
 
        usec_delay(1);
 
-       if (hw->phy.wait_for_link) {
+       if (hw->phy.autoneg_wait_to_complete) {
                DEBUGOUT("Waiting for forced speed/duplex link "
                         "on GG82563 phy.\n");
 
@@ -691,7 +737,8 @@
                        goto out;
 
                if (!link) {
-                       /* We didn't get link.
+                       /*
+                        * We didn't get link.
                         * Reset the DSP and cross our fingers.
                         */
                        ret_val = e1000_phy_reset_dsp_generic(hw);
@@ -706,11 +753,12 @@
                        goto out;
        }
 
-       ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data);
+       ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, 
&phy_data);
        if (ret_val)
                goto out;
 
-       /* Resetting the phy means we need to verify the TX_CLK corresponds
+       /*
+        * Resetting the phy means we need to verify the TX_CLK corresponds
         * to the link speed.  10Mbps -> 2.5MHz, else 25MHz.
         */
        phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
@@ -719,11 +767,12 @@
        else
                phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
 
-       /* In addition, we must re-enable CRS on Tx for both half and full
+       /*
+        * In addition, we must re-enable CRS on Tx for both half and full
         * duplex.
         */
        phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
-       ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data);
+       ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, 
phy_data);
 
 out:
        return ret_val;
@@ -736,25 +785,34 @@
  *  Find the approximate cable length as measured by the GG82563 PHY.
  *  This is a function pointer entry point called by the phy module.
  **/
-STATIC s32
-e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u16 phy_data, index;
 
        DEBUGFUNC("e1000_get_cable_length_80003es2lan");
 
-       ret_val = e1000_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
+       if (!(hw->phy.ops.read_reg))
+               goto out;
+
+       ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
        if (ret_val)
                goto out;
 
        index = phy_data & GG82563_DSPD_CABLE_LENGTH;
-       phy->min_cable_length = e1000_gg82563_cable_length_table[index];
-       phy->max_cable_length = e1000_gg82563_cable_length_table[index+5];
 
-       phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
+       if (index < GG82563_CABLE_LENGTH_TABLE_SIZE + 5) {
+               phy->min_cable_length = e1000_gg82563_cable_length_table[index];
+               phy->max_cable_length =
+                                e1000_gg82563_cable_length_table[index+5];
 
+               phy->cable_length = (phy->min_cable_length +
+                                    phy->max_cable_length) / 2;
+       } else {
+               ret_val = E1000_ERR_PHY;
+       }
+
 out:
        return ret_val;
 }
@@ -766,32 +824,25 @@
  *  @duplex: pointer to duplex buffer
  *
  *  Retrieve the current speed and duplex configuration.
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, u16 
*duplex)
+static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
+                                              u16 *duplex)
 {
        s32 ret_val;
 
        DEBUGFUNC("e1000_get_link_up_info_80003es2lan");
 
-       if (hw->media_type == e1000_media_type_copper) {
+       if (hw->phy.media_type == e1000_media_type_copper) {
                ret_val = e1000_get_speed_and_duplex_copper_generic(hw,
                                                                    speed,
                                                                    duplex);
-               if (ret_val)
-                       goto out;
-               if (*speed == SPEED_1000)
-                       ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
-               else
-                       ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw,
-                                                             *duplex);
-       } else
+               hw->phy.ops.cfg_on_link_up(hw);
+       } else {
                ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw,
                                                                  speed,
                                                                  duplex);
+       }
 
-out:
        return ret_val;
 }
 
@@ -800,23 +851,21 @@
  *  @hw: pointer to the HW structure
  *
  *  Perform a global reset to the ESB2 controller.
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
 {
        u32 ctrl, icr;
        s32 ret_val;
 
        DEBUGFUNC("e1000_reset_hw_80003es2lan");
 
-       /* Prevent the PCI-E bus from sticking if there is no TLP connection
+       /*
+        * 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) {
+       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);
@@ -829,8 +878,10 @@
 
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
 
+       ret_val = e1000_acquire_phy_80003es2lan(hw);
        DEBUGOUT("Issuing a global reset to MAC\n");
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+       e1000_release_phy_80003es2lan(hw);
 
        ret_val = e1000_get_auto_rd_done_generic(hw);
        if (ret_val)
@@ -841,6 +892,8 @@
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
        icr = E1000_READ_REG(hw, E1000_ICR);
 
+       e1000_check_alt_mac_addr_generic(hw);
+
 out:
        return ret_val;
 }
@@ -850,10 +903,8 @@
  *  @hw: pointer to the HW structure
  *
  *  Initialize the hw bits, LED, VFTA, MTA, link and hw counters.
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_hw_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 reg_data;
@@ -868,12 +919,12 @@
        ret_val = e1000_id_led_init_generic(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
-               goto out;
+               /* This is not fatal and we should not stop init due to this */
        }
 
        /* Disabling VLAN filtering */
        DEBUGOUT("Initializing the IEEE VLAN\n");
-       e1000_clear_vfta(hw);
+       mac->ops.clear_vfta(hw);
 
        /* Setup the receive address. */
        e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
@@ -884,19 +935,19 @@
                E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
 
        /* Setup link and flow control */
-       ret_val = e1000_setup_link(hw);
+       ret_val = mac->ops.setup_link(hw);
 
        /* Set the transmit descriptor write-back policy */
-       reg_data = E1000_READ_REG(hw, E1000_TXDCTL);
+       reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
        reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
                   E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
-       E1000_WRITE_REG(hw, E1000_TXDCTL, reg_data);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
 
        /* ...for both queues. */
-       reg_data = E1000_READ_REG(hw, E1000_TXDCTL1);
+       reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
        reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
                   E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
-       E1000_WRITE_REG(hw, E1000_TXDCTL1, reg_data);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
 
        /* Enable retransmit on late collisions */
        reg_data = E1000_READ_REG(hw, E1000_TCTL);
@@ -919,14 +970,14 @@
        reg_data &= ~0x00100000;
        E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data);
 
-       /* Clear all of the statistics registers (clear on read).  It is
+       /*
+        * 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_80003es2lan(hw);
 
-out:
        return ret_val;
 }
 
@@ -936,42 +987,37 @@
  *
  *  Initializes required hardware-dependent bits needed for normal operation.
  **/
-static void
-e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
+static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
 {
        u32 reg;
 
        DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan");
 
-       if (hw->mac.disable_hw_init_bits)
-               goto out;
-
        /* Transmit Descriptor Control 0 */
-       reg = E1000_READ_REG(hw, E1000_TXDCTL);
+       reg = E1000_READ_REG(hw, E1000_TXDCTL(0));
        reg |= (1 << 22);
-       E1000_WRITE_REG(hw, E1000_TXDCTL, reg);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg);
 
        /* Transmit Descriptor Control 1 */
-       reg = E1000_READ_REG(hw, E1000_TXDCTL1);
+       reg = E1000_READ_REG(hw, E1000_TXDCTL(1));
        reg |= (1 << 22);
-       E1000_WRITE_REG(hw, E1000_TXDCTL1, reg);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg);
 
        /* Transmit Arbitration Control 0 */
-       reg = E1000_READ_REG(hw, E1000_TARC0);
+       reg = E1000_READ_REG(hw, E1000_TARC(0));
        reg &= ~(0xF << 27); /* 30:27 */
-       if (hw->media_type != e1000_media_type_copper)
+       if (hw->phy.media_type != e1000_media_type_copper)
                reg &= ~(1 << 20);
-       E1000_WRITE_REG(hw, E1000_TARC0, reg);
+       E1000_WRITE_REG(hw, E1000_TARC(0), reg);
 
        /* Transmit Arbitration Control 1 */
-       reg = E1000_READ_REG(hw, E1000_TARC1);
+       reg = E1000_READ_REG(hw, E1000_TARC(1));
        if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR)
                reg &= ~(1 << 28);
        else
                reg |= (1 << 28);
-       E1000_WRITE_REG(hw, E1000_TARC1, reg);
+       E1000_WRITE_REG(hw, E1000_TARC(1), reg);
 
-out:
        return;
 }
 
@@ -981,18 +1027,17 @@
  *
  *  Setup some GG82563 PHY registers for obtaining link
  **/
-static s32
-e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
 {
-       struct   e1000_phy_info *phy = &hw->phy;
-       s32  ret_val;
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
        u32 ctrl_ext;
        u16 data;
 
        DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan");
 
        if (!phy->reset_disable) {
-               ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+               ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
                                             &data);
                if (ret_val)
                        goto out;
@@ -1001,19 +1046,20 @@
                /* Use 25MHz for both link down and 1000Base-T for Tx clock. */
                data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
 
-               ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+               ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
                                              data);
                if (ret_val)
                        goto out;
 
-               /* Options:
+               /*
+                * 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)
                 */
-               ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &data);
+               ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, 
&data);
                if (ret_val)
                        goto out;
 
@@ -1032,22 +1078,23 @@
                        break;
                }
 
-               /* Options:
+               /*
+                * Options:
                 *   disable_polarity_correction = 0 (default)
                 *       Automatic Correction for Reversed Cable Polarity
                 *   0 - Disabled
                 *   1 - Enabled
                 */
                data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
-               if (phy->disable_polarity_correction == TRUE)
+               if (phy->disable_polarity_correction)
                        data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
 
-               ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, data);
+               ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, 
data);
                if (ret_val)
                        goto out;
 
                /* SW Reset the PHY so all changes take effect */
-               ret_val = e1000_phy_commit(hw);
+               ret_val = hw->phy.ops.commit(hw);
                if (ret_val) {
                        DEBUGOUT("Error Resetting the PHY\n");
                        goto out;
@@ -1055,20 +1102,32 @@
 
        }
 
-       /* Bypass RX and TX FIFO's */
-       ret_val = e1000_write_kmrn_reg(hw,
+       /* Bypass Rx and Tx FIFO's */
+       ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
                                E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
                                E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
                                        E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data);
+       ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
+                                     E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
+                                     &data);
        if (ret_val)
                goto out;
+       data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
+       ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+                                      E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
+                                      data);
+       if (ret_val)
+               goto out;
 
+       ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data);
+       if (ret_val)
+               goto out;
+
        data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
-       ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, data);
+       ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data);
        if (ret_val)
                goto out;
 
@@ -1076,47 +1135,48 @@
        ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
        E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
 
-       ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
+       ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
        if (ret_val)
                goto out;
 
-       /* Do not init these registers when the HW is in IAMT mode, since the
+       /*
+        * Do not init these registers when the HW is in IAMT mode, since the
         * firmware will have already initialized them.  We only initialize
         * them if the HW is not in IAMT mode.
         */
-       if (e1000_check_mng_mode(hw) == FALSE) {
+       if (!(hw->mac.ops.check_mng_mode(hw))) {
                /* Enable Electrical Idle on the PHY */
                data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
-               ret_val = e1000_write_phy_reg(hw,
-                                            GG82563_PHY_PWR_MGMT_CTRL,
-                                            data);
+               ret_val = hw->phy.ops.write_reg(hw,
+                                               GG82563_PHY_PWR_MGMT_CTRL,
+                                               data);
                if (ret_val)
                        goto out;
+               ret_val = hw->phy.ops.read_reg(hw,
+                                              GG82563_PHY_KMRN_MODE_CTRL,
+                                              &data);
+                       if (ret_val)
+                               goto out;
 
-               ret_val = e1000_read_phy_reg(hw,
-                                           GG82563_PHY_KMRN_MODE_CTRL,
-                                           &data);
-               if (ret_val)
-                       goto out;
-
                data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
-               ret_val = e1000_write_phy_reg(hw,
-                                            GG82563_PHY_KMRN_MODE_CTRL,
-                                            data);
+               ret_val = hw->phy.ops.write_reg(hw,
+                                               GG82563_PHY_KMRN_MODE_CTRL,
+                                               data);
 
                if (ret_val)
                        goto out;
        }
 
-       /* Workaround: Disable padding in Kumeran interface in the MAC
+       /*
+        * Workaround: Disable padding in Kumeran interface in the MAC
         * and in the PHY to avoid CRC errors.
         */
-       ret_val = e1000_read_phy_reg(hw, GG82563_PHY_INBAND_CTRL, &data);
+       ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data);
        if (ret_val)
                goto out;
 
        data |= GG82563_ICR_DIS_PADDING;
-       ret_val = e1000_write_phy_reg(hw, GG82563_PHY_INBAND_CTRL, data);
+       ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data);
        if (ret_val)
                goto out;
 
@@ -1131,11 +1191,10 @@
  *  Essentially a wrapper for setting up all things "copper" related.
  *  This is a function pointer entry point called by the mac module.
  **/
-STATIC s32
-e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
 {
        u32 ctrl;
-       s32  ret_val;
+       s32 ret_val;
        u16 reg_data;
 
        DEBUGFUNC("e1000_setup_copper_link_80003es2lan");
@@ -1145,26 +1204,31 @@
        ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
 
-       /* Set the mac to wait the maximum time between each
+       /*
+        * Set the mac to wait the maximum time between each
         * iteration and increase the max iterations when
-        * polling the phy; this fixes erroneous timeouts at 10Mbps. */
-       ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+        * polling the phy; this fixes erroneous timeouts at 10Mbps.
+        */
+       ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
+                                                  0xFFFF);
        if (ret_val)
                goto out;
-       ret_val = e1000_read_kmrn_reg(hw, GG82563_REG(0x34, 9), &reg_data);
+       ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
+                                                 &reg_data);
        if (ret_val)
                goto out;
        reg_data |= 0x3F;
-       ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data);
+       ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
+                                                  reg_data);
        if (ret_val)
                goto out;
-       ret_val = e1000_read_kmrn_reg(hw,
+       ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
                                      E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
                                      &reg_data);
        if (ret_val)
                goto out;
        reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
-       ret_val = e1000_write_kmrn_reg(hw,
+       ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
                                       E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
                                       reg_data);
        if (ret_val)
@@ -1181,6 +1245,40 @@
 }
 
 /**
+ *  e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up
+ *  @hw: pointer to the HW structure
+ *  @duplex: current duplex setting
+ *
+ *  Configure the KMRN interface by applying last minute quirks for
+ *  10/100 operation.
+ **/
+static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 speed;
+       u16 duplex;
+
+       DEBUGFUNC("e1000_configure_on_link_up");
+
+       if (hw->phy.media_type == e1000_media_type_copper) {
+
+               ret_val = e1000_get_speed_and_duplex_copper_generic(hw,
+                                                                   &speed,
+                                                                   &duplex);
+               if (ret_val)
+                       goto out;
+
+               if (speed == SPEED_1000)
+                       ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
+               else
+                       ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex);
+       }
+
+out:
+       return ret_val;
+}
+
+/**
  *  e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation
  *  @hw: pointer to the HW structure
  *  @duplex: current duplex setting
@@ -1188,8 +1286,7 @@
  *  Configure the KMRN interface by applying last minute quirks for
  *  10/100 operation.
  **/
-static s32
-e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
+static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
 {
        s32 ret_val = E1000_SUCCESS;
        u32 tipg;
@@ -1199,7 +1296,7 @@
        DEBUGFUNC("e1000_configure_kmrn_for_10_100");
 
        reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
-       ret_val = e1000_write_kmrn_reg(hw,
+       ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
                                       E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
                                       reg_data);
        if (ret_val)
@@ -1213,13 +1310,13 @@
 
 
        do {
-               ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
-                                            &reg_data);
+               ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                              &reg_data);
                if (ret_val)
                        goto out;
 
-               ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
-                                            &reg_data2);
+               ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                              &reg_data2);
                if (ret_val)
                        goto out;
                i++;
@@ -1230,7 +1327,7 @@
        else
                reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
 
-       ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+       ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, 
reg_data);
 
 out:
        return ret_val;
@@ -1243,8 +1340,7 @@
  *  Configure the KMRN interface by applying last minute quirks for
  *  gigabit operation.
  **/
-static s32
-e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
+static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
        u16 reg_data, reg_data2;
@@ -1254,7 +1350,7 @@
        DEBUGFUNC("e1000_configure_kmrn_for_1000");
 
        reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
-       ret_val = e1000_write_kmrn_reg(hw,
+       ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
                                       E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
                                       reg_data);
        if (ret_val)
@@ -1268,72 +1364,170 @@
 
 
        do {
-               ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
-                                            &reg_data);
+               ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                              &reg_data);
                if (ret_val)
                        goto out;
 
-               ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
-                                            &reg_data2);
+               ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                              &reg_data2);
                if (ret_val)
                        goto out;
                i++;
        } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
 
        reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
-       ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+       ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, 
reg_data);
 
 out:
        return ret_val;
 }
 
 /**
+ *  e1000_read_kmrn_reg_80003es2lan - Read kumeran register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Acquire semaphore, then read the PHY register at offset
+ *  using the kumeran interface.  The information retrieved is stored in data.
+ *  Release the semaphore before exiting.
+ **/
+s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       u32 kmrnctrlsta;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_read_kmrn_reg_80003es2lan");
+
+       ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
+       if (ret_val)
+               goto out;
+
+       kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
+                      E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
+       E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
+
+       usec_delay(2);
+
+       kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
+       *data = (u16)kmrnctrlsta;
+
+       e1000_release_mac_csr_80003es2lan(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_write_kmrn_reg_80003es2lan - Write kumeran register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquire semaphore, then write the data to PHY register
+ *  at the offset using the kumeran interface.  Release semaphore
+ *  before exiting.
+ **/
+s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       u32 kmrnctrlsta;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_write_kmrn_reg_80003es2lan");
+
+       ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
+       if (ret_val)
+               goto out;
+
+       kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
+                      E1000_KMRNCTRLSTA_OFFSET) | data;
+       E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
+
+       usec_delay(2);
+
+       e1000_release_mac_csr_80003es2lan(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_read_mac_addr_80003es2lan - Read device MAC address
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_read_mac_addr_80003es2lan");
+       if (e1000_check_alt_mac_addr_generic(hw))
+               ret_val = e1000_read_mac_addr_generic(hw);
+
+       return ret_val;
+}
+
+/**
+ * e1000_power_down_phy_copper_80003es2lan - 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_80003es2lan(struct e1000_hw *hw)
+{
+       /* If the management interface is not enabled, then power down */
+       if (!(hw->mac.ops.check_mng_mode(hw) ||
+             hw->phy.ops.check_reset_block(hw)))
+               e1000_power_down_phy_copper(hw);
+
+       return;
+}
+
+/**
  *  e1000_clear_hw_cntrs_80003es2lan - 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_80003es2lan(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw)
 {
-       volatile u32 temp;
-
        DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan");
 
        e1000_clear_hw_cntrs_base_generic(hw);
 
-       temp = E1000_READ_REG(hw, E1000_PRC64);
-       temp = E1000_READ_REG(hw, E1000_PRC127);
-       temp = E1000_READ_REG(hw, E1000_PRC255);
-       temp = E1000_READ_REG(hw, E1000_PRC511);
-       temp = E1000_READ_REG(hw, E1000_PRC1023);
-       temp = E1000_READ_REG(hw, E1000_PRC1522);
-       temp = E1000_READ_REG(hw, E1000_PTC64);
-       temp = E1000_READ_REG(hw, E1000_PTC127);
-       temp = E1000_READ_REG(hw, E1000_PTC255);
-       temp = E1000_READ_REG(hw, E1000_PTC511);
-       temp = E1000_READ_REG(hw, E1000_PTC1023);
-       temp = E1000_READ_REG(hw, E1000_PTC1522);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_ALGNERRC);
-       temp = E1000_READ_REG(hw, E1000_RXERRC);
-       temp = E1000_READ_REG(hw, E1000_TNCRS);
-       temp = E1000_READ_REG(hw, E1000_CEXTERR);
-       temp = E1000_READ_REG(hw, E1000_TSCTC);
-       temp = E1000_READ_REG(hw, E1000_TSCTFC);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_MGTPRC);
-       temp = E1000_READ_REG(hw, E1000_MGTPDC);
-       temp = E1000_READ_REG(hw, E1000_MGTPTC);
+       E1000_READ_REG(hw, E1000_MGTPRC);
+       E1000_READ_REG(hw, E1000_MGTPDC);
+       E1000_READ_REG(hw, E1000_MGTPTC);
 
-       temp = E1000_READ_REG(hw, E1000_IAC);
-       temp = E1000_READ_REG(hw, E1000_ICRXOC);
+       E1000_READ_REG(hw, E1000_IAC);
+       E1000_READ_REG(hw, E1000_ICRXOC);
 
-       temp = E1000_READ_REG(hw, E1000_ICRXPTC);
-       temp = E1000_READ_REG(hw, E1000_ICRXATC);
-       temp = E1000_READ_REG(hw, E1000_ICTXPTC);
-       temp = E1000_READ_REG(hw, E1000_ICTXATC);
-       temp = E1000_READ_REG(hw, E1000_ICTXQEC);
-       temp = E1000_READ_REG(hw, E1000_ICTXQMTC);
-       temp = E1000_READ_REG(hw, E1000_ICRXDMTC);
+       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);
 }
Index: dev/em/Jamfile
===================================================================
--- dev/em/Jamfile      (Revision 28889)
+++ dev/em/Jamfile      (Arbeitskopie)
@@ -20,6 +20,7 @@
        e1000_mac.c
        e1000_manage.c
        e1000_nvm.c
+       e1000_osdep.c
        e1000_phy.c
        if_em.c
 
Index: dev/em/e1000_defines.h
===================================================================
--- dev/em/e1000_defines.h      (Revision 28889)
+++ dev/em/e1000_defines.h      (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,32 +29,12 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_defines.h,v 1.3 2007/05/16 00:14:23 jfv Exp 
$*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_defines.h,v 1.2 2008/11/26 23:57:23 jfv 
Exp $*/
 
-
 #ifndef _E1000_DEFINES_H_
 #define _E1000_DEFINES_H_
 
-#define E1000_TXD_POPTS_IXSM 0x01       /* Insert IP checksum */
-#define E1000_TXD_POPTS_TXSM 0x02       /* Insert TCP/UDP checksum */
-#define E1000_TXD_CMD_EOP    0x01000000 /* End of Packet */
-#define E1000_TXD_CMD_IFCS   0x02000000 /* Insert FCS (Ethernet CRC) */
-#define E1000_TXD_CMD_IC     0x04000000 /* Insert Checksum */
-#define E1000_TXD_CMD_RS     0x08000000 /* Report Status */
-#define E1000_TXD_CMD_RPS    0x10000000 /* Report Packet Sent */
-#define E1000_TXD_CMD_DEXT   0x20000000 /* Descriptor extension (0 = legacy) */
-#define E1000_TXD_CMD_VLE    0x40000000 /* Add VLAN tag */
-#define E1000_TXD_CMD_IDE    0x80000000 /* Enable Tidv register */
-#define E1000_TXD_STAT_DD    0x00000001 /* Descriptor Done */
-#define E1000_TXD_STAT_EC    0x00000002 /* Excess Collisions */
-#define E1000_TXD_STAT_LC    0x00000004 /* Late Collisions */
-#define E1000_TXD_STAT_TU    0x00000008 /* Transmit underrun */
-#define E1000_TXD_CMD_TCP    0x01000000 /* TCP packet */
-#define E1000_TXD_CMD_IP     0x02000000 /* IP packet */
-#define E1000_TXD_CMD_TSE    0x04000000 /* TCP Seg enable */
-#define E1000_TXD_STAT_TC    0x00000004 /* Tx Underrun */
-/* Extended desc bits for Linksec and timesync */
 /* Number of Transmit and Receive Descriptors must be a multiple of 8 */
 #define REQ_TX_DESCRIPTOR_MULTIPLE  8
 #define REQ_RX_DESCRIPTOR_MULTIPLE  8
@@ -65,7 +45,10 @@
 #define E1000_WUC_PME_EN     0x00000002 /* PME Enable */
 #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_LSCWO      0x00000020 /* Link Status wake up override */
 #define E1000_WUC_SPM        0x80000000 /* Enable SPM */
+#define E1000_WUC_PHY_WAKE   0x00000100 /* if PHY supports wakeup */
 
 /* Wake Up Filter Control */
 #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
@@ -76,14 +59,29 @@
 #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      0x00008000 /* Ignore WakeOn TCO packets */
+#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_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_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */
-#define E1000_WUFC_FLX_OFFSET 16       /* Offset to the Flexible Filters bits 
*/
-#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
+#define E1000_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */
+#define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 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  0x000F00FF /* Mask for all wakeup filters */
+#define E1000_WUFC_FLX_OFFSET   16 /* Offset to the Flexible Filters bits */
+#define E1000_WUFC_FLX_FILTERS  0x000F0000 /*Mask for the 4 flexible filters */
+/*
+ * 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
@@ -94,6 +92,11 @@
 #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
@@ -105,6 +108,10 @@
 
 /* Four Flexible Filters are supported */
 #define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
+/* 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
@@ -119,11 +126,13 @@
 #define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN
 #define E1000_CTRL_EXT_GPI2_EN   0x00000004 /* Maps SDP6 to GPI2 */
 #define E1000_CTRL_EXT_GPI3_EN   0x00000008 /* Maps SDP7 to GPI3 */
-#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */
-#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */
+/* Reserved (bits 4,5) in >= 82575 */
+#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Definable Pin 4 */
+#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Definable Pin 5 */
 #define E1000_CTRL_EXT_PHY_INT   E1000_CTRL_EXT_SDP5_DATA
-#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */
-#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
+#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Definable Pin 6 */
+#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */
+/* SDP 4/5 (bits 8,9) are reserved in >= 82575 */
 #define E1000_CTRL_EXT_SDP4_DIR  0x00000100 /* Direction of SDP4 0=in 1=out */
 #define E1000_CTRL_EXT_SDP5_DIR  0x00000200 /* Direction of SDP5 0=in 1=out */
 #define E1000_CTRL_EXT_SDP6_DIR  0x00000400 /* Direction of SDP6 0=in 1=out */
@@ -131,6 +140,8 @@
 #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_LINK_MODE_MASK 0x00C00000
@@ -147,14 +158,19 @@
 #define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
 #define E1000_CTRL_EXT_WR_WMARK_384   0x02000000
 #define E1000_CTRL_EXT_WR_WMARK_448   0x03000000
-#define E1000_CTRL_EXT_CANC           0x04000000 /* Interrupt delay 
cancellation */
+#define E1000_CTRL_EXT_CANC           0x04000000 /* Int delay cancellation */
 #define E1000_CTRL_EXT_DRV_LOAD       0x10000000 /* Driver loaded bit for FW */
-#define E1000_CTRL_EXT_IAME           0x08000000 /* Interrupt acknowledge 
Auto-mask */
-#define E1000_CTRL_EXT_INT_TIMER_CLR  0x20000000 /* Clear Interrupt timers 
after IMS clear */
-#define E1000_CRTL_EXT_PB_PAREN       0x01000000 /* packet buffer parity error 
detection enabled */
-#define E1000_CTRL_EXT_DF_PAREN       0x02000000 /* descriptor FIFO parity 
error detection enable */
+/* IAME enable bit (27) was removed in >= 82575 */
+#define E1000_CTRL_EXT_IAME           0x08000000 /* Int acknowledge Auto-mask 
*/
+#define E1000_CTRL_EXT_INT_TIMER_CLR  0x20000000 /* Clear Interrupt timers
+                                                  * after IMS clear */
+#define E1000_CRTL_EXT_PB_PAREN       0x01000000 /* packet buffer parity error
+                                                  * detection enabled */
+#define E1000_CTRL_EXT_DF_PAREN       0x02000000 /* descriptor FIFO parity
+                                                  * error detection enable */
 #define E1000_CTRL_EXT_GHOST_PAREN    0x40000000
 #define E1000_CTRL_EXT_PBA_CLR        0x80000000 /* PBA Clear */
+#define E1000_CTRL_EXT_LSECCK         0x00001000
 #define E1000_I2CCMD_REG_ADDR_SHIFT   16
 #define E1000_I2CCMD_REG_ADDR         0x00FF0000
 #define E1000_I2CCMD_PHY_ADDR_SHIFT   24
@@ -167,13 +183,18 @@
 #define E1000_I2CCMD_ERROR            0x80000000
 #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 Decriptor bit definitions */
+/* Receive Descriptor bit definitions */
 #define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
 #define E1000_RXD_STAT_EOP      0x02    /* End of Packet */
 #define E1000_RXD_STAT_IXSM     0x04    /* Ignore checksum */
 #define E1000_RXD_STAT_VP       0x08    /* IEEE VLAN Packet */
-#define E1000_RXD_STAT_UDPCS    0x10    /* UDP xsum caculated */
+#define E1000_RXD_STAT_UDPCS    0x10    /* UDP xsum calculated */
 #define E1000_RXD_STAT_TCPCS    0x20    /* TCP xsum calculated */
 #define E1000_RXD_STAT_IPCS     0x40    /* IP xsum calculated */
 #define E1000_RXD_STAT_PIF      0x80    /* passed in-exact filter */
@@ -203,6 +224,13 @@
 #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  |                \
@@ -243,20 +271,20 @@
 #define E1000_MANC_IPV6_EN       0x00000800 /* Enable IPv6 */
 #define E1000_MANC_SNAP_EN       0x00001000 /* Accept LLC/SNAP */
 #define E1000_MANC_ARP_EN        0x00002000 /* Enable ARP Request Filtering */
-#define E1000_MANC_NEIGHBOR_EN   0x00004000 /* Enable Neighbor Discovery
-                                             * Filtering */
+/* Enable Neighbor Discovery Filtering */
+#define E1000_MANC_NEIGHBOR_EN   0x00004000
 #define E1000_MANC_ARP_RES_EN    0x00008000 /* Enable ARP response Filtering */
 #define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
 #define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
 #define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
 #define E1000_MANC_RCV_ALL       0x00080000 /* Receive All Enabled */
 #define E1000_MANC_BLK_PHY_RST_ON_IDE   0x00040000 /* Block phy resets */
-#define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000 /* Enable MAC address
-                                                    * filtering */
-#define E1000_MANC_EN_MNG2HOST   0x00200000 /* Enable MNG packets to host
-                                             * memory */
-#define E1000_MANC_EN_IP_ADDR_FILTER    0x00400000 /* Enable IP address
-                                                    * filtering */
+/* Enable MAC address filtering */
+#define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000
+/* Enable MNG packets to host memory */
+#define E1000_MANC_EN_MNG2HOST   0x00200000
+/* Enable IP address filtering */
+#define E1000_MANC_EN_IP_ADDR_FILTER    0x00400000
 #define E1000_MANC_EN_XSUM_FILTER   0x00800000 /* Enable checksum filtering */
 #define E1000_MANC_BR_EN            0x01000000 /* Enable broadcast filtering */
 #define E1000_MANC_SMB_REQ       0x01000000 /* SMBus Request */
@@ -311,7 +339,8 @@
 #define E1000_RCTL_FLXBUF_MASK    0x78000000    /* Flexible buffer size */
 #define E1000_RCTL_FLXBUF_SHIFT   27            /* Flexible buffer shift */
 
-/* Use byte values for the following shift parameters
+/*
+ * Use byte values for the following shift parameters
  * Usage:
  *     psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
  *                  E1000_PSRCTL_BSIZE0_MASK) |
@@ -341,7 +370,10 @@
 #define E1000_SWFW_EEP_SM   0x1
 #define E1000_SWFW_PHY0_SM  0x2
 #define E1000_SWFW_PHY1_SM  0x4
+#define E1000_SWFW_CSR_SM   0x8
 
+/* FACTPS Definitions */
+#define E1000_FACTPS_LFS    0x40000000  /* LAN Function Select */
 /* Device Control */
 #define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
 #define E1000_CTRL_BEM      0x00000002  /* Endian Mode.0=little,1=big */
@@ -361,9 +393,12 @@
 #define E1000_CTRL_FRCSPD   0x00000800  /* Force Speed */
 #define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
 #define E1000_CTRL_D_UD_EN  0x00002000  /* Dock/Undock enable */
-#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock 
indication in SDP[0] */
-#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through 
PHYRST_N pin */
-#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external 
LINK_0 and LINK_1 pins */
+#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock
+                                             * indication in SDP[0] */
+#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through
+                                               * PHYRST_N pin */
+#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external
+                                           * LINK_0 and LINK_1 pins */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
 #define E1000_CTRL_SWDPIN2  0x00100000  /* SWDPIN 2 value */
@@ -378,10 +413,11 @@
 #define E1000_CTRL_RTE      0x20000000  /* Routing tag enable */
 #define E1000_CTRL_VME      0x40000000  /* IEEE VLAN mode enable */
 #define E1000_CTRL_PHY_RST  0x80000000  /* PHY Reset */
-#define E1000_CTRL_SW2FW_INT 0x02000000  /* Initiate an interrupt to 
manageability engine */
+#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to ME */
 #define E1000_CTRL_I2C_ENA  0x02000000  /* I2C enable */
 
-/* Bit definitions for the Management Data IO (MDIO) and Management Data
+/*
+ * Bit definitions for the Management Data IO (MDIO) and Management Data
  * Clock (MDC) pins in the Device Control Register.
  */
 #define E1000_CTRL_PHY_RESET_DIR  E1000_CTRL_SWDPIO0
@@ -394,6 +430,7 @@
 #define E1000_CTRL_PHY_RESET4     E1000_CTRL_EXT_SDP4_DATA
 
 #define E1000_CONNSW_ENRGSRC             0x4
+#define E1000_PCS_CFG_PCS_EN             8
 #define E1000_PCS_LCTL_FLV_LINK_UP       1
 #define E1000_PCS_LCTL_FSV_10            0
 #define E1000_PCS_LCTL_FSV_100           2
@@ -402,6 +439,7 @@
 #define E1000_PCS_LCTL_FSD               0x10
 #define E1000_PCS_LCTL_FORCE_LINK        0x20
 #define E1000_PCS_LCTL_LOW_LINK_LATCH    0x40
+#define E1000_PCS_LCTL_FORCE_FCTRL       0x80
 #define E1000_PCS_LCTL_AN_ENABLE         0x10000
 #define E1000_PCS_LCTL_AN_RESTART        0x20000
 #define E1000_PCS_LCTL_AN_TIMEOUT        0x40000
@@ -439,8 +477,9 @@
 #define E1000_STATUS_SPEED_1000 0x00000080      /* Speed 1000Mb/s */
 #define E1000_STATUS_LAN_INIT_DONE 0x00000200   /* Lan Init Completion by NVM 
*/
 #define E1000_STATUS_ASDV       0x00000300      /* Auto speed detect value */
-#define E1000_STATUS_DOCK_CI    0x00000800      /* Change in Dock/Undock 
state. Clear on write '0'. */
-#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master 
requests. */
+#define E1000_STATUS_DOCK_CI    0x00000800      /* Change in Dock/Undock state.
+                                                 * Clear on write '0'. */
+#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */
 #define E1000_STATUS_MTXCKOK    0x00000400      /* MTX clock running OK */
 #define E1000_STATUS_PCI66      0x00000800      /* In 66Mhz slot */
 #define E1000_STATUS_BUS64      0x00001000      /* In 64 bit slot */
@@ -450,14 +489,15 @@
 #define E1000_STATUS_BMC_SKU_1  0x00200000 /* BMC SRAM disabled */
 #define E1000_STATUS_BMC_SKU_2  0x00400000 /* BMC SDRAM disabled */
 #define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */
-#define E1000_STATUS_BMC_LITE   0x01000000 /* BMC external code execution 
disabled */
+#define E1000_STATUS_BMC_LITE   0x01000000 /* BMC external code execution
+                                            * disabled */
 #define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */
 #define E1000_STATUS_FUSE_8       0x04000000
 #define E1000_STATUS_FUSE_9       0x08000000
 #define E1000_STATUS_SERDES0_DIS  0x10000000 /* SERDES disabled on port 0 */
 #define E1000_STATUS_SERDES1_DIS  0x20000000 /* SERDES disabled on port 1 */
 
-/* Constants used to intrepret the masked PCI-X bus speed. */
+/* Constants used to interpret the masked PCI-X bus speed. */
 #define E1000_STATUS_PCIX_SPEED_66  0x00000000 /* PCI-X bus speed  50-66 MHz */
 #define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed  66-100 MHz 
*/
 #define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz 
*/
@@ -478,10 +518,10 @@
 #define ADVERTISE_1000_FULL               0x0020
 
 /* 1000/H is not supported, nor spec-compliant. */
-#define E1000_ALL_SPEED_DUPLEX ( ADVERTISE_10_HALF |   ADVERTISE_10_FULL | \
+#define E1000_ALL_SPEED_DUPLEX  (ADVERTISE_10_HALF |   ADVERTISE_10_FULL | \
                                 ADVERTISE_100_HALF |  ADVERTISE_100_FULL | \
                                                      ADVERTISE_1000_FULL)
-#define E1000_ALL_NOT_GIG      ( ADVERTISE_10_HALF |   ADVERTISE_10_FULL | \
+#define E1000_ALL_NOT_GIG       (ADVERTISE_10_HALF |   ADVERTISE_10_FULL | \
                                 ADVERTISE_100_HALF |  ADVERTISE_100_FULL)
 #define E1000_ALL_100_SPEED    (ADVERTISE_100_HALF |  ADVERTISE_100_FULL)
 #define E1000_ALL_10_SPEED      (ADVERTISE_10_HALF |   ADVERTISE_10_FULL)
@@ -533,6 +573,7 @@
 /* Transmit Descriptor bit definitions */
 #define E1000_TXD_DTYP_D     0x00100000 /* Data Descriptor */
 #define E1000_TXD_DTYP_C     0x00000000 /* Context Descriptor */
+#define E1000_TXD_POPTS_SHIFT 8         /* POPTS shift */
 #define E1000_TXD_POPTS_IXSM 0x01       /* Insert IP checksum */
 #define E1000_TXD_POPTS_TXSM 0x02       /* Insert TCP/UDP checksum */
 #define E1000_TXD_CMD_EOP    0x01000000 /* End of Packet */
@@ -551,6 +592,9 @@
 #define E1000_TXD_CMD_IP     0x02000000 /* IP packet */
 #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 */
@@ -596,6 +640,7 @@
 #define E1000_RFCTL_EXTEN               0x00008000
 #define E1000_RFCTL_IPV6_EX_DIS         0x00010000
 #define E1000_RFCTL_NEW_IPV6_EXT_DIS    0x00020000
+#define E1000_RFCTL_LEF                 0x00040000
 
 /* Collision related configuration parameters */
 #define E1000_COLLISION_THRESHOLD       15
@@ -604,9 +649,7 @@
 #define E1000_COLD_SHIFT                12
 
 /* Default values for the transmit IPG register */
-#ifndef NO_82542_SUPPORT
 #define DEFAULT_82542_TIPG_IPGT        10
-#endif
 #define DEFAULT_82543_TIPG_IPGT_FIBER  9
 #define DEFAULT_82543_TIPG_IPGT_COPPER 8
 
@@ -614,15 +657,11 @@
 #define E1000_TIPG_IPGR1_MASK 0x000FFC00
 #define E1000_TIPG_IPGR2_MASK 0x3FF00000
 
-#ifndef NO_82542_SUPPORT
 #define DEFAULT_82542_TIPG_IPGR1 2
-#endif
 #define DEFAULT_82543_TIPG_IPGR1 8
 #define E1000_TIPG_IPGR1_SHIFT  10
 
-#ifndef NO_82542_SUPPORT
 #define DEFAULT_82542_TIPG_IPGR2 10
-#endif
 #define DEFAULT_82543_TIPG_IPGR2 6
 #define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
 #define E1000_TIPG_IPGR2_SHIFT  20
@@ -651,9 +690,10 @@
 #define E1000_KABGTXD_BGSQLBIAS           0x00050000
 
 /* PBA constants */
-#define E1000_PBA_8K  0x0008    /* 8KB, default Rx allocation */
-#define E1000_PBA_12K 0x000C    /* 12KB, default Rx allocation */
-#define E1000_PBA_16K 0x0010    /* 16KB, default TX allocation */
+#define E1000_PBA_6K  0x0006   /* 6KB */
+#define E1000_PBA_8K  0x0008    /* 8KB */
+#define E1000_PBA_12K 0x000C    /* 12KB */
+#define E1000_PBA_16K 0x0010    /* 16KB */
 #define E1000_PBA_20K 0x0014
 #define E1000_PBA_22K 0x0016
 #define E1000_PBA_24K 0x0018
@@ -662,7 +702,8 @@
 #define E1000_PBA_34K 0x0022
 #define E1000_PBA_38K 0x0026
 #define E1000_PBA_40K 0x0028
-#define E1000_PBA_48K 0x0030    /* 48KB, default RX allocation */
+#define E1000_PBA_48K 0x0030    /* 48KB */
+#define E1000_PBA_64K 0x0040    /* 64KB */
 
 #define E1000_PBS_16K E1000_PBA_16K
 #define E1000_PBS_24K E1000_PBA_24K
@@ -687,8 +728,9 @@
 #define E1000_ICR_RXDMT0        0x00000010 /* rx desc min. threshold (0) */
 #define E1000_ICR_RXO           0x00000040 /* rx overrun */
 #define E1000_ICR_RXT0          0x00000080 /* rx timer intr (ring 0) */
+#define E1000_ICR_VMMB          0x00000100 /* VM MB event */
 #define E1000_ICR_MDAC          0x00000200 /* MDIO access complete */
-#define E1000_ICR_RXCFG         0x00000400 /* RX /c/ ordered set */
+#define E1000_ICR_RXCFG         0x00000400 /* Rx /c/ ordered set */
 #define E1000_ICR_GPI_EN0       0x00000800 /* GP Int 0 */
 #define E1000_ICR_GPI_EN1       0x00001000 /* GP Int 1 */
 #define E1000_ICR_GPI_EN2       0x00002000 /* GP Int 2 */
@@ -698,17 +740,26 @@
 #define E1000_ICR_ACK           0x00020000 /* Receive Ack frame */
 #define E1000_ICR_MNG           0x00040000 /* Manageability event */
 #define E1000_ICR_DOCK          0x00080000 /* Dock/Undock */
-#define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver 
should claim the interrupt */
-#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO 
parity error */
-#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO 
parity error */
-#define E1000_ICR_HOST_ARB_PAR  0x00400000 /* host arb read buffer parity 
error */
+#define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver
+                                            * should claim the interrupt */
+#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* Q0 Rx desc FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* Q0 Tx desc FIFO parity error */
+#define E1000_ICR_HOST_ARB_PAR  0x00400000 /* host arb read buffer parity err 
*/
 #define E1000_ICR_PB_PAR        0x00800000 /* packet buffer parity error */
-#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO 
parity error */
-#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO 
parity error */
+#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* Q1 Rx desc FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* Q1 Tx desc FIFO parity error */
 #define E1000_ICR_ALL_PARITY    0x03F00000 /* all parity error bits */
-#define E1000_ICR_DSW           0x00000020 /* FW changed the status of DISSW 
bit in the FWSM */
-#define E1000_ICR_PHYINT        0x00001000 /* LAN connected device generates 
an interrupt */
-#define E1000_ICR_EPRST         0x00100000 /* ME handware reset occurs */
+#define E1000_ICR_DSW           0x00000020 /* FW changed the status of DISSW
+                                            * bit in the FWSM */
+#define E1000_ICR_PHYINT        0x00001000 /* LAN connected device generates
+                                            * 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 */
 
 /* Extended Interrupt Cause Read */
 #define E1000_EICR_RX_QUEUE0    0x00000001 /* Rx Queue 0 Interrupt */
@@ -727,7 +778,8 @@
 #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
+/*
+ * This defines the bits that are set in the Interrupt Mask
  * Set/Read Register.  Each bit is documented below:
  *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
  *   o RXSEQ  = Receive Sequence Error
@@ -736,7 +788,8 @@
     E1000_IMS_RXDMT0 |    \
     E1000_IMS_RXSEQ)
 
-/* This defines the bits that are set in the Interrupt Mask
+/*
+ * This defines the bits that are set in the Interrupt Mask
  * Set/Read Register.  Each bit is documented below:
  *   o RXT0   = Receiver Timer Interrupt (ring 0)
  *   o TXDW   = Transmit Descriptor Written Back
@@ -755,12 +808,13 @@
 #define E1000_IMS_TXDW      E1000_ICR_TXDW      /* Transmit desc written back 
*/
 #define E1000_IMS_TXQE      E1000_ICR_TXQE      /* Transmit Queue empty */
 #define E1000_IMS_LSC       E1000_ICR_LSC       /* Link Status Change */
+#define E1000_IMS_VMMB      E1000_ICR_VMMB      /* Mail box activity */
 #define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* rx sequence error */
 #define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold */
 #define E1000_IMS_RXO       E1000_ICR_RXO       /* rx overrun */
 #define E1000_IMS_RXT0      E1000_ICR_RXT0      /* rx timer intr */
 #define E1000_IMS_MDAC      E1000_ICR_MDAC      /* MDIO access complete */
-#define E1000_IMS_RXCFG     E1000_ICR_RXCFG     /* RX /c/ ordered set */
+#define E1000_IMS_RXCFG     E1000_ICR_RXCFG     /* Rx /c/ ordered set */
 #define E1000_IMS_GPI_EN0   E1000_ICR_GPI_EN0   /* GP Int 0 */
 #define E1000_IMS_GPI_EN1   E1000_ICR_GPI_EN1   /* GP Int 1 */
 #define E1000_IMS_GPI_EN2   E1000_ICR_GPI_EN2   /* GP Int 2 */
@@ -770,15 +824,27 @@
 #define E1000_IMS_ACK       E1000_ICR_ACK       /* Receive Ack frame */
 #define E1000_IMS_MNG       E1000_ICR_MNG       /* Manageability event */
 #define E1000_IMS_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
-#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx 
descriptor FIFO parity error */
-#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx 
descriptor FIFO parity error */
-#define E1000_IMS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read 
buffer parity error */
-#define E1000_IMS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer 
parity error */
-#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx 
descriptor FIFO parity error */
-#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx 
descriptor FIFO parity error */
+#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO
+                                                         * parity error */
+#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO
+                                                         * parity error */
+#define E1000_IMS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer
+                                                         * parity error */
+#define E1000_IMS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity
+                                                         * error */
+#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO
+                                                         * parity error */
+#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO
+                                                         * parity error */
 #define E1000_IMS_DSW       E1000_ICR_DSW
 #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 */
 
 /* Extended Interrupt Mask Set */
 #define E1000_EIMS_RX_QUEUE0    E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
@@ -801,7 +867,7 @@
 #define E1000_ICS_RXO       E1000_ICR_RXO       /* rx overrun */
 #define E1000_ICS_RXT0      E1000_ICR_RXT0      /* rx timer intr */
 #define E1000_ICS_MDAC      E1000_ICR_MDAC      /* MDIO access complete */
-#define E1000_ICS_RXCFG     E1000_ICR_RXCFG     /* RX /c/ ordered set */
+#define E1000_ICS_RXCFG     E1000_ICR_RXCFG     /* Rx /c/ ordered set */
 #define E1000_ICS_GPI_EN0   E1000_ICR_GPI_EN0   /* GP Int 0 */
 #define E1000_ICS_GPI_EN1   E1000_ICR_GPI_EN1   /* GP Int 1 */
 #define E1000_ICS_GPI_EN2   E1000_ICR_GPI_EN2   /* GP Int 2 */
@@ -811,13 +877,20 @@
 #define E1000_ICS_ACK       E1000_ICR_ACK       /* Receive Ack frame */
 #define E1000_ICS_MNG       E1000_ICR_MNG       /* Manageability event */
 #define E1000_ICS_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
-#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx 
descriptor FIFO parity error */
-#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx 
descriptor FIFO parity error */
-#define E1000_ICS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read 
buffer parity error */
-#define E1000_ICS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer 
parity error */
-#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx 
descriptor FIFO parity error */
-#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx 
descriptor FIFO parity error */
+#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO
+                                                         * parity error */
+#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO
+                                                         * parity error */
+#define E1000_ICS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer
+                                                         * parity error */
+#define E1000_ICS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity
+                                                         * error */
+#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO
+                                                         * parity error */
+#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO
+                                                         * parity error */
 #define E1000_ICS_DSW       E1000_ICR_DSW
+#define E1000_ICS_DOUTSYNC  E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
 #define E1000_ICS_PHYINT    E1000_ICR_PHYINT
 #define E1000_ICS_EPRST     E1000_ICR_EPRST
 
@@ -841,8 +914,8 @@
 #define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
 #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
 #define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
-#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
-                                              still to be processed. */
+/* Enable the counting of descriptors still to be processed. */
+#define E1000_TXDCTL_COUNT_DESC 0x00400000
 
 /* Flow Control Constants */
 #define FLOW_CONTROL_ADDRESS_LOW  0x00C28001
@@ -854,7 +927,8 @@
 #define E1000_VLAN_FILTER_TBL_SIZE 128  /* VLAN Filter Table (4096 bits) */
 
 /* Receive Address */
-/* Number of high/low register pairs in the RAR. The RAR (Receive Address
+/*
+ * Number of high/low register pairs in the RAR. The RAR (Receive Address
  * Registers) holds the directed and multicast addresses that we monitor.
  * Technically, we have 16 spots.  However, we reserve one of these spots
  * (RAR[15]) for our directed address used by controllers with
@@ -1021,7 +1095,7 @@
 #define SR_1000T_LP_FD_CAPS       0x0800 /* LP is 1000T FD capable */
 #define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
 #define SR_1000T_LOCAL_RX_STATUS  0x2000 /* Local receiver OK */
-#define SR_1000T_MS_CONFIG_RES    0x4000 /* 1=Local TX is Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_RES    0x4000 /* 1=Local Tx is Master, 0=Slave */
 #define SR_1000T_MS_CONFIG_FAULT  0x8000 /* Master/Slave config fault */
 
 #define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5
@@ -1029,13 +1103,13 @@
 /* PHY 1000 MII Register/Bit Definitions */
 /* PHY Registers defined by IEEE */
 #define PHY_CONTROL      0x00 /* Control Register */
-#define PHY_STATUS       0x01 /* Status Regiser */
+#define PHY_STATUS       0x01 /* Status Register */
 #define PHY_ID1          0x02 /* Phy Id Reg (word 1) */
 #define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
 #define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
 #define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
 #define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
-#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page Tx */
 #define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
 #define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
 #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
@@ -1054,8 +1128,8 @@
 #define E1000_EECD_GNT       0x00000080 /* NVM Access Grant */
 #define E1000_EECD_PRES      0x00000100 /* NVM Present */
 #define E1000_EECD_SIZE      0x00000200 /* NVM Size (0=64 word 1=256 word) */
-#define E1000_EECD_ADDR_BITS 0x00000400 /* NVM Addressing bits based on type
-                                         * (0-small, 1-large) */
+/* NVM Addressing bits based on type 0=small, 1=large */
+#define E1000_EECD_ADDR_BITS 0x00000400
 #define E1000_EECD_TYPE      0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
 #ifndef E1000_NVM_GRANT_ATTEMPTS
 #define E1000_NVM_GRANT_ATTEMPTS   1000 /* NVM # attempts to gain grant */
@@ -1074,7 +1148,7 @@
 
 #define E1000_NVM_SWDPIN0   0x0001   /* SWDPIN 0 NVM Value */
 #define E1000_NVM_LED_LOGIC 0x0020   /* Led Logic Word */
-#define E1000_NVM_RW_REG_DATA   16   /* Offset to data in NVM read/write 
registers */
+#define E1000_NVM_RW_REG_DATA   16   /* Offset to data in NVM read/write regs 
*/
 #define E1000_NVM_RW_REG_DONE   2    /* Offset to READ/WRITE done bit */
 #define E1000_NVM_RW_REG_START  1    /* Start operation */
 #define E1000_NVM_RW_ADDR_SHIFT 2    /* Shift to the address bits */
@@ -1086,7 +1160,7 @@
 #define NVM_COMPAT                 0x0003
 #define NVM_ID_LED_SETTINGS        0x0004
 #define NVM_VERSION                0x0005
-#define NVM_SERDES_AMPLITUDE       0x0006 /* For SERDES output amplitude 
adjustment. */
+#define NVM_SERDES_AMPLITUDE       0x0006 /* SERDES output amplitude */
 #define NVM_PHY_CLASS_WORD         0x0007
 #define NVM_INIT_CONTROL1_REG      0x000A
 #define NVM_INIT_CONTROL2_REG      0x000F
@@ -1097,6 +1171,7 @@
 #define NVM_INIT_CONTROL3_PORT_A   0x0024
 #define NVM_CFG                    0x0012
 #define NVM_FLASH_VERSION          0x0032
+#define NVM_ALT_MAC_ADDR_PTR       0x0037
 #define NVM_CHECKSUM_REG           0x003F
 
 #define E1000_NVM_CFG_DONE_PORT_0  0x40000 /* MNG config cycle done */
@@ -1132,7 +1207,7 @@
 #define NVM_WRITE_OPCODE_MICROWIRE 0x5  /* NVM write opcode */
 #define NVM_ERASE_OPCODE_MICROWIRE 0x7  /* NVM erase opcode */
 #define NVM_EWEN_OPCODE_MICROWIRE  0x13 /* NVM erase/write enable */
-#define NVM_EWDS_OPCODE_MICROWIRE  0x10 /* NVM erast/write disable */
+#define NVM_EWDS_OPCODE_MICROWIRE  0x10 /* NVM erase/write disable */
 
 /* NVM Commands - SPI */
 #define NVM_MAX_RETRY_SPI          5000 /* Max wait of 5ms, for RDY signal */
@@ -1199,7 +1274,8 @@
 #define MAX_PHY_MULTI_PAGE_REG 0xF
 
 /* Bit definitions for valid PHY IDs. */
-/* I = Integrated
+/*
+ * I = Integrated
  * E = External
  */
 #define M88E1000_E_PHY_ID    0x01410C50
@@ -1213,6 +1289,9 @@
 #define IFE_E_PHY_ID         0x02A80330
 #define IFE_PLUS_E_PHY_ID    0x02A80320
 #define IFE_C_E_PHY_ID       0x02A80310
+#define BME1000_E_PHY_ID     0x01410CB0
+#define BME1000_E_PHY_ID_R2  0x01410CB1
+#define IGP04E1000_E_PHY_ID  0x02A80391
 #define M88_VENDOR           0x0141
 
 /* M88E1000 Specific Registers */
@@ -1233,26 +1312,22 @@
 #define M88E1000_PSCR_JABBER_DISABLE    0x0001 /* 1=Jabber Function disabled */
 #define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled 
*/
 #define M88E1000_PSCR_SQE_TEST          0x0004 /* 1=SQE Test enabled */
-#define M88E1000_PSCR_CLK125_DISABLE    0x0010 /* 1=CLK125 low,
-                                                * 0=CLK125 toggling
-                                                */
+/* 1=CLK125 low, 0=CLK125 toggling */
+#define M88E1000_PSCR_CLK125_DISABLE    0x0010
 #define M88E1000_PSCR_MDI_MANUAL_MODE  0x0000  /* MDI Crossover Mode bits 6:5 
*/
                                                /* Manual MDI configuration */
 #define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020  /* Manual MDIX configuration */
-#define M88E1000_PSCR_AUTO_X_1000T     0x0040  /* 1000BASE-T: Auto crossover,
-                                                *  100BASE-TX/10BASE-T:
-                                                *  MDI Mode
-                                                */
-#define M88E1000_PSCR_AUTO_X_MODE      0x0060  /* Auto crossover enabled
-                                                * all speeds.
-                                                */
+/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
+#define M88E1000_PSCR_AUTO_X_1000T     0x0040
+/* Auto crossover enabled all speeds */
+#define M88E1000_PSCR_AUTO_X_MODE      0x0060
+/*
+ * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold
+ * 0=Normal 10BASE-T Rx Threshold
+ */
 #define M88E1000_PSCR_EN_10BT_EXT_DIST 0x0080
-                                        /* 1=Enable Extended 10BASE-T distance
-                                         * (Lower 10BASE-T RX Threshold)
-                                         * 0=Normal 10BASE-T RX Threshold */
+/* 1=5-bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
 #define M88E1000_PSCR_MII_5BIT_ENABLE      0x0100
-                                        /* 1=5-Bit interface in 100BASE-TX
-                                         * 0=MII interface in 100BASE-TX */
 #define M88E1000_PSCR_SCRAMBLER_DISABLE    0x0200 /* 1=Scrambler disable */
 #define M88E1000_PSCR_FORCE_LINK_GOOD      0x0400 /* 1=Force link good */
 #define M88E1000_PSCR_ASSERT_CRS_ON_TX     0x0800 /* 1=Assert CRS on Transmit 
*/
@@ -1262,8 +1337,14 @@
 #define M88E1000_PSSR_REV_POLARITY       0x0002 /* 1=Polarity reversed */
 #define M88E1000_PSSR_DOWNSHIFT          0x0020 /* 1=Downshifted */
 #define M88E1000_PSSR_MDIX               0x0040 /* 1=MDIX; 0=MDI */
-#define M88E1000_PSSR_CABLE_LENGTH       0x0380 /* 0=<50M;1=50-80M;2=80-110M;
-                                            * 3=110-140M;4=>140M */
+/*
+ * 0 = <50M
+ * 1 = 50-80M
+ * 2 = 80-110M
+ * 3 = 110-140M
+ * 4 = >140M
+ */
+#define M88E1000_PSSR_CABLE_LENGTH       0x0380
 #define M88E1000_PSSR_LINK               0x0400 /* 1=Link up, 0=Link down */
 #define M88E1000_PSSR_SPD_DPLX_RESOLVED  0x0800 /* 1=Speed & Duplex resolved */
 #define M88E1000_PSSR_PAGE_RCVD          0x1000 /* 1=Page received */
@@ -1277,20 +1358,26 @@
 
 /* M88E1000 Extended PHY Specific Control Register */
 #define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */
-#define M88E1000_EPSCR_DOWN_NO_IDLE   0x8000 /* 1=Lost lock detect enabled.
-                                              * Will assert lost lock and bring
-                                              * link down if idle not seen
-                                              * within 1ms in 1000BASE-T
-                                              */
-/* Number of times we will attempt to autonegotiate before downshifting if we
- * are the master */
+/*
+ * 1 = Lost lock detect enabled.
+ * Will assert lost lock and bring
+ * link down if idle not seen
+ * within 1ms in 1000BASE-T
+ */
+#define M88E1000_EPSCR_DOWN_NO_IDLE   0x8000
+/*
+ * Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master
+ */
 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X   0x0000
 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X   0x0400
 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X   0x0800
 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X   0x0C00
-/* Number of times we will attempt to autonegotiate before downshifting if we
- * are the slave */
+/*
+ * Number of times we will attempt to autonegotiate before downshifting if we
+ * are the slave
+ */
 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK  0x0300
 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS   0x0000
 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X    0x0100
@@ -1311,7 +1398,11 @@
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X    0x0C00
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X    0x0E00
 
-/* Bits...
+/* BME1000 PHY Specific Control Register */
+#define BME1000_PSCR_ENABLE_DOWNSHIFT   0x0800 /* 1 = enable downshift */
+
+/*
+ * Bits...
  * 15-5: page
  * 4-0: register offset
  */
@@ -1400,4 +1491,29 @@
 #define E1000_GEN_CTL_READY             0x80000000
 #define E1000_GEN_CTL_ADDRESS_SHIFT     8
 #define E1000_GEN_POLL_TIMEOUT          640
-#endif
+
+/* 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
+
+#endif /* _E1000_DEFINES_H_ */
Index: dev/em/e1000_82540.c
===================================================================
--- dev/em/e1000_82540.c        (Revision 28889)
+++ dev/em/e1000_82540.c        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,61 +29,61 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82540.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82540.c,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
-
-/* e1000_82540
- * e1000_82545
- * e1000_82546
- * e1000_82545_rev_3
- * e1000_82546_rev_3
+/*
+ * 82540EM Gigabit Ethernet Controller
+ * 82540EP Gigabit Ethernet Controller
+ * 82545EM Gigabit Ethernet Controller (Copper)
+ * 82545EM Gigabit Ethernet Controller (Fiber)
+ * 82545GM Gigabit Ethernet Controller
+ * 82546EB Gigabit Ethernet Controller (Copper)
+ * 82546EB Gigabit Ethernet Controller (Fiber)
+ * 82546GB Gigabit Ethernet Controller
  */
 
 #include "e1000_api.h"
 
-void e1000_init_function_pointers_82540(struct e1000_hw *hw);
-
-STATIC s32  e1000_init_phy_params_82540(struct e1000_hw *hw);
-STATIC s32  e1000_init_nvm_params_82540(struct e1000_hw *hw);
-STATIC s32  e1000_init_mac_params_82540(struct e1000_hw *hw);
+static s32  e1000_init_phy_params_82540(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_82540(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82540(struct e1000_hw *hw);
 static s32  e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw);
-STATIC void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw);
-STATIC s32  e1000_init_hw_82540(struct e1000_hw *hw);
-STATIC s32  e1000_reset_hw_82540(struct e1000_hw *hw);
+static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw);
+static s32  e1000_init_hw_82540(struct e1000_hw *hw);
+static s32  e1000_reset_hw_82540(struct e1000_hw *hw);
 static s32  e1000_set_phy_mode_82540(struct e1000_hw *hw);
 static s32  e1000_set_vco_speed_82540(struct e1000_hw *hw);
-STATIC s32  e1000_setup_copper_link_82540(struct e1000_hw *hw);
-STATIC s32  e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw);
+static s32  e1000_setup_copper_link_82540(struct e1000_hw *hw);
+static s32  e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw);
+static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw);
 
 /**
  * e1000_init_phy_params_82540 - Init PHY func ptrs.
  * @hw: pointer to the HW structure
- *
- * This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_phy_params_82540(struct e1000_hw *hw)
+static s32 e1000_init_phy_params_82540(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
-       phy->addr                       = 1;
-       phy->autoneg_mask               = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-       phy->reset_delay_us             = 10000;
-       phy->type                       = e1000_phy_m88;
+       phy->addr                      = 1;
+       phy->autoneg_mask              = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us            = 10000;
+       phy->type                      = e1000_phy_m88;
 
        /* Function Pointers */
-       func->check_polarity            = e1000_check_polarity_m88;
-       func->commit_phy                = e1000_phy_sw_reset_generic;
-       func->force_speed_duplex        = e1000_phy_force_speed_duplex_m88;
-       func->get_cable_length          = e1000_get_cable_length_m88;
-       func->get_cfg_done              = e1000_get_cfg_done_generic;
-       func->read_phy_reg              = e1000_read_phy_reg_m88;
-       func->reset_phy                 = e1000_phy_hw_reset_generic;
-       func->write_phy_reg             = e1000_write_phy_reg_m88;
-       func->get_phy_info              = e1000_get_phy_info_m88;
+       phy->ops.check_polarity        = e1000_check_polarity_m88;
+       phy->ops.commit                = e1000_phy_sw_reset_generic;
+       phy->ops.force_speed_duplex    = e1000_phy_force_speed_duplex_m88;
+       phy->ops.get_cable_length      = e1000_get_cable_length_m88;
+       phy->ops.get_cfg_done          = e1000_get_cfg_done_generic;
+       phy->ops.read_reg              = e1000_read_phy_reg_m88;
+       phy->ops.reset                 = e1000_phy_hw_reset_generic;
+       phy->ops.write_reg             = e1000_write_phy_reg_m88;
+       phy->ops.get_info              = e1000_get_phy_info_m88;
+       phy->ops.power_up              = e1000_power_up_phy_copper;
+       phy->ops.power_down            = e1000_power_down_phy_copper_82540;
 
        ret_val = e1000_get_phy_id(hw);
        if (ret_val)
@@ -112,14 +112,10 @@
 /**
  * e1000_init_nvm_params_82540 - Init NVM func ptrs.
  * @hw: pointer to the HW structure
- *
- * This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_nvm_params_82540(struct e1000_hw *hw)
+static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_functions *func = &hw->func;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
 
        DEBUGFUNC("e1000_init_nvm_params_82540");
@@ -143,13 +139,13 @@
        }
 
        /* Function Pointers */
-       func->acquire_nvm        = e1000_acquire_nvm_generic;
-       func->read_nvm           = e1000_read_nvm_microwire;
-       func->release_nvm        = e1000_release_nvm_generic;
-       func->update_nvm         = e1000_update_nvm_checksum_generic;
-       func->valid_led_default  = e1000_valid_led_default_generic;
-       func->validate_nvm       = e1000_validate_nvm_checksum_generic;
-       func->write_nvm          = e1000_write_nvm_microwire;
+       nvm->ops.acquire            = e1000_acquire_nvm_generic;
+       nvm->ops.read               = e1000_read_nvm_microwire;
+       nvm->ops.release            = e1000_release_nvm_generic;
+       nvm->ops.update             = e1000_update_nvm_checksum_generic;
+       nvm->ops.valid_led_default  = e1000_valid_led_default_generic;
+       nvm->ops.validate           = e1000_validate_nvm_checksum_generic;
+       nvm->ops.write              = e1000_write_nvm_microwire;
 
        return E1000_SUCCESS;
 }
@@ -157,14 +153,10 @@
 /**
  * e1000_init_mac_params_82540 - Init MAC func ptrs.
  * @hw: pointer to the HW structure
- *
- * This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_mac_params_82540(struct e1000_hw *hw)
+static s32 e1000_init_mac_params_82540(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_mac_params_82540");
@@ -175,14 +167,14 @@
        case E1000_DEV_ID_82545GM_FIBER:
        case E1000_DEV_ID_82546EB_FIBER:
        case E1000_DEV_ID_82546GB_FIBER:
-               hw->media_type = e1000_media_type_fiber;
+               hw->phy.media_type = e1000_media_type_fiber;
                break;
        case E1000_DEV_ID_82545GM_SERDES:
        case E1000_DEV_ID_82546GB_SERDES:
-               hw->media_type = e1000_media_type_internal_serdes;
+               hw->phy.media_type = e1000_media_type_internal_serdes;
                break;
        default:
-               hw->media_type = e1000_media_type_copper;
+               hw->phy.media_type = e1000_media_type_copper;
                break;
        }
 
@@ -194,28 +186,30 @@
        /* Function pointers */
 
        /* bus type/speed/width */
-       func->get_bus_info = e1000_get_bus_info_pci_generic;
+       mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
+       /* function id */
+       mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
        /* reset */
-       func->reset_hw = e1000_reset_hw_82540;
+       mac->ops.reset_hw = e1000_reset_hw_82540;
        /* hw initialization */
-       func->init_hw = e1000_init_hw_82540;
+       mac->ops.init_hw = e1000_init_hw_82540;
        /* link setup */
-       func->setup_link = e1000_setup_link_generic;
+       mac->ops.setup_link = e1000_setup_link_generic;
        /* physical interface setup */
-       func->setup_physical_interface =
-               (hw->media_type == e1000_media_type_copper)
+       mac->ops.setup_physical_interface =
+               (hw->phy.media_type == e1000_media_type_copper)
                        ? e1000_setup_copper_link_82540
                        : e1000_setup_fiber_serdes_link_82540;
        /* check for link */
-       switch (hw->media_type) {
+       switch (hw->phy.media_type) {
        case e1000_media_type_copper:
-               func->check_for_link = e1000_check_for_copper_link_generic;
+               mac->ops.check_for_link = e1000_check_for_copper_link_generic;
                break;
        case e1000_media_type_fiber:
-               func->check_for_link = e1000_check_for_fiber_link_generic;
+               mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
                break;
        case e1000_media_type_internal_serdes:
-               func->check_for_link = e1000_check_for_serdes_link_generic;
+               mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
                break;
        default:
                ret_val = -E1000_ERR_CONFIG;
@@ -223,27 +217,27 @@
                break;
        }
        /* link info */
-       func->get_link_up_info =
-               (hw->media_type == e1000_media_type_copper)
+       mac->ops.get_link_up_info =
+               (hw->phy.media_type == e1000_media_type_copper)
                        ? e1000_get_speed_and_duplex_copper_generic
                        : e1000_get_speed_and_duplex_fiber_serdes_generic;
        /* multicast address update */
-       func->mc_addr_list_update = e1000_mc_addr_list_update_generic;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
        /* writing VFTA */
-       func->write_vfta = e1000_write_vfta_generic;
+       mac->ops.write_vfta = e1000_write_vfta_generic;
        /* clearing VFTA */
-       func->clear_vfta = e1000_clear_vfta_generic;
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
        /* setting MTA */
-       func->mta_set = e1000_mta_set_generic;
+       mac->ops.mta_set = e1000_mta_set_generic;
        /* setup LED */
-       func->setup_led = e1000_setup_led_generic;
+       mac->ops.setup_led = e1000_setup_led_generic;
        /* cleanup LED */
-       func->cleanup_led = e1000_cleanup_led_generic;
+       mac->ops.cleanup_led = e1000_cleanup_led_generic;
        /* turn on/off LED */
-       func->led_on = e1000_led_on_generic;
-       func->led_off = e1000_led_off_generic;
+       mac->ops.led_on = e1000_led_on_generic;
+       mac->ops.led_off = e1000_led_off_generic;
        /* clear hardware counters */
-       func->clear_hw_cntrs = e1000_clear_hw_cntrs_82540;
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82540;
 
 out:
        return ret_val;
@@ -253,28 +247,24 @@
  * e1000_init_function_pointers_82540 - Init func ptrs.
  * @hw: pointer to the HW structure
  *
- * The only function explicitly called by the api module to initialize
- * all function pointers and parameters.
+ * Called to initialize all function pointers and parameters.
  **/
-void
-e1000_init_function_pointers_82540(struct e1000_hw *hw)
+void e1000_init_function_pointers_82540(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_init_function_pointers_82540");
 
-       hw->func.init_mac_params = e1000_init_mac_params_82540;
-       hw->func.init_nvm_params = e1000_init_nvm_params_82540;
-       hw->func.init_phy_params = e1000_init_phy_params_82540;
+       hw->mac.ops.init_params = e1000_init_mac_params_82540;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82540;
+       hw->phy.ops.init_params = e1000_init_phy_params_82540;
 }
 
 /**
  *  e1000_reset_hw_82540 - Reset hardware
  *  @hw: pointer to the HW structure
  *
- *  This resets the hardware into a known state.  This is a
- *  function pointer entry point called by the api module.
+ *  This resets the hardware into a known state.
  **/
-STATIC s32
-e1000_reset_hw_82540(struct e1000_hw *hw)
+static s32 e1000_reset_hw_82540(struct e1000_hw *hw)
 {
        u32 ctrl, icr, manc;
        s32 ret_val = E1000_SUCCESS;
@@ -288,7 +278,8 @@
        E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
        E1000_WRITE_FLUSH(hw);
 
-       /* Delay to allow any outstanding PCI transactions to complete
+       /*
+        * Delay to allow any outstanding PCI transactions to complete
         * before resetting the device.
         */
        msec_delay(10);
@@ -302,7 +293,8 @@
                E1000_WRITE_REG(hw, E1000_CTRL_DUP, ctrl | E1000_CTRL_RST);
                break;
        default:
-               /* These controllers can't ack the 64-bit write when
+               /*
+                * These controllers can't ack the 64-bit write when
                 * issuing the reset, so we use IO-mapping as a
                 * workaround to issue the reset.
                 */
@@ -328,11 +320,9 @@
  *  e1000_init_hw_82540 - Initialize hardware
  *  @hw: pointer to the HW structure
  *
- *  This inits the hardware readying it for operation.  This is a
- *  function pointer entry point called by the api module.
+ *  This inits the hardware readying it for operation.
  **/
-STATIC s32
-e1000_init_hw_82540(struct e1000_hw *hw)
+static s32 e1000_init_hw_82540(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 txdctl, ctrl_ext;
@@ -345,16 +335,16 @@
        ret_val = e1000_id_led_init_generic(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
-               goto out;
+               /* This is not fatal and we should not stop init due to this */
        }
 
        /* Disabling VLAN filtering */
        DEBUGOUT("Initializing the IEEE VLAN\n");
-       if (mac->type < e1000_82545_rev_3) {
+       if (mac->type < e1000_82545_rev_3)
                E1000_WRITE_REG(hw, E1000_VET, 0);
-       }
-       e1000_clear_vfta(hw);
 
+       mac->ops.clear_vfta(hw);
+
        /* Setup the receive address. */
        e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
 
@@ -362,7 +352,8 @@
        DEBUGOUT("Zeroing the MTA\n");
        for (i = 0; i < mac->mta_reg_count; i++) {
                E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
-               /* Avoid back to back register writes by adding the register
+               /*
+                * Avoid back to back register writes by adding the register
                 * read (flush).  This is to protect against some strange
                 * bridge configurations that may issue Memory Write Block
                 * (MWB) to our register space.  The *_rev_3 hardware at
@@ -376,14 +367,15 @@
                e1000_pcix_mmrbc_workaround_generic(hw);
 
        /* Setup link and flow control */
-       ret_val = e1000_setup_link(hw);
+       ret_val = mac->ops.setup_link(hw);
 
-       txdctl = E1000_READ_REG(hw, E1000_TXDCTL);
+       txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
        txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
                 E1000_TXDCTL_FULL_TX_DESC_WB;
-       E1000_WRITE_REG(hw, E1000_TXDCTL, txdctl);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
 
-       /* Clear all of the statistics registers (clear on read).  It is
+       /*
+        * 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.
@@ -393,13 +385,14 @@
        if ((hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER) ||
            (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3)) {
                ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
-               /* Relaxed ordering must be disabled to avoid a parity
-                * error crash in a PCI slot. */
+               /*
+                * Relaxed ordering must be disabled to avoid a parity
+                * error crash in a PCI slot.
+                */
                ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
                E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
        }
 
-out:
        return ret_val;
 }
 
@@ -410,11 +403,9 @@
  *  Calls the appropriate function to configure 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.  If link is
- *  not established, we return -E1000_ERR_PHY (-2).  This is a function
- *  pointer entry point called by the api module.
+ *  not established, we return -E1000_ERR_PHY (-2).
  **/
-STATIC s32
-e1000_setup_copper_link_82540(struct e1000_hw *hw)
+static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32 ret_val = E1000_SUCCESS;
@@ -433,11 +424,11 @@
 
        if (hw->mac.type == e1000_82545_rev_3 ||
            hw->mac.type == e1000_82546_rev_3) {
-               ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &data);
+               ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, 
&data);
                if (ret_val)
                        goto out;
                data |= 0x00000008;
-               ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, data);
+               ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, 
data);
                if (ret_val)
                        goto out;
        }
@@ -459,11 +450,9 @@
  *  Set the output amplitude to the value in the EEPROM and adjust the VCO
  *  speed to improve Bit Error Rate (BER) performance.  Configures collision
  *  distance and flow control for fiber and serdes links.  Upon successful
- *  setup, poll for link.  This is a function pointer entry point called by
- *  the api module.
+ *  setup, poll for link.
  **/
-STATIC s32
-e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw)
+static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val = E1000_SUCCESS;
@@ -473,8 +462,9 @@
        switch (mac->type) {
        case e1000_82545_rev_3:
        case e1000_82546_rev_3:
-               if (hw->media_type == e1000_media_type_internal_serdes) {
-                       /* If we're on serdes media, adjust the output
+               if (hw->phy.media_type == e1000_media_type_internal_serdes) {
+                       /*
+                        * If we're on serdes media, adjust the output
                         * amplitude to value set in the EEPROM.
                         */
                        ret_val = e1000_adjust_serdes_amplitude_82540(hw);
@@ -499,25 +489,23 @@
  *  e1000_adjust_serdes_amplitude_82540 - Adjust amplitude based on EEPROM
  *  @hw: pointer to the HW structure
  *
- *  Adjust the SERDES ouput amplitude based on the EEPROM settings.
+ *  Adjust the SERDES output amplitude based on the EEPROM settings.
  **/
-static s32
-e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw)
+static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
        u16 nvm_data;
 
        DEBUGFUNC("e1000_adjust_serdes_amplitude_82540");
 
-       ret_val = e1000_read_nvm(hw, NVM_SERDES_AMPLITUDE, 1, &nvm_data);
-       if (ret_val) {
+       ret_val = hw->nvm.ops.read(hw, NVM_SERDES_AMPLITUDE, 1, &nvm_data);
+       if (ret_val)
                goto out;
-       }
 
        if (nvm_data != NVM_RESERVED_WORD) {
                /* Adjust serdes output amplitude only. */
                nvm_data &= NVM_SERDES_AMPLITUDE_MASK;
-               ret_val = e1000_write_phy_reg(hw,
+               ret_val = hw->phy.ops.write_reg(hw,
                                             M88E1000_PHY_EXT_CTRL,
                                             nvm_data);
                if (ret_val)
@@ -534,8 +522,7 @@
  *
  *  Set the VCO speed to improve Bit Error Rate (BER) performance.
  **/
-static s32
-e1000_set_vco_speed_82540(struct e1000_hw *hw)
+static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw)
 {
        s32  ret_val = E1000_SUCCESS;
        u16 default_page = 0;
@@ -545,41 +532,41 @@
 
        /* Set PHY register 30, page 5, bit 8 to 0 */
 
-       ret_val = e1000_read_phy_reg(hw,
+       ret_val = hw->phy.ops.read_reg(hw,
                                    M88E1000_PHY_PAGE_SELECT,
                                    &default_page);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
+       ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
        if (ret_val)
                goto out;
 
        phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
        if (ret_val)
                goto out;
 
        /* Set PHY register 30, page 4, bit 11 to 1 */
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
+       ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
        if (ret_val)
                goto out;
 
        phy_data |= M88E1000_PHY_VCO_REG_BIT11;
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
                                      default_page);
 
 out:
@@ -595,8 +582,7 @@
  *    1.  Do a PHY soft reset.
  *    2.  Restart auto-negotiation or force link.
  **/
-static s32
-e1000_set_phy_mode_82540(struct e1000_hw *hw)
+static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val = E1000_SUCCESS;
@@ -607,22 +593,22 @@
        if (hw->mac.type != e1000_82545_rev_3)
                goto out;
 
-       ret_val = e1000_read_nvm(hw, NVM_PHY_CLASS_WORD, 1, &nvm_data);
+       ret_val = hw->nvm.ops.read(hw, NVM_PHY_CLASS_WORD, 1, &nvm_data);
        if (ret_val) {
                ret_val = -E1000_ERR_PHY;
                goto out;
        }
 
        if ((nvm_data != NVM_RESERVED_WORD) && (nvm_data & NVM_PHY_CLASS_A)) {
-               ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
-                                             0x000B);
+               ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
+                                             0x000B);
                if (ret_val) {
                        ret_val = -E1000_ERR_PHY;
                        goto out;
                }
-               ret_val = e1000_write_phy_reg(hw,
-                                            M88E1000_PHY_GEN_CONTROL,
-                                            0x8104);
+               ret_val = hw->phy.ops.write_reg(hw,
+                                             M88E1000_PHY_GEN_CONTROL,
+                                             0x8104);
                if (ret_val) {
                        ret_val = -E1000_ERR_PHY;
                        goto out;
@@ -636,42 +622,55 @@
 }
 
 /**
+ * e1000_power_down_phy_copper_82540 - Remove link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, remove the link.
+ **/
+static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw)
+{
+       /* If the management interface is not enabled, then power down */
+       if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))
+               e1000_power_down_phy_copper(hw);
+
+       return;
+}
+
+/**
  *  e1000_clear_hw_cntrs_82540 - 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_82540(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw)
 {
-       volatile u32 temp;
-
        DEBUGFUNC("e1000_clear_hw_cntrs_82540");
 
        e1000_clear_hw_cntrs_base_generic(hw);
 
-       temp = E1000_READ_REG(hw, E1000_PRC64);
-       temp = E1000_READ_REG(hw, E1000_PRC127);
-       temp = E1000_READ_REG(hw, E1000_PRC255);
-       temp = E1000_READ_REG(hw, E1000_PRC511);
-       temp = E1000_READ_REG(hw, E1000_PRC1023);
-       temp = E1000_READ_REG(hw, E1000_PRC1522);
-       temp = E1000_READ_REG(hw, E1000_PTC64);
-       temp = E1000_READ_REG(hw, E1000_PTC127);
-       temp = E1000_READ_REG(hw, E1000_PTC255);
-       temp = E1000_READ_REG(hw, E1000_PTC511);
-       temp = E1000_READ_REG(hw, E1000_PTC1023);
-       temp = E1000_READ_REG(hw, E1000_PTC1522);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_ALGNERRC);
-       temp = E1000_READ_REG(hw, E1000_RXERRC);
-       temp = E1000_READ_REG(hw, E1000_TNCRS);
-       temp = E1000_READ_REG(hw, E1000_CEXTERR);
-       temp = E1000_READ_REG(hw, E1000_TSCTC);
-       temp = E1000_READ_REG(hw, E1000_TSCTFC);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_MGTPRC);
-       temp = E1000_READ_REG(hw, E1000_MGTPDC);
-       temp = E1000_READ_REG(hw, E1000_MGTPTC);
+       E1000_READ_REG(hw, E1000_MGTPRC);
+       E1000_READ_REG(hw, E1000_MGTPDC);
+       E1000_READ_REG(hw, E1000_MGTPTC);
 }
 
Index: dev/em/e1000_hw.h
===================================================================
--- dev/em/e1000_hw.h   (Revision 28889)
+++ dev/em/e1000_hw.h   (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,10 +29,9 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_hw.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_hw.h,v 1.2 2008/11/26 23:57:23 jfv Exp $*/
 
-
 #ifndef _E1000_HW_H_
 #define _E1000_HW_H_
 
@@ -42,9 +41,7 @@
 
 struct e1000_hw;
 
-#ifndef NO_82542_SUPPORT
 #define E1000_DEV_ID_82542                    0x1000
-#endif
 #define E1000_DEV_ID_82543GC_FIBER            0x1001
 #define E1000_DEV_ID_82543GC_COPPER           0x1004
 #define E1000_DEV_ID_82544EI_COPPER           0x1008
@@ -86,6 +83,7 @@
 #define E1000_DEV_ID_82571EB_SERDES_DUAL      0x10D9
 #define E1000_DEV_ID_82571EB_SERDES_QUAD      0x10DA
 #define E1000_DEV_ID_82571EB_QUAD_COPPER      0x10A4
+#define E1000_DEV_ID_82571PT_QUAD_COPPER      0x10D5
 #define E1000_DEV_ID_82571EB_QUAD_FIBER       0x10A5
 #define E1000_DEV_ID_82571EB_QUAD_COPPER_LP   0x10BC
 #define E1000_DEV_ID_82572EI_COPPER           0x107D
@@ -95,6 +93,7 @@
 #define E1000_DEV_ID_82573E                   0x108B
 #define E1000_DEV_ID_82573E_IAMT              0x108C
 #define E1000_DEV_ID_82573L                   0x109A
+#define E1000_DEV_ID_82574L                   0x10D3
 #define E1000_DEV_ID_80003ES2LAN_COPPER_DPT   0x1096
 #define E1000_DEV_ID_80003ES2LAN_SERDES_DPT   0x1098
 #define E1000_DEV_ID_80003ES2LAN_COPPER_SPT   0x10BA
@@ -106,17 +105,28 @@
 #define E1000_DEV_ID_ICH8_IFE_GT              0x10C4
 #define E1000_DEV_ID_ICH8_IFE_G               0x10C5
 #define E1000_DEV_ID_ICH8_IGP_M               0x104D
+#define E1000_DEV_ID_ICH9_IGP_M               0x10BF
+#define E1000_DEV_ID_ICH9_IGP_M_AMT           0x10F5
+#define E1000_DEV_ID_ICH9_IGP_M_V             0x10CB
 #define E1000_DEV_ID_ICH9_IGP_AMT             0x10BD
+#define E1000_DEV_ID_ICH9_BM                  0x10E5
 #define E1000_DEV_ID_ICH9_IGP_C               0x294C
 #define E1000_DEV_ID_ICH9_IFE                 0x10C0
 #define E1000_DEV_ID_ICH9_IFE_GT              0x10C3
 #define E1000_DEV_ID_ICH9_IFE_G               0x10C2
+#define E1000_DEV_ID_ICH10_R_BM_LM            0x10CC
+#define E1000_DEV_ID_ICH10_R_BM_LF            0x10CD
+#define E1000_DEV_ID_ICH10_R_BM_V             0x10CE
+#define E1000_DEV_ID_ICH10_D_BM_LM            0x10DE
+#define E1000_DEV_ID_ICH10_D_BM_LF            0x10DF
+#define E1000_DEV_ID_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_VF                 0x10CA
 #define E1000_DEV_ID_82575EB_COPPER           0x10A7
 #define E1000_DEV_ID_82575EB_FIBER_SERDES     0x10A9
-#define E1000_DEV_ID_82575EM_COPPER           0x10AA
-#define E1000_DEV_ID_82575EM_FIBER_SERDES     0x10AC
 #define E1000_DEV_ID_82575GB_QUAD_COPPER      0x10D6
-
 #define E1000_REVISION_0 0
 #define E1000_REVISION_1 1
 #define E1000_REVISION_2 2
@@ -126,11 +136,9 @@
 #define E1000_FUNC_0     0
 #define E1000_FUNC_1     1
 
-typedef enum {
+enum e1000_mac_type {
        e1000_undefined = 0,
-#ifndef NO_82542_SUPPORT
        e1000_82542,
-#endif
        e1000_82543,
        e1000_82544,
        e1000_82540,
@@ -145,39 +153,43 @@
        e1000_82571,
        e1000_82572,
        e1000_82573,
+       e1000_82574,
        e1000_80003es2lan,
        e1000_ich8lan,
        e1000_ich9lan,
+       e1000_ich10lan,
        e1000_82575,
-       e1000_num_macs  /* List is 1-based, so subtract 1 for true count. */
-} e1000_mac_type;
+       e1000_82576,
+       e1000_vfadapt,
+       e1000_num_macs  /* List is 1-based, so subtract 1 for TRUE count. */
+};
 
-typedef enum {
+enum e1000_media_type {
        e1000_media_type_unknown = 0,
        e1000_media_type_copper = 1,
        e1000_media_type_fiber = 2,
        e1000_media_type_internal_serdes = 3,
        e1000_num_media_types
-} e1000_media_type;
+};
 
-typedef enum {
+enum e1000_nvm_type {
        e1000_nvm_unknown = 0,
        e1000_nvm_none,
        e1000_nvm_eeprom_spi,
        e1000_nvm_eeprom_microwire,
        e1000_nvm_flash_hw,
        e1000_nvm_flash_sw
-} e1000_nvm_type;
+};
 
-typedef enum {
+enum e1000_nvm_override {
        e1000_nvm_override_none = 0,
        e1000_nvm_override_spi_small,
        e1000_nvm_override_spi_large,
        e1000_nvm_override_microwire_small,
        e1000_nvm_override_microwire_large
-} e1000_nvm_override;
+};
 
-typedef enum {
+enum e1000_phy_type {
        e1000_phy_unknown = 0,
        e1000_phy_none,
        e1000_phy_m88,
@@ -186,17 +198,19 @@
        e1000_phy_gg82563,
        e1000_phy_igp_3,
        e1000_phy_ife,
-} e1000_phy_type;
+       e1000_phy_bm,
+       e1000_phy_vf,
+};
 
-typedef enum {
+enum e1000_bus_type {
        e1000_bus_type_unknown = 0,
        e1000_bus_type_pci,
        e1000_bus_type_pcix,
        e1000_bus_type_pci_express,
        e1000_bus_type_reserved
-} e1000_bus_type;
+};
 
-typedef enum {
+enum e1000_bus_speed {
        e1000_bus_speed_unknown = 0,
        e1000_bus_speed_33,
        e1000_bus_speed_66,
@@ -204,83 +218,98 @@
        e1000_bus_speed_120,
        e1000_bus_speed_133,
        e1000_bus_speed_2500,
+       e1000_bus_speed_5000,
        e1000_bus_speed_reserved
-} e1000_bus_speed;
+};
 
-typedef enum {
+enum e1000_bus_width {
        e1000_bus_width_unknown = 0,
        e1000_bus_width_pcie_x1,
        e1000_bus_width_pcie_x2,
        e1000_bus_width_pcie_x4 = 4,
+       e1000_bus_width_pcie_x8 = 8,
        e1000_bus_width_32,
        e1000_bus_width_64,
        e1000_bus_width_reserved
-} e1000_bus_width;
+};
 
-typedef enum {
+enum e1000_1000t_rx_status {
        e1000_1000t_rx_status_not_ok = 0,
        e1000_1000t_rx_status_ok,
        e1000_1000t_rx_status_undefined = 0xFF
-} e1000_1000t_rx_status;
+};
 
-typedef enum {
+enum e1000_rev_polarity {
        e1000_rev_polarity_normal = 0,
        e1000_rev_polarity_reversed,
        e1000_rev_polarity_undefined = 0xFF
-} e1000_rev_polarity;
+};
 
-typedef enum {
+enum e1000_fc_mode {
        e1000_fc_none = 0,
        e1000_fc_rx_pause,
        e1000_fc_tx_pause,
        e1000_fc_full,
        e1000_fc_default = 0xFF
-} e1000_fc_mode;
+};
 
-typedef enum {
+enum e1000_ffe_config {
        e1000_ffe_config_enabled = 0,
        e1000_ffe_config_active,
        e1000_ffe_config_blocked
-} e1000_ffe_config;
+};
 
-typedef enum {
+enum e1000_dsp_config {
        e1000_dsp_config_disabled = 0,
        e1000_dsp_config_enabled,
        e1000_dsp_config_activated,
        e1000_dsp_config_undefined = 0xFF
-} e1000_dsp_config;
+};
 
+enum e1000_ms_type {
+       e1000_ms_hw_default = 0,
+       e1000_ms_force_master,
+       e1000_ms_force_slave,
+       e1000_ms_auto
+};
+
+enum e1000_smart_speed {
+       e1000_smart_speed_default = 0,
+       e1000_smart_speed_on,
+       e1000_smart_speed_off
+};
+
 /* Receive Descriptor */
 struct e1000_rx_desc {
-       u64 buffer_addr; /* Address of the descriptor's data buffer */
-       u16 length;      /* Length of data DMAed into data buffer */
-       u16 csum;        /* Packet checksum */
-       u8  status;      /* Descriptor status */
-       u8  errors;      /* Descriptor Errors */
-       u16 special;
+       __le64 buffer_addr; /* Address of the descriptor's data buffer */
+       __le16 length;      /* Length of data DMAed into data buffer */
+       __le16 csum;        /* Packet checksum */
+       u8  status;         /* Descriptor status */
+       u8  errors;         /* Descriptor Errors */
+       __le16 special;
 };
 
 /* Receive Descriptor - Extended */
 union e1000_rx_desc_extended {
        struct {
-               u64 buffer_addr;
-               u64 reserved;
+               __le64 buffer_addr;
+               __le64 reserved;
        } read;
        struct {
                struct {
-                       u32 mrq;              /* Multiple Rx Queues */
+                       __le32 mrq;           /* Multiple Rx Queues */
                        union {
-                               u32 rss;            /* RSS Hash */
+                               __le32 rss;         /* RSS Hash */
                                struct {
-                                       u16 ip_id;  /* IP id */
-                                       u16 csum;   /* Packet Checksum */
+                                       __le16 ip_id;  /* IP id */
+                                       __le16 csum;   /* Packet Checksum */
                                } csum_ip;
                        } hi_dword;
                } lower;
                struct {
-                       u32 status_error;     /* ext status/error */
-                       u16 length;
-                       u16 vlan;             /* VLAN tag */
+                       __le32 status_error;  /* ext status/error */
+                       __le16 length;
+                       __le16 vlan;          /* VLAN tag */
                } upper;
        } wb;  /* writeback */
 };
@@ -290,49 +319,49 @@
 union e1000_rx_desc_packet_split {
        struct {
                /* one buffer for protocol header(s), three data buffers */
-               u64 buffer_addr[MAX_PS_BUFFERS];
+               __le64 buffer_addr[MAX_PS_BUFFERS];
        } read;
        struct {
                struct {
-                       u32 mrq;              /* Multiple Rx Queues */
+                       __le32 mrq;           /* Multiple Rx Queues */
                        union {
-                               u32 rss;              /* RSS Hash */
+                               __le32 rss;           /* RSS Hash */
                                struct {
-                                       u16 ip_id;    /* IP id */
-                                       u16 csum;     /* Packet Checksum */
+                                       __le16 ip_id;    /* IP id */
+                                       __le16 csum;     /* Packet Checksum */
                                } csum_ip;
                        } hi_dword;
                } lower;
                struct {
-                       u32 status_error;     /* ext status/error */
-                       u16 length0;          /* length of buffer 0 */
-                       u16 vlan;             /* VLAN tag */
+                       __le32 status_error;  /* ext status/error */
+                       __le16 length0;       /* length of buffer 0 */
+                       __le16 vlan;          /* VLAN tag */
                } middle;
                struct {
-                       u16 header_status;
-                       u16 length[3];        /* length of buffers 1-3 */
+                       __le16 header_status;
+                       __le16 length[3];     /* length of buffers 1-3 */
                } upper;
-               u64 reserved;
+               __le64 reserved;
        } wb; /* writeback */
 };
 
 /* Transmit Descriptor */
 struct e1000_tx_desc {
-       u64 buffer_addr;      /* Address of the descriptor's data buffer */
+       __le64 buffer_addr;   /* Address of the descriptor's data buffer */
        union {
-               u32 data;
+               __le32 data;
                struct {
-                       u16 length;    /* Data buffer length */
-                       u8 cso;        /* Checksum offset */
-                       u8 cmd;        /* Descriptor control */
+                       __le16 length;    /* Data buffer length */
+                       u8 cso;           /* Checksum offset */
+                       u8 cmd;           /* Descriptor control */
                } flags;
        } lower;
        union {
-               u32 data;
+               __le32 data;
                struct {
-                       u8 status;     /* Descriptor status */
-                       u8 css;        /* Checksum start */
-                       u16 special;
+                       u8 status;        /* Descriptor status */
+                       u8 css;           /* Checksum start */
+                       __le16 special;
                } fields;
        } upper;
 };
@@ -340,49 +369,49 @@
 /* Offload Context Descriptor */
 struct e1000_context_desc {
        union {
-               u32 ip_config;
+               __le32 ip_config;
                struct {
-                       u8 ipcss;      /* IP checksum start */
-                       u8 ipcso;      /* IP checksum offset */
-                       u16 ipcse;     /* IP checksum end */
+                       u8 ipcss;         /* IP checksum start */
+                       u8 ipcso;         /* IP checksum offset */
+                       __le16 ipcse;     /* IP checksum end */
                } ip_fields;
        } lower_setup;
        union {
-               u32 tcp_config;
+               __le32 tcp_config;
                struct {
-                       u8 tucss;      /* TCP checksum start */
-                       u8 tucso;      /* TCP checksum offset */
-                       u16 tucse;     /* TCP checksum end */
+                       u8 tucss;         /* TCP checksum start */
+                       u8 tucso;         /* TCP checksum offset */
+                       __le16 tucse;     /* TCP checksum end */
                } tcp_fields;
        } upper_setup;
-       u32 cmd_and_length;
+       __le32 cmd_and_length;
        union {
-               u32 data;
+               __le32 data;
                struct {
-                       u8 status;     /* Descriptor status */
-                       u8 hdr_len;    /* Header length */
-                       u16 mss;       /* Maximum segment size */
+                       u8 status;        /* Descriptor status */
+                       u8 hdr_len;       /* Header length */
+                       __le16 mss;       /* Maximum segment size */
                } fields;
        } tcp_seg_setup;
 };
 
 /* Offload data descriptor */
 struct e1000_data_desc {
-       u64 buffer_addr;   /* Address of the descriptor's buffer address */
+       __le64 buffer_addr;   /* Address of the descriptor's buffer address */
        union {
-               u32 data;
+               __le32 data;
                struct {
-                       u16 length;    /* Data buffer length */
+                       __le16 length;    /* Data buffer length */
                        u8 typ_len_ext;
                        u8 cmd;
                } flags;
        } lower;
        union {
-               u32 data;
+               __le32 data;
                struct {
-                       u8 status;     /* Descriptor status */
-                       u8 popts;      /* Packet Options */
-                       u16 special;   /* */
+                       u8 status;        /* Descriptor status */
+                       u8 popts;         /* Packet Options */
+                       __le16 special;
                } fields;
        } upper;
 };
@@ -419,10 +448,8 @@
        u64 bprc;
        u64 mprc;
        u64 gptc;
-       u64 gorcl;
-       u64 gorch;
-       u64 gotcl;
-       u64 gotch;
+       u64 gorc;
+       u64 gotc;
        u64 rnbc;
        u64 ruc;
        u64 rfc;
@@ -431,10 +458,8 @@
        u64 mgprc;
        u64 mgpdc;
        u64 mgptc;
-       u64 torl;
-       u64 torh;
-       u64 totl;
-       u64 toth;
+       u64 tor;
+       u64 tot;
        u64 tpr;
        u64 tpt;
        u64 ptc64;
@@ -463,15 +488,46 @@
        u64 rpthc;
        u64 hgptc;
        u64 htcbdpc;
-       u64 hgorcl;
-       u64 hgorch;
-       u64 hgotcl;
-       u64 hgotch;
+       u64 hgorc;
+       u64 hgotc;
        u64 lenerrs;
        u64 scvpc;
        u64 hrmpc;
+       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;
        u32 receive_errors;
@@ -522,82 +578,85 @@
 #include "e1000_nvm.h"
 #include "e1000_manage.h"
 
-struct e1000_functions {
+struct e1000_mac_operations {
        /* Function pointers for the MAC. */
-       s32       (*init_mac_params)(struct e1000_hw *);
-       s32       (*blink_led)(struct e1000_hw *);
-       s32       (*check_for_link)(struct e1000_hw *);
-       boolean_t (*check_mng_mode)(struct e1000_hw *hw);
-       s32       (*cleanup_led)(struct e1000_hw *);
-       void      (*clear_hw_cntrs)(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 *);
-       s32       (*led_on)(struct e1000_hw *);
-       s32       (*led_off)(struct e1000_hw *);
-       void      (*mc_addr_list_update)(struct e1000_hw *, u8 *, u32, u32,
-                                        u32);
-       void      (*remove_device)(struct e1000_hw *);
-       s32       (*reset_hw)(struct e1000_hw *);
-       s32       (*init_hw)(struct e1000_hw *);
-       s32       (*setup_link)(struct e1000_hw *);
-       s32       (*setup_physical_interface)(struct e1000_hw *);
-       s32       (*setup_led)(struct e1000_hw *);
-       void      (*write_vfta)(struct e1000_hw *, u32, u32);
-       void      (*mta_set)(struct e1000_hw *, u32);
-       void      (*config_collision_dist)(struct e1000_hw*);
-       void      (*rar_set)(struct e1000_hw*, u8*, u32);
-       s32       (*validate_mdi_setting)(struct e1000_hw*);
-       s32       (*mng_host_if_write)(struct e1000_hw*, u8*, u16, u16, u8*);
-       s32       (*mng_write_cmd_header)(struct e1000_hw *hw,
-                           struct e1000_host_mng_command_header*);
-       s32       (*mng_enable_host_if)(struct e1000_hw*);
-       s32       (*wait_autoneg)(struct e1000_hw*);
+       s32  (*init_params)(struct e1000_hw *);
+       s32  (*blink_led)(struct e1000_hw *);
+       s32  (*check_for_link)(struct e1000_hw *);
+       bool (*check_mng_mode)(struct e1000_hw *hw);
+       s32  (*cleanup_led)(struct e1000_hw *);
+       void (*clear_hw_cntrs)(struct e1000_hw *);
+       void (*clear_vfta)(struct e1000_hw *);
+       s32  (*get_bus_info)(struct e1000_hw *);
+       void (*set_lan_id)(struct e1000_hw *);
+       s32  (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+       s32  (*led_on)(struct e1000_hw *);
+       s32  (*led_off)(struct e1000_hw *);
+       void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32);
+       s32  (*reset_hw)(struct e1000_hw *);
+       s32  (*init_hw)(struct e1000_hw *);
+       void (*shutdown_serdes)(struct e1000_hw *);
+       s32  (*setup_link)(struct e1000_hw *);
+       s32  (*setup_physical_interface)(struct e1000_hw *);
+       s32  (*setup_led)(struct e1000_hw *);
+       void (*write_vfta)(struct e1000_hw *, u32, u32);
+       void (*mta_set)(struct e1000_hw *, u32);
+       void (*config_collision_dist)(struct e1000_hw *);
+       void (*rar_set)(struct e1000_hw *, u8*, u32);
+       s32  (*read_mac_addr)(struct e1000_hw *);
+       s32  (*validate_mdi_setting)(struct e1000_hw *);
+       s32  (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*);
+       s32  (*mng_write_cmd_header)(struct e1000_hw *hw,
+                      struct e1000_host_mng_command_header*);
+       s32  (*mng_enable_host_if)(struct e1000_hw *);
+       s32  (*wait_autoneg)(struct e1000_hw *);
+};
 
-       /* Function pointers for the PHY. */
-       s32       (*init_phy_params)(struct e1000_hw *);
-       s32       (*acquire_phy)(struct e1000_hw *);
-       s32       (*check_polarity)(struct e1000_hw *);
-       s32       (*check_reset_block)(struct e1000_hw *);
-       s32       (*commit_phy)(struct e1000_hw *);
-       s32       (*force_speed_duplex)(struct e1000_hw *);
-       s32       (*get_cfg_done)(struct e1000_hw *hw);
-       s32       (*get_cable_length)(struct e1000_hw *);
-       s32       (*get_phy_info)(struct e1000_hw *);
-       s32       (*read_phy_reg)(struct e1000_hw *, u32, u16 *);
-       void      (*release_phy)(struct e1000_hw *);
-       s32       (*reset_phy)(struct e1000_hw *);
-       s32       (*set_d0_lplu_state)(struct e1000_hw *, boolean_t);
-       s32       (*set_d3_lplu_state)(struct e1000_hw *, boolean_t);
-       s32       (*write_phy_reg)(struct e1000_hw *, u32, u16);
+struct e1000_phy_operations {
+       s32  (*init_params)(struct e1000_hw *);
+       s32  (*acquire)(struct e1000_hw *);
+       s32  (*cfg_on_link_up)(struct e1000_hw *);
+       s32  (*check_polarity)(struct e1000_hw *);
+       s32  (*check_reset_block)(struct e1000_hw *);
+       s32  (*commit)(struct e1000_hw *);
+       s32  (*force_speed_duplex)(struct e1000_hw *);
+       s32  (*get_cfg_done)(struct e1000_hw *hw);
+       s32  (*get_cable_length)(struct e1000_hw *);
+       s32  (*get_info)(struct e1000_hw *);
+       s32  (*read_reg)(struct e1000_hw *, u32, u16 *);
+       void (*release)(struct e1000_hw *);
+       s32  (*reset)(struct e1000_hw *);
+       s32  (*set_d0_lplu_state)(struct e1000_hw *, bool);
+       s32  (*set_d3_lplu_state)(struct e1000_hw *, bool);
+       s32  (*write_reg)(struct e1000_hw *, u32, u16);
+       void (*power_up)(struct e1000_hw *);
+       void (*power_down)(struct e1000_hw *);
+};
 
-       /* Function pointers for the NVM. */
-       s32       (*init_nvm_params)(struct e1000_hw *);
-       s32       (*acquire_nvm)(struct e1000_hw *);
-       s32       (*read_nvm)(struct e1000_hw *, u16, u16, u16 *);
-       void      (*release_nvm)(struct e1000_hw *);
-       void      (*reload_nvm)(struct e1000_hw *);
-       s32       (*update_nvm)(struct e1000_hw *);
-       s32       (*valid_led_default)(struct e1000_hw *, u16 *);
-       s32       (*validate_nvm)(struct e1000_hw *);
-       s32       (*write_nvm)(struct e1000_hw *, u16, u16, u16 *);
+struct e1000_nvm_operations {
+       s32  (*init_params)(struct e1000_hw *);
+       s32  (*acquire)(struct e1000_hw *);
+       s32  (*read)(struct e1000_hw *, u16, u16, u16 *);
+       void (*release)(struct e1000_hw *);
+       void (*reload)(struct e1000_hw *);
+       s32  (*update)(struct e1000_hw *);
+       s32  (*valid_led_default)(struct e1000_hw *, u16 *);
+       s32  (*validate)(struct e1000_hw *);
+       s32  (*write)(struct e1000_hw *, u16, u16, u16 *);
 };
 
 struct e1000_mac_info {
+       struct e1000_mac_operations ops;
        u8 addr[6];
        u8 perm_addr[6];
 
-       e1000_mac_type type;
-       e1000_fc_mode  fc;
-       e1000_fc_mode  original_fc;
+       enum e1000_mac_type type;
 
        u32 collision_delta;
        u32 ledctl_default;
        u32 ledctl_mode1;
        u32 ledctl_mode2;
-       u32 max_frame_size;
        u32 mc_filter_type;
-       u32 min_frame_size;
        u32 tx_packet_delta;
        u32 txcw;
 
@@ -608,44 +667,39 @@
        u16 ifs_step_size;
        u16 mta_reg_count;
        u16 rar_entry_count;
-       u16 fc_high_water;
-       u16 fc_low_water;
-       u16 fc_pause_time;
 
        u8  forced_speed_duplex;
 
-       boolean_t adaptive_ifs;
-       boolean_t arc_subsystem_valid;
-       boolean_t asf_firmware_present;
-       boolean_t autoneg;
-       boolean_t autoneg_failed;
-       boolean_t disable_av;
-       boolean_t disable_hw_init_bits;
-       boolean_t fc_send_xon;
-       boolean_t fc_strict_ieee;
-       boolean_t get_link_status;
-       boolean_t ifs_params_forced;
-       boolean_t in_ifs_mode;
-       boolean_t report_tx_early;
-       boolean_t serdes_has_link;
-       boolean_t tx_pkt_filtering;
+       bool adaptive_ifs;
+       bool arc_subsystem_valid;
+       bool asf_firmware_present;
+       bool autoneg;
+       bool autoneg_failed;
+       bool get_link_status;
+       bool in_ifs_mode;
+       bool report_tx_early;
+       bool serdes_has_link;
+       bool tx_pkt_filtering;
 };
 
 struct e1000_phy_info {
-       e1000_phy_type type;
+       struct e1000_phy_operations ops;
+       enum e1000_phy_type type;
 
-       e1000_1000t_rx_status local_rx;
-       e1000_1000t_rx_status remote_rx;
-       e1000_ms_type ms_type;
-       e1000_ms_type original_ms_type;
-       e1000_rev_polarity cable_polarity;
-       e1000_smart_speed smart_speed;
+       enum e1000_1000t_rx_status local_rx;
+       enum e1000_1000t_rx_status remote_rx;
+       enum e1000_ms_type ms_type;
+       enum e1000_ms_type original_ms_type;
+       enum e1000_rev_polarity cable_polarity;
+       enum e1000_smart_speed smart_speed;
 
        u32 addr;
        u32 id;
        u32 reset_delay_us; /* in usec */
        u32 revision;
 
+       enum e1000_media_type media_type;
+
        u16 autoneg_advertised;
        u16 autoneg_mask;
        u16 cable_length;
@@ -654,17 +708,18 @@
 
        u8 mdix;
 
-       boolean_t disable_polarity_correction;
-       boolean_t is_mdix;
-       boolean_t polarity_correction;
-       boolean_t reset_disable;
-       boolean_t speed_downgraded;
-       boolean_t wait_for_link;
+       bool disable_polarity_correction;
+       bool is_mdix;
+       bool polarity_correction;
+       bool reset_disable;
+       bool speed_downgraded;
+       bool autoneg_wait_to_complete;
 };
 
 struct e1000_nvm_info {
-       e1000_nvm_type type;
-       e1000_nvm_override override;
+       struct e1000_nvm_operations ops;
+       enum e1000_nvm_type type;
+       enum e1000_nvm_override override;
 
        u32 flash_bank_size;
        u32 flash_base_addr;
@@ -677,35 +732,89 @@
 };
 
 struct e1000_bus_info {
-       e1000_bus_type type;
-       e1000_bus_speed speed;
-       e1000_bus_width width;
+       enum e1000_bus_type type;
+       enum e1000_bus_speed speed;
+       enum e1000_bus_width width;
 
-       u32 snoop;
-
        u16 func;
        u16 pci_cmd_word;
 };
 
+struct e1000_fc_info {
+       u32 high_water;          /* Flow control high-water mark */
+       u32 low_water;           /* Flow control low-water mark */
+       u16 pause_time;          /* Flow control pause timer */
+       bool send_xon;           /* Flow control send XON */
+       bool strict_ieee;        /* Strict IEEE mode */
+       enum e1000_fc_mode current_mode; /* FC mode in effect */
+       enum e1000_fc_mode requested_mode; /* FC mode requested by caller */
+};
+
+struct e1000_dev_spec_82541 {
+       enum e1000_dsp_config dsp_config;
+       enum e1000_ffe_config ffe_config;
+       u16 spd_default;
+       bool phy_init_script;
+};
+
+struct e1000_dev_spec_82542 {
+       bool dma_fairness;
+};
+
+struct e1000_dev_spec_82543 {
+       u32  tbi_compatibility;
+       bool dma_fairness;
+       bool init_phy_disabled;
+};
+
+struct e1000_dev_spec_82571 {
+       bool laa_is_present;
+};
+
+struct e1000_shadow_ram {
+       u16  value;
+       bool modified;
+};
+
+#define E1000_SHADOW_RAM_WORDS         2048
+
+struct e1000_dev_spec_ich8lan {
+       bool kmrn_lock_loss_workaround_enabled;
+       struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS];
+};
+
+struct e1000_dev_spec_82575 {
+       bool sgmii_active;
+};
+
+struct e1000_dev_spec_vf {
+       u32     vf_number;
+};
+
 struct e1000_hw {
        void *back;
-       void *dev_spec;
 
        u8 *hw_addr;
        u8 *flash_address;
        unsigned long io_base;
 
-       struct e1000_functions func;
        struct e1000_mac_info  mac;
+       struct e1000_fc_info   fc;
        struct e1000_phy_info  phy;
        struct e1000_nvm_info  nvm;
        struct e1000_bus_info  bus;
        struct e1000_host_mng_dhcp_cookie mng_cookie;
 
-       e1000_media_type media_type;
+       union {
+               struct e1000_dev_spec_82541     _82541;
+               struct e1000_dev_spec_82542     _82542;
+               struct e1000_dev_spec_82543     _82543;
+               struct e1000_dev_spec_82571     _82571;
+               struct e1000_dev_spec_ich8lan   ich8lan;
+               struct e1000_dev_spec_82575     _82575;
+               struct e1000_dev_spec_vf        vf;
+       } dev_spec;
 
-       u32 dev_spec_size;
-
        u16 device_id;
        u16 subsystem_vendor_id;
        u16 subsystem_device_id;
@@ -714,12 +823,17 @@
        u8  revision_id;
 };
 
+#include "e1000_82541.h"
+#include "e1000_82543.h"
+#include "e1000_82571.h"
+#include "e1000_80003es2lan.h"
+#include "e1000_ich8lan.h"
+#include "e1000_82575.h"
+
 /* These functions must be implemented by drivers */
 void e1000_pci_clear_mwi(struct e1000_hw *hw);
 void e1000_pci_set_mwi(struct e1000_hw *hw);
-s32  e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, u32 size);
 s32  e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
-void e1000_free_dev_spec_struct(struct e1000_hw *hw);
 void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
 void e1000_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
 
Index: dev/em/e1000_82541.c
===================================================================
--- dev/em/e1000_82541.c        (Revision 28889)
+++ dev/em/e1000_82541.c        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,43 +29,42 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82541.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82541.c,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
-
-/* e1000_82541
- * e1000_82547
- * e1000_82541_rev_2
- * e1000_82547_rev_2
+/*
+ * 82541EI Gigabit Ethernet Controller
+ * 82541ER Gigabit Ethernet Controller
+ * 82541GI Gigabit Ethernet Controller
+ * 82541PI Gigabit Ethernet Controller
+ * 82547EI Gigabit Ethernet Controller
+ * 82547GI Gigabit Ethernet Controller
  */
 
 #include "e1000_api.h"
-#include "e1000_82541.h"
 
-void e1000_init_function_pointers_82541(struct e1000_hw *hw);
-
-STATIC s32  e1000_init_phy_params_82541(struct e1000_hw *hw);
-STATIC s32  e1000_init_nvm_params_82541(struct e1000_hw *hw);
-STATIC s32  e1000_init_mac_params_82541(struct e1000_hw *hw);
-STATIC s32  e1000_reset_hw_82541(struct e1000_hw *hw);
-STATIC s32  e1000_init_hw_82541(struct e1000_hw *hw);
-STATIC s32  e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
+static s32  e1000_init_phy_params_82541(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_82541(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82541(struct e1000_hw *hw);
+static s32  e1000_reset_hw_82541(struct e1000_hw *hw);
+static s32  e1000_init_hw_82541(struct e1000_hw *hw);
+static s32  e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
                                          u16 *duplex);
-STATIC s32  e1000_phy_hw_reset_82541(struct e1000_hw *hw);
-STATIC s32  e1000_setup_copper_link_82541(struct e1000_hw *hw);
-STATIC s32  e1000_check_for_link_82541(struct e1000_hw *hw);
-STATIC s32  e1000_get_cable_length_igp_82541(struct e1000_hw *hw);
-STATIC s32  e1000_set_d3_lplu_state_82541(struct e1000_hw *hw,
-                                          boolean_t active);
-STATIC s32  e1000_setup_led_82541(struct e1000_hw *hw);
-STATIC s32  e1000_cleanup_led_82541(struct e1000_hw *hw);
-STATIC void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw);
+static s32  e1000_phy_hw_reset_82541(struct e1000_hw *hw);
+static s32  e1000_setup_copper_link_82541(struct e1000_hw *hw);
+static s32  e1000_check_for_link_82541(struct e1000_hw *hw);
+static s32  e1000_get_cable_length_igp_82541(struct e1000_hw *hw);
+static s32  e1000_set_d3_lplu_state_82541(struct e1000_hw *hw,
+                                          bool active);
+static s32  e1000_setup_led_82541(struct e1000_hw *hw);
+static s32  e1000_cleanup_led_82541(struct e1000_hw *hw);
+static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw);
 static s32  e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
-                                                     boolean_t link_up);
+                                                     bool link_up);
 static s32  e1000_phy_init_script_82541(struct e1000_hw *hw);
+static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw);
 
-static const
-u16 e1000_igp_cable_length_table[] =
+static const u16 e1000_igp_cable_length_table[] =
     { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
       5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
       25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
@@ -78,43 +77,34 @@
                 (sizeof(e1000_igp_cable_length_table) / \
                  sizeof(e1000_igp_cable_length_table[0]))
 
-struct e1000_dev_spec_82541 {
-       e1000_dsp_config dsp_config;
-       e1000_ffe_config ffe_config;
-       u16 spd_default;
-       boolean_t phy_init_script;
-};
-
 /**
  *  e1000_init_phy_params_82541 - Init PHY func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_phy_params_82541(struct e1000_hw *hw)
+static s32 e1000_init_phy_params_82541(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_phy_params_82541");
 
-       phy->addr                       = 1;
-       phy->autoneg_mask               = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-       phy->reset_delay_us             = 10000;
-       phy->type                       = e1000_phy_igp;
+       phy->addr                      = 1;
+       phy->autoneg_mask              = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us            = 10000;
+       phy->type                      = e1000_phy_igp;
 
        /* Function Pointers */
-       func->check_polarity            = e1000_check_polarity_igp;
-       func->force_speed_duplex        = e1000_phy_force_speed_duplex_igp;
-       func->get_cable_length          = e1000_get_cable_length_igp_82541;
-       func->get_cfg_done              = e1000_get_cfg_done_generic;
-       func->get_phy_info              = e1000_get_phy_info_igp;
-       func->read_phy_reg              = e1000_read_phy_reg_igp;
-       func->reset_phy                 = e1000_phy_hw_reset_82541;
-       func->set_d3_lplu_state         = e1000_set_d3_lplu_state_82541;
-       func->write_phy_reg             = e1000_write_phy_reg_igp;
+       phy->ops.check_polarity        = e1000_check_polarity_igp;
+       phy->ops.force_speed_duplex    = e1000_phy_force_speed_duplex_igp;
+       phy->ops.get_cable_length      = e1000_get_cable_length_igp_82541;
+       phy->ops.get_cfg_done          = e1000_get_cfg_done_generic;
+       phy->ops.get_info              = e1000_get_phy_info_igp;
+       phy->ops.read_reg              = e1000_read_phy_reg_igp;
+       phy->ops.reset                 = e1000_phy_hw_reset_82541;
+       phy->ops.set_d3_lplu_state     = e1000_set_d3_lplu_state_82541;
+       phy->ops.write_reg             = e1000_write_phy_reg_igp;
+       phy->ops.power_up              = e1000_power_up_phy_copper;
+       phy->ops.power_down            = e1000_power_down_phy_copper_82541;
 
        ret_val = e1000_get_phy_id(hw);
        if (ret_val)
@@ -133,14 +123,10 @@
 /**
  *  e1000_init_nvm_params_82541 - Init NVM func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_nvm_params_82541(struct e1000_hw *hw)
+static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw)
 {
        struct   e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_functions *func = &hw->func;
        s32  ret_val = E1000_SUCCESS;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
        u16 size;
@@ -180,25 +166,27 @@
                                          ? 32 : 8;
 
                /* Function Pointers */
-               func->acquire_nvm       = e1000_acquire_nvm_generic;
-               func->read_nvm          = e1000_read_nvm_spi;
-               func->release_nvm       = e1000_release_nvm_generic;
-               func->update_nvm        = e1000_update_nvm_checksum_generic;
-               func->valid_led_default = e1000_valid_led_default_generic;
-               func->validate_nvm      = e1000_validate_nvm_checksum_generic;
-               func->write_nvm         = e1000_write_nvm_spi;
+               nvm->ops.acquire        = e1000_acquire_nvm_generic;
+               nvm->ops.read           = e1000_read_nvm_spi;
+               nvm->ops.release        = e1000_release_nvm_generic;
+               nvm->ops.update         = e1000_update_nvm_checksum_generic;
+               nvm->ops.valid_led_default = e1000_valid_led_default_generic;
+               nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
+               nvm->ops.write          = e1000_write_nvm_spi;
 
-               /* nvm->word_size must be discovered after the pointers
+               /*
+                * nvm->word_size must be discovered after the pointers
                 * are set so we can verify the size from the nvm image
                 * itself.  Temporarily set it to a dummy value so the
                 * read will work.
                 */
                nvm->word_size = 64;
-               ret_val = e1000_read_nvm(hw, NVM_CFG, 1, &size);
+               ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size);
                if (ret_val)
                        goto out;
                size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT;
-               /* if size != 0, it can be added to a constant and become
+               /*
+                * if size != 0, it can be added to a constant and become
                 * the left-shift value to set the word_size.  Otherwise,
                 * word_size stays at 64.
                 */
@@ -215,13 +203,13 @@
                                          ? 256 : 64;
 
                /* Function Pointers */
-               func->acquire_nvm       = e1000_acquire_nvm_generic;
-               func->read_nvm          = e1000_read_nvm_microwire;
-               func->release_nvm       = e1000_release_nvm_generic;
-               func->update_nvm        = e1000_update_nvm_checksum_generic;
-               func->valid_led_default = e1000_valid_led_default_generic;
-               func->validate_nvm      = e1000_validate_nvm_checksum_generic;
-               func->write_nvm         = e1000_write_nvm_microwire;
+               nvm->ops.acquire        = e1000_acquire_nvm_generic;
+               nvm->ops.read           = e1000_read_nvm_microwire;
+               nvm->ops.release        = e1000_release_nvm_generic;
+               nvm->ops.update         = e1000_update_nvm_checksum_generic;
+               nvm->ops.valid_led_default = e1000_valid_led_default_generic;
+               nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
+               nvm->ops.write          = e1000_write_nvm_microwire;
        }
 
 out:
@@ -231,20 +219,15 @@
 /**
  *  e1000_init_mac_params_82541 - Init MAC func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_mac_params_82541(struct e1000_hw *hw)
+static s32 e1000_init_mac_params_82541(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
-       s32 ret_val;
 
        DEBUGFUNC("e1000_init_mac_params_82541");
 
        /* Set media type */
-       hw->media_type = e1000_media_type_copper;
+       hw->phy.media_type = e1000_media_type_copper;
        /* Set mta register count */
        mac->mta_reg_count = 128;
        /* Set rar entry count */
@@ -255,73 +238,64 @@
        /* Function Pointers */
 
        /* bus type/speed/width */
-       func->get_bus_info = e1000_get_bus_info_pci_generic;
+       mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
+       /* function id */
+       mac->ops.set_lan_id = e1000_set_lan_id_single_port;
        /* reset */
-       func->reset_hw = e1000_reset_hw_82541;
+       mac->ops.reset_hw = e1000_reset_hw_82541;
        /* hw initialization */
-       func->init_hw = e1000_init_hw_82541;
+       mac->ops.init_hw = e1000_init_hw_82541;
        /* link setup */
-       func->setup_link = e1000_setup_link_generic;
+       mac->ops.setup_link = e1000_setup_link_generic;
        /* physical interface link setup */
-       func->setup_physical_interface = e1000_setup_copper_link_82541;
+       mac->ops.setup_physical_interface = e1000_setup_copper_link_82541;
        /* check for link */
-       func->check_for_link = e1000_check_for_link_82541;
+       mac->ops.check_for_link = e1000_check_for_link_82541;
        /* link info */
-       func->get_link_up_info = e1000_get_link_up_info_82541;
+       mac->ops.get_link_up_info = e1000_get_link_up_info_82541;
        /* multicast address update */
-       func->mc_addr_list_update = e1000_mc_addr_list_update_generic;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
        /* writing VFTA */
-       func->write_vfta = e1000_write_vfta_generic;
+       mac->ops.write_vfta = e1000_write_vfta_generic;
        /* clearing VFTA */
-       func->clear_vfta = e1000_clear_vfta_generic;
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
        /* setting MTA */
-       func->mta_set = e1000_mta_set_generic;
+       mac->ops.mta_set = e1000_mta_set_generic;
        /* setup LED */
-       func->setup_led = e1000_setup_led_82541;
+       mac->ops.setup_led = e1000_setup_led_82541;
        /* cleanup LED */
-       func->cleanup_led = e1000_cleanup_led_82541;
+       mac->ops.cleanup_led = e1000_cleanup_led_82541;
        /* turn on/off LED */
-       func->led_on = e1000_led_on_generic;
-       func->led_off = e1000_led_off_generic;
-       /* remove device */
-       func->remove_device = e1000_remove_device_generic;
+       mac->ops.led_on = e1000_led_on_generic;
+       mac->ops.led_off = e1000_led_off_generic;
        /* clear hardware counters */
-       func->clear_hw_cntrs = e1000_clear_hw_cntrs_82541;
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541;
 
-       hw->dev_spec_size = sizeof(struct e1000_dev_spec_82541);
-
-       /* Device-specific structure allocation */
-       ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size);
-
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
  *  e1000_init_function_pointers_82541 - Init func ptrs.
  *  @hw: pointer to the HW structure
  *
- *  The only function explicitly called by the api module to initialize
- *  all function pointers and parameters.
+ *  Called to initialize all function pointers and parameters.
  **/
-void
-e1000_init_function_pointers_82541(struct e1000_hw *hw)
+void e1000_init_function_pointers_82541(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_init_function_pointers_82541");
 
-       hw->func.init_mac_params = e1000_init_mac_params_82541;
-       hw->func.init_nvm_params = e1000_init_nvm_params_82541;
-       hw->func.init_phy_params = e1000_init_phy_params_82541;
+       hw->mac.ops.init_params = e1000_init_mac_params_82541;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82541;
+       hw->phy.ops.init_params = e1000_init_phy_params_82541;
 }
 
 /**
  *  e1000_reset_hw_82541 - Reset hardware
  *  @hw: pointer to the HW structure
  *
- *  This resets the hardware into a known state.  This is a
- *  function pointer entry point called by the api module.
+ *  This resets the hardware into a known state.
  **/
-STATIC s32
-e1000_reset_hw_82541(struct e1000_hw *hw)
+static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
 {
        u32 ledctl, ctrl, icr, manc;
 
@@ -334,7 +308,8 @@
        E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
        E1000_WRITE_FLUSH(hw);
 
-       /* Delay to allow any outstanding PCI transactions to complete
+       /*
+        * Delay to allow any outstanding PCI transactions to complete
         * before resetting the device.
         */
        msec_delay(10);
@@ -351,7 +326,8 @@
        switch (hw->mac.type) {
        case e1000_82541:
        case e1000_82541_rev_2:
-               /* These controllers can't ack the 64-bit write when
+               /*
+                * These controllers can't ack the 64-bit write when
                 * issuing the reset, so we use IO-mapping as a
                 * workaround to issue the reset.
                 */
@@ -394,11 +370,9 @@
  *  e1000_init_hw_82541 - Initialize hardware
  *  @hw: pointer to the HW structure
  *
- *  This inits the hardware readying it for operation.  This is a
- *  function pointer entry point called by the api module.
+ *  This inits the hardware readying it for operation.
  **/
-STATIC s32
-e1000_init_hw_82541(struct e1000_hw *hw)
+static s32 e1000_init_hw_82541(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 i, txdctl;
@@ -410,12 +384,12 @@
        ret_val = e1000_id_led_init_generic(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
-               goto out;
+               /* This is not fatal and we should not stop init due to this */
        }
 
        /* Disabling VLAN filtering */
        DEBUGOUT("Initializing the IEEE VLAN\n");
-       e1000_clear_vfta(hw);
+       mac->ops.clear_vfta(hw);
 
        /* Setup the receive address. */
        e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
@@ -424,7 +398,8 @@
        DEBUGOUT("Zeroing the MTA\n");
        for (i = 0; i < mac->mta_reg_count; i++) {
                E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
-               /* Avoid back to back register writes by adding the register
+               /*
+                * Avoid back to back register writes by adding the register
                 * read (flush).  This is to protect against some strange
                 * bridge configurations that may issue Memory Write Block
                 * (MWB) to our register space.
@@ -433,21 +408,21 @@
        }
 
        /* Setup link and flow control */
-       ret_val = e1000_setup_link(hw);
+       ret_val = mac->ops.setup_link(hw);
 
-       txdctl = E1000_READ_REG(hw, E1000_TXDCTL);
+       txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
        txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
                 E1000_TXDCTL_FULL_TX_DESC_WB;
-       E1000_WRITE_REG(hw, E1000_TXDCTL, txdctl);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
 
-       /* Clear all of the statistics registers (clear on read).  It is
+       /*
+        * 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_82541(hw);
 
-out:
        return ret_val;
 }
 
@@ -458,10 +433,9 @@
  * @duplex: pointer to duplex buffer
  *
  * Retrieve the current speed and duplex configuration.
- * This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, u16 *duplex)
+static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
+                                        u16 *duplex)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -476,19 +450,20 @@
        if (!phy->speed_downgraded)
                goto out;
 
-       /* IGP01 PHY may advertise full duplex operation after speed
+       /*
+        * IGP01 PHY may advertise full duplex operation after speed
         * downgrade even if it is operating at half duplex.
         * Here we set the duplex settings to match the duplex in the
         * link partner's capabilities.
         */
-       ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &data);
+       ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data);
        if (ret_val)
                goto out;
 
-       if (!(data & NWAY_ER_LP_NWAY_CAPS))
+       if (!(data & NWAY_ER_LP_NWAY_CAPS)) {
                *duplex = HALF_DUPLEX;
-       else {
-               ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, &data);
+       } else {
+               ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data);
                if (ret_val)
                        goto out;
 
@@ -512,11 +487,9 @@
  *  Verify the reset block is not blocking us from resetting.  Acquire
  *  semaphore (if necessary) and read/set/write the device control reset
  *  bit in the PHY.  Wait the appropriate delay time for the device to
- *  reset and relase the semaphore (if necessary).
- *  This is a function pointer entry point called by the api module.
+ *  reset and release the semaphore (if necessary).
  **/
-STATIC s32
-e1000_phy_hw_reset_82541(struct e1000_hw *hw)
+static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw)
 {
        s32 ret_val;
        u32 ledctl;
@@ -548,14 +521,12 @@
  *  Calls the appropriate function to configure 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.  If link is
- *  not established, we return -E1000_ERR_PHY (-2).  This is a function
- *  pointer entry point called by the api module.
+ *  not established, we return -E1000_ERR_PHY (-2).
  **/
-STATIC s32
-e1000_setup_copper_link_82541(struct e1000_hw *hw)
+static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       struct e1000_dev_spec_82541 *dev_spec;
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
        s32  ret_val;
        u32 ctrl, ledctl;
 
@@ -568,14 +539,13 @@
 
        hw->phy.reset_disable = FALSE;
 
-       dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;
-
        /* Earlier revs of the IGP phy require us to force MDI. */
        if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) {
                dev_spec->dsp_config = e1000_dsp_config_disabled;
                phy->mdix = 1;
-       } else
+       } else {
                dev_spec->dsp_config = e1000_dsp_config_enabled;
+       }
 
        ret_val = e1000_copper_link_setup_igp(hw);
        if (ret_val)
@@ -603,19 +573,18 @@
  *  @hw: pointer to the HW structure
  *
  *  This checks the link condition of the adapter and stores the
- *  results in the hw->mac structure. This is a function pointer entry
- *  point called by the api module.
+ *  results in the hw->mac structure.
  **/
-STATIC s32
-e1000_check_for_link_82541(struct e1000_hw *hw)
+static s32 e1000_check_for_link_82541(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_check_for_link_82541");
 
-       /* We only want to go out to the PHY registers to see if Auto-Neg
+       /*
+        * We only want to go out to the PHY registers to see if Auto-Neg
         * has completed and/or if our link status has changed.  The
         * get_link_status flag is set upon receiving a Link Status
         * Change or Rx Sequence Error interrupt.
@@ -625,7 +594,8 @@
                goto out;
        }
 
-       /* First we want to see if the MII Status Register reports
+       /*
+        * First we want to see if the MII Status Register reports
         * link.  If so, then we want to get the current speed/duplex
         * of the PHY.
         */
@@ -640,11 +610,14 @@
 
        mac->get_link_status = FALSE;
 
-       /* Check if there was DownShift, must be checked
-        * immediately after link-up */
+       /*
+        * Check if there was DownShift, must be checked
+        * immediately after link-up
+        */
        e1000_check_downshift_generic(hw);
 
-       /* If we are forcing speed/duplex, then we simply return since
+       /*
+        * If we are forcing speed/duplex, then we simply return since
         * we have already determined whether we have link or not.
         */
        if (!mac->autoneg) {
@@ -654,13 +627,15 @@
 
        ret_val = e1000_config_dsp_after_link_change_82541(hw, TRUE);
 
-       /* Auto-Neg is enabled.  Auto Speed Detection takes care
+       /*
+        * Auto-Neg is enabled.  Auto Speed Detection takes care
         * of MAC speed/duplex configuration.  So we only need to
         * configure Collision Distance in the MAC.
         */
        e1000_config_collision_dist_generic(hw);
 
-       /* Configure Flow Control now that Auto-Neg has completed.
+       /*
+        * Configure Flow Control now that Auto-Neg has completed.
         * First, we need to restore the desired flow control
         * settings because we may have had to re-autoneg with a
         * different link partner.
@@ -684,13 +659,12 @@
  *
  *  82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
  *  gigabit link is achieved to improve link quality.
- *  This is a function pointer entry point called by the api module.
  **/
-static s32
-e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, boolean_t 
link_up)
+static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
+                                                    bool link_up)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       struct e1000_dev_spec_82541 *dev_spec;
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
        s32 ret_val;
        u32 idle_errs = 0;
        u16 phy_data, phy_saved_data, speed, duplex, i;
@@ -703,10 +677,8 @@
 
        DEBUGFUNC("e1000_config_dsp_after_link_change_82541");
 
-       dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;
-
        if (link_up) {
-               ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+               ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
                if (ret_val) {
                        DEBUGOUT("Error getting link speed and duplex\n");
                        goto out;
@@ -717,7 +689,7 @@
                        goto out;
                }
 
-               ret_val = e1000_get_cable_length(hw);
+               ret_val = phy->ops.get_cable_length(hw);
                if (ret_val)
                        goto out;
 
@@ -725,7 +697,7 @@
                    phy->min_cable_length >= 50) {
 
                        for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
-                               ret_val = e1000_read_phy_reg(hw,
+                               ret_val = phy->ops.read_reg(hw,
                                                            dsp_reg_array[i],
                                                            &phy_data);
                                if (ret_val)
@@ -733,7 +705,7 @@
 
                                phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
 
-                               ret_val = e1000_write_phy_reg(hw,
+                               ret_val = phy->ops.write_reg(hw,
                                                             dsp_reg_array[i],
                                                             phy_data);
                                if (ret_val)
@@ -749,13 +721,13 @@
                }
 
                /* clear previous idle error counts */
-               ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+               ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
                if (ret_val)
                        goto out;
 
                for (i = 0; i < ffe_idle_err_timeout; i++) {
                        usec_delay(1000);
-                       ret_val = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                    PHY_1000T_STATUS,
                                                    &phy_data);
                        if (ret_val)
@@ -765,7 +737,7 @@
                        if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
                                dev_spec->ffe_config = e1000_ffe_config_active;
 
-                               ret_val = e1000_write_phy_reg(hw,
+                               ret_val = phy->ops.write_reg(hw,
                                                  IGP01E1000_PHY_DSP_FFE,
                                                  IGP01E1000_PHY_DSP_FFE_CM_CP);
                                if (ret_val)
@@ -779,28 +751,30 @@
                }
        } else {
                if (dev_spec->dsp_config == e1000_dsp_config_activated) {
-                       /* Save off the current value of register 0x2F5B
-                        * to be restored at the end of the routines. */
-                       ret_val = e1000_read_phy_reg(hw,
+                       /*
+                        * Save off the current value of register 0x2F5B
+                        * to be restored at the end of the routines.
+                        */
+                       ret_val = phy->ops.read_reg(hw,
                                                    0x2F5B,
                                                    &phy_saved_data);
                        if (ret_val)
                                goto out;
 
                        /* Disable the PHY transmitter */
-                       ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
+                       ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
                        if (ret_val)
                                goto out;
 
                        msec_delay_irq(20);
 
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                     0x0000,
                                                     IGP01E1000_IEEE_FORCE_GIG);
                        if (ret_val)
                                goto out;
                        for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
-                               ret_val = e1000_read_phy_reg(hw,
+                               ret_val = phy->ops.read_reg(hw,
                                                            dsp_reg_array[i],
                                                            &phy_data);
                                if (ret_val)
@@ -809,14 +783,14 @@
                                phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
                                phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
 
-                               ret_val = e1000_write_phy_reg(hw,
+                               ret_val = phy->ops.write_reg(hw,
                                                             dsp_reg_array[i],
                                                             phy_data);
                                if (ret_val)
                                        goto out;
                        }
 
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                               0x0000,
                                               IGP01E1000_IEEE_RESTART_AUTONEG);
                        if (ret_val)
@@ -825,7 +799,7 @@
                        msec_delay_irq(20);
 
                        /* Now enable the transmitter */
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                     0x2F5B,
                                                     phy_saved_data);
                        if (ret_val)
@@ -839,32 +813,34 @@
                        goto out;
                }
 
-               /* Save off the current value of register 0x2F5B
-                * to be restored at the end of the routines. */
-               ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+               /*
+                * Save off the current value of register 0x2F5B
+                * to be restored at the end of the routines.
+                */
+               ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data);
                if (ret_val)
                        goto out;
 
                /* Disable the PHY transmitter */
-               ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
+               ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
                if (ret_val)
                        goto out;
 
                msec_delay_irq(20);
 
-               ret_val = e1000_write_phy_reg(hw,
+               ret_val = phy->ops.write_reg(hw,
                                             0x0000,
                                             IGP01E1000_IEEE_FORCE_GIG);
                if (ret_val)
                        goto out;
 
-               ret_val = e1000_write_phy_reg(hw,
+               ret_val = phy->ops.write_reg(hw,
                                             IGP01E1000_PHY_DSP_FFE,
                                             IGP01E1000_PHY_DSP_FFE_DEFAULT);
                if (ret_val)
                        goto out;
 
-               ret_val = e1000_write_phy_reg(hw,
+               ret_val = phy->ops.write_reg(hw,
                                             0x0000,
                                             IGP01E1000_IEEE_RESTART_AUTONEG);
                if (ret_val)
@@ -873,7 +849,7 @@
                msec_delay_irq(20);
 
                /* Now enable the transmitter */
-               ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+               ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data);
 
                if (ret_val)
                        goto out;
@@ -891,14 +867,12 @@
  *
  *  The automatic gain control (agc) normalizes the amplitude of the
  *  received signal, adjusting for the attenuation produced by the
- *  cable.  By reading the AGC registers, which reperesent the
- *  cobination of course and fine gain value, the value can be put
+ *  cable.  By reading the AGC registers, which represent the
+ *  combination of coarse and fine gain value, the value can be put
  *  into a lookup table to obtain the approximate cable length
- *  for each channel.  This is a function pointer entry point called by the
- *  api module.
+ *  for each channel.
  **/
-STATIC s32
-e1000_get_cable_length_igp_82541(struct e1000_hw *hw)
+static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val = E1000_SUCCESS;
@@ -915,7 +889,7 @@
 
        /* Read the AGC registers for all channels */
        for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
-               ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &data);
+               ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data);
                if (ret_val)
                        goto out;
 
@@ -966,15 +940,13 @@
  *  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 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.  This is a function pointer entry point called by the
- *  api module.
+ *  maintained.
  **/
-STATIC s32
-e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, boolean_t active)
+static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -992,42 +964,44 @@
                break;
        }
 
-       ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &data);
+       ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data);
        if (ret_val)
                goto out;
 
        if (!active) {
                data &= ~IGP01E1000_GMII_FLEX_SPD;
-               ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, data);
+               ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
                if (ret_val)
                        goto out;
 
-               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               /*
+                * 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. */
+                * SmartSpeed, so performance is maintained.
+                */
                if (phy->smart_speed == e1000_smart_speed_on) {
-                       ret_val = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                    IGP01E1000_PHY_PORT_CONFIG,
                                                    &data);
                        if (ret_val)
                                goto out;
 
                        data |= IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       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 = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                    IGP01E1000_PHY_PORT_CONFIG,
                                                    &data);
                        if (ret_val)
                                goto out;
 
                        data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
@@ -1037,19 +1011,19 @@
                   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
                   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
                data |= IGP01E1000_GMII_FLEX_SPD;
-               ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, data);
+               ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
                if (ret_val)
                        goto out;
 
                /* When LPLU is enabled, we should disable SmartSpeed */
-               ret_val = e1000_read_phy_reg(hw,
+               ret_val = phy->ops.read_reg(hw,
                                            IGP01E1000_PHY_PORT_CONFIG,
                                            &data);
                if (ret_val)
                        goto out;
 
                data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-               ret_val = e1000_write_phy_reg(hw,
+               ret_val = phy->ops.write_reg(hw,
                                             IGP01E1000_PHY_PORT_CONFIG,
                                             data);
        }
@@ -1063,28 +1037,24 @@
  *  @hw: pointer to the HW structure
  *
  *  This prepares the SW controllable LED for use and saves the current state
- *  of the LED so it can be later restored.  This is a function pointer entry
- *  point called by the api module.
+ *  of the LED so it can be later restored.
  **/
-STATIC s32
-e1000_setup_led_82541(struct e1000_hw *hw)
+static s32 e1000_setup_led_82541(struct e1000_hw *hw)
 {
-       struct e1000_dev_spec_82541 *dev_spec;
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
        s32 ret_val;
 
        DEBUGFUNC("e1000_setup_led_82541");
 
-       dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;
-
-       ret_val = e1000_read_phy_reg(hw,
-                                   IGP01E1000_GMII_FIFO,
-                                   &dev_spec->spd_default);
+       ret_val = hw->phy.ops.read_reg(hw,
+                                      IGP01E1000_GMII_FIFO,
+                                      &dev_spec->spd_default);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_write_phy_reg(hw,
-                                    IGP01E1000_GMII_FIFO,
-                                    (u16)(dev_spec->spd_default &
+       ret_val = hw->phy.ops.write_reg(hw,
+                                       IGP01E1000_GMII_FIFO,
+                                       (u16)(dev_spec->spd_default &
                                                ~IGP01E1000_GMII_SPD));
        if (ret_val)
                goto out;
@@ -1100,22 +1070,18 @@
  *  @hw: pointer to the HW structure
  *
  *  Remove the current LED configuration and set the LED configuration
- *  to the default value, saved from the EEPROM.  This is a function pointer
- *  entry point called by the api module.
+ *  to the default value, saved from the EEPROM.
  **/
-STATIC s32
-e1000_cleanup_led_82541(struct e1000_hw *hw)
+static s32 e1000_cleanup_led_82541(struct e1000_hw *hw)
 {
-       struct e1000_dev_spec_82541 *dev_spec;
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
        s32 ret_val;
 
        DEBUGFUNC("e1000_cleanup_led_82541");
 
-       dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;
-
-       ret_val = e1000_write_phy_reg(hw,
-                                    IGP01E1000_GMII_FIFO,
-                                    dev_spec->spd_default);
+       ret_val = hw->phy.ops.write_reg(hw,
+                                       IGP01E1000_GMII_FIFO,
+                                       dev_spec->spd_default);
        if (ret_val)
                goto out;
 
@@ -1131,17 +1097,14 @@
  *
  *  Initializes the IGP PHY.
  **/
-static s32
-e1000_phy_init_script_82541(struct e1000_hw *hw)
+static s32 e1000_phy_init_script_82541(struct e1000_hw *hw)
 {
-       struct e1000_dev_spec_82541 *dev_spec;
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
        u32 ret_val;
        u16 phy_saved_data;
 
        DEBUGFUNC("e1000_phy_init_script_82541");
 
-       dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;
-
        if (!dev_spec->phy_init_script) {
                ret_val = E1000_SUCCESS;
                goto out;
@@ -1150,65 +1113,67 @@
        /* Delay after phy reset to enable NVM configuration to load */
        msec_delay(20);
 
-       /* Save off the current value of register 0x2F5B to be restored at
-        * the end of this routine. */
-       ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+       /*
+        * Save off the current value of register 0x2F5B to be restored at
+        * the end of this routine.
+        */
+       ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data);
 
        /* Disabled the PHY transmitter */
-       e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
+       hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003);
 
        msec_delay(20);
 
-       e1000_write_phy_reg(hw, 0x0000, 0x0140);
+       hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
 
        msec_delay(5);
 
        switch (hw->mac.type) {
        case e1000_82541:
        case e1000_82547:
-               e1000_write_phy_reg(hw, 0x1F95, 0x0001);
+               hw->phy.ops.write_reg(hw, 0x1F95, 0x0001);
 
-               e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
+               hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21);
 
-               e1000_write_phy_reg(hw, 0x1F79, 0x0018);
+               hw->phy.ops.write_reg(hw, 0x1F79, 0x0018);
 
-               e1000_write_phy_reg(hw, 0x1F30, 0x1600);
+               hw->phy.ops.write_reg(hw, 0x1F30, 0x1600);
 
-               e1000_write_phy_reg(hw, 0x1F31, 0x0014);
+               hw->phy.ops.write_reg(hw, 0x1F31, 0x0014);
 
-               e1000_write_phy_reg(hw, 0x1F32, 0x161C);
+               hw->phy.ops.write_reg(hw, 0x1F32, 0x161C);
 
-               e1000_write_phy_reg(hw, 0x1F94, 0x0003);
+               hw->phy.ops.write_reg(hw, 0x1F94, 0x0003);
 
-               e1000_write_phy_reg(hw, 0x1F96, 0x003F);
+               hw->phy.ops.write_reg(hw, 0x1F96, 0x003F);
 
-               e1000_write_phy_reg(hw, 0x2010, 0x0008);
+               hw->phy.ops.write_reg(hw, 0x2010, 0x0008);
                break;
        case e1000_82541_rev_2:
        case e1000_82547_rev_2:
-               e1000_write_phy_reg(hw, 0x1F73, 0x0099);
+               hw->phy.ops.write_reg(hw, 0x1F73, 0x0099);
                break;
        default:
                break;
        }
 
-       e1000_write_phy_reg(hw, 0x0000, 0x3300);
+       hw->phy.ops.write_reg(hw, 0x0000, 0x3300);
 
        msec_delay(20);
 
        /* Now enable the transmitter */
-       e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+       hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data);
 
        if (hw->mac.type == e1000_82547) {
                u16 fused, fine, coarse;
 
                /* Move to analog registers page */
-               e1000_read_phy_reg(hw,
+               hw->phy.ops.read_reg(hw,
                                  IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
                                  &fused);
 
                if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
-                       e1000_read_phy_reg(hw,
+                       hw->phy.ops.read_reg(hw,
                                          IGP01E1000_ANALOG_FUSE_STATUS,
                                          &fused);
 
@@ -1226,10 +1191,10 @@
                                (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
                                (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
 
-                       e1000_write_phy_reg(hw,
+                       hw->phy.ops.write_reg(hw,
                                           IGP01E1000_ANALOG_FUSE_CONTROL,
                                           fused);
-                       e1000_write_phy_reg(hw,
+                       hw->phy.ops.write_reg(hw,
                                      IGP01E1000_ANALOG_FUSE_BYPASS,
                                      IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
                }
@@ -1245,12 +1210,11 @@
  *  @state: boolean value used to enable/disable PHY init script
  *
  *  Allows the driver to enable/disable the PHY init script, if the PHY is an
- *  IGP PHY.  This is a function pointer entry point called by the api module.
+ *  IGP PHY.
  **/
-void
-e1000_init_script_state_82541(struct e1000_hw *hw, boolean_t state)
+void e1000_init_script_state_82541(struct e1000_hw *hw, bool state)
 {
-       struct e1000_dev_spec_82541 *dev_spec;
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
 
        DEBUGFUNC("e1000_init_script_state_82541");
 
@@ -1259,13 +1223,6 @@
                goto out;
        }
 
-       dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               goto out;
-       }
-
        dev_spec->phy_init_script = state;
 
 out:
@@ -1273,41 +1230,54 @@
 }
 
 /**
+ * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, remove the link.
+ **/
+static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw)
+{
+       /* If the management interface is not enabled, then power down */
+       if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))
+               e1000_power_down_phy_copper(hw);
+
+       return;
+}
+
+/**
  *  e1000_clear_hw_cntrs_82541 - 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_82541(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw)
 {
-       volatile u32 temp;
-
        DEBUGFUNC("e1000_clear_hw_cntrs_82541");
 
        e1000_clear_hw_cntrs_base_generic(hw);
 
-       temp = E1000_READ_REG(hw, E1000_PRC64);
-       temp = E1000_READ_REG(hw, E1000_PRC127);
-       temp = E1000_READ_REG(hw, E1000_PRC255);
-       temp = E1000_READ_REG(hw, E1000_PRC511);
-       temp = E1000_READ_REG(hw, E1000_PRC1023);
-       temp = E1000_READ_REG(hw, E1000_PRC1522);
-       temp = E1000_READ_REG(hw, E1000_PTC64);
-       temp = E1000_READ_REG(hw, E1000_PTC127);
-       temp = E1000_READ_REG(hw, E1000_PTC255);
-       temp = E1000_READ_REG(hw, E1000_PTC511);
-       temp = E1000_READ_REG(hw, E1000_PTC1023);
-       temp = E1000_READ_REG(hw, E1000_PTC1522);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_ALGNERRC);
-       temp = E1000_READ_REG(hw, E1000_RXERRC);
-       temp = E1000_READ_REG(hw, E1000_TNCRS);
-       temp = E1000_READ_REG(hw, E1000_CEXTERR);
-       temp = E1000_READ_REG(hw, E1000_TSCTC);
-       temp = E1000_READ_REG(hw, E1000_TSCTFC);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_MGTPRC);
-       temp = E1000_READ_REG(hw, E1000_MGTPDC);
-       temp = E1000_READ_REG(hw, E1000_MGTPTC);
+       E1000_READ_REG(hw, E1000_MGTPRC);
+       E1000_READ_REG(hw, E1000_MGTPDC);
+       E1000_READ_REG(hw, E1000_MGTPTC);
 }
Index: dev/em/e1000_80003es2lan.h
===================================================================
--- dev/em/e1000_80003es2lan.h  (Revision 28889)
+++ dev/em/e1000_80003es2lan.h  (Arbeitskopie)
@@ -1,6 +1,6 @@
 
/*******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, 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: src/sys/dev/em/e1000_80003es2lan.h,v 1.3 2007/05/16 00:14:23 jfv 
Exp $*/
+/* $FreeBSD: src/sys/dev/e1000/e1000_80003es2lan.h,v 1.1 2008/07/30 21:56:53 
jfv Exp $ */
 
 
 #ifndef _E1000_80003ES2LAN_H_
@@ -39,6 +39,7 @@
 #define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL       0x00
 #define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL        0x02
 #define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL         0x10
+#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE  0x1F
 
 #define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS    0x0008
 #define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS    0x0800
@@ -46,12 +47,13 @@
 
 #define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004
 #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT   0x0000
+#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE          0x2000
 
 #define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
-#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000
+#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN        0x00010000
 
-#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN   0x8
-#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9
+#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN       0x8
+#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN     0x9
 
 /* GG82563 PHY Specific Status Register (Page 0, Register 16 */
 #define GG82563_PSCR_POLARITY_REVERSAL_DISABLE  0x0002 /* 1=Reversal Disabled 
*/
@@ -61,37 +63,40 @@
 #define GG82563_PSCR_CROSSOVER_MODE_AUTO        0x0060 /* 11=Auto crossover */
 
 /* PHY Specific Control Register 2 (Page 0, Register 26) */
-#define GG82563_PSCR2_REVERSE_AUTO_NEG              0x2000
-                                                /* 1=Reverse Auto-Negotiation 
*/
+#define GG82563_PSCR2_REVERSE_AUTO_NEG          0x2000
+                                               /* 1=Reverse Auto-Negotiation */
 
 /* MAC Specific Control Register (Page 2, Register 21) */
 /* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
-#define GG82563_MSCR_TX_CLK_MASK                    0x0007
-#define GG82563_MSCR_TX_CLK_10MBPS_2_5              0x0004
-#define GG82563_MSCR_TX_CLK_100MBPS_25              0x0005
-#define GG82563_MSCR_TX_CLK_1000MBPS_2_5            0x0006
-#define GG82563_MSCR_TX_CLK_1000MBPS_25             0x0007
+#define GG82563_MSCR_TX_CLK_MASK                0x0007
+#define GG82563_MSCR_TX_CLK_10MBPS_2_5          0x0004
+#define GG82563_MSCR_TX_CLK_100MBPS_25          0x0005
+#define GG82563_MSCR_TX_CLK_1000MBPS_2_5        0x0006
+#define GG82563_MSCR_TX_CLK_1000MBPS_25         0x0007
 
-#define GG82563_MSCR_ASSERT_CRS_ON_TX               0x0010 /* 1=Assert */
+#define GG82563_MSCR_ASSERT_CRS_ON_TX           0x0010 /* 1=Assert */
 
 /* DSP Distance Register (Page 5, Register 26) */
-#define GG82563_DSPD_CABLE_LENGTH               0x0007 /* 0 = <50M;
-                                                          1 = 50-80M;
-                                                          2 = 80-110M;
-                                                          3 = 110-140M;
-                                                          4 = >140M */
+/*
+ * 0 = <50M
+ * 1 = 50-80M
+ * 2 = 80-100M
+ * 3 = 110-140M
+ * 4 = >140M
+ */
+#define GG82563_DSPD_CABLE_LENGTH               0x0007
 
 /* Kumeran Mode Control Register (Page 193, Register 16) */
-#define GG82563_KMCR_PASS_FALSE_CARRIER             0x0800
+#define GG82563_KMCR_PASS_FALSE_CARRIER         0x0800
 
 /* Max number of times Kumeran read/write should be validated */
-#define GG82563_MAX_KMRN_RETRY  0x5
+#define GG82563_MAX_KMRN_RETRY                  0x5
 
 /* Power Management Control Register (Page 193, Register 20) */
-#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE         0x0001
-                                           /* 1=Enable SERDES Electrical Idle 
*/
+#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE     0x0001
+                                          /* 1=Enable SERDES Electrical Idle */
 
 /* In-Band Control Register (Page 194, Register 18) */
-#define GG82563_ICR_DIS_PADDING                     0x0010 /* Disable Padding 
*/
+#define GG82563_ICR_DIS_PADDING                 0x0010 /* Disable Padding */
 
 #endif
Index: dev/em/e1000_82542.c
===================================================================
--- dev/em/e1000_82542.c        (Revision 28889)
+++ dev/em/e1000_82542.c        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,40 +29,32 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82542.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82542.c,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
-
-/* e1000_82542 (rev 1 & 2)
+/*
+ * 82542 Gigabit Ethernet Controller
  */
 
 #include "e1000_api.h"
 
-void e1000_init_function_pointers_82542(struct e1000_hw *hw);
+static s32  e1000_init_phy_params_82542(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_82542(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82542(struct e1000_hw *hw);
+static s32  e1000_get_bus_info_82542(struct e1000_hw *hw);
+static s32  e1000_reset_hw_82542(struct e1000_hw *hw);
+static s32  e1000_init_hw_82542(struct e1000_hw *hw);
+static s32  e1000_setup_link_82542(struct e1000_hw *hw);
+static s32  e1000_led_on_82542(struct e1000_hw *hw);
+static s32  e1000_led_off_82542(struct e1000_hw *hw);
+static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index);
+static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw);
 
-STATIC s32  e1000_init_phy_params_82542(struct e1000_hw *hw);
-STATIC s32  e1000_init_nvm_params_82542(struct e1000_hw *hw);
-STATIC s32  e1000_init_mac_params_82542(struct e1000_hw *hw);
-STATIC s32  e1000_get_bus_info_82542(struct e1000_hw *hw);
-STATIC s32  e1000_reset_hw_82542(struct e1000_hw *hw);
-STATIC s32  e1000_init_hw_82542(struct e1000_hw *hw);
-STATIC s32  e1000_setup_link_82542(struct e1000_hw *hw);
-STATIC s32  e1000_led_on_82542(struct e1000_hw *hw);
-STATIC s32  e1000_led_off_82542(struct e1000_hw *hw);
-STATIC void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw);
-
-struct e1000_dev_spec_82542 {
-       boolean_t dma_fairness;
-};
-
 /**
  *  e1000_init_phy_params_82542 - Init PHY func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_phy_params_82542(struct e1000_hw *hw)
+static s32 e1000_init_phy_params_82542(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val = E1000_SUCCESS;
@@ -77,14 +69,10 @@
 /**
  *  e1000_init_nvm_params_82542 - Init NVM func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_nvm_params_82542(struct e1000_hw *hw)
+static s32 e1000_init_nvm_params_82542(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_functions *func = &hw->func;
 
        DEBUGFUNC("e1000_init_nvm_params_82542");
 
@@ -95,11 +83,11 @@
        nvm->word_size          = 64;
 
        /* Function Pointers */
-       func->read_nvm          = e1000_read_nvm_microwire;
-       func->release_nvm       = e1000_stop_nvm;
-       func->write_nvm         = e1000_write_nvm_microwire;
-       func->update_nvm        = e1000_update_nvm_checksum_generic;
-       func->validate_nvm      = e1000_validate_nvm_checksum_generic;
+       nvm->ops.read           = e1000_read_nvm_microwire;
+       nvm->ops.release        = e1000_stop_nvm;
+       nvm->ops.write          = e1000_write_nvm_microwire;
+       nvm->ops.update         = e1000_update_nvm_checksum_generic;
+       nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
 
        return E1000_SUCCESS;
 }
@@ -107,20 +95,15 @@
 /**
  *  e1000_init_mac_params_82542 - Init MAC func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_mac_params_82542(struct e1000_hw *hw)
+static s32 e1000_init_mac_params_82542(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_mac_params_82542");
 
        /* Set media type */
-       hw->media_type = e1000_media_type_fiber;
+       hw->phy.media_type = e1000_media_type_fiber;
 
        /* Set mta register count */
        mac->mta_reg_count = 128;
@@ -130,58 +113,53 @@
        /* Function pointers */
 
        /* bus type/speed/width */
-       func->get_bus_info = e1000_get_bus_info_82542;
+       mac->ops.get_bus_info = e1000_get_bus_info_82542;
+       /* function id */
+       mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
        /* reset */
-       func->reset_hw = e1000_reset_hw_82542;
+       mac->ops.reset_hw = e1000_reset_hw_82542;
        /* hw initialization */
-       func->init_hw = e1000_init_hw_82542;
+       mac->ops.init_hw = e1000_init_hw_82542;
        /* link setup */
-       func->setup_link = e1000_setup_link_82542;
+       mac->ops.setup_link = e1000_setup_link_82542;
        /* phy/fiber/serdes setup */
-       func->setup_physical_interface = e1000_setup_fiber_serdes_link_generic;
+       mac->ops.setup_physical_interface = 
e1000_setup_fiber_serdes_link_generic;
        /* check for link */
-       func->check_for_link = e1000_check_for_fiber_link_generic;
+       mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
        /* multicast address update */
-       func->mc_addr_list_update = e1000_mc_addr_list_update_generic;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
        /* writing VFTA */
-       func->write_vfta = e1000_write_vfta_generic;
+       mac->ops.write_vfta = e1000_write_vfta_generic;
        /* clearing VFTA */
-       func->clear_vfta = e1000_clear_vfta_generic;
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
        /* setting MTA */
-       func->mta_set = e1000_mta_set_generic;
+       mac->ops.mta_set = e1000_mta_set_generic;
+       /* set RAR */
+       mac->ops.rar_set = e1000_rar_set_82542;
        /* turn on/off LED */
-       func->led_on = e1000_led_on_82542;
-       func->led_off = e1000_led_off_82542;
-       /* remove device */
-       func->remove_device = e1000_remove_device_generic;
+       mac->ops.led_on = e1000_led_on_82542;
+       mac->ops.led_off = e1000_led_off_82542;
        /* clear hardware counters */
-       func->clear_hw_cntrs = e1000_clear_hw_cntrs_82542;
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82542;
        /* link info */
-       func->get_link_up_info = 
e1000_get_speed_and_duplex_fiber_serdes_generic;
+       mac->ops.get_link_up_info = 
e1000_get_speed_and_duplex_fiber_serdes_generic;
 
-       hw->dev_spec_size = sizeof(struct e1000_dev_spec_82542);
-
-       /* Device-specific structure allocation */
-       ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size);
-
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
  *  e1000_init_function_pointers_82542 - Init func ptrs.
  *  @hw: pointer to the HW structure
  *
- *  The only function explicitly called by the api module to initialize
- *  all function pointers and parameters.
+ *  Called to initialize all function pointers and parameters.
  **/
-void
-e1000_init_function_pointers_82542(struct e1000_hw *hw)
+void e1000_init_function_pointers_82542(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_init_function_pointers_82542");
 
-       hw->func.init_mac_params = e1000_init_mac_params_82542;
-       hw->func.init_nvm_params = e1000_init_nvm_params_82542;
-       hw->func.init_phy_params = e1000_init_phy_params_82542;
+       hw->mac.ops.init_params = e1000_init_mac_params_82542;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82542;
+       hw->phy.ops.init_params = e1000_init_phy_params_82542;
 }
 
 /**
@@ -189,11 +167,9 @@
  *  @hw: pointer to the HW structure
  *
  *  This will obtain information about the HW bus for which the
- *  adaper is attached and stores it in the hw structure.  This is a function
- *  pointer entry point called by the api module.
+ *  adapter is attached and stores it in the hw structure.
  **/
-STATIC s32
-e1000_get_bus_info_82542(struct e1000_hw *hw)
+static s32 e1000_get_bus_info_82542(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_get_bus_info_82542");
 
@@ -208,11 +184,9 @@
  *  e1000_reset_hw_82542 - Reset hardware
  *  @hw: pointer to the HW structure
  *
- *  This resets the hardware into a known state.  This is a
- *  function pointer entry point called by the api module.
+ *  This resets the hardware into a known state.
  **/
-STATIC s32
-e1000_reset_hw_82542(struct e1000_hw *hw)
+static s32 e1000_reset_hw_82542(struct e1000_hw *hw)
 {
        struct e1000_bus_info *bus = &hw->bus;
        s32 ret_val = E1000_SUCCESS;
@@ -232,7 +206,8 @@
        E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
        E1000_WRITE_FLUSH(hw);
 
-       /* Delay to allow any outstanding PCI transactions to complete before
+       /*
+        * Delay to allow any outstanding PCI transactions to complete before
         * resetting the device
         */
        msec_delay(10);
@@ -242,7 +217,7 @@
        DEBUGOUT("Issuing a global reset to 82542/82543 MAC\n");
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
 
-       e1000_reload_nvm(hw);
+       hw->nvm.ops.reload(hw);
        msec_delay(2);
 
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
@@ -260,25 +235,21 @@
  *  e1000_init_hw_82542 - Initialize hardware
  *  @hw: pointer to the HW structure
  *
- *  This inits the hardware readying it for operation.  This is a
- *  function pointer entry point called by the api module.
+ *  This inits the hardware readying it for operation.
  **/
-STATIC s32
-e1000_init_hw_82542(struct e1000_hw *hw)
+static s32 e1000_init_hw_82542(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_dev_spec_82542 *dev_spec;
+       struct e1000_dev_spec_82542 *dev_spec = &hw->dev_spec._82542;
        s32 ret_val = E1000_SUCCESS;
        u32 ctrl;
        u16 i;
 
        DEBUGFUNC("e1000_init_hw_82542");
 
-       dev_spec = (struct e1000_dev_spec_82542 *)hw->dev_spec;
-
        /* Disabling VLAN filtering */
        E1000_WRITE_REG(hw, E1000_VET, 0);
-       e1000_clear_vfta(hw);
+       mac->ops.clear_vfta(hw);
 
        /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
        if (hw->revision_id == E1000_REVISION_2) {
@@ -306,7 +277,8 @@
        for (i = 0; i < mac->mta_reg_count; i++)
                E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
 
-       /* Set the PCI priority bit correctly in the CTRL register.  This
+       /*
+        * Set the PCI priority bit correctly in the CTRL register.  This
         * determines if the adapter gives priority to receives, or if it
         * gives equal priority to transmits and receives.
         */
@@ -318,7 +290,8 @@
        /* Setup link and flow control */
        ret_val = e1000_setup_link_82542(hw);
 
-       /* Clear all of the statistics registers (clear on read).  It is
+       /*
+        * 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.
@@ -336,14 +309,11 @@
  *  control.  Calls the appropriate media-specific link configuration
  *  function.  Assuming the adapter has a valid link partner, a valid link
  *  should be established.  Assumes the hardware has previously been reset
- *  and the transmitter and receiver are not enabled.  This is a function
- *  pointer entry point called by the api module.
+ *  and the transmitter and receiver are not enabled.
  **/
-STATIC s32
-e1000_setup_link_82542(struct e1000_hw *hw)
+static s32 e1000_setup_link_82542(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_setup_link_82542");
@@ -352,25 +322,27 @@
        if (ret_val)
                goto out;
 
-       mac->fc &= ~e1000_fc_tx_pause;
+       hw->fc.requested_mode &= ~e1000_fc_tx_pause;
 
        if (mac->report_tx_early == 1)
-               mac->fc &= ~e1000_fc_rx_pause;
+               hw->fc.requested_mode &= ~e1000_fc_rx_pause;
 
-       /* We want to save off the original Flow Control configuration just in
-        * case we get disconnected and then reconnected into a different hub
-        * or switch with different Flow Control capabilities.
+       /*
+        * Save off the requested flow control mode for use later.  Depending
+        * on the link partner's capabilities, we may or may not use this mode.
         */
-       mac->original_fc = mac->fc;
+       hw->fc.current_mode = hw->fc.requested_mode;
 
-       DEBUGOUT1("After fix-ups FlowControl is now = %x\n", mac->fc);
+       DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
+                                                    hw->fc.current_mode);
 
        /* Call the necessary subroutine to configure the link. */
-       ret_val = func->setup_physical_interface(hw);
+       ret_val = mac->ops.setup_physical_interface(hw);
        if (ret_val)
                goto out;
 
-       /* Initialize the flow control address, type, and PAUSE timer
+       /*
+        * Initialize the flow control address, type, and PAUSE timer
         * registers to their default values.  This is done even if flow
         * control is disabled, because it does not hurt anything to
         * initialize these registers.
@@ -381,7 +353,7 @@
        E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH);
        E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE);
 
-       E1000_WRITE_REG(hw, E1000_FCTTV, mac->fc_pause_time);
+       E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
 
        ret_val = e1000_set_fc_watermarks_generic(hw);
 
@@ -393,11 +365,9 @@
  *  e1000_led_on_82542 - Turn on SW controllable LED
  *  @hw: pointer to the HW structure
  *
- *  Turns the SW defined LED on.  This is a function pointer entry point
- *  called by the api module.
+ *  Turns the SW defined LED on.
  **/
-STATIC s32
-e1000_led_on_82542(struct e1000_hw *hw)
+static s32 e1000_led_on_82542(struct e1000_hw *hw)
 {
        u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
 
@@ -414,11 +384,9 @@
  *  e1000_led_off_82542 - Turn off SW controllable LED
  *  @hw: pointer to the HW structure
  *
- *  Turns the SW defined LED off.  This is a function pointer entry point
- *  called by the api module.
+ *  Turns the SW defined LED off.
  **/
-STATIC s32
-e1000_led_off_82542(struct e1000_hw *hw)
+static s32 e1000_led_off_82542(struct e1000_hw *hw)
 {
        u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
 
@@ -432,7 +400,40 @@
 }
 
 /**
- *  e1000_translate_register_82542 - Translate the proper regiser offset
+ *  e1000_rar_set_82542 - Set receive address register
+ *  @hw: pointer to the HW structure
+ *  @addr: pointer to the receive address
+ *  @index: receive address array register
+ *
+ *  Sets the receive address array register at index to the address passed
+ *  in by addr.
+ **/
+static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+       u32 rar_low, rar_high;
+
+       DEBUGFUNC("e1000_rar_set_82542");
+
+       /*
+        * HW expects these in little endian so we reverse the byte order
+        * from network order (big endian) to little endian
+        */
+       rar_low = ((u32) addr[0] |
+                  ((u32) addr[1] << 8) |
+                  ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+
+       rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+
+       /* If MAC address zero, no need to set the AV bit */
+       if (rar_low || rar_high)
+               rar_high |= E1000_RAH_AV;
+
+       E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
+       E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
+}
+
+/**
+ *  e1000_translate_register_82542 - Translate the proper register offset
  *  @reg: e1000 register to be read
  *
  *  Registers in 82542 are located in different offsets than other adapters
@@ -440,10 +441,10 @@
  *  the name of the register to read and returns the correct offset for
  *  82542 silicon.
  **/
-u32
-e1000_translate_register_82542(u32 reg)
+u32 e1000_translate_register_82542(u32 reg)
 {
-       /* Some of the 82542 registers are located at different
+       /*
+        * Some of the 82542 registers are located at different
         * offsets than they are in newer adapters.
         * Despite the difference in location, the registers
         * function in the same manner.
@@ -455,34 +456,34 @@
        case E1000_RDTR:
                reg = 0x00108;
                break;
-       case E1000_RDBAL:
+       case E1000_RDBAL(0):
                reg = 0x00110;
                break;
-       case E1000_RDBAH:
+       case E1000_RDBAH(0):
                reg = 0x00114;
                break;
-       case E1000_RDLEN:
+       case E1000_RDLEN(0):
                reg = 0x00118;
                break;
-       case E1000_RDH:
+       case E1000_RDH(0):
                reg = 0x00120;
                break;
-       case E1000_RDT:
+       case E1000_RDT(0):
                reg = 0x00128;
                break;
-       case E1000_RDBAL1:
+       case E1000_RDBAL(1):
                reg = 0x00138;
                break;
-       case E1000_RDBAH1:
+       case E1000_RDBAH(1):
                reg = 0x0013C;
                break;
-       case E1000_RDLEN1:
+       case E1000_RDLEN(1):
                reg = 0x00140;
                break;
-       case E1000_RDH1:
+       case E1000_RDH(1):
                reg = 0x00148;
                break;
-       case E1000_RDT1:
+       case E1000_RDT(1):
                reg = 0x00150;
                break;
        case E1000_FCRTH:
@@ -494,19 +495,19 @@
        case E1000_MTA:
                reg = 0x00200;
                break;
-       case E1000_TDBAL:
+       case E1000_TDBAL(0):
                reg = 0x00420;
                break;
-       case E1000_TDBAH:
+       case E1000_TDBAH(0):
                reg = 0x00424;
                break;
-       case E1000_TDLEN:
+       case E1000_TDLEN(0):
                reg = 0x00428;
                break;
-       case E1000_TDH:
+       case E1000_TDH(0):
                reg = 0x00430;
                break;
-       case E1000_TDT:
+       case E1000_TDT(0):
                reg = 0x00438;
                break;
        case E1000_TIDV:
@@ -534,25 +535,22 @@
  *
  *  Clears the hardware counters by reading the counter registers.
  **/
-STATIC void
-e1000_clear_hw_cntrs_82542(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw)
 {
-       volatile u32 temp;
-
        DEBUGFUNC("e1000_clear_hw_cntrs_82542");
 
        e1000_clear_hw_cntrs_base_generic(hw);
 
-       temp = E1000_READ_REG(hw, E1000_PRC64);
-       temp = E1000_READ_REG(hw, E1000_PRC127);
-       temp = E1000_READ_REG(hw, E1000_PRC255);
-       temp = E1000_READ_REG(hw, E1000_PRC511);
-       temp = E1000_READ_REG(hw, E1000_PRC1023);
-       temp = E1000_READ_REG(hw, E1000_PRC1522);
-       temp = E1000_READ_REG(hw, E1000_PTC64);
-       temp = E1000_READ_REG(hw, E1000_PTC127);
-       temp = E1000_READ_REG(hw, E1000_PTC255);
-       temp = E1000_READ_REG(hw, E1000_PTC511);
-       temp = E1000_READ_REG(hw, E1000_PTC1023);
-       temp = E1000_READ_REG(hw, E1000_PTC1522);
+       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);
 }
Index: dev/em/e1000_82543.c
===================================================================
--- dev/em/e1000_82543.c        (Revision 28889)
+++ dev/em/e1000_82543.c        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,76 +29,70 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82543.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82543.c,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
-
-/* e1000_82543
- * e1000_82544
+/*
+ * 82543GC Gigabit Ethernet Controller (Fiber)
+ * 82543GC Gigabit Ethernet Controller (Copper)
+ * 82544EI Gigabit Ethernet Controller (Copper)
+ * 82544EI Gigabit Ethernet Controller (Fiber)
+ * 82544GC Gigabit Ethernet Controller (Copper)
+ * 82544GC Gigabit Ethernet Controller (LOM)
  */
 
 #include "e1000_api.h"
-#include "e1000_82543.h"
 
-void e1000_init_function_pointers_82543(struct e1000_hw *hw);
+static s32  e1000_init_phy_params_82543(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_82543(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82543(struct e1000_hw *hw);
+static s32  e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset,
+                                     u16 *data);
+static s32  e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset,
+                                      u16 data);
+static s32  e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw);
+static s32  e1000_phy_hw_reset_82543(struct e1000_hw *hw);
+static s32  e1000_reset_hw_82543(struct e1000_hw *hw);
+static s32  e1000_init_hw_82543(struct e1000_hw *hw);
+static s32  e1000_setup_link_82543(struct e1000_hw *hw);
+static s32  e1000_setup_copper_link_82543(struct e1000_hw *hw);
+static s32  e1000_setup_fiber_link_82543(struct e1000_hw *hw);
+static s32  e1000_check_for_copper_link_82543(struct e1000_hw *hw);
+static s32  e1000_check_for_fiber_link_82543(struct e1000_hw *hw);
+static s32  e1000_led_on_82543(struct e1000_hw *hw);
+static s32  e1000_led_off_82543(struct e1000_hw *hw);
+static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset,
+                                   u32 value);
+static void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value);
+static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw);
+static s32  e1000_config_mac_to_phy_82543(struct e1000_hw *hw);
+static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw);
+static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
+static s32  e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw);
+static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
+static u16  e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw);
+static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
+                                           u16 count);
+static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw);
+static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state);
 
-STATIC s32       e1000_init_phy_params_82543(struct e1000_hw *hw);
-STATIC s32       e1000_init_nvm_params_82543(struct e1000_hw *hw);
-STATIC s32       e1000_init_mac_params_82543(struct e1000_hw *hw);
-STATIC s32       e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset,
-                                          u16 *data);
-STATIC s32       e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset,
-                                           u16 data);
-STATIC s32       e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw);
-STATIC s32       e1000_phy_hw_reset_82543(struct e1000_hw *hw);
-STATIC s32       e1000_reset_hw_82543(struct e1000_hw *hw);
-STATIC s32       e1000_init_hw_82543(struct e1000_hw *hw);
-STATIC s32       e1000_setup_link_82543(struct e1000_hw *hw);
-STATIC s32       e1000_setup_copper_link_82543(struct e1000_hw *hw);
-STATIC s32       e1000_setup_fiber_link_82543(struct e1000_hw *hw);
-STATIC s32       e1000_check_for_copper_link_82543(struct e1000_hw *hw);
-STATIC s32       e1000_check_for_fiber_link_82543(struct e1000_hw *hw);
-STATIC s32       e1000_led_on_82543(struct e1000_hw *hw);
-STATIC s32       e1000_led_off_82543(struct e1000_hw *hw);
-STATIC void      e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset,
-                                        u32 value);
-STATIC void      e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value);
-STATIC void      e1000_clear_hw_cntrs_82543(struct e1000_hw *hw);
-static s32       e1000_config_mac_to_phy_82543(struct e1000_hw *hw);
-static boolean_t e1000_init_phy_disabled_82543(struct e1000_hw *hw);
-static void      e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
-static s32       e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw);
-static void      e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
-static u16       e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw);
-static void      e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
-                                                u16 count);
-static boolean_t e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw);
-static void      e1000_set_tbi_sbp_82543(struct e1000_hw *hw, boolean_t state);
-
-struct e1000_dev_spec_82543 {
-       u32  tbi_compatibility;
-       boolean_t dma_fairness;
-       boolean_t init_phy_disabled;
-};
-
 /**
  *  e1000_init_phy_params_82543 - Init PHY func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_phy_params_82543(struct e1000_hw *hw)
+static s32 e1000_init_phy_params_82543(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_phy_params_82543");
 
-       if (hw->media_type != e1000_media_type_copper) {
+       if (hw->phy.media_type != e1000_media_type_copper) {
                phy->type               = e1000_phy_none;
                goto out;
+       } else {
+               phy->ops.power_up       = e1000_power_up_phy_copper;
+               phy->ops.power_down     = e1000_power_down_phy_copper;
        }
 
        phy->addr                       = 1;
@@ -107,28 +101,29 @@
        phy->type                       = e1000_phy_m88;
 
        /* Function Pointers */
-       func->check_polarity            = e1000_check_polarity_m88;
-       func->commit_phy                = e1000_phy_sw_reset_generic;
-       func->force_speed_duplex        = e1000_phy_force_speed_duplex_82543;
-       func->get_cable_length          = e1000_get_cable_length_m88;
-       func->get_cfg_done              = e1000_get_cfg_done_generic;
-       func->read_phy_reg              = (hw->mac.type == e1000_82543)
+       phy->ops.check_polarity         = e1000_check_polarity_m88;
+       phy->ops.commit                 = e1000_phy_sw_reset_generic;
+       phy->ops.force_speed_duplex     = e1000_phy_force_speed_duplex_82543;
+       phy->ops.get_cable_length       = e1000_get_cable_length_m88;
+       phy->ops.get_cfg_done           = e1000_get_cfg_done_generic;
+       phy->ops.read_reg               = (hw->mac.type == e1000_82543)
                                          ? e1000_read_phy_reg_82543
                                          : e1000_read_phy_reg_m88;
-       func->reset_phy                 = (hw->mac.type == e1000_82543)
+       phy->ops.reset                  = (hw->mac.type == e1000_82543)
                                          ? e1000_phy_hw_reset_82543
                                          : e1000_phy_hw_reset_generic;
-       func->write_phy_reg             = (hw->mac.type == e1000_82543)
+       phy->ops.write_reg              = (hw->mac.type == e1000_82543)
                                          ? e1000_write_phy_reg_82543
                                          : e1000_write_phy_reg_m88;
-       func->get_phy_info              = e1000_get_phy_info_m88;
+       phy->ops.get_info               = e1000_get_phy_info_m88;
 
-       /* The external PHY of the 82543 can be in a funky state.
+       /*
+        * The external PHY of the 82543 can be in a funky state.
         * Resetting helps us read the PHY registers for acquiring
         * the PHY ID.
         */
        if (!e1000_init_phy_disabled_82543(hw)) {
-               ret_val = e1000_phy_hw_reset(hw);
+               ret_val = phy->ops.reset(hw);
                if (ret_val) {
                        DEBUGOUT("Resetting PHY during init failed.\n");
                        goto out;
@@ -167,14 +162,10 @@
 /**
  *  e1000_init_nvm_params_82543 - Init NVM func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_nvm_params_82543(struct e1000_hw *hw)
+static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_functions *func = &hw->func;
 
        DEBUGFUNC("e1000_init_nvm_params_82543");
 
@@ -185,11 +176,11 @@
        nvm->opcode_bits        =  3;
 
        /* Function Pointers */
-       func->read_nvm          = e1000_read_nvm_microwire;
-       func->update_nvm        = e1000_update_nvm_checksum_generic;
-       func->valid_led_default = e1000_valid_led_default_generic;
-       func->validate_nvm      = e1000_validate_nvm_checksum_generic;
-       func->write_nvm         = e1000_write_nvm_microwire;
+       nvm->ops.read           = e1000_read_nvm_microwire;
+       nvm->ops.update         = e1000_update_nvm_checksum_generic;
+       nvm->ops.valid_led_default = e1000_valid_led_default_generic;
+       nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
+       nvm->ops.write          = e1000_write_nvm_microwire;
 
        return E1000_SUCCESS;
 }
@@ -197,15 +188,10 @@
 /**
  *  e1000_init_mac_params_82543 - Init MAC func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_mac_params_82543(struct e1000_hw *hw)
+static s32 e1000_init_mac_params_82543(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
-       s32 ret_val;
 
        DEBUGFUNC("e1000_init_mac_params_82543");
 
@@ -213,10 +199,10 @@
        switch (hw->device_id) {
        case E1000_DEV_ID_82543GC_FIBER:
        case E1000_DEV_ID_82544EI_FIBER:
-               hw->media_type = e1000_media_type_fiber;
+               hw->phy.media_type = e1000_media_type_fiber;
                break;
        default:
-               hw->media_type = e1000_media_type_copper;
+               hw->phy.media_type = e1000_media_type_copper;
                break;
        }
 
@@ -228,89 +214,78 @@
        /* Function pointers */
 
        /* bus type/speed/width */
-       func->get_bus_info = e1000_get_bus_info_pci_generic;
+       mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
+       /* function id */
+       mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
        /* reset */
-       func->reset_hw = e1000_reset_hw_82543;
+       mac->ops.reset_hw = e1000_reset_hw_82543;
        /* hw initialization */
-       func->init_hw = e1000_init_hw_82543;
+       mac->ops.init_hw = e1000_init_hw_82543;
        /* link setup */
-       func->setup_link = e1000_setup_link_82543;
+       mac->ops.setup_link = e1000_setup_link_82543;
        /* physical interface setup */
-       func->setup_physical_interface =
-               (hw->media_type == e1000_media_type_copper)
+       mac->ops.setup_physical_interface =
+               (hw->phy.media_type == e1000_media_type_copper)
                        ? e1000_setup_copper_link_82543
                        : e1000_setup_fiber_link_82543;
        /* check for link */
-       func->check_for_link =
-               (hw->media_type == e1000_media_type_copper)
+       mac->ops.check_for_link =
+               (hw->phy.media_type == e1000_media_type_copper)
                        ? e1000_check_for_copper_link_82543
                        : e1000_check_for_fiber_link_82543;
        /* link info */
-       func->get_link_up_info =
-               (hw->media_type == e1000_media_type_copper)
+       mac->ops.get_link_up_info =
+               (hw->phy.media_type == e1000_media_type_copper)
                        ? e1000_get_speed_and_duplex_copper_generic
                        : e1000_get_speed_and_duplex_fiber_serdes_generic;
        /* multicast address update */
-       func->mc_addr_list_update = e1000_mc_addr_list_update_generic;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
        /* writing VFTA */
-       func->write_vfta = e1000_write_vfta_82543;
+       mac->ops.write_vfta = e1000_write_vfta_82543;
        /* clearing VFTA */
-       func->clear_vfta = e1000_clear_vfta_generic;
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
        /* setting MTA */
-       func->mta_set = e1000_mta_set_82543;
+       mac->ops.mta_set = e1000_mta_set_82543;
        /* turn on/off LED */
-       func->led_on = e1000_led_on_82543;
-       func->led_off = e1000_led_off_82543;
-       /* remove device */
-       func->remove_device = e1000_remove_device_generic;
+       mac->ops.led_on = e1000_led_on_82543;
+       mac->ops.led_off = e1000_led_off_82543;
        /* clear hardware counters */
-       func->clear_hw_cntrs = e1000_clear_hw_cntrs_82543;
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82543;
 
-       hw->dev_spec_size = sizeof(struct e1000_dev_spec_82543);
-
-       /* Device-specific structure allocation */
-       ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size);
-       if (ret_val)
-               goto out;
-
        /* Set tbi compatibility */
        if ((hw->mac.type != e1000_82543) ||
-           (hw->media_type == e1000_media_type_fiber))
+           (hw->phy.media_type == e1000_media_type_fiber))
                e1000_set_tbi_compatibility_82543(hw, FALSE);
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
  *  e1000_init_function_pointers_82543 - Init func ptrs.
  *  @hw: pointer to the HW structure
  *
- *  The only function explicitly called by the api module to initialize
- *  all function pointers and parameters.
+ *  Called to initialize all function pointers and parameters.
  **/
-void
-e1000_init_function_pointers_82543(struct e1000_hw *hw)
+void e1000_init_function_pointers_82543(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_init_function_pointers_82543");
 
-       hw->func.init_mac_params = e1000_init_mac_params_82543;
-       hw->func.init_nvm_params = e1000_init_nvm_params_82543;
-       hw->func.init_phy_params = e1000_init_phy_params_82543;
+       hw->mac.ops.init_params = e1000_init_mac_params_82543;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82543;
+       hw->phy.ops.init_params = e1000_init_phy_params_82543;
 }
 
 /**
  *  e1000_tbi_compatibility_enabled_82543 - Returns TBI compat status
  *  @hw: pointer to the HW structure
  *
- *  Returns the curent status of 10-bit Interface (TBI) compatibility
+ *  Returns the current status of 10-bit Interface (TBI) compatibility
  *  (enabled/disabled).
  **/
-static boolean_t
-e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw)
+static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw)
 {
-       struct e1000_dev_spec_82543 *dev_spec;
-       boolean_t state = FALSE;
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       bool state = FALSE;
 
        DEBUGFUNC("e1000_tbi_compatibility_enabled_82543");
 
@@ -319,13 +294,6 @@
                goto out;
        }
 
-       dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               goto out;
-       }
-
        state = (dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED)
                ? TRUE : FALSE;
 
@@ -340,10 +308,9 @@
  *
  *  Enables or disabled 10-bit Interface (TBI) compatibility.
  **/
-void
-e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, boolean_t state)
+void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state)
 {
-       struct e1000_dev_spec_82543 *dev_spec;
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
 
        DEBUGFUNC("e1000_set_tbi_compatibility_82543");
 
@@ -352,13 +319,6 @@
                goto out;
        }
 
-       dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               goto out;
-       }
-
        if (state)
                dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED;
        else
@@ -372,14 +332,13 @@
  *  e1000_tbi_sbp_enabled_82543 - Returns TBI SBP status
  *  @hw: pointer to the HW structure
  *
- *  Returns the curent status of 10-bit Interface (TBI) store bad packet (SBP)
+ *  Returns the current status of 10-bit Interface (TBI) store bad packet (SBP)
  *  (enabled/disabled).
  **/
-boolean_t
-e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw)
+bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw)
 {
-       struct e1000_dev_spec_82543 *dev_spec;
-       boolean_t state = FALSE;
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       bool state = FALSE;
 
        DEBUGFUNC("e1000_tbi_sbp_enabled_82543");
 
@@ -388,13 +347,6 @@
                goto out;
        }
 
-       dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               goto out;
-       }
-
        state = (dev_spec->tbi_compatibility & TBI_SBP_ENABLED)
                ? TRUE : FALSE;
 
@@ -409,15 +361,12 @@
  *
  *  Enables or disabled 10-bit Interface (TBI) store bad packet (SBP).
  **/
-static void
-e1000_set_tbi_sbp_82543(struct e1000_hw *hw, boolean_t state)
+static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state)
 {
-       struct e1000_dev_spec_82543 *dev_spec;
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
 
        DEBUGFUNC("e1000_set_tbi_sbp_82543");
 
-       dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
-
        if (state && e1000_tbi_compatibility_enabled_82543(hw))
                dev_spec->tbi_compatibility |= TBI_SBP_ENABLED;
        else
@@ -431,13 +380,12 @@
  *  @hw: pointer to the HW structure
  *
  *  Returns the current status of whether PHY initialization is disabled.
- *  True if PHY initialization is disabled else false.
+ *  True if PHY initialization is disabled else FALSE.
  **/
-static boolean_t
-e1000_init_phy_disabled_82543(struct e1000_hw *hw)
+static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw)
 {
-       struct e1000_dev_spec_82543 *dev_spec;
-       boolean_t ret_val;
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       bool ret_val;
 
        DEBUGFUNC("e1000_init_phy_disabled_82543");
 
@@ -446,14 +394,6 @@
                goto out;
        }
 
-       dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               ret_val = FALSE;
-               goto out;
-       }
-
        ret_val = dev_spec->init_phy_disabled;
 
 out:
@@ -466,21 +406,21 @@
  *  @stats: Struct containing statistic register values
  *  @frame_len: The length of the frame in question
  *  @mac_addr: The Ethernet destination address of the frame in question
+ *  @max_frame_size: The maximum frame size
  *
  *  Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
  **/
-void
-e1000_tbi_adjust_stats_82543(struct e1000_hw *hw, struct e1000_hw_stats *stats,
-                             u32 frame_len, u8 *mac_addr)
+void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
+                                  struct e1000_hw_stats *stats, u32 frame_len,
+                                  u8 *mac_addr, u32 max_frame_size)
 {
-       u64 carry_bit;
-
-       if (e1000_tbi_sbp_enabled_82543(hw) == FALSE)
+       if (!(e1000_tbi_sbp_enabled_82543(hw)))
                goto out;
 
        /* First adjust the frame length. */
        frame_len--;
-       /* We need to adjust the statistics counters, since the hardware
+       /*
+        * We need to adjust the statistics counters, since the hardware
         * counters overcount this packet as a CRC error and undercount
         * the packet as a good packet
         */
@@ -490,18 +430,10 @@
        stats->gprc++;
 
        /* Adjust the Good Octets received counters             */
-       carry_bit = 0x80000000 & stats->gorcl;
-       stats->gorcl += frame_len;
-       /* If the high bit of Gorcl (the low 32 bits of the Good Octets
-        * Received Count) was one before the addition,
-        * AND it is zero after, then we lost the carry out,
-        * need to add one to Gorch (Good Octets Received Count High).
-        * This could be simplified if all environments supported
-        * 64-bit integers.
-        */
-       if (carry_bit && ((stats->gorcl & 0x80000000) == 0))
-               stats->gorch++;
-       /* Is this a broadcast or multicast?  Check broadcast first,
+       stats->gorc += frame_len;
+
+       /*
+        * Is this a broadcast or multicast?  Check broadcast first,
         * since the test for a multicast frame will test positive on
         * a broadcast frame.
         */
@@ -512,13 +444,15 @@
                /* Multicast packet */
                stats->mprc++;
 
-       /* In this case, the hardware has overcounted the number of
+       /*
+        * In this case, the hardware has overcounted the number of
         * oversize frames.
         */
-       if ((frame_len == hw->mac.max_frame_size) && (stats->roc > 0))
+       if ((frame_len == max_frame_size) && (stats->roc > 0))
                stats->roc--;
 
-       /* Adjust the bin counters when the extra byte put the frame in the
+       /*
+        * Adjust the bin counters when the extra byte put the frame in the
         * wrong bin. Remember that the frame_len was adjusted above.
         */
        if (frame_len == 64) {
@@ -552,8 +486,7 @@
  *
  *  Reads the PHY at offset and stores the information read to data.
  **/
-STATIC s32
-e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data)
 {
        u32 mdic;
        s32 ret_val = E1000_SUCCESS;
@@ -566,13 +499,15 @@
                goto out;
        }
 
-       /* We must first send a preamble through the MDIO pin to signal the
+       /*
+        * We must first send a preamble through the MDIO pin to signal the
         * beginning of an MII instruction.  This is done by sending 32
         * consecutive "1" bits.
         */
        e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
 
-       /* Now combine the next few fields that are required for a read
+       /*
+        * Now combine the next few fields that are required for a read
         * operation.  We use this method instead of calling the
         * e1000_shift_out_mdi_bits routine five different times.  The format
         * of an MII read instruction consists of a shift out of 14 bits and
@@ -588,7 +523,8 @@
 
        e1000_shift_out_mdi_bits_82543(hw, mdic, 14);
 
-       /* Now that we've shifted out the read command to the MII, we need to
+       /*
+        * Now that we've shifted out the read command to the MII, we need to
         * "shift in" the 16-bit value (18 total bits) of the requested PHY
         * register address.
         */
@@ -606,8 +542,7 @@
  *
  *  Writes data to the PHY at offset.
  **/
-STATIC s32
-e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data)
+static s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data)
 {
        u32 mdic;
        s32 ret_val = E1000_SUCCESS;
@@ -620,14 +555,16 @@
                goto out;
        }
 
-       /* We'll need to use the SW defined pins to shift the write command
+       /*
+        * We'll need to use the SW defined pins to shift the write command
         * out to the PHY. We first send a preamble to the PHY to signal the
         * beginning of the MII instruction.  This is done by sending 32
         * consecutive "1" bits.
         */
        e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
 
-       /* Now combine the remaining required fields that will indicate a
+       /*
+        * Now combine the remaining required fields that will indicate a
         * write operation. We use this method instead of calling the
         * e1000_shift_out_mdi_bits routine for each field in the command. The
         * format of a MII write instruction is as follows:
@@ -652,10 +589,10 @@
  *  Raise the management data input clock by setting the MDC bit in the control
  *  register.
  **/
-static void
-e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
+static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
 {
-       /* Raise the clock input to the Management Data Clock (by setting the
+       /*
+        * Raise the clock input to the Management Data Clock (by setting the
         * MDC bit), and then delay a sufficient amount of time.
         */
        E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl | E1000_CTRL_MDC));
@@ -668,13 +605,13 @@
  *  @hw: pointer to the HW structure
  *  @ctrl: pointer to the control register
  *
- *  Lower the management data input clock by clearing the MDC bit in the 
control
- *  register.
+ *  Lower the management data input clock by clearing the MDC bit in the
+ *  control register.
  **/
-static void
-e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
+static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
 {
-       /* Lower the clock input to the Management Data Clock (by clearing the
+       /*
+        * Lower the clock input to the Management Data Clock (by clearing the
         * MDC bit), and then delay a sufficient amount of time.
         */
        E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl & ~E1000_CTRL_MDC));
@@ -692,12 +629,13 @@
  *  "data" parameter will be shifted out to the PHY one bit at a time.
  *  In order to do this, "data" must be broken down into bits.
  **/
-static void
-e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data, u16 count)
+static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
+                                           u16 count)
 {
        u32 ctrl, mask;
 
-       /* We need to shift "count" number of bits out to the PHY.  So, the
+       /*
+        * We need to shift "count" number of bits out to the PHY.  So, the
         * value in the "data" parameter will be shifted out to the PHY one
         * bit at a time.  In order to do this, "data" must be broken down
         * into bits.
@@ -711,7 +649,8 @@
        ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
 
        while (mask) {
-               /* A "1" is shifted out to the PHY by setting the MDIO bit to
+               /*
+                * A "1" is shifted out to the PHY by setting the MDIO bit to
                 * "1" and then raising and lowering the Management Data Clock.
                 * A "0" is shifted out to the PHY by setting the MDIO bit to
                 * "0" and then raising and lowering the clock.
@@ -740,14 +679,14 @@
  *  the PHY (setting the MDC bit), and then reading the value of the data out
  *  MDIO bit.
  **/
-static u16
-e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw)
+static u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw)
 {
        u32 ctrl;
        u16 data = 0;
        u8 i;
 
-       /* In order to read a register from the PHY, we need to shift in a
+       /*
+        * In order to read a register from the PHY, we need to shift in a
         * total of 18 bits from the PHY.  The first two bit (turnaround)
         * times are used to avoid contention on the MDIO pin when a read
         * operation is performed.  These two bits are ignored by us and
@@ -757,7 +696,8 @@
         */
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
 
-       /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
+       /*
+        * Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
         * input.
         */
        ctrl &= ~E1000_CTRL_MDIO_DIR;
@@ -766,7 +706,8 @@
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
        E1000_WRITE_FLUSH(hw);
 
-       /* Raise and lower the clock before reading in the data.  This accounts
+       /*
+        * Raise and lower the clock before reading in the data.  This accounts
         * for the turnaround bits.  The first clock occurred when we clocked
         * out the last bit of the Register Address.
         */
@@ -797,8 +738,7 @@
  *  if the PHY is not auto-negotiating and the speed is forced to 10Mbit,
  *  then call the function for polarity reversal workaround.
  **/
-STATIC s32
-e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw)
+static s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw)
 {
        s32 ret_val;
 
@@ -821,45 +761,49 @@
  *  @hw: pointer to the HW structure
  *
  *  When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity
- *  inadvertantly.  To workaround the issue, we disable the transmitter on
+ *  inadvertently.  To workaround the issue, we disable the transmitter on
  *  the PHY until we have established the link partner's link parameters.
  **/
-static s32
-e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw)
+static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw)
 {
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u16 mii_status_reg;
        u16 i;
-       boolean_t link;
+       bool link;
 
+       if (!(hw->phy.ops.write_reg))
+               goto out;
+
        /* Polarity reversal workaround for forced 10F/10H links. */
 
        /* Disable the transmitter on the PHY */
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
        if (ret_val)
                goto out;
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
        if (ret_val)
                goto out;
 
-       /* This loop will early-out if the NO link condition has been met.
+       /*
+        * This loop will early-out if the NO link condition has been met.
         * In other words, DO NOT use e1000_phy_has_link_generic() here.
         */
        for (i = PHY_FORCE_TIME; i > 0; i--) {
-               /* Read the MII Status Register and wait for Link Status bit
+               /*
+                * Read the MII Status Register and wait for Link Status bit
                 * to be clear.
                 */
 
-               ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
                if (ret_val)
                        goto out;
 
-               ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
                if (ret_val)
                        goto out;
 
@@ -873,27 +817,28 @@
 
        /* Now we will re-enable the transmitter on the PHY */
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
        if (ret_val)
                goto out;
        msec_delay_irq(50);
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
        if (ret_val)
                goto out;
        msec_delay_irq(50);
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
        if (ret_val)
                goto out;
        msec_delay_irq(50);
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
        if (ret_val)
                goto out;
 
-       /* Read the MII Status Register and wait for Link Status bit
+       /*
+        * Read the MII Status Register and wait for Link Status bit
         * to be set.
         */
        ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_TIME, 100000, &link);
@@ -911,18 +856,17 @@
  *  Sets the PHY_RESET_DIR bit in the extended device control register
  *  to put the PHY into a reset and waits for completion.  Once the reset
  *  has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out
- *  of reset.  This is a function pointer entry point called by the api module.
+ *  of reset.
  **/
-STATIC s32
-e1000_phy_hw_reset_82543(struct e1000_hw *hw)
+static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw)
 {
-       struct e1000_functions *func = &hw->func;
        u32 ctrl_ext;
        s32 ret_val;
 
        DEBUGFUNC("e1000_phy_hw_reset_82543");
 
-       /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
+       /*
+        * Read the Extended Device Control Register, assert the PHY_RESET_DIR
         * bit to put the PHY into reset...
         */
        ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
@@ -940,8 +884,11 @@
 
        usec_delay(150);
 
-       ret_val = func->get_cfg_done(hw);
+       if (!(hw->phy.ops.get_cfg_done))
+               return E1000_SUCCESS;
 
+       ret_val = hw->phy.ops.get_cfg_done(hw);
+
        return ret_val;
 }
 
@@ -949,11 +896,9 @@
  *  e1000_reset_hw_82543 - Reset hardware
  *  @hw: pointer to the HW structure
  *
- *  This resets the hardware into a known state.  This is a
- *  function pointer entry point called by the api module.
+ *  This resets the hardware into a known state.
  **/
-STATIC s32
-e1000_reset_hw_82543(struct e1000_hw *hw)
+static s32 e1000_reset_hw_82543(struct e1000_hw *hw)
 {
        u32 ctrl, icr;
        s32 ret_val = E1000_SUCCESS;
@@ -969,7 +914,8 @@
 
        e1000_set_tbi_sbp_82543(hw, FALSE);
 
-       /* Delay to allow any outstanding PCI transactions to complete before
+       /*
+        * Delay to allow any outstanding PCI transactions to complete before
         * resetting the device
         */
        msec_delay(10);
@@ -980,16 +926,18 @@
        if (hw->mac.type == e1000_82543) {
                E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
        } else {
-               /* The 82544 can't ACK the 64-bit write when issuing the
+               /*
+                * The 82544 can't ACK the 64-bit write when issuing the
                 * reset, so use IO-mapping as a workaround.
                 */
                E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
        }
 
-       /* After MAC reset, force reload of NVM to restore power-on
+       /*
+        * After MAC reset, force reload of NVM to restore power-on
         * settings to device.
         */
-       e1000_reload_nvm(hw);
+       hw->nvm.ops.reload(hw);
        msec_delay(2);
 
        /* Masking off and clearing any pending interrupts */
@@ -1005,28 +953,19 @@
  *
  *  This inits the hardware readying it for operation.
  **/
-STATIC s32
-e1000_init_hw_82543(struct e1000_hw *hw)
+static s32 e1000_init_hw_82543(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_dev_spec_82543 *dev_spec;
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
        u32 ctrl;
        s32 ret_val;
        u16 i;
 
        DEBUGFUNC("e1000_init_hw_82543");
 
-       dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-       }
-
        /* Disabling VLAN filtering */
        E1000_WRITE_REG(hw, E1000_VET, 0);
-       e1000_clear_vfta(hw);
+       mac->ops.clear_vfta(hw);
 
        /* Setup the receive address. */
        e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
@@ -1038,7 +977,8 @@
                E1000_WRITE_FLUSH(hw);
        }
 
-       /* Set the PCI priority bit correctly in the CTRL register.  This
+       /*
+        * Set the PCI priority bit correctly in the CTRL register.  This
         * determines if the adapter gives priority to receives, or if it
         * gives equal priority to transmits and receives.
         */
@@ -1050,16 +990,16 @@
        e1000_pcix_mmrbc_workaround_generic(hw);
 
        /* Setup link and flow control */
-       ret_val = e1000_setup_link(hw);
+       ret_val = mac->ops.setup_link(hw);
 
-       /* Clear all of the statistics registers (clear on read).  It is
+       /*
+        * 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_82543(hw);
 
-out:
        return ret_val;
 }
 
@@ -1076,8 +1016,7 @@
  *  should be established.  Assumes the hardware has previously been reset
  *  and the transmitter and receiver are not enabled.
  **/
-STATIC s32
-e1000_setup_link_82543(struct e1000_hw *hw)
+static s32 e1000_setup_link_82543(struct e1000_hw *hw)
 {
        u32 ctrl_ext;
        s32  ret_val;
@@ -1085,14 +1024,15 @@
 
        DEBUGFUNC("e1000_setup_link_82543");
 
-       /* Take the 4 bits from NVM word 0xF that determine the initial
+       /*
+        * Take the 4 bits from NVM word 0xF that determine the initial
         * polarity value for the SW controlled pins, and setup the
         * Extended Device Control reg with that info.
         * This is needed because one of the SW controlled pins is used for
         * signal detection.  So this should be done before phy setup.
         */
        if (hw->mac.type == e1000_82543) {
-               ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+               ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data);
                if (ret_val) {
                        DEBUGOUT("NVM Read Error\n");
                        ret_val = -E1000_ERR_NVM;
@@ -1117,17 +1057,17 @@
  *  for link, once link is established calls to configure collision distance
  *  and flow control are called.
  **/
-STATIC s32
-e1000_setup_copper_link_82543(struct e1000_hw *hw)
+static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32 ret_val;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_setup_copper_link_82543");
 
        ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU;
-       /* With 82543, we need to force speed and duplex on the MAC
+       /*
+        * With 82543, we need to force speed and duplex on the MAC
         * equal to what the PHY speed and duplex configuration is.
         * In addition, we need to perform a hardware reset on the
         * PHY to take it out of reset.
@@ -1135,7 +1075,7 @@
        if (hw->mac.type == e1000_82543) {
                ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
                E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
-               ret_val = e1000_phy_hw_reset(hw);
+               ret_val = hw->phy.ops.reset(hw);
                if (ret_val)
                        goto out;
                hw->phy.reset_disable = FALSE;
@@ -1150,14 +1090,18 @@
                goto out;
 
        if (hw->mac.autoneg) {
-               /* Setup autoneg and flow control advertisement and perform
-                * autonegotiation. */
+               /*
+                * Setup autoneg and flow control advertisement and perform
+                * autonegotiation.
+                */
                ret_val = e1000_copper_link_autoneg(hw);
                if (ret_val)
                        goto out;
        } else {
-               /* PHY will be set to 10H, 10F, 100H or 100F
-                * depending on user settings. */
+               /*
+                * PHY will be set to 10H, 10F, 100H or 100F
+                * depending on user settings.
+                */
                DEBUGOUT("Forcing Speed and Duplex\n");
                ret_val = e1000_phy_force_speed_duplex_82543(hw);
                if (ret_val) {
@@ -1166,7 +1110,8 @@
                }
        }
 
-       /* Check link status. Wait up to 100 microseconds for link to become
+       /*
+        * Check link status. Wait up to 100 microseconds for link to become
         * valid.
         */
        ret_val = e1000_phy_has_link_generic(hw,
@@ -1180,9 +1125,9 @@
        if (link) {
                DEBUGOUT("Valid link established!!!\n");
                /* Config the MAC and PHY after link is up */
-               if (hw->mac.type == e1000_82544)
+               if (hw->mac.type == e1000_82544) {
                        e1000_config_collision_dist_generic(hw);
-               else {
+               } else {
                        ret_val = e1000_config_mac_to_phy_82543(hw);
                        if (ret_val)
                                goto out;
@@ -1203,8 +1148,7 @@
  *  Configures collision distance and flow control for fiber links.  Upon
  *  successful setup, poll for link.
  **/
-STATIC s32
-e1000_setup_fiber_link_82543(struct e1000_hw *hw)
+static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32 ret_val;
@@ -1228,7 +1172,8 @@
        E1000_WRITE_FLUSH(hw);
        msec_delay(1);
 
-       /* For these adapters, the SW defineable pin 1 is cleared when the
+       /*
+        * For these adapters, the SW definable pin 1 is cleared when the
         * optics detect a signal.  If we have a signal, then poll for a
         * "Link-Up" indication.
         */
@@ -1253,14 +1198,13 @@
  *   - configure flow control after link up
  *   - configure tbi compatibility
  **/
-STATIC s32
-e1000_check_for_copper_link_82543(struct e1000_hw *hw)
+static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 icr, rctl;
        s32 ret_val;
        u16 speed, duplex;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_check_for_copper_link_82543");
 
@@ -1280,11 +1224,13 @@
 
        e1000_check_downshift_generic(hw);
 
-       /* If we are forcing speed/duplex, then we can return since
+       /*
+        * If we are forcing speed/duplex, then we can return since
         * we have already determined whether we have link or not.
         */
        if (!mac->autoneg) {
-               /* If speed and duplex are forced to 10H or 10F, then we will
+               /*
+                * If speed and duplex are forced to 10H or 10F, then we will
                 * implement the polarity reversal workaround.  We disable
                 * interrupts first, and upon returning, place the devices
                 * interrupt state to its previous value except for the link
@@ -1303,7 +1249,8 @@
                goto out;
        }
 
-       /* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
+       /*
+        * We have a M88E1000 PHY and Auto-Neg is enabled.  If we
         * have Si on board that is 82544 or newer, Auto
         * Speed Detection takes care of MAC speed/duplex
         * configuration.  So we only need to configure Collision
@@ -1321,7 +1268,8 @@
                }
        }
 
-       /* Configure Flow Control now that Auto-Neg has completed.
+       /*
+        * Configure Flow Control now that Auto-Neg has completed.
         * First, we need to restore the desired flow control
         * settings because we may have had to re-autoneg with a
         * different link partner.
@@ -1331,7 +1279,8 @@
                DEBUGOUT("Error configuring flow control\n");
        }
 
-       /* At this point we know that we are on copper and we have
+       /*
+        * At this point we know that we are on copper and we have
         * auto-negotiated link.  These are conditions for checking the link
         * partner capability register.  We use the link speed to determine if
         * TBI compatibility needs to be turned on or off.  If the link is not
@@ -1339,17 +1288,19 @@
         * at gigabit speed, we turn on TBI compatibility.
         */
        if (e1000_tbi_compatibility_enabled_82543(hw)) {
-               ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+               ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
                if (ret_val) {
                        DEBUGOUT("Error getting link speed and duplex\n");
                        return ret_val;
                }
                if (speed != SPEED_1000) {
-                       /* If link speed is not set to gigabit speed,
+                       /*
+                        * If link speed is not set to gigabit speed,
                         * we do not need to enable TBI compatibility.
                         */
                        if (e1000_tbi_sbp_enabled_82543(hw)) {
-                               /* If we previously were in the mode,
+                               /*
+                                * If we previously were in the mode,
                                 * turn it off.
                                 */
                                e1000_set_tbi_sbp_82543(hw, FALSE);
@@ -1358,7 +1309,8 @@
                                E1000_WRITE_REG(hw, E1000_RCTL, rctl);
                        }
                } else {
-                       /* If TBI compatibility is was previously off,
+                       /*
+                        * If TBI compatibility is was previously off,
                         * turn it on. For compatibility with a TBI link
                         * partner, we will store bad packets. Some
                         * frames have an additional byte on the end and
@@ -1383,8 +1335,7 @@
  *  Checks for link up on the hardware.  If link is not up and we have
  *  a signal, then we need to force link up.
  **/
-STATIC s32
-e1000_check_for_fiber_link_82543(struct e1000_hw *hw)
+static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 rxcw, ctrl, status;
@@ -1393,10 +1344,11 @@
        DEBUGFUNC("e1000_check_for_fiber_link_82543");
 
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
-       status = E1000_READ_REG(hw, E1000_CTRL);
-       rxcw = E1000_READ_REG(hw, E1000_CTRL);
+       status = E1000_READ_REG(hw, E1000_STATUS);
+       rxcw = E1000_READ_REG(hw, E1000_RXCW);
 
-       /* If we don't have link (auto-negotiation failed or link partner
+       /*
+        * If we don't have link (auto-negotiation failed or link partner
         * cannot auto-negotiate), the cable is plugged in (we have signal),
         * and our link partner is not trying to auto-negotiate with us (we
         * are receiving idles or data), we need to force link up. We also
@@ -1429,7 +1381,8 @@
                        goto out;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-               /* If we are forcing link and we are receiving /C/ ordered
+               /*
+                * If we are forcing link and we are receiving /C/ ordered
                 * sets, re-enable auto-negotiation in the TXCW register
                 * and disable forced link in the Device Control register
                 * in an attempt to auto-negotiate with our link partner.
@@ -1452,24 +1405,27 @@
  *  For the 82543 silicon, we need to set the MAC to match the settings
  *  of the PHY, even if the PHY is auto-negotiating.
  **/
-static s32
-e1000_config_mac_to_phy_82543(struct e1000_hw *hw)
+static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw)
 {
        u32 ctrl;
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u16 phy_data;
 
        DEBUGFUNC("e1000_config_mac_to_phy_82543");
 
+       if (!(hw->phy.ops.read_reg))
+               goto out;
+
        /* Set the bits to force speed and duplex */
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
        ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
        ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
 
-       /* Set up duplex in the Device Control and Transmit Control
+       /*
+        * Set up duplex in the Device Control and Transmit Control
         * registers depending on negotiated values.
         */
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+       ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
        if (ret_val)
                goto out;
 
@@ -1479,7 +1435,8 @@
 
        e1000_config_collision_dist_generic(hw);
 
-       /* Set up speed in the Device Control register depending on
+       /*
+        * Set up speed in the Device Control register depending on
         * negotiated values.
         */
        if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
@@ -1502,8 +1459,7 @@
  *  This writes a 32-bit value to a 32-bit offset in the VLAN filter
  *  table.
  **/
-STATIC void
-e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value)
+static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value)
 {
        u32 temp;
 
@@ -1515,8 +1471,9 @@
                E1000_WRITE_FLUSH(hw);
                E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp);
                E1000_WRITE_FLUSH(hw);
-       } else
+       } else {
                e1000_write_vfta_generic(hw, offset, value);
+       }
 }
 
 /**
@@ -1529,8 +1486,7 @@
  *  current value is read, the new bit is OR'd in and the new value is
  *  written back into the register.
  **/
-STATIC void
-e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value)
+static void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value)
 {
        u32 hash_bit, hash_reg, mta, temp;
 
@@ -1538,7 +1494,8 @@
 
        hash_reg = (hash_value >> 5);
 
-       /* If we are on an 82544 and we are trying to write an odd offset
+       /*
+        * If we are on an 82544 and we are trying to write an odd offset
         * in the MTA, save off the previous entry before writing and
         * restore the old value after writing.
         */
@@ -1553,27 +1510,26 @@
                E1000_WRITE_FLUSH(hw);
                E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg - 1, temp);
                E1000_WRITE_FLUSH(hw);
-       } else
+       } else {
                e1000_mta_set_generic(hw, hash_value);
+       }
 }
 
 /**
  *  e1000_led_on_82543 - Turn on SW controllable LED
  *  @hw: pointer to the HW structure
  *
- *  Turns the SW defined LED on.  This is a function pointer entry point
- *  called by the api module.
+ *  Turns the SW defined LED on.
  **/
-STATIC s32
-e1000_led_on_82543(struct e1000_hw *hw)
+static s32 e1000_led_on_82543(struct e1000_hw *hw)
 {
        u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
 
        DEBUGFUNC("e1000_led_on_82543");
 
        if (hw->mac.type == e1000_82544 &&
-           hw->media_type == e1000_media_type_copper) {
-               /* Clear SW-defineable Pin 0 to turn on the LED */
+           hw->phy.media_type == e1000_media_type_copper) {
+               /* Clear SW-definable Pin 0 to turn on the LED */
                ctrl &= ~E1000_CTRL_SWDPIN0;
                ctrl |= E1000_CTRL_SWDPIO0;
        } else {
@@ -1590,19 +1546,17 @@
  *  e1000_led_off_82543 - Turn off SW controllable LED
  *  @hw: pointer to the HW structure
  *
- *  Turns the SW defined LED off.  This is a function pointer entry point
- *  called by the api module.
+ *  Turns the SW defined LED off.
  **/
-STATIC s32
-e1000_led_off_82543(struct e1000_hw *hw)
+static s32 e1000_led_off_82543(struct e1000_hw *hw)
 {
        u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
 
        DEBUGFUNC("e1000_led_off_82543");
 
        if (hw->mac.type == e1000_82544 &&
-           hw->media_type == e1000_media_type_copper) {
-               /* Set SW-defineable Pin 0 to turn off the LED */
+           hw->phy.media_type == e1000_media_type_copper) {
+               /* Set SW-definable Pin 0 to turn off the LED */
                ctrl |= E1000_CTRL_SWDPIN0;
                ctrl |= E1000_CTRL_SWDPIO0;
        } else {
@@ -1620,32 +1574,29 @@
  *
  *  Clears the hardware counters by reading the counter registers.
  **/
-STATIC void
-e1000_clear_hw_cntrs_82543(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw)
 {
-       volatile u32 temp;
-
        DEBUGFUNC("e1000_clear_hw_cntrs_82543");
 
        e1000_clear_hw_cntrs_base_generic(hw);
 
-       temp = E1000_READ_REG(hw, E1000_PRC64);
-       temp = E1000_READ_REG(hw, E1000_PRC127);
-       temp = E1000_READ_REG(hw, E1000_PRC255);
-       temp = E1000_READ_REG(hw, E1000_PRC511);
-       temp = E1000_READ_REG(hw, E1000_PRC1023);
-       temp = E1000_READ_REG(hw, E1000_PRC1522);
-       temp = E1000_READ_REG(hw, E1000_PTC64);
-       temp = E1000_READ_REG(hw, E1000_PTC127);
-       temp = E1000_READ_REG(hw, E1000_PTC255);
-       temp = E1000_READ_REG(hw, E1000_PTC511);
-       temp = E1000_READ_REG(hw, E1000_PTC1023);
-       temp = E1000_READ_REG(hw, E1000_PTC1522);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_ALGNERRC);
-       temp = E1000_READ_REG(hw, E1000_RXERRC);
-       temp = E1000_READ_REG(hw, E1000_TNCRS);
-       temp = E1000_READ_REG(hw, E1000_CEXTERR);
-       temp = E1000_READ_REG(hw, E1000_TSCTC);
-       temp = E1000_READ_REG(hw, E1000_TSCTFC);
+       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);
 }
Index: dev/em/e1000_manage.c
===================================================================
--- dev/em/e1000_manage.c       (Revision 28889)
+++ dev/em/e1000_manage.c       (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,12 +29,10 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_manage.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_manage.c,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
-
 #include "e1000_api.h"
-#include "e1000_manage.h"
 
 static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
 
@@ -46,8 +44,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)
+static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
 {
        u32 i;
        u8  sum = 0;
@@ -69,12 +66,11 @@
  *
  *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
  *
- *  This function checks whether the HOST IF is enabled for command operaton
+ *  This function checks whether the HOST IF is enabled for command operation
  *  and also checks whether the previous command is completed.  It busy waits
  *  in case of previous command is not completed.
  **/
-s32
-e1000_mng_enable_host_if_generic(struct e1000_hw * hw)
+s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
 {
        u32 hicr;
        s32 ret_val = E1000_SUCCESS;
@@ -108,14 +104,13 @@
 }
 
 /**
- *  e1000_check_mng_mode_generic - Generic check managament mode
+ *  e1000_check_mng_mode_generic - Generic check management mode
  *  @hw: pointer to the HW structure
  *
- *  Reads the firmware semaphore register and returns true (>0) if
- *  manageability is enabled, else false (0).
+ *  Reads the firmware semaphore register and returns TRUE (>0) if
+ *  manageability is enabled, else FALSE (0).
  **/
-boolean_t
-e1000_check_mng_mode_generic(struct e1000_hw *hw)
+bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
 {
        u32 fwsm;
 
@@ -123,8 +118,8 @@
 
        fwsm = E1000_READ_REG(hw, E1000_FWSM);
 
-       return ((fwsm & E1000_FWSM_MODE_MASK) ==
-               (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
+       return (fwsm & E1000_FWSM_MODE_MASK) ==
+               (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
 }
 
 /**
@@ -134,28 +129,28 @@
  *  Enables packet filtering on transmit packets if manageability is enabled
  *  and host interface is enabled.
  **/
-boolean_t
-e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
+bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
 {
        struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
        u32 *buffer = (u32 *)&hw->mng_cookie;
        u32 offset;
        s32 ret_val, hdr_csum, csum;
        u8 i, len;
-       boolean_t tx_filter = TRUE;
+       bool tx_filter = TRUE;
 
        DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
 
        /* No manageability, no filtering */
-       if (!e1000_check_mng_mode(hw)) {
+       if (!hw->mac.ops.check_mng_mode(hw)) {
                tx_filter = FALSE;
                goto out;
        }
 
-       /* If we can't read from the host interface for whatever
+       /*
+        * If we can't read from the host interface for whatever
         * reason, disable filtering.
         */
-       ret_val = e1000_mng_enable_host_if(hw);
+       ret_val = hw->mac.ops.mng_enable_host_if(hw);
        if (ret_val != E1000_SUCCESS) {
                tx_filter = FALSE;
                goto out;
@@ -166,14 +161,15 @@
        offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
        for (i = 0; i < len; i++) {
                *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
-                                                          E1000_HOST_IF,
-                                                          offset + i);
+                                                          E1000_HOST_IF,
+                                                          offset + i);
        }
        hdr_csum = hdr->checksum;
        hdr->checksum = 0;
        csum = e1000_calculate_checksum((u8 *)hdr,
                                        E1000_MNG_DHCP_COOKIE_LENGTH);
-       /* If either the checksums or signature don't match, then
+       /*
+        * If either the checksums or signature don't match, then
         * the cookie area isn't considered valid, in which case we
         * take the safe route of assuming Tx filtering is enabled.
         */
@@ -199,8 +195,8 @@
  *
  *  Writes the DHCP information to the host interface.
  **/
-s32
-e1000_mng_write_dhcp_info_generic(struct e1000_hw * hw, u8 *buffer, u16 length)
+s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
+                                      u16 length)
 {
        struct e1000_host_mng_command_header hdr;
        s32 ret_val;
@@ -215,18 +211,18 @@
        hdr.checksum = 0;
 
        /* Enable the host interface */
-       ret_val = e1000_mng_enable_host_if(hw);
+       ret_val = hw->mac.ops.mng_enable_host_if(hw);
        if (ret_val)
                goto out;
 
        /* Populate the host interface with the contents of "buffer". */
-       ret_val = e1000_mng_host_if_write(hw, buffer, length,
+       ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
                                          sizeof(hdr), &(hdr.checksum));
        if (ret_val)
                goto out;
 
        /* Write the manageability command header */
-       ret_val = e1000_mng_write_cmd_header(hw, &hdr);
+       ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
        if (ret_val)
                goto out;
 
@@ -245,9 +241,8 @@
  *
  *  Writes the command header after does the checksum calculation.
  **/
-s32
-e1000_mng_write_cmd_header_generic(struct e1000_hw * hw,
-                                   struct e1000_host_mng_command_header * hdr)
+s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
+                                    struct e1000_host_mng_command_header *hdr)
 {
        u16 i, length = sizeof(struct e1000_host_mng_command_header);
 
@@ -260,7 +255,8 @@
        length >>= 2;
        /* Write 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 *) hdr 
+ i));
+               E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
+                                           *((u32 *) hdr + i));
                E1000_WRITE_FLUSH(hw);
        }
 
@@ -268,7 +264,7 @@
 }
 
 /**
- *  e1000_mng_host_if_write_generic - Writes to the manageability host 
interface
+ *  e1000_mng_host_if_write_generic - Write to the manageability host interface
  *  @hw: pointer to the HW structure
  *  @buffer: pointer to the host interface buffer
  *  @length: size of the buffer
@@ -279,9 +275,8 @@
  *  It also does alignment considerations to do the writes in most efficient
  *  way.  Also fills up the sum of the buffer in *buffer parameter.
  **/
-s32
-e1000_mng_host_if_write_generic(struct e1000_hw * hw, u8 *buffer, u16 length,
-                                u16 offset, u8 *sum)
+s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
+                                    u16 length, u16 offset, u8 *sum)
 {
        u8 *tmp;
        u8 *bufptr = buffer;
@@ -319,15 +314,18 @@
        /* Calculate length in DWORDs */
        length >>= 2;
 
-       /* The device driver writes the relevant command block into the
-        * ram area. */
+       /*
+        * The device driver writes the relevant command block into the
+        * ram area.
+        */
        for (i = 0; i < length; i++) {
                for (j = 0; j < sizeof(u32); j++) {
                        *(tmp + j) = *bufptr++;
                        *sum += *(tmp + j);
                }
 
-               E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, 
data);
+               E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
+                                           data);
        }
        if (remaining) {
                for (j = 0; j < sizeof(u32); j++) {
@@ -351,12 +349,11 @@
  *
  *  Verifies the hardware needs to allow ARPs to be processed by the host.
  **/
-boolean_t
-e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
 {
        u32 manc;
        u32 fwsm, factps;
-       boolean_t ret_val = FALSE;
+       bool ret_val = FALSE;
 
        DEBUGFUNC("e1000_enable_mng_pass_thru");
 
@@ -369,7 +366,7 @@
            !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
                goto out;
 
-       if (hw->mac.arc_subsystem_valid == TRUE) {
+       if (hw->mac.arc_subsystem_valid) {
                fwsm = E1000_READ_REG(hw, E1000_FWSM);
                factps = E1000_READ_REG(hw, E1000_FACTPS);
 
@@ -379,12 +376,13 @@
                        ret_val = TRUE;
                        goto out;
                }
-       } else
+       } else {
                if ((manc & E1000_MANC_SMBUS_EN) &&
                    !(manc & E1000_MANC_ASF_EN)) {
                        ret_val = TRUE;
                        goto out;
                }
+       }
 
 out:
        return ret_val;
Index: dev/em/e1000_82541.h
===================================================================
--- dev/em/e1000_82541.h        (Revision 28889)
+++ dev/em/e1000_82541.h        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,10 +29,9 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82541.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82541.h,v 1.1 2008/07/30 21:56:53 jfv Exp 
$*/
 
-
 #ifndef _E1000_82541_H_
 #define _E1000_82541_H_
 
@@ -88,4 +87,6 @@
 #define IGP01E1000_MSE_CHANNEL_B                 0x0F00
 #define IGP01E1000_MSE_CHANNEL_A                 0xF000
 
+
+void e1000_init_script_state_82541(struct e1000_hw *hw, bool state);
 #endif
Index: dev/em/e1000_82543.h
===================================================================
--- dev/em/e1000_82543.h        (Revision 28889)
+++ dev/em/e1000_82543.h        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,10 +29,9 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82543.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82543.h,v 1.1 2008/07/30 21:56:53 jfv Exp 
$*/
 
-
 #ifndef _E1000_82543_H_
 #define _E1000_82543_H_
 
@@ -44,7 +43,15 @@
 #define PHY_TURNAROUND    0x2
 
 #define TBI_COMPAT_ENABLED 0x1 /* Global "knob" for the workaround */
-#define TBI_SBP_ENABLED    0x2 /* If TBI_COMPAT_ENABLED,
-                                * then this is the current state (on/off) */
+/* If TBI_COMPAT_ENABLED, then this is the current state (on/off) */
+#define TBI_SBP_ENABLED    0x2 
+                                
+void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
+                                  struct e1000_hw_stats *stats,
+                                  u32 frame_len, u8 *mac_addr,
+                                  u32 max_frame_size);
+void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw,
+                                       bool state);
+bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw);
 
 #endif
Index: dev/em/LICENSE
===================================================================
--- dev/em/LICENSE      (Revision 28889)
+++ dev/em/LICENSE      (Arbeitskopie)
@@ -1,6 +1,6 @@
-$FreeBSD: src/sys/dev/em/LICENSE,v 1.6 2007/05/04 00:00:11 jfv Exp $
+$FreeBSD: src/sys/dev/e1000/LICENSE,v 1.1 2008/07/30 21:56:53 jfv Exp $
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
Index: dev/em/e1000_manage.h
===================================================================
--- dev/em/e1000_manage.h       (Revision 28889)
+++ dev/em/e1000_manage.h       (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,30 +29,30 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_manage.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_manage.h,v 1.1 2008/07/30 21:56:53 jfv Exp 
$*/
 
-
 #ifndef _E1000_MANAGE_H_
 #define _E1000_MANAGE_H_
 
-boolean_t e1000_check_mng_mode_generic(struct e1000_hw *hw);
-boolean_t e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw);
-s32       e1000_mng_enable_host_if_generic(struct e1000_hw *hw);
-s32       e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
-                                          u16 length, u16 offset, u8 *sum);
-s32       e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
-                                     struct e1000_host_mng_command_header 
*hdr);
-s32       e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw,
-                                            u8 *buffer, u16 length);
+bool e1000_check_mng_mode_generic(struct e1000_hw *hw);
+bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw);
+s32  e1000_mng_enable_host_if_generic(struct e1000_hw *hw);
+s32  e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
+                                     u16 length, u16 offset, u8 *sum);
+s32  e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
+                                    struct e1000_host_mng_command_header *hdr);
+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);
 
-typedef enum {
+enum e1000_mng_mode {
        e1000_mng_mode_none = 0,
        e1000_mng_mode_asf,
        e1000_mng_mode_pt,
        e1000_mng_mode_ipmi,
        e1000_mng_mode_host_if_only
-} e1000_mng_mode;
+};
 
 #define E1000_FACTPS_MNGCG    0x20000000
 
@@ -71,18 +71,18 @@
 #define E1000_VFTA_ENTRY_MASK                0x7F
 #define E1000_VFTA_ENTRY_BIT_SHIFT_MASK      0x1F
 
-#define E1000_HI_MAX_BLOCK_BYTE_LENGTH       1792 /* Number of bytes in range 
*/
-#define E1000_HI_MAX_BLOCK_DWORD_LENGTH      448 /* Number of dwords in range 
*/
+#define E1000_HI_MAX_BLOCK_BYTE_LENGTH       1792 /* Num of bytes in range */
+#define E1000_HI_MAX_BLOCK_DWORD_LENGTH      448 /* Num of dwords in range */
 #define E1000_HI_COMMAND_TIMEOUT             500 /* Process HI command limit */
 
 #define E1000_HICR_EN              0x01  /* Enable bit - RO */
-#define E1000_HICR_C               0x02  /* Driver sets this bit when done
-                                          * to put command in RAM */
+/* Driver sets this bit when done to put command in RAM */
+#define E1000_HICR_C               0x02
 #define E1000_HICR_SV              0x04  /* Status Validity */
 #define E1000_HICR_FW_RESET_ENABLE 0x40
 #define E1000_HICR_FW_RESET        0x80
 
-#define E1000_IAMT_SIGNATURE  0x544D4149 /* Intel(R) Active Management
-                                          * Technology signature */
+/* Intel(R) Active Management Technology signature */
+#define E1000_IAMT_SIGNATURE  0x544D4149
 
 #endif
Index: dev/em/e1000_phy.c
===================================================================
--- dev/em/e1000_phy.c  (Revision 28889)
+++ dev/em/e1000_phy.c  (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,27 +29,22 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_phy.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_phy.c,v 1.2 2008/11/26 23:57:23 jfv Exp $*/
 
-
 #include "e1000_api.h"
-#include "e1000_phy.h"
 
-static s32  e1000_get_phy_cfg_done(struct e1000_hw *hw);
-static void e1000_release_phy(struct e1000_hw *hw);
-static s32  e1000_acquire_phy(struct e1000_hw *hw);
-
+static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
+static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
+                                          u16 *data, bool read);
 /* Cable length tables */
-static const
-u16 e1000_m88_cable_length_table[] =
+static const u16 e1000_m88_cable_length_table[] =
        { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
 #define M88E1000_CABLE_LENGTH_TABLE_SIZE \
                 (sizeof(e1000_m88_cable_length_table) / \
                  sizeof(e1000_m88_cable_length_table[0]))
 
-static const
-u16 e1000_igp_2_cable_length_table[] =
+static const u16 e1000_igp_2_cable_length_table[] =
     { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
       0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
       6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
@@ -63,6 +58,78 @@
                  sizeof(e1000_igp_2_cable_length_table[0]))
 
 /**
+ *  e1000_init_phy_ops_generic - Initialize PHY function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  Setups up the function pointers to no-op functions
+ **/
+void e1000_init_phy_ops_generic(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       DEBUGFUNC("e1000_init_phy_ops_generic");
+
+       /* Initialize function pointers */
+       phy->ops.init_params = e1000_null_ops_generic;
+       phy->ops.acquire = e1000_null_ops_generic;
+       phy->ops.check_polarity = e1000_null_ops_generic;
+       phy->ops.check_reset_block = e1000_null_ops_generic;
+       phy->ops.commit = e1000_null_ops_generic;
+       phy->ops.force_speed_duplex = e1000_null_ops_generic;
+       phy->ops.get_cfg_done = e1000_null_ops_generic;
+       phy->ops.get_cable_length = e1000_null_ops_generic;
+       phy->ops.get_info = e1000_null_ops_generic;
+       phy->ops.read_reg = e1000_null_read_reg;
+       phy->ops.release = e1000_null_phy_generic;
+       phy->ops.reset = e1000_null_ops_generic;
+       phy->ops.set_d0_lplu_state = e1000_null_lplu_state;
+       phy->ops.set_d3_lplu_state = e1000_null_lplu_state;
+       phy->ops.write_reg = e1000_null_write_reg;
+       phy->ops.power_up = e1000_null_phy_generic;
+       phy->ops.power_down = e1000_null_phy_generic;
+       phy->ops.cfg_on_link_up = e1000_null_ops_generic;
+}
+
+/**
+ *  e1000_null_read_reg - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       DEBUGFUNC("e1000_null_read_reg");
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_null_phy_generic - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_phy_generic(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_null_phy_generic");
+       return;
+}
+
+/**
+ *  e1000_null_lplu_state - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active)
+{
+       DEBUGFUNC("e1000_null_lplu_state");
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_null_write_reg - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       DEBUGFUNC("e1000_null_write_reg");
+       return E1000_SUCCESS;
+}
+
+/**
  *  e1000_check_reset_block_generic - Check if PHY reset is blocked
  *  @hw: pointer to the HW structure
  *
@@ -70,8 +137,7 @@
  *  is blocked.  If a reset is not blocked return E1000_SUCCESS, otherwise
  *  return E1000_BLK_PHY_RESET (12).
  **/
-s32
-e1000_check_reset_block_generic(struct e1000_hw *hw)
+s32 e1000_check_reset_block_generic(struct e1000_hw *hw)
 {
        u32 manc;
 
@@ -90,8 +156,7 @@
  *  Reads the PHY registers and stores the PHY ID and possibly the PHY
  *  revision in the hardware structure.
  **/
-s32
-e1000_get_phy_id(struct e1000_hw *hw)
+s32 e1000_get_phy_id(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val = E1000_SUCCESS;
@@ -99,13 +164,16 @@
 
        DEBUGFUNC("e1000_get_phy_id");
 
-       ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id);
+       if (!(phy->ops.read_reg))
+               goto out;
+
+       ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
        if (ret_val)
                goto out;
 
        phy->id = (u32)(phy_id << 16);
        usec_delay(20);
-       ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id);
+       ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
        if (ret_val)
                goto out;
 
@@ -122,18 +190,20 @@
  *
  *  Reset the digital signal processor.
  **/
-s32
-e1000_phy_reset_dsp_generic(struct e1000_hw *hw)
+s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw)
 {
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_phy_reset_dsp_generic");
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
+       if (!(hw->phy.ops.write_reg))
+               goto out;
+
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
 
 out:
        return ret_val;
@@ -145,11 +215,10 @@
  *  @offset: register offset to be read
  *  @data: pointer to the read data
  *
- *  Reads the MDI control regsiter in the PHY at offset and stores the
+ *  Reads the MDI control register in the PHY at offset and stores the
  *  information read to data.
  **/
-static s32
-e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, mdic = 0;
@@ -157,13 +226,8 @@
 
        DEBUGFUNC("e1000_read_phy_reg_mdic");
 
-       if (offset > MAX_PHY_REG_ADDRESS) {
-               DEBUGOUT1("PHY Address %d is out of range\n", offset);
-               ret_val = -E1000_ERR_PARAM;
-               goto out;
-       }
-
-       /* Set up Op-code, Phy Address, and register offset in the MDI
+       /*
+        * Set up Op-code, Phy Address, and register offset in the MDI
         * Control register.  The MAC will take care of interfacing with the
         * PHY to retrieve the desired data.
         */
@@ -173,8 +237,12 @@
 
        E1000_WRITE_REG(hw, E1000_MDIC, mdic);
 
-       /* Poll the ready bit to see if the MDI read completed */
-       for (i = 0; i < 64; i++) {
+       /*
+        * Poll the ready bit to see if the MDI read completed
+        * Increasing the time out as testing showed failures with
+        * the lower time out
+        */
+       for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
                usec_delay(50);
                mdic = E1000_READ_REG(hw, E1000_MDIC);
                if (mdic & E1000_MDIC_READY)
@@ -204,8 +272,7 @@
  *
  *  Writes data to MDI control register in the PHY at offset.
  **/
-static s32
-e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, mdic = 0;
@@ -213,13 +280,8 @@
 
        DEBUGFUNC("e1000_write_phy_reg_mdic");
 
-       if (offset > MAX_PHY_REG_ADDRESS) {
-               DEBUGOUT1("PHY Address %d is out of range\n", offset);
-               ret_val = -E1000_ERR_PARAM;
-               goto out;
-       }
-
-       /* Set up Op-code, Phy Address, and register offset in the MDI
+       /*
+        * Set up Op-code, Phy Address, and register offset in the MDI
         * Control register.  The MAC will take care of interfacing with the
         * PHY to retrieve the desired data.
         */
@@ -230,9 +292,13 @@
 
        E1000_WRITE_REG(hw, E1000_MDIC, mdic);
 
-       /* Poll the ready bit to see if the MDI read completed */
-       for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) {
-               usec_delay(5);
+       /*
+        * Poll the ready bit to see if the MDI read completed
+        * Increasing the time out as testing showed failures with
+        * the lower time out
+        */
+       for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+               usec_delay(50);
                mdic = E1000_READ_REG(hw, E1000_MDIC);
                if (mdic & E1000_MDIC_READY)
                        break;
@@ -242,6 +308,11 @@
                ret_val = -E1000_ERR_PHY;
                goto out;
        }
+       if (mdic & E1000_MDIC_ERROR) {
+               DEBUGOUT("MDI Error\n");
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+       }
 
 out:
        return ret_val;
@@ -257,22 +328,23 @@
  *  and storing the retrieved information in data.  Release any acquired
  *  semaphores before exiting.
  **/
-s32
-e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_read_phy_reg_m88");
 
-       ret_val = e1000_acquire_phy(hw);
+       if (!(hw->phy.ops.acquire))
+               goto out;
+
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_read_phy_reg_mdic(hw,
-                                         MAX_PHY_REG_ADDRESS & offset,
+       ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                          data);
 
-       e1000_release_phy(hw);
+       hw->phy.ops.release(hw);
 
 out:
        return ret_val;
@@ -287,22 +359,23 @@
  *  Acquires semaphore, if necessary, then writes the data to PHY register
  *  at the offset.  Release any acquired semaphores before exiting.
  **/
-s32
-e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
 {
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_write_phy_reg_m88");
 
-       ret_val = e1000_acquire_phy(hw);
+       if (!(hw->phy.ops.acquire))
+               goto out;
+
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_write_phy_reg_mdic(hw,
-                                          MAX_PHY_REG_ADDRESS & offset,
+       ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                           data);
 
-       e1000_release_phy(hw);
+       hw->phy.ops.release(hw);
 
 out:
        return ret_val;
@@ -318,32 +391,33 @@
  *  and storing the retrieved information in data.  Release any acquired
  *  semaphores before exiting.
  **/
-s32
-e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_read_phy_reg_igp");
 
-       ret_val = e1000_acquire_phy(hw);
+       if (!(hw->phy.ops.acquire))
+               goto out;
+
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                goto out;
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
                ret_val = e1000_write_phy_reg_mdic(hw,
-                                                  IGP01E1000_PHY_PAGE_SELECT,
-                                                  (u16)offset);
+                                                  IGP01E1000_PHY_PAGE_SELECT,
+                                                  (u16)offset);
                if (ret_val) {
-                       e1000_release_phy(hw);
+                       hw->phy.ops.release(hw);
                        goto out;
                }
        }
 
-       ret_val = e1000_read_phy_reg_mdic(hw,
-                                         MAX_PHY_REG_ADDRESS & offset,
-                                         data);
+       ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                         data);
 
-       e1000_release_phy(hw);
+       hw->phy.ops.release(hw);
 
 out:
        return ret_val;
@@ -358,32 +432,33 @@
  *  Acquires semaphore, if necessary, then writes the data to PHY register
  *  at the offset.  Release any acquired semaphores before exiting.
  **/
-s32
-e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
 {
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_write_phy_reg_igp");
 
-       ret_val = e1000_acquire_phy(hw);
+       if (!(hw->phy.ops.acquire))
+               goto out;
+
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                goto out;
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
                ret_val = e1000_write_phy_reg_mdic(hw,
-                                                  IGP01E1000_PHY_PAGE_SELECT,
-                                                  (u16)offset);
+                                                  IGP01E1000_PHY_PAGE_SELECT,
+                                                  (u16)offset);
                if (ret_val) {
-                       e1000_release_phy(hw);
+                       hw->phy.ops.release(hw);
                        goto out;
                }
        }
 
-       ret_val = e1000_write_phy_reg_mdic(hw,
-                                          MAX_PHY_REG_ADDRESS & offset,
-                                          data);
+       ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
 
-       e1000_release_phy(hw);
+       hw->phy.ops.release(hw);
 
 out:
        return ret_val;
@@ -399,15 +474,17 @@
  *  using the kumeran interface.  The information retrieved is stored in data.
  *  Release any acquired semaphores before exiting.
  **/
-s32
-e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data)
 {
        u32 kmrnctrlsta;
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_read_kmrn_reg_generic");
 
-       ret_val = e1000_acquire_phy(hw);
+       if (!(hw->phy.ops.acquire))
+               goto out;
+
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                goto out;
 
@@ -420,7 +497,7 @@
        kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
        *data = (u16)kmrnctrlsta;
 
-       e1000_release_phy(hw);
+       hw->phy.ops.release(hw);
 
 out:
        return ret_val;
@@ -436,15 +513,17 @@
  *  at the offset using the kumeran interface.  Release any acquired semaphores
  *  before exiting.
  **/
-s32
-e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data)
 {
        u32 kmrnctrlsta;
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_write_kmrn_reg_generic");
 
-       ret_val = e1000_acquire_phy(hw);
+       if (!(hw->phy.ops.acquire))
+               goto out;
+
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                goto out;
 
@@ -453,7 +532,7 @@
        E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
 
        usec_delay(2);
-       e1000_release_phy(hw);
+       hw->phy.ops.release(hw);
 
 out:
        return ret_val;
@@ -466,8 +545,7 @@
  *  Sets up MDI/MDI-X and polarity for m88 PHY's.  If necessary, transmit clock
  *  and downshift values are set also.
  **/
-s32
-e1000_copper_link_setup_m88(struct e1000_hw *hw)
+s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -481,13 +559,16 @@
        }
 
        /* Enable CRS on TX. This must be set for half-duplex operation. */
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
                goto out;
 
-       phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+       /* For newer PHYs this bit is downshift enable */
+       if (phy->type == e1000_phy_m88)
+               phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
 
-       /* Options:
+       /*
+        * Options:
         *   MDI/MDI-X = 0 (default)
         *   0 - Auto for all speeds
         *   1 - MDI mode
@@ -497,22 +578,23 @@
        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:
-                       phy_data |= M88E1000_PSCR_AUTO_X_1000T;
-                       break;
-               case 0:
-               default:
-                       phy_data |= M88E1000_PSCR_AUTO_X_MODE;
-                       break;
+       case 1:
+               phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+               break;
+       case 2:
+               phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+               break;
+       case 3:
+               phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+               break;
+       case 0:
+       default:
+               phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+               break;
        }
 
-       /* Options:
+       /*
+        * Options:
         *   disable_polarity_correction = 0 (default)
         *       Automatic Correction for Reversed Cable Polarity
         *   0 - Disabled
@@ -522,16 +604,22 @@
        if (phy->disable_polarity_correction == 1)
                phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
 
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+       /* Enable downshift on BM (disabled by default) */
+       if (phy->type == e1000_phy_bm)
+               phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
+
+       ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
        if (ret_val)
                goto out;
 
-       if (phy->revision < E1000_REVISION_4) {
-               /* Force TX_CLK in the Extended PHY Specific Control Register
+       if ((phy->type == e1000_phy_m88) &&
+           (phy->revision < E1000_REVISION_4) &&
+           (phy->id != BME1000_E_PHY_ID_R2)) {
+               /*
+                * Force TX_CLK in the Extended PHY Specific Control Register
                 * to 25MHz clock.
                 */
-               ret_val = e1000_read_phy_reg(hw,
-                                            M88E1000_EXT_PHY_SPEC_CTRL,
+               ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
                                             &phy_data);
                if (ret_val)
                        goto out;
@@ -546,19 +634,30 @@
                } else {
                        /* Configure Master and Slave downshift values */
                        phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
-                                     M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
+                                    M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
                        phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
-                                    M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
+                                    M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
                }
-               ret_val = e1000_write_phy_reg(hw,
-                                            M88E1000_EXT_PHY_SPEC_CTRL,
+               ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
                                             phy_data);
                if (ret_val)
                        goto out;
        }
 
+       if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) {
+               /* Set PHY page 0, register 29 to 0x0003 */
+               ret_val = phy->ops.write_reg(hw, 29, 0x0003);
+               if (ret_val)
+                       goto out;
+
+               /* Set PHY page 0, register 30 to 0x0000 */
+               ret_val = phy->ops.write_reg(hw, 30, 0x0000);
+               if (ret_val)
+                       goto out;
+       }
+
        /* Commit the changes. */
-       ret_val = e1000_phy_commit(hw);
+       ret_val = phy->ops.commit(hw);
        if (ret_val) {
                DEBUGOUT("Error committing the PHY changes\n");
                goto out;
@@ -575,8 +674,7 @@
  *  Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for
  *  igp PHY's.
  **/
-s32
-e1000_copper_link_setup_igp(struct e1000_hw *hw)
+s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -589,20 +687,25 @@
                goto out;
        }
 
-       ret_val = e1000_phy_hw_reset(hw);
+       ret_val = hw->phy.ops.reset(hw);
        if (ret_val) {
                DEBUGOUT("Error resetting the PHY.\n");
                goto out;
        }
 
-       /* Wait 15ms for MAC to configure PHY from NVM settings. */
-       msec_delay(15);
+       /*
+        * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
+        * timeout issues when LFS is enabled.
+        */
+       msec_delay(100);
 
-       /* The NVM settings will configure LPLU in D3 for
-        * non-IGP1 PHYs. */
+       /*
+        * The NVM settings will configure LPLU in D3 for
+        * non-IGP1 PHYs.
+        */
        if (phy->type == e1000_phy_igp) {
                /* disable lplu d3 during driver init */
-               ret_val = e1000_set_d3_lplu_state(hw, FALSE);
+               ret_val = hw->phy.ops.set_d3_lplu_state(hw, FALSE);
                if (ret_val) {
                        DEBUGOUT("Error Disabling LPLU D3\n");
                        goto out;
@@ -610,13 +713,15 @@
        }
 
        /* disable lplu d0 during driver init */
-       ret_val = e1000_set_d0_lplu_state(hw, FALSE);
-       if (ret_val) {
-               DEBUGOUT("Error Disabling LPLU D0\n");
-               goto out;
+       if (hw->phy.ops.set_d0_lplu_state) {
+               ret_val = hw->phy.ops.set_d0_lplu_state(hw, FALSE);
+               if (ret_val) {
+                       DEBUGOUT("Error Disabling LPLU D0\n");
+                       goto out;
+               }
        }
        /* Configure mdi-mdix settings */
-       ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data);
+       ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data);
        if (ret_val)
                goto out;
 
@@ -634,42 +739,44 @@
                data |= IGP01E1000_PSCR_AUTO_MDIX;
                break;
        }
-       ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, data);
+       ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data);
        if (ret_val)
                goto out;
 
        /* set auto-master slave resolution settings */
        if (hw->mac.autoneg) {
-               /* when autonegotiation advertisement is only 1000Mbps then we
+               /*
+                * when autonegotiation advertisement is only 1000Mbps then we
                 * should disable SmartSpeed and enable Auto MasterSlave
-                * resolution as hardware default. */
+                * resolution as hardware default.
+                */
                if (phy->autoneg_advertised == ADVERTISE_1000_FULL) {
                        /* Disable SmartSpeed */
-                       ret_val = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     &data);
                        if (ret_val)
                                goto out;
 
                        data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
                                goto out;
 
                        /* Set auto Master/Slave resolution process */
-                       ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &data);
+                       ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
                        if (ret_val)
                                goto out;
 
                        data &= ~CR_1000T_MS_ENABLE;
-                       ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, data);
+                       ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
                        if (ret_val)
                                goto out;
                }
 
-               ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &data);
+               ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
                if (ret_val)
                        goto out;
 
@@ -693,7 +800,7 @@
                default:
                        break;
                }
-               ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, data);
+               ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
                if (ret_val)
                        goto out;
        }
@@ -709,10 +816,9 @@
  *  Performs initial bounds checking on autoneg advertisement parameter, then
  *  configure to advertise the full capability.  Setup the PHY to autoneg
  *  and restart the negotiation process between the link partner.  If
- *  wait_for_link, then wait for autoneg to complete before exiting.
+ *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
  **/
-s32
-e1000_copper_link_autoneg(struct e1000_hw *hw)
+s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -720,12 +826,14 @@
 
        DEBUGFUNC("e1000_copper_link_autoneg");
 
-       /* Perform some bounds checking on the autoneg advertisement
+       /*
+        * Perform some bounds checking on the autoneg advertisement
         * parameter.
         */
        phy->autoneg_advertised &= phy->autoneg_mask;
 
-       /* If autoneg_advertised is zero, we assume it was not defaulted
+       /*
+        * If autoneg_advertised is zero, we assume it was not defaulted
         * by the calling code so we set to advertise full capability.
         */
        if (phy->autoneg_advertised == 0)
@@ -739,23 +847,25 @@
        }
        DEBUGOUT("Restarting Auto-Neg\n");
 
-       /* Restart auto-negotiation by setting the Auto Neg Enable bit and
+       /*
+        * Restart auto-negotiation by setting the Auto Neg Enable bit and
         * the Auto Neg Restart bit in the PHY control register.
         */
-       ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &phy_ctrl);
+       ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
        if (ret_val)
                goto out;
 
        phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
-       ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, phy_ctrl);
+       ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
        if (ret_val)
                goto out;
 
-       /* Does the user want to wait for Auto-Neg to complete here, or
+       /*
+        * Does the user want to wait for Auto-Neg to complete here, or
         * check at a later time (for example, callback routine).
         */
-       if (phy->wait_for_link) {
-               ret_val = e1000_wait_autoneg(hw);
+       if (phy->autoneg_wait_to_complete) {
+               ret_val = hw->mac.ops.wait_autoneg(hw);
                if (ret_val) {
                        DEBUGOUT("Error while waiting for "
                                 "autoneg to complete\n");
@@ -778,8 +888,7 @@
  *  return successful.  Otherwise, setup advertisement and flow control to
  *  the appropriate values for the wanted auto-negotiation.
  **/
-s32
-e1000_phy_setup_autoneg(struct e1000_hw *hw)
+s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -791,27 +900,28 @@
        phy->autoneg_advertised &= phy->autoneg_mask;
 
        /* Read the MII Auto-Neg Advertisement Register (Address 4). */
-       ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
+       ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
        if (ret_val)
                goto out;
 
        if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
                /* Read the MII 1000Base-T Control Register (Address 9). */
-               ret_val = e1000_read_phy_reg(hw,
-                                           PHY_1000T_CTRL,
+               ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
                                            &mii_1000t_ctrl_reg);
                if (ret_val)
                        goto out;
        }
 
-       /* Need to parse both autoneg_advertised and fc and set up
+       /*
+        * Need to parse both autoneg_advertised and fc and set up
         * the appropriate PHY registers.  First we will parse for
         * autoneg_advertised software override.  Since we can advertise
         * a plethora of combinations, we need to check each bit
         * individually.
         */
 
-       /* First we clear all the 10/100 mb speed bits in the Auto-Neg
+       /*
+        * First we clear all the 10/100 mb speed bits in the Auto-Neg
         * Advertisement Register (Address 4) and the 1000 mb speed bits in
         * the  1000Base-T Control Register (Address 9).
         */
@@ -848,9 +958,8 @@
        }
 
        /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
-       if (phy->autoneg_advertised & ADVERTISE_1000_HALF) {
+       if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
                DEBUGOUT("Advertise 1000mb Half duplex request denied!\n");
-       }
 
        /* Do we want to advertise 1000 Mb Full Duplex? */
        if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
@@ -858,7 +967,8 @@
                mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
        }
 
-       /* Check for a software override of the flow control settings, and
+       /*
+        * Check for a software override of the flow control settings, and
         * setup the PHY advertisement registers accordingly.  If
         * auto-negotiation is enabled, then software will have to set the
         * "PAUSE" bits to the correct value in the Auto-Negotiation
@@ -871,38 +981,42 @@
         *          but not send pause frames).
         *      2:  Tx flow control is enabled (we can send pause frames
         *          but we do not support receiving pause frames).
-        *      3:  Both Rx and TX flow control (symmetric) are enabled.
+        *      3:  Both Rx and Tx flow control (symmetric) are enabled.
         *  other:  No software override.  The flow control configuration
         *          in the EEPROM is used.
         */
-       switch (hw->mac.fc) {
+       switch (hw->fc.current_mode) {
        case e1000_fc_none:
-               /* Flow control (RX & TX) is completely disabled by a
+               /*
+                * Flow control (Rx & Tx) is completely disabled by a
                 * software over-ride.
                 */
                mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
                break;
        case e1000_fc_rx_pause:
-               /* RX Flow control is enabled, and TX Flow control is
+               /*
+                * Rx Flow control is enabled, and Tx Flow control is
                 * disabled, by a software over-ride.
-                */
-               /* Since there really isn't a way to advertise that we are
-                * capable of RX Pause ONLY, we will advertise that we
-                * support both symmetric and asymmetric RX PAUSE.  Later
+                *
+                * Since there really isn't a way to advertise that we are
+                * capable of Rx Pause ONLY, we will advertise that we
+                * support both symmetric and asymmetric Rx PAUSE.  Later
                 * (in e1000_config_fc_after_link_up) we will disable the
                 * hw's ability to send PAUSE frames.
                 */
                mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
                break;
        case e1000_fc_tx_pause:
-               /* TX Flow control is enabled, and RX Flow control is
+               /*
+                * Tx Flow control is enabled, and Rx Flow control is
                 * disabled, by a software over-ride.
                 */
                mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
                mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
                break;
        case e1000_fc_full:
-               /* Flow control (both RX and TX) is enabled by a software
+               /*
+                * Flow control (both Rx and Tx) is enabled by a software
                 * over-ride.
                 */
                mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
@@ -913,14 +1027,14 @@
                goto out;
        }
 
-       ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
+       ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
        if (ret_val)
                goto out;
 
        DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
 
        if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
-               ret_val = e1000_write_phy_reg(hw,
+               ret_val = phy->ops.write_reg(hw,
                                              PHY_1000T_CTRL,
                                              mii_1000t_ctrl_reg);
                if (ret_val)
@@ -940,32 +1054,36 @@
  *  to configure collision distance and flow control are called.  If link is
  *  not established, we return -E1000_ERR_PHY (-2).
  **/
-s32
-e1000_setup_copper_link_generic(struct e1000_hw *hw)
+s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
 {
        s32 ret_val;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_setup_copper_link_generic");
 
        if (hw->mac.autoneg) {
-               /* Setup autoneg and flow control advertisement and perform
-                * autonegotiation. */
+               /*
+                * Setup autoneg and flow control advertisement and perform
+                * autonegotiation.
+                */
                ret_val = e1000_copper_link_autoneg(hw);
                if (ret_val)
                        goto out;
        } else {
-               /* PHY will be set to 10H, 10F, 100H or 100F
-                * depending on user settings. */
+               /*
+                * PHY will be set to 10H, 10F, 100H or 100F
+                * depending on user settings.
+                */
                DEBUGOUT("Forcing Speed and Duplex\n");
-               ret_val = e1000_phy_force_speed_duplex(hw);
+               ret_val = hw->phy.ops.force_speed_duplex(hw);
                if (ret_val) {
                        DEBUGOUT("Error Forcing Speed and Duplex\n");
                        goto out;
                }
        }
 
-       /* Check link status. Wait up to 100 microseconds for link to become
+       /*
+        * Check link status. Wait up to 100 microseconds for link to become
         * valid.
         */
        ret_val = e1000_phy_has_link_generic(hw,
@@ -995,37 +1113,37 @@
  *  auto-crossover to force MDI manually.  Waits for link and returns
  *  successful if link up is successful, else -E1000_ERR_PHY (-2).
  **/
-s32
-e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
+s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
        u16 phy_data;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_phy_force_speed_duplex_igp");
 
-       ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &phy_data);
+       ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
        if (ret_val)
                goto out;
 
        e1000_phy_force_speed_duplex_setup(hw, &phy_data);
 
-       ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, phy_data);
+       ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
        if (ret_val)
                goto out;
 
-       /* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
+       /*
+        * Clear Auto-Crossover to force MDI manually.  IGP requires MDI
         * forced whenever speed and duplex are forced.
         */
-       ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+       ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
        if (ret_val)
                goto out;
 
        phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
        phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
 
-       ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
+       ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
        if (ret_val)
                goto out;
 
@@ -1033,7 +1151,7 @@
 
        usec_delay(1);
 
-       if (phy->wait_for_link) {
+       if (phy->autoneg_wait_to_complete) {
                DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n");
 
                ret_val = e1000_phy_has_link_generic(hw,
@@ -1043,9 +1161,8 @@
                if (ret_val)
                        goto out;
 
-               if (!link) {
+               if (!link)
                        DEBUGOUT("Link taking longer than expected.\n");
-               }
 
                /* Try once more */
                ret_val = e1000_phy_has_link_generic(hw,
@@ -1067,63 +1184,62 @@
  *  Calls the PHY setup function to force speed and duplex.  Clears the
  *  auto-crossover to force MDI manually.  Resets the PHY to commit the
  *  changes.  If time expires while waiting for link up, we reset the DSP.
- *  After reset, TX_CLK and CRS on TX must be set.  Return successful upon
+ *  After reset, TX_CLK and CRS on Tx must be set.  Return successful upon
  *  successful completion, else return corresponding error code.
  **/
-s32
-e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
        u16 phy_data;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_phy_force_speed_duplex_m88");
 
-       /* Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
+       /*
+        * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
         * forced whenever speed and duplex are forced.
         */
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
                goto out;
 
        phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+       ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
        if (ret_val)
                goto out;
 
        DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
 
-       ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &phy_data);
+       ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
        if (ret_val)
                goto out;
 
        e1000_phy_force_speed_duplex_setup(hw, &phy_data);
 
+       ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
+       if (ret_val)
+               goto out;
+
        /* Reset the phy to commit changes. */
-       phy_data |= MII_CR_RESET;
-
-       ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, phy_data);
+       ret_val = hw->phy.ops.commit(hw);
        if (ret_val)
                goto out;
 
-       usec_delay(1);
-
-       if (phy->wait_for_link) {
+       if (phy->autoneg_wait_to_complete) {
                DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n");
 
-               ret_val = e1000_phy_has_link_generic(hw,
-                                                    PHY_FORCE_LIMIT,
-                                                    100000,
-                                                    &link);
+               ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+                                                    100000, &link);
                if (ret_val)
                        goto out;
 
                if (!link) {
-                       /* We didn't get link.
+                       /*
+                        * We didn't get link.
                         * Reset the DSP and cross our fingers.
                         */
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                      M88E1000_PHY_PAGE_SELECT,
                                                      0x001d);
                        if (ret_val)
@@ -1134,36 +1250,36 @@
                }
 
                /* Try once more */
-               ret_val = e1000_phy_has_link_generic(hw,
-                                                    PHY_FORCE_LIMIT,
-                                                    100000,
-                                                    &link);
+               ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+                                                    100000, &link);
                if (ret_val)
                        goto out;
        }
 
-       ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
+       ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
                goto out;
 
-       /* Resetting the phy means we need to re-force TX_CLK in the
+       /*
+        * Resetting the phy means we need to re-force TX_CLK in the
         * Extended PHY Specific Control Register to 25MHz clock from
         * the reset value of 2.5MHz.
         */
        phy_data |= M88E1000_EPSCR_TX_CLK_25;
-       ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
+       ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
        if (ret_val)
                goto out;
 
-       /* In addition, we must re-enable CRS on Tx for both half and full
+       /*
+        * In addition, we must re-enable CRS on Tx for both half and full
         * duplex.
         */
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
                goto out;
 
        phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-       ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+       ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
 
 out:
        return ret_val;
@@ -1181,8 +1297,7 @@
  *  caller must write to the PHY_CONTROL register for these settings to
  *  take affect.
  **/
-void
-e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
+void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 ctrl;
@@ -1190,7 +1305,7 @@
        DEBUGFUNC("e1000_phy_force_speed_duplex_setup");
 
        /* Turn off flow control when forcing speed/duplex */
-       mac->fc = e1000_fc_none;
+       hw->fc.current_mode = e1000_fc_none;
 
        /* Force speed/duplex on the mac */
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
@@ -1240,58 +1355,61 @@
  *  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 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_generic(struct e1000_hw *hw, boolean_t active)
+s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u16 data;
 
        DEBUGFUNC("e1000_set_d3_lplu_state_generic");
 
-       ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
+       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_D3_LPLU;
-               ret_val = e1000_write_phy_reg(hw,
-                                            IGP02E1000_PHY_POWER_MGMT,
+               ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
                                             data);
                if (ret_val)
                        goto out;
-               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               /*
+                * 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. */
+                * SmartSpeed, so performance is maintained.
+                */
                if (phy->smart_speed == e1000_smart_speed_on) {
-                       ret_val = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                    IGP01E1000_PHY_PORT_CONFIG,
                                                    &data);
                        if (ret_val)
                                goto out;
 
                        data |= IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       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 = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     &data);
                        if (ret_val)
                                goto out;
 
                        data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
@@ -1301,22 +1419,19 @@
                   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
                   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
                data |= IGP02E1000_PM_D3_LPLU;
-               ret_val = e1000_write_phy_reg(hw,
-                                             IGP02E1000_PHY_POWER_MGMT,
+               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 = e1000_read_phy_reg(hw,
-                                            IGP01E1000_PHY_PORT_CONFIG,
+               ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                             &data);
                if (ret_val)
                        goto out;
 
                data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-               ret_val = e1000_write_phy_reg(hw,
-                                             IGP01E1000_PHY_PORT_CONFIG,
+               ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                              data);
        }
 
@@ -1325,15 +1440,14 @@
 }
 
 /**
- *  e1000_check_downshift_generic - Checks whether a downshift in speed occured
+ *  e1000_check_downshift_generic - Checks whether a downshift in speed 
occurred
  *  @hw: pointer to the HW structure
  *
  *  Success returns 0, Failure returns 1
  *
  *  A downshift is detected by querying the PHY link health.
  **/
-s32
-e1000_check_downshift_generic(struct e1000_hw *hw)
+s32 e1000_check_downshift_generic(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -1344,6 +1458,7 @@
        switch (phy->type) {
        case e1000_phy_m88:
        case e1000_phy_gg82563:
+       case e1000_phy_bm:
                offset  = M88E1000_PHY_SPEC_STATUS;
                mask    = M88E1000_PSSR_DOWNSHIFT;
                break;
@@ -1360,7 +1475,7 @@
                goto out;
        }
 
-       ret_val = e1000_read_phy_reg(hw, offset, &phy_data);
+       ret_val = phy->ops.read_reg(hw, offset, &phy_data);
 
        if (!ret_val)
                phy->speed_downgraded = (phy_data & mask) ? TRUE : FALSE;
@@ -1377,8 +1492,7 @@
  *
  *  Polarity is determined based on the PHY specific status register.
  **/
-s32
-e1000_check_polarity_m88(struct e1000_hw *hw)
+s32 e1000_check_polarity_m88(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -1386,7 +1500,7 @@
 
        DEBUGFUNC("e1000_check_polarity_m88");
 
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &data);
+       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data);
 
        if (!ret_val)
                phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY)
@@ -1405,8 +1519,7 @@
  *  Polarity is determined based on the PHY port status register, and the
  *  current speed (since there is no polarity at 100Mbps).
  **/
-s32
-e1000_check_polarity_igp(struct e1000_hw *hw)
+s32 e1000_check_polarity_igp(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -1414,9 +1527,11 @@
 
        DEBUGFUNC("e1000_check_polarity_igp");
 
-       /* Polarity is determined based on the speed of
-        * our connection. */
-       ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
+       /*
+        * Polarity is determined based on the speed of
+        * our connection.
+        */
+       ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
        if (ret_val)
                goto out;
 
@@ -1425,14 +1540,15 @@
                offset  = IGP01E1000_PHY_PCS_INIT_REG;
                mask    = IGP01E1000_PHY_POLARITY_MASK;
        } else {
-               /* This really only applies to 10Mbps since
+               /*
+                * This really only applies to 10Mbps since
                 * there is no polarity for 100Mbps (always 0).
                 */
                offset  = IGP01E1000_PHY_PORT_STATUS;
                mask    = IGP01E1000_PSSR_POLARITY_REVERSED;
        }
 
-       ret_val = e1000_read_phy_reg(hw, offset, &data);
+       ret_val = phy->ops.read_reg(hw, offset, &data);
 
        if (!ret_val)
                phy->cable_polarity = (data & mask)
@@ -1444,26 +1560,28 @@
 }
 
 /**
- *  e1000_wait_autoneg_generic - Wait for auto-neg compeletion
+ *  e1000_wait_autoneg_generic - Wait for auto-neg completion
  *  @hw: pointer to the HW structure
  *
  *  Waits for auto-negotiation to complete or for the auto-negotiation time
  *  limit to expire, which ever happens first.
  **/
-s32
-e1000_wait_autoneg_generic(struct e1000_hw *hw)
+s32 e1000_wait_autoneg_generic(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
        u16 i, phy_status;
 
        DEBUGFUNC("e1000_wait_autoneg_generic");
 
+       if (!(hw->phy.ops.read_reg))
+               return E1000_SUCCESS;
+
        /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
        for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
-               ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
                if (ret_val)
                        break;
-               ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
                if (ret_val)
                        break;
                if (phy_status & MII_SR_AUTONEG_COMPLETE)
@@ -1471,7 +1589,8 @@
                msec_delay(100);
        }
 
-       /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
+       /*
+        * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
         * has completed.
         */
        return ret_val;
@@ -1486,24 +1605,27 @@
  *
  *  Polls the PHY status register for link, 'iterations' number of times.
  **/
-s32
-e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
-                           u32 usec_interval, boolean_t *success)
+s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
+                               u32 usec_interval, bool *success)
 {
        s32 ret_val = E1000_SUCCESS;
        u16 i, phy_status;
 
        DEBUGFUNC("e1000_phy_has_link_generic");
 
+       if (!(hw->phy.ops.read_reg))
+               return E1000_SUCCESS;
+
        for (i = 0; i < iterations; i++) {
-               /* Some PHYs require the PHY_STATUS register to be read
+               /*
+                * Some PHYs require the PHY_STATUS register to be read
                 * twice due to the link bit being sticky.  No harm doing
                 * it across the board.
                 */
-               ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
                if (ret_val)
                        break;
-               ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
                if (ret_val)
                        break;
                if (phy_status & MII_SR_LINK_STATUS)
@@ -1534,8 +1656,7 @@
  *     3                       110 - 140 meters
  *     4                       > 140 meters
  **/
-s32
-e1000_get_cable_length_m88(struct e1000_hw *hw)
+s32 e1000_get_cable_length_m88(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -1543,16 +1664,21 @@
 
        DEBUGFUNC("e1000_get_cable_length_m88");
 
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
        if (ret_val)
                goto out;
 
        index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
                M88E1000_PSSR_CABLE_LENGTH_SHIFT;
-       phy->min_cable_length = e1000_m88_cable_length_table[index];
-       phy->max_cable_length = e1000_m88_cable_length_table[index+1];
+       if (index < M88E1000_CABLE_LENGTH_TABLE_SIZE + 1) {
+               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;
+               phy->cable_length = (phy->min_cable_length +
+                                    phy->max_cable_length) / 2;
+       } else {
+               ret_val = E1000_ERR_PHY;
+       }
 
 out:
        return ret_val;
@@ -1564,16 +1690,15 @@
  *
  *  The automatic gain control (agc) normalizes the amplitude of the
  *  received signal, adjusting for the attenuation produced by the
- *  cable.  By reading the AGC registers, which reperesent the
- *  cobination of course and fine gain value, the value can be put
+ *  cable.  By reading the AGC registers, which represent the
+ *  combination of coarse and fine gain value, the value can be put
  *  into a lookup table to obtain the approximate cable length
  *  for each channel.
  **/
-s32
-e1000_get_cable_length_igp_2(struct e1000_hw *hw)
+s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u16 phy_data, i, agc_value = 0;
        u16 cur_agc_index, max_agc_index = 0;
        u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
@@ -1587,14 +1712,16 @@
 
        /* Read the AGC registers for all channels */
        for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
-               ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
+               ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data);
                if (ret_val)
                        goto out;
 
-               /* Getting bits 15:9, which represent the combination of
-                * course and fine gain values.  The result is a number
+               /*
+                * Getting bits 15:9, which represent the combination of
+                * coarse and fine gain values.  The result is a number
                 * that can be put into the lookup table to obtain the
-                * approximate cable length. */
+                * approximate cable length.
+                */
                cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
                                IGP02E1000_AGC_LENGTH_MASK;
 
@@ -1641,17 +1768,16 @@
  *  special status register to determine MDI/MDIx and current speed.  If
  *  speed is 1000, then determine cable length, local and remote receiver.
  **/
-s32
-e1000_get_phy_info_m88(struct e1000_hw *hw)
+s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32  ret_val;
        u16 phy_data;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_get_phy_info_m88");
 
-       if (hw->media_type != e1000_media_type_copper) {
+       if (hw->phy.media_type != e1000_media_type_copper) {
                DEBUGOUT("Phy info is only valid for copper media\n");
                ret_val = -E1000_ERR_CONFIG;
                goto out;
@@ -1667,30 +1793,29 @@
                goto out;
        }
 
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
                goto out;
 
        phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL)
-                                  ? TRUE
-                                  : FALSE;
+                                  ? TRUE : FALSE;
 
        ret_val = e1000_check_polarity_m88(hw);
        if (ret_val)
                goto out;
 
-       ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
        if (ret_val)
                goto out;
 
        phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? TRUE : FALSE;
 
        if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
-               ret_val = e1000_get_cable_length(hw);
+               ret_val = hw->phy.ops.get_cable_length(hw);
                if (ret_val)
                        goto out;
 
-               ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+               ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
                if (ret_val)
                        goto out;
 
@@ -1721,13 +1846,12 @@
  *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
  *  determine on the cable length, local and remote receiver.
  **/
-s32
-e1000_get_phy_info_igp(struct e1000_hw *hw)
+s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
        u16 data;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_get_phy_info_igp");
 
@@ -1747,7 +1871,7 @@
        if (ret_val)
                goto out;
 
-       ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
+       ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
        if (ret_val)
                goto out;
 
@@ -1755,11 +1879,11 @@
 
        if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
            IGP01E1000_PSSR_SPEED_1000MBPS) {
-               ret_val = e1000_get_cable_length(hw);
+               ret_val = hw->phy.ops.get_cable_length(hw);
                if (ret_val)
                        goto out;
 
-               ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &data);
+               ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
                if (ret_val)
                        goto out;
 
@@ -1787,20 +1911,22 @@
  *  Does a software reset of the PHY by reading the PHY control register and
  *  setting/write the control register reset bit to the PHY.
  **/
-s32
-e1000_phy_sw_reset_generic(struct e1000_hw *hw)
+s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw)
 {
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u16 phy_ctrl;
 
        DEBUGFUNC("e1000_phy_sw_reset_generic");
 
-       ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &phy_ctrl);
+       if (!(hw->phy.ops.read_reg))
+               goto out;
+
+       ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
        if (ret_val)
                goto out;
 
        phy_ctrl |= MII_CR_RESET;
-       ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, phy_ctrl);
+       ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
        if (ret_val)
                goto out;
 
@@ -1817,24 +1943,23 @@
  *  Verify the reset block is not blocking us from resetting.  Acquire
  *  semaphore (if necessary) and read/set/write the device control reset
  *  bit in the PHY.  Wait the appropriate delay time for the device to
- *  reset and relase the semaphore (if necessary).
+ *  reset and release the semaphore (if necessary).
  **/
-s32
-e1000_phy_hw_reset_generic(struct e1000_hw *hw)
+s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32  ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u32 ctrl;
 
        DEBUGFUNC("e1000_phy_hw_reset_generic");
 
-       ret_val = e1000_check_reset_block(hw);
+       ret_val = phy->ops.check_reset_block(hw);
        if (ret_val) {
                ret_val = E1000_SUCCESS;
                goto out;
        }
 
-       ret_val = e1000_acquire_phy(hw);
+       ret_val = phy->ops.acquire(hw);
        if (ret_val)
                goto out;
 
@@ -1849,9 +1974,9 @@
 
        usec_delay(150);
 
-       e1000_release_phy(hw);
+       phy->ops.release(hw);
 
-       ret_val = e1000_get_phy_cfg_done(hw);
+       ret_val = phy->ops.get_cfg_done(hw);
 
 out:
        return ret_val;
@@ -1864,8 +1989,7 @@
  *  Generic function to wait 10 milli-seconds for configuration to complete
  *  and return success.
  **/
-s32
-e1000_get_cfg_done_generic(struct e1000_hw *hw)
+s32 e1000_get_cfg_done_generic(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_get_cfg_done_generic");
 
@@ -1874,150 +1998,87 @@
        return E1000_SUCCESS;
 }
 
-/* Internal function pointers */
-
 /**
- *  e1000_get_phy_cfg_done - Generic PHY configuration done
- *  @hw: pointer to the HW structure
- *
- *  Return success if silicon family did not implement a family specific
- *  get_cfg_done function.
- **/
-s32
-e1000_get_phy_cfg_done(struct e1000_hw *hw)
-{
-       if (hw->func.get_cfg_done != NULL)
-               return hw->func.get_cfg_done(hw);
-       else
-               return E1000_SUCCESS;
-}
-
-/**
- *  e1000_release_phy - Generic release PHY
- *  @hw: pointer to the HW structure
- *
- *  Return if silicon family does not require a semaphore when accessing the
- *  PHY.
- **/
-void
-e1000_release_phy(struct e1000_hw *hw)
-{
-       if (hw->func.release_phy != NULL)
-               hw->func.release_phy(hw);
-}
-
-/**
- *  e1000_acquire_phy - Generic acquire PHY
- *  @hw: pointer to the HW structure
- *
- *  Return success if silicon family does not require a semaphore when
- *  accessing the PHY.
- **/
-s32
-e1000_acquire_phy(struct e1000_hw *hw)
-{
-       if (hw->func.acquire_phy != NULL)
-               return hw->func.acquire_phy(hw);
-       else
-               return E1000_SUCCESS;
-}
-
-/**
- *  e1000_phy_force_speed_duplex - Generic force PHY speed/duplex
- *  @hw: pointer to the HW structure
- *
- *  When the silicon family has not implemented a forced speed/duplex
- *  function for the PHY, simply return E1000_SUCCESS.
- **/
-s32
-e1000_phy_force_speed_duplex(struct e1000_hw *hw)
-{
-       if (hw->func.force_speed_duplex != NULL)
-               return hw->func.force_speed_duplex(hw);
-       else
-               return E1000_SUCCESS;
-}
-
-/**
  *  e1000_phy_init_script_igp3 - Inits the IGP3 PHY
  *  @hw: pointer to the HW structure
  *
  *  Initializes a Intel Gigabit PHY3 when an EEPROM is not present.
  **/
-s32
-e1000_phy_init_script_igp3(struct e1000_hw *hw)
+s32 e1000_phy_init_script_igp3(struct e1000_hw *hw)
 {
        DEBUGOUT("Running IGP 3 PHY init script\n");
 
        /* PHY init IGP 3 */
        /* Enable rise/fall, 10-mode work in class-A */
-       e1000_write_phy_reg(hw, 0x2F5B, 0x9018);
+       hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018);
        /* Remove all caps from Replica path filter */
-       e1000_write_phy_reg(hw, 0x2F52, 0x0000);
+       hw->phy.ops.write_reg(hw, 0x2F52, 0x0000);
        /* Bias trimming for ADC, AFE and Driver (Default) */
-       e1000_write_phy_reg(hw, 0x2FB1, 0x8B24);
+       hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24);
        /* Increase Hybrid poly bias */
-       e1000_write_phy_reg(hw, 0x2FB2, 0xF8F0);
-       /* Add 4% to TX amplitude in Giga mode */
-       e1000_write_phy_reg(hw, 0x2010, 0x10B0);
+       hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0);
+       /* Add 4% to Tx amplitude in Gig mode */
+       hw->phy.ops.write_reg(hw, 0x2010, 0x10B0);
        /* Disable trimming (TTT) */
-       e1000_write_phy_reg(hw, 0x2011, 0x0000);
+       hw->phy.ops.write_reg(hw, 0x2011, 0x0000);
        /* Poly DC correction to 94.6% + 2% for all channels */
-       e1000_write_phy_reg(hw, 0x20DD, 0x249A);
+       hw->phy.ops.write_reg(hw, 0x20DD, 0x249A);
        /* ABS DC correction to 95.9% */
-       e1000_write_phy_reg(hw, 0x20DE, 0x00D3);
+       hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3);
        /* BG temp curve trim */
-       e1000_write_phy_reg(hw, 0x28B4, 0x04CE);
+       hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE);
        /* Increasing ADC OPAMP stage 1 currents to max */
-       e1000_write_phy_reg(hw, 0x2F70, 0x29E4);
+       hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4);
        /* Force 1000 ( required for enabling PHY regs configuration) */
-       e1000_write_phy_reg(hw, 0x0000, 0x0140);
+       hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
        /* Set upd_freq to 6 */
-       e1000_write_phy_reg(hw, 0x1F30, 0x1606);
+       hw->phy.ops.write_reg(hw, 0x1F30, 0x1606);
        /* Disable NPDFE */
-       e1000_write_phy_reg(hw, 0x1F31, 0xB814);
+       hw->phy.ops.write_reg(hw, 0x1F31, 0xB814);
        /* Disable adaptive fixed FFE (Default) */
-       e1000_write_phy_reg(hw, 0x1F35, 0x002A);
+       hw->phy.ops.write_reg(hw, 0x1F35, 0x002A);
        /* Enable FFE hysteresis */
-       e1000_write_phy_reg(hw, 0x1F3E, 0x0067);
+       hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067);
        /* Fixed FFE for short cable lengths */
-       e1000_write_phy_reg(hw, 0x1F54, 0x0065);
+       hw->phy.ops.write_reg(hw, 0x1F54, 0x0065);
        /* Fixed FFE for medium cable lengths */
-       e1000_write_phy_reg(hw, 0x1F55, 0x002A);
+       hw->phy.ops.write_reg(hw, 0x1F55, 0x002A);
        /* Fixed FFE for long cable lengths */
-       e1000_write_phy_reg(hw, 0x1F56, 0x002A);
+       hw->phy.ops.write_reg(hw, 0x1F56, 0x002A);
        /* Enable Adaptive Clip Threshold */
-       e1000_write_phy_reg(hw, 0x1F72, 0x3FB0);
+       hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0);
        /* AHT reset limit to 1 */
-       e1000_write_phy_reg(hw, 0x1F76, 0xC0FF);
+       hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF);
        /* Set AHT master delay to 127 msec */
-       e1000_write_phy_reg(hw, 0x1F77, 0x1DEC);
+       hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC);
        /* Set scan bits for AHT */
-       e1000_write_phy_reg(hw, 0x1F78, 0xF9EF);
+       hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF);
        /* Set AHT Preset bits */
-       e1000_write_phy_reg(hw, 0x1F79, 0x0210);
+       hw->phy.ops.write_reg(hw, 0x1F79, 0x0210);
        /* Change integ_factor of channel A to 3 */
-       e1000_write_phy_reg(hw, 0x1895, 0x0003);
+       hw->phy.ops.write_reg(hw, 0x1895, 0x0003);
        /* Change prop_factor of channels BCD to 8 */
-       e1000_write_phy_reg(hw, 0x1796, 0x0008);
+       hw->phy.ops.write_reg(hw, 0x1796, 0x0008);
        /* Change cg_icount + enable integbp for channels BCD */
-       e1000_write_phy_reg(hw, 0x1798, 0xD008);
-       /* Change cg_icount + enable integbp + change prop_factor_master
+       hw->phy.ops.write_reg(hw, 0x1798, 0xD008);
+       /*
+        * Change cg_icount + enable integbp + change prop_factor_master
         * to 8 for channel A
         */
-       e1000_write_phy_reg(hw, 0x1898, 0xD918);
+       hw->phy.ops.write_reg(hw, 0x1898, 0xD918);
        /* Disable AHT in Slave mode on channel A */
-       e1000_write_phy_reg(hw, 0x187A, 0x0800);
-       /* Enable LPLU and disable AN to 1000 in non-D0a states,
+       hw->phy.ops.write_reg(hw, 0x187A, 0x0800);
+       /*
+        * Enable LPLU and disable AN to 1000 in non-D0a states,
         * Enable SPD+B2B
         */
-       e1000_write_phy_reg(hw, 0x0019, 0x008D);
+       hw->phy.ops.write_reg(hw, 0x0019, 0x008D);
        /* Enable restart AN on an1000_dis change */
-       e1000_write_phy_reg(hw, 0x001B, 0x2080);
+       hw->phy.ops.write_reg(hw, 0x001B, 0x2080);
        /* Enable wh_fifo read clock in 10/100 modes */
-       e1000_write_phy_reg(hw, 0x0014, 0x0045);
+       hw->phy.ops.write_reg(hw, 0x0014, 0x0045);
        /* Restart AN, Speed selection is 1000 */
-       e1000_write_phy_reg(hw, 0x0000, 0x1340);
+       hw->phy.ops.write_reg(hw, 0x0000, 0x1340);
 
        return E1000_SUCCESS;
 }
@@ -2028,10 +2089,9 @@
  *
  *  Returns the phy type from the id.
  **/
-e1000_phy_type
-e1000_get_phy_type_from_id(u32 phy_id)
+enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
 {
-       e1000_phy_type phy_type = e1000_phy_unknown;
+       enum e1000_phy_type phy_type = e1000_phy_unknown;
 
        switch (phy_id) {
        case M88E1000_I_PHY_ID:
@@ -2054,6 +2114,10 @@
        case IFE_C_E_PHY_ID:
                phy_type = e1000_phy_ife;
                break;
+       case BME1000_E_PHY_ID:
+       case BME1000_E_PHY_ID_R2:
+               phy_type = e1000_phy_bm;
+               break;
        default:
                phy_type = e1000_phy_unknown;
                break;
@@ -2061,4 +2125,430 @@
        return phy_type;
 }
 
+/**
+ *  e1000_determine_phy_address - Determines PHY address.
+ *  @hw: pointer to the HW structure
+ *
+ *  This uses a trial and error method to loop through possible PHY
+ *  addresses. It tests each by reading the PHY ID registers and
+ *  checking for a match.
+ **/
+s32 e1000_determine_phy_address(struct e1000_hw *hw)
+{
+       s32 ret_val = -E1000_ERR_PHY_TYPE;
+       u32 phy_addr = 0;
+       u32 i;
+       enum e1000_phy_type phy_type = e1000_phy_unknown;
 
+       for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) {
+               hw->phy.addr = phy_addr;
+               i = 0;
+
+               do {
+                       e1000_get_phy_id(hw);
+                       phy_type = e1000_get_phy_type_from_id(hw->phy.id);
+
+                       /*
+                        * If phy_type is valid, break - we found our
+                        * PHY address
+                        */
+                       if (phy_type  != e1000_phy_unknown) {
+                               ret_val = E1000_SUCCESS;
+                               goto out;
+                       }
+                       msec_delay(1);
+                       i++;
+               } while (i < 10);
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_get_phy_addr_for_bm_page - Retrieve PHY page address
+ *  @page: page to access
+ *
+ *  Returns the phy address for the page requested.
+ **/
+static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
+{
+       u32 phy_addr = 2;
+
+       if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31))
+               phy_addr = 1;
+
+       return phy_addr;
+}
+
+/**
+ *  e1000_write_phy_reg_bm - Write BM PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore, if necessary, then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       s32 ret_val;
+       u32 page_select = 0;
+       u32 page = offset >> IGP_PAGE_SHIFT;
+       u32 page_shift = 0;
+
+       DEBUGFUNC("e1000_write_phy_reg_bm");
+
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+                                                        FALSE);
+               goto out;
+       }
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               goto out;
+
+       hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
+
+       if (offset > MAX_PHY_MULTI_PAGE_REG) {
+               /*
+                * Page select is register 31 for phy address 1 and 22 for
+                * phy address 2 and 3. Page select is shifted only for
+                * phy address 1.
+                */
+               if (hw->phy.addr == 1) {
+                       page_shift = IGP_PAGE_SHIFT;
+                       page_select = IGP01E1000_PHY_PAGE_SELECT;
+               } else {
+                       page_shift = 0;
+                       page_select = BM_PHY_PAGE_SELECT;
+               }
+
+               /* Page is shifted left, PHY expects (page x 32) */
+               ret_val = e1000_write_phy_reg_mdic(hw, page_select,
+                                                  (page << page_shift));
+               if (ret_val) {
+                       hw->phy.ops.release(hw);
+                       goto out;
+               }
+       }
+
+       ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
+
+       hw->phy.ops.release(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_read_phy_reg_bm - Read BM PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Acquires semaphore, if necessary, then reads the PHY register at offset
+ *  and storing the retrieved information in data.  Release any acquired
+ *  semaphores before exiting.
+ **/
+s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       s32 ret_val;
+       u32 page_select = 0;
+       u32 page = offset >> IGP_PAGE_SHIFT;
+       u32 page_shift = 0;
+
+       DEBUGFUNC("e1000_read_phy_reg_bm");
+
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+                                                        TRUE);
+               goto out;
+       }
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               goto out;
+
+       hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
+
+       if (offset > MAX_PHY_MULTI_PAGE_REG) {
+               /*
+                * Page select is register 31 for phy address 1 and 22 for
+                * phy address 2 and 3. Page select is shifted only for
+                * phy address 1.
+                */
+               if (hw->phy.addr == 1) {
+                       page_shift = IGP_PAGE_SHIFT;
+                       page_select = IGP01E1000_PHY_PAGE_SELECT;
+               } else {
+                       page_shift = 0;
+                       page_select = BM_PHY_PAGE_SELECT;
+               }
+
+               /* Page is shifted left, PHY expects (page x 32) */
+               ret_val = e1000_write_phy_reg_mdic(hw, page_select,
+                                                  (page << page_shift));
+               if (ret_val) {
+                       hw->phy.ops.release(hw);
+                       goto out;
+               }
+       }
+
+       ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                         data);
+       hw->phy.ops.release(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_read_phy_reg_bm2 - Read BM PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Acquires semaphore, if necessary, then reads the PHY register at offset
+ *  and storing the retrieved information in data.  Release any acquired
+ *  semaphores before exiting.
+ **/
+s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       s32 ret_val;
+       u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
+
+       DEBUGFUNC("e1000_write_phy_reg_bm2");
+
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+                                                        TRUE);
+               goto out;
+       }
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               goto out;
+
+       hw->phy.addr = 1;
+
+       if (offset > MAX_PHY_MULTI_PAGE_REG) {
+
+               /* Page is shifted left, PHY expects (page x 32) */
+               ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
+                                                  page);
+
+               if (ret_val) {
+                       hw->phy.ops.release(hw);
+                       goto out;
+               }
+       }
+
+       ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                         data);
+       hw->phy.ops.release(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_write_phy_reg_bm2 - Write BM PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore, if necessary, then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       s32 ret_val;
+       u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
+
+       DEBUGFUNC("e1000_write_phy_reg_bm2");
+
+       /* Page 800 works differently than the rest so it has its own func */
+       if (page == BM_WUC_PAGE) {
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+                                                        FALSE);
+               goto out;
+       }
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               goto out;
+
+       hw->phy.addr = 1;
+
+       if (offset > MAX_PHY_MULTI_PAGE_REG) {
+               /* Page is shifted left, PHY expects (page x 32) */
+               ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
+                                                  page);
+
+               if (ret_val) {
+                       hw->phy.ops.release(hw);
+                       goto out;
+               }
+       }
+
+       ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
+
+       hw->phy.ops.release(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read or written
+ *  @data: pointer to the data to read or write
+ *  @read: determines if operation is read or write
+ *
+ *  Acquires semaphore, if necessary, then reads the PHY register at offset
+ *  and storing the retrieved information in data.  Release any acquired
+ *  semaphores before exiting. Note that procedure to read the wakeup
+ *  registers are different. It works as such:
+ *  1) Set page 769, register 17, bit 2 = 1
+ *  2) Set page to 800 for host (801 if we were manageability)
+ *  3) Write the address using the address opcode (0x11)
+ *  4) Read or write the data using the data opcode (0x12)
+ *  5) Restore 769_17.2 to its original value
+ **/
+static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
+                                          u16 *data, bool read)
+{
+       s32 ret_val;
+       u16 reg = ((u16)offset);
+       u16 phy_reg = 0;
+       u8  phy_acquired = 1;
+
+       DEBUGFUNC("e1000_read_phy_wakeup_reg_bm");
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val) {
+               DEBUGOUT("Could not acquire PHY\n");
+               phy_acquired = 0;
+               goto out;
+       }
+
+       /* All operations in this function are phy address 1 */
+       hw->phy.addr = 1;
+
+       /* Set page 769 */
+       e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
+                                (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
+
+       ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
+       if (ret_val) {
+               DEBUGOUT("Could not read PHY page 769\n");
+               goto out;
+       }
+
+       /* First clear bit 4 to avoid a power state change */
+       phy_reg &= ~(BM_WUC_HOST_WU_BIT);
+       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+       if (ret_val) {
+               DEBUGOUT("Could not clear PHY page 769 bit 4\n");
+               goto out;
+       }
+
+       /* Write bit 2 = 1, and clear bit 4 to 769_17 */
+       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG,
+                                          phy_reg | BM_WUC_ENABLE_BIT);
+       if (ret_val) {
+               DEBUGOUT("Could not write PHY page 769 bit 2\n");
+               goto out;
+       }
+
+       /* Select page 800 */
+       ret_val = e1000_write_phy_reg_mdic(hw,
+                                          IGP01E1000_PHY_PAGE_SELECT,
+                                          (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+
+       /* Write the page 800 offset value using opcode 0x11 */
+       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
+       if (ret_val) {
+               DEBUGOUT("Could not write address opcode to page 800\n");
+               goto out;
+       }
+
+       if (read) {
+               /* Read the page 800 value using opcode 0x12 */
+               ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
+                                                       data);
+       } else {
+               /* Read the page 800 value using opcode 0x12 */
+               ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
+                                                       *data);
+       }
+
+       if (ret_val) {
+               DEBUGOUT("Could not read data value from page 800\n");
+               goto out;
+       }
+
+       /*
+        * Restore 769_17.2 to its original value
+        * Set page 769
+        */
+       e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
+                                (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
+
+       /* Clear 769_17.2 */
+       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+       if (ret_val) {
+               DEBUGOUT("Could not clear PHY page 769 bit 2\n");
+               goto out;
+       }
+
+out:
+       if (phy_acquired == 1)
+               hw->phy.ops.release(hw);
+       return ret_val;
+}
+
+/**
+ * e1000_power_up_phy_copper - Restore copper link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, restore the link to previous
+ * settings.
+ **/
+void e1000_power_up_phy_copper(struct e1000_hw *hw)
+{
+       u16 mii_reg = 0;
+
+       /* The PHY will retain its settings across a power down/up cycle */
+       hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
+       mii_reg &= ~MII_CR_POWER_DOWN;
+       hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
+}
+
+/**
+ * e1000_power_down_phy_copper - Restore copper link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, restore the link to previous
+ * settings.
+ **/
+void e1000_power_down_phy_copper(struct e1000_hw *hw)
+{
+       u16 mii_reg = 0;
+
+       /* The PHY will retain its settings across a power down/up cycle */
+       hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
+       mii_reg |= MII_CR_POWER_DOWN;
+       hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
+       msec_delay(1);
+}
Index: dev/em/e1000_nvm.c
===================================================================
--- dev/em/e1000_nvm.c  (Revision 28889)
+++ dev/em/e1000_nvm.c  (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,22 +29,82 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_nvm.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_nvm.c,v 1.2 2008/11/26 23:57:23 jfv Exp $*/
 
-
 #include "e1000_api.h"
-#include "e1000_nvm.h"
 
 /**
+ *  e1000_init_nvm_ops_generic - Initialize NVM function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  Setups up the function pointers to no-op functions
+ **/
+void e1000_init_nvm_ops_generic(struct e1000_hw *hw)
+{
+       struct e1000_nvm_info *nvm = &hw->nvm;
+       DEBUGFUNC("e1000_init_nvm_ops_generic");
+
+       /* Initialize function pointers */
+       nvm->ops.init_params = e1000_null_ops_generic;
+       nvm->ops.acquire = e1000_null_ops_generic;
+       nvm->ops.read = e1000_null_read_nvm;
+       nvm->ops.release = e1000_null_nvm_generic;
+       nvm->ops.reload = e1000_reload_nvm_generic;
+       nvm->ops.update = e1000_null_ops_generic;
+       nvm->ops.valid_led_default = e1000_null_led_default;
+       nvm->ops.validate = e1000_null_ops_generic;
+       nvm->ops.write = e1000_null_write_nvm;
+}
+
+/**
+ *  e1000_null_nvm_read - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c)
+{
+       DEBUGFUNC("e1000_null_read_nvm");
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_null_nvm_generic - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_nvm_generic(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_null_nvm_generic");
+       return;
+}
+
+/**
+ *  e1000_null_led_default - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_led_default(struct e1000_hw *hw, u16 *data)
+{
+       DEBUGFUNC("e1000_null_led_default");
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_null_write_nvm - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c)
+{
+       DEBUGFUNC("e1000_null_write_nvm");
+       return E1000_SUCCESS;
+}
+
+/**
  *  e1000_raise_eec_clk - Raise EEPROM clock
  *  @hw: pointer to the HW structure
  *  @eecd: pointer to the EEPROM
  *
  *  Enable/Raise the EEPROM clock bit.
  **/
-static void
-e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
+static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
 {
        *eecd = *eecd | E1000_EECD_SK;
        E1000_WRITE_REG(hw, E1000_EECD, *eecd);
@@ -59,8 +119,7 @@
  *
  *  Clear/Lower the EEPROM clock bit.
  **/
-static void
-e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
+static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
 {
        *eecd = *eecd & ~E1000_EECD_SK;
        E1000_WRITE_REG(hw, E1000_EECD, *eecd);
@@ -78,8 +137,7 @@
  *  "data" parameter will be shifted out to the EEPROM one bit at a time.
  *  In order to do this, "data" must be broken down into bits.
  **/
-static void
-e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
+static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
@@ -90,7 +148,8 @@
        mask = 0x01 << (count - 1);
        if (nvm->type == e1000_nvm_eeprom_microwire)
                eecd &= ~E1000_EECD_DO;
-       else if (nvm->type == e1000_nvm_eeprom_spi)
+       else
+       if (nvm->type == e1000_nvm_eeprom_spi)
                eecd |= E1000_EECD_DO;
 
        do {
@@ -125,8 +184,7 @@
  *  "DO" bit.  During this "shifting in" process the data in "DI" bit should
  *  always be clear.
  **/
-static u16
-e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
+static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
 {
        u32 eecd;
        u32 i;
@@ -163,8 +221,7 @@
  *  Polls the EEPROM status bit for either read or write completion based
  *  upon the value of 'ee_reg'.
  **/
-s32
-e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
+s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
 {
        u32 attempts = 100000;
        u32 i, reg = 0;
@@ -197,8 +254,7 @@
  *  Return successful if access grant bit set, else clear the request for
  *  EEPROM access and return -E1000_ERR_NVM (-1).
  **/
-s32
-e1000_acquire_nvm_generic(struct e1000_hw *hw)
+s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
 {
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
        s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
@@ -233,8 +289,7 @@
  *
  *  Return the EEPROM to a standby state.
  **/
-static void
-e1000_standby_nvm(struct e1000_hw *hw)
+static void e1000_standby_nvm(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
@@ -256,7 +311,8 @@
                usec_delay(nvm->delay_usec);
 
                e1000_lower_eec_clk(hw, &eecd);
-       } else if (nvm->type == e1000_nvm_eeprom_spi) {
+       } else
+       if (nvm->type == e1000_nvm_eeprom_spi) {
                /* Toggle CS to flush commands */
                eecd |= E1000_EECD_CS;
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
@@ -275,8 +331,7 @@
  *
  *  Terminates the current command by inverting the EEPROM's chip select pin.
  **/
-void
-e1000_stop_nvm(struct e1000_hw *hw)
+void e1000_stop_nvm(struct e1000_hw *hw)
 {
        u32 eecd;
 
@@ -288,7 +343,7 @@
                eecd |= E1000_EECD_CS;
                e1000_lower_eec_clk(hw, &eecd);
        } else if (hw->nvm.type == e1000_nvm_eeprom_microwire) {
-               /* CS on Microcwire is active-high */
+               /* CS on Microwire is active-high */
                eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
                e1000_raise_eec_clk(hw, &eecd);
@@ -302,8 +357,7 @@
  *
  *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
  **/
-void
-e1000_release_nvm_generic(struct e1000_hw *hw)
+void e1000_release_nvm_generic(struct e1000_hw *hw)
 {
        u32 eecd;
 
@@ -322,8 +376,7 @@
  *
  *  Setups the EEPROM for reading and writing.
  **/
-static s32
-e1000_ready_nvm_eeprom(struct e1000_hw *hw)
+static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
@@ -340,17 +393,20 @@
                /* Set CS */
                eecd |= E1000_EECD_CS;
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
-       } else if (nvm->type == e1000_nvm_eeprom_spi) {
+       } else
+       if (nvm->type == e1000_nvm_eeprom_spi) {
                /* Clear SK and CS */
                eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
                usec_delay(1);
                timeout = NVM_MAX_RETRY_SPI;
 
-               /* Read "Status Register" repeatedly until the LSB is cleared.
+               /*
+                * Read "Status Register" repeatedly until the LSB is cleared.
                 * The EEPROM will signal that the command has been completed
                 * by clearing bit 0 of the internal status register.  If it's
-                * not cleared within 'timeout', then error out. */
+                * not cleared within 'timeout', then error out.
+                */
                while (timeout) {
                        e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
                                                 hw->nvm.opcode_bits);
@@ -383,8 +439,7 @@
  *
  *  Reads a 16 bit word from the EEPROM.
  **/
-s32
-e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        u32 i = 0;
@@ -394,8 +449,10 @@
 
        DEBUGFUNC("e1000_read_nvm_spi");
 
-       /* A check for invalid values:  offset too large, too many words,
-        * and not enough words. */
+       /*
+        * A check for invalid values:  offset too large, too many words,
+        * and not enough words.
+        */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
@@ -403,7 +460,7 @@
                goto out;
        }
 
-       ret_val = e1000_acquire_nvm(hw);
+       ret_val = nvm->ops.acquire(hw);
        if (ret_val)
                goto out;
 
@@ -420,16 +477,18 @@
        e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
        e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
 
-       /* Read the data.  SPI NVMs increment the address with each byte
+       /*
+        * Read the data.  SPI NVMs increment the address with each byte
         * read and will roll over if reading beyond the end.  This allows
-        * us to read the whole NVM from any offset */
+        * us to read the whole NVM from any offset
+        */
        for (i = 0; i < words; i++) {
                word_in = e1000_shift_in_eec_bits(hw, 16);
                data[i] = (word_in >> 8) | (word_in << 8);
        }
 
 release:
-       e1000_release_nvm(hw);
+       nvm->ops.release(hw);
 
 out:
        return ret_val;
@@ -444,8 +503,8 @@
  *
  *  Reads a 16 bit word from the EEPROM.
  **/
-s32
-e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
+                             u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        u32 i = 0;
@@ -454,8 +513,10 @@
 
        DEBUGFUNC("e1000_read_nvm_microwire");
 
-       /* A check for invalid values:  offset too large, too many words,
-        * and not enough words. */
+       /*
+        * A check for invalid values:  offset too large, too many words,
+        * and not enough words.
+        */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
@@ -463,7 +524,7 @@
                goto out;
        }
 
-       ret_val = e1000_acquire_nvm(hw);
+       ret_val = nvm->ops.acquire(hw);
        if (ret_val)
                goto out;
 
@@ -477,14 +538,16 @@
                e1000_shift_out_eec_bits(hw, (u16)(offset + i),
                                        nvm->address_bits);
 
-               /* Read the data.  For microwire, each word requires the
-                * overhead of setup and tear-down. */
+               /*
+                * Read the data.  For microwire, each word requires the
+                * overhead of setup and tear-down.
+                */
                data[i] = e1000_shift_in_eec_bits(hw, 16);
                e1000_standby_nvm(hw);
        }
 
 release:
-       e1000_release_nvm(hw);
+       nvm->ops.release(hw);
 
 out:
        return ret_val;
@@ -499,8 +562,7 @@
  *
  *  Reads a 16 bit word from the EEPROM using the EERD register.
  **/
-s32
-e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        u32 i, eerd = 0;
@@ -508,8 +570,10 @@
 
        DEBUGFUNC("e1000_read_nvm_eerd");
 
-       /* A check for invalid values:  offset too large, too many words,
-        * and not enough words. */
+       /*
+        * A check for invalid values:  offset too large, too many words,
+        * too many words for the offset, and not enough words.
+        */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
@@ -526,7 +590,8 @@
                if (ret_val)
                        break;
 
-               data[i] = (E1000_READ_REG(hw, E1000_EERD) >> 
E1000_NVM_RW_REG_DATA);
+               data[i] = (E1000_READ_REG(hw, E1000_EERD) >>
+                          E1000_NVM_RW_REG_DATA);
        }
 
 out:
@@ -543,10 +608,9 @@
  *  Writes data to EEPROM at offset using SPI interface.
  *
  *  If e1000_update_nvm_checksum is not called after this function , the
- *  EEPROM will most likley contain an invalid checksum.
+ *  EEPROM will most likely contain an invalid checksum.
  **/
-s32
-e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        s32 ret_val;
@@ -554,8 +618,10 @@
 
        DEBUGFUNC("e1000_write_nvm_spi");
 
-       /* A check for invalid values:  offset too large, too many words,
-        * and not enough words. */
+       /*
+        * A check for invalid values:  offset too large, too many words,
+        * and not enough words.
+        */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
@@ -563,12 +629,10 @@
                goto out;
        }
 
-       ret_val = e1000_acquire_nvm(hw);
+       ret_val = nvm->ops.acquire(hw);
        if (ret_val)
                goto out;
 
-       msec_delay(10);
-
        while (widx < words) {
                u8 write_opcode = NVM_WRITE_OPCODE_SPI;
 
@@ -584,8 +648,10 @@
 
                e1000_standby_nvm(hw);
 
-               /* Some SPI eeproms use the 8th address bit embedded in the
-                * opcode */
+               /*
+                * Some SPI eeproms use the 8th address bit embedded in the
+                * opcode
+                */
                if ((nvm->address_bits == 8) && (offset >= 128))
                        write_opcode |= NVM_A8_OPCODE_SPI;
 
@@ -610,7 +676,7 @@
 
        msec_delay(10);
 release:
-       e1000_release_nvm(hw);
+       nvm->ops.release(hw);
 
 out:
        return ret_val;
@@ -626,10 +692,10 @@
  *  Writes data to EEPROM at offset using microwire interface.
  *
  *  If e1000_update_nvm_checksum is not called after this function , the
- *  EEPROM will most likley contain an invalid checksum.
+ *  EEPROM will most likely contain an invalid checksum.
  **/
-s32
-e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 
*data)
+s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
+                              u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        s32  ret_val;
@@ -639,8 +705,10 @@
 
        DEBUGFUNC("e1000_write_nvm_microwire");
 
-       /* A check for invalid values:  offset too large, too many words,
-        * and not enough words. */
+       /*
+        * A check for invalid values:  offset too large, too many words,
+        * and not enough words.
+        */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
@@ -648,7 +716,7 @@
                goto out;
        }
 
-       ret_val = e1000_acquire_nvm(hw);
+       ret_val = nvm->ops.acquire(hw);
        if (ret_val)
                goto out;
 
@@ -698,41 +766,40 @@
        e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
 
 release:
-       e1000_release_nvm(hw);
+       nvm->ops.release(hw);
 
 out:
        return ret_val;
 }
 
 /**
- *  e1000_read_part_num_generic - Read device part number
+ *  e1000_read_pba_num_generic - Read device part number
  *  @hw: pointer to the HW structure
- *  @part_num: pointer to device part number
+ *  @pba_num: pointer to device part number
  *
  *  Reads the product board assembly (PBA) number from the EEPROM and stores
- *  the value in part_num.
+ *  the value in pba_num.
  **/
-s32
-e1000_read_part_num_generic(struct e1000_hw *hw, u32 *part_num)
+s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num)
 {
        s32  ret_val;
        u16 nvm_data;
 
-       DEBUGFUNC("e1000_read_part_num_generic");
+       DEBUGFUNC("e1000_read_pba_num_generic");
 
-       ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
+       ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
                goto out;
        }
-       *part_num = (u32)(nvm_data << 16);
+       *pba_num = (u32)(nvm_data << 16);
 
-       ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
+       ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
                goto out;
        }
-       *part_num |= nvm_data;
+       *pba_num |= nvm_data;
 
 out:
        return ret_val;
@@ -746,8 +813,7 @@
  *  Since devices with two ports use the same EEPROM, we increment the
  *  last bit in the MAC address for the second port.
  **/
-s32
-e1000_read_mac_addr_generic(struct e1000_hw *hw)
+s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
 {
        s32  ret_val = E1000_SUCCESS;
        u16 offset, nvm_data, i;
@@ -756,7 +822,7 @@
 
        for (i = 0; i < ETH_ADDR_LEN; i += 2) {
                offset = i >> 1;
-               ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);
+               ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
                if (ret_val) {
                        DEBUGOUT("NVM Read Error\n");
                        goto out;
@@ -783,8 +849,7 @@
  *  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_generic(struct e1000_hw *hw)
+s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
        u16 checksum = 0;
@@ -793,7 +858,7 @@
        DEBUGFUNC("e1000_validate_nvm_checksum_generic");
 
        for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
-               ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
+               ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
                if (ret_val) {
                        DEBUGOUT("NVM Read Error\n");
                        goto out;
@@ -819,8 +884,7 @@
  *  up to the checksum.  Then calculates the EEPROM checksum and writes the
  *  value to the EEPROM.
  **/
-s32
-e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
+s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
 {
        s32  ret_val;
        u16 checksum = 0;
@@ -829,7 +893,7 @@
        DEBUGFUNC("e1000_update_nvm_checksum");
 
        for (i = 0; i < NVM_CHECKSUM_REG; i++) {
-               ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
+               ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
                if (ret_val) {
                        DEBUGOUT("NVM Read Error while updating checksum.\n");
                        goto out;
@@ -837,10 +901,9 @@
                checksum += nvm_data;
        }
        checksum = (u16) NVM_SUM - checksum;
-       ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum);
-       if (ret_val) {
+       ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
+       if (ret_val)
                DEBUGOUT("NVM Write Error while updating checksum.\n");
-       }
 
 out:
        return ret_val;
@@ -853,8 +916,7 @@
  *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
  *  extended control register.
  **/
-void
-e1000_reload_nvm_generic(struct e1000_hw *hw)
+void e1000_reload_nvm_generic(struct e1000_hw *hw)
 {
        u32 ctrl_ext;
 
@@ -867,35 +929,3 @@
        E1000_WRITE_FLUSH(hw);
 }
 
-/* Function pointers local to this file and not intended for public use */
-
-/**
- *  e1000_acquire_nvm - Acquire exclusive access to EEPROM
- *  @hw: pointer to the HW structure
- *
- *  For those silicon families which have implemented a NVM acquire function,
- *  run the defined function else return success.
- **/
-s32
-e1000_acquire_nvm(struct e1000_hw *hw)
-{
-       if (hw->func.acquire_nvm != NULL)
-               return hw->func.acquire_nvm(hw);
-       else
-               return E1000_SUCCESS;
-}
-
-/**
- *  e1000_release_nvm - Release exclusive access to EEPROM
- *  @hw: pointer to the HW structure
- *
- *  For those silicon families which have implemented a NVM release function,
- *  run the defined fucntion else return success.
- **/
-void
-e1000_release_nvm(struct e1000_hw *hw)
-{
-       if (hw->func.release_nvm != NULL)
-               hw->func.release_nvm(hw);
-}
-
Index: dev/em/e1000_mac.c
===================================================================
--- dev/em/e1000_mac.c  (Revision 28889)
+++ dev/em/e1000_mac.c  (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,30 +29,140 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_mac.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_mac.c,v 1.2 2008/11/26 23:57:23 jfv Exp $*/
 
-
 #include "e1000_api.h"
-#include "e1000_mac.h"
 
+static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
+
 /**
- *  e1000_remove_device_generic - Free device specific structure
+ *  e1000_init_mac_ops_generic - Initialize MAC function pointers
  *  @hw: pointer to the HW structure
  *
- *  If a device specific structure was allocated, this function will
- *  free it.
+ *  Setups up the function pointers to no-op functions
  **/
-void
-e1000_remove_device_generic(struct e1000_hw *hw)
+void e1000_init_mac_ops_generic(struct e1000_hw *hw)
 {
-       DEBUGFUNC("e1000_remove_device_generic");
+       struct e1000_mac_info *mac = &hw->mac;
+       DEBUGFUNC("e1000_init_mac_ops_generic");
 
-       /* Freeing the dev_spec member of e1000_hw structure */
-       e1000_free_dev_spec_struct(hw);
+       /* General Setup */
+       mac->ops.init_params = e1000_null_ops_generic;
+       mac->ops.init_hw = e1000_null_ops_generic;
+       mac->ops.reset_hw = e1000_null_ops_generic;
+       mac->ops.setup_physical_interface = e1000_null_ops_generic;
+       mac->ops.get_bus_info = e1000_null_ops_generic;
+       mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie;
+       mac->ops.read_mac_addr = e1000_read_mac_addr_generic;
+       mac->ops.config_collision_dist = e1000_config_collision_dist_generic;
+       mac->ops.clear_hw_cntrs = e1000_null_mac_generic;
+       /* LED */
+       mac->ops.cleanup_led = e1000_null_ops_generic;
+       mac->ops.setup_led = e1000_null_ops_generic;
+       mac->ops.blink_led = e1000_null_ops_generic;
+       mac->ops.led_on = e1000_null_ops_generic;
+       mac->ops.led_off = e1000_null_ops_generic;
+       /* LINK */
+       mac->ops.setup_link = e1000_null_ops_generic;
+       mac->ops.get_link_up_info = e1000_null_link_info;
+       mac->ops.check_for_link = e1000_null_ops_generic;
+       mac->ops.wait_autoneg = e1000_wait_autoneg_generic;
+       /* Management */
+       mac->ops.check_mng_mode = e1000_null_mng_mode;
+       mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic;
+       mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic;
+       mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic;
+       /* VLAN, MC, etc. */
+       mac->ops.update_mc_addr_list = e1000_null_update_mc;
+       mac->ops.clear_vfta = e1000_null_mac_generic;
+       mac->ops.write_vfta = e1000_null_write_vfta;
+       mac->ops.mta_set = e1000_null_mta_set;
+       mac->ops.rar_set = e1000_rar_set_generic;
+       mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic;
 }
 
 /**
+ *  e1000_null_ops_generic - No-op function, returns 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_ops_generic(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_null_ops_generic");
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_null_mac_generic - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_mac_generic(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_null_mac_generic");
+       return;
+}
+
+/**
+ *  e1000_null_link_info - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d)
+{
+       DEBUGFUNC("e1000_null_link_info");
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_null_mng_mode - No-op function, return FALSE
+ *  @hw: pointer to the HW structure
+ **/
+bool e1000_null_mng_mode(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_null_mng_mode");
+       return FALSE;
+}
+
+/**
+ *  e1000_null_update_mc - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a, u32 b, u32 c)
+{
+       DEBUGFUNC("e1000_null_update_mc");
+       return;
+}
+
+/**
+ *  e1000_null_write_vfta - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b)
+{
+       DEBUGFUNC("e1000_null_write_vfta");
+       return;
+}
+
+/**
+ *  e1000_null_set_mta - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_mta_set(struct e1000_hw *hw, u32 a)
+{
+       DEBUGFUNC("e1000_null_mta_set");
+       return;
+}
+
+/**
+ *  e1000_null_rar_set - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a)
+{
+       DEBUGFUNC("e1000_null_rar_set");
+       return;
+}
+
+/**
  *  e1000_get_bus_info_pci_generic - Get PCI(x) bus information
  *  @hw: pointer to the HW structure
  *
@@ -60,13 +170,12 @@
  *  network interface.  The following bus information is determined and stored:
  *  bus speed, bus width, type (PCI/PCIx), and PCI(-x) function.
  **/
-s32
-e1000_get_bus_info_pci_generic(struct e1000_hw *hw)
+s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw)
 {
+       struct e1000_mac_info *mac = &hw->mac;
        struct e1000_bus_info *bus = &hw->bus;
        u32 status = E1000_READ_REG(hw, E1000_STATUS);
        s32 ret_val = E1000_SUCCESS;
-       u16 pci_header_type;
 
        DEBUGFUNC("e1000_get_bus_info_pci_generic");
 
@@ -103,12 +212,7 @@
                     : e1000_bus_width_32;
 
        /* Which PCI(-X) function? */
-       e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type);
-       if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC)
-               bus->func = (status & E1000_STATUS_FUNC_MASK)
-                           >> E1000_STATUS_FUNC_SHIFT;
-       else
-               bus->func = 0;
+       mac->ops.set_lan_id(hw);
 
        return ret_val;
 }
@@ -121,13 +225,13 @@
  *  network interface.  The following bus information is determined and stored:
  *  bus speed, bus width, type (PCIe), and PCIe function.
  **/
-s32
-e1000_get_bus_info_pcie_generic(struct e1000_hw *hw)
+s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw)
 {
+       struct e1000_mac_info *mac = &hw->mac;
        struct e1000_bus_info *bus = &hw->bus;
+
        s32 ret_val;
-       u32 status;
-       u16 pcie_link_status, pci_header_type;
+       u16 pcie_link_status;
 
        DEBUGFUNC("e1000_get_bus_info_pcie_generic");
 
@@ -140,19 +244,70 @@
        if (ret_val)
                bus->width = e1000_bus_width_unknown;
        else
-               bus->width = (e1000_bus_width)((pcie_link_status &
+               bus->width = (enum e1000_bus_width)((pcie_link_status &
                                                PCIE_LINK_WIDTH_MASK) >>
                                               PCIE_LINK_WIDTH_SHIFT);
 
+       mac->ops.set_lan_id(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port 
devices
+ *
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines the LAN function id by reading memory-mapped registers
+ *  and swaps the port value if requested.
+ **/
+void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+       u32 reg;
+
+       reg = E1000_READ_REG(hw, E1000_STATUS);
+       bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT;
+
+       /* check for a port swap */
+       reg = E1000_READ_REG(hw, E1000_FACTPS);
+       if (reg & E1000_FACTPS_LFS)
+               bus->func ^= 0x1;
+}
+
+/**
+ *  e1000_set_lan_id_multi_port_pci - Set LAN id for PCI multiple port devices
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines the LAN function id by reading PCI config space.
+ **/
+void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+       u16 pci_header_type;
+       u32 status;
+
        e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type);
        if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) {
                status = E1000_READ_REG(hw, E1000_STATUS);
                bus->func = (status & E1000_STATUS_FUNC_MASK)
                            >> E1000_STATUS_FUNC_SHIFT;
-       } else
+       } else {
                bus->func = 0;
+       }
+}
 
-       return E1000_SUCCESS;
+/**
+ *  e1000_set_lan_id_single_port - Set LAN id for a single port device
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets the LAN function id to zero for a single port device.
+ **/
+void e1000_set_lan_id_single_port(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+
+       bus->func = 0;
 }
 
 /**
@@ -162,8 +317,7 @@
  *  Clears the register array which contains the VLAN filter table by
  *  setting all the values to 0.
  **/
-void
-e1000_clear_vfta_generic(struct e1000_hw *hw)
+void e1000_clear_vfta_generic(struct e1000_hw *hw)
 {
        u32 offset;
 
@@ -184,8 +338,7 @@
  *  Writes value at the given offset in the register array which stores
  *  the VLAN filter table.
  **/
-void
-e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
+void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
 {
        DEBUGFUNC("e1000_write_vfta_generic");
 
@@ -202,8 +355,7 @@
  *  register to the devices MAC address and clearing all the other receive
  *  address registers to 0.
  **/
-void
-e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count)
+void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count)
 {
        u32 i;
 
@@ -212,7 +364,7 @@
        /* Setup the receive address */
        DEBUGOUT("Programming MAC Address into RAR[0]\n");
 
-       e1000_rar_set_generic(hw, hw->mac.addr, 0);
+       hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
 
        /* Zero out the other (rar_entry_count - 1) receive addresses */
        DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1);
@@ -225,6 +377,68 @@
 }
 
 /**
+ *  e1000_check_alt_mac_addr_generic - Check for alternate MAC addr
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks the nvm for an alternate MAC address.  An alternate MAC address
+ *  can be setup by pre-boot software and must be treated like a permanent
+ *  address and must override the actual permanent MAC address.  If an
+ *  alternate MAC address is found it is saved in the hw struct and
+ *  programmed into RAR0 and the function returns success, otherwise the
+ *  function returns an error.
+ **/
+s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
+{
+       u32 i;
+       s32 ret_val = E1000_SUCCESS;
+       u16 offset, nvm_alt_mac_addr_offset, nvm_data;
+       u8 alt_mac_addr[ETH_ADDR_LEN];
+
+       DEBUGFUNC("e1000_check_alt_mac_addr_generic");
+
+       ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1,
+                                &nvm_alt_mac_addr_offset);
+       if (ret_val) {
+               DEBUGOUT("NVM Read Error\n");
+               goto out;
+       }
+
+       if (nvm_alt_mac_addr_offset == 0xFFFF) {
+               ret_val = -(E1000_NOT_IMPLEMENTED);
+               goto out;
+       }
+
+       if (hw->bus.func == E1000_FUNC_1)
+               nvm_alt_mac_addr_offset += ETH_ADDR_LEN/sizeof(u16);
+
+       for (i = 0; i < ETH_ADDR_LEN; i += 2) {
+               offset = nvm_alt_mac_addr_offset + (i >> 1);
+               ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
+               if (ret_val) {
+                       DEBUGOUT("NVM Read Error\n");
+                       goto out;
+               }
+
+               alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
+               alt_mac_addr[i + 1] = (u8)(nvm_data >> 8);
+       }
+
+       /* if multicast bit is set, the alternate address will not be used */
+       if (alt_mac_addr[0] & 0x01) {
+               ret_val = -(E1000_NOT_IMPLEMENTED);
+               goto out;
+       }
+
+       for (i = 0; i < ETH_ADDR_LEN; i++)
+               hw->mac.addr[i] = hw->mac.perm_addr[i] = alt_mac_addr[i];
+
+       hw->mac.ops.rar_set(hw, hw->mac.perm_addr, 0);
+
+out:
+       return ret_val;
+}
+
+/**
  *  e1000_rar_set_generic - Set receive address register
  *  @hw: pointer to the HW structure
  *  @addr: pointer to the receive address
@@ -233,27 +447,28 @@
  *  Sets the receive address array register at index to the address passed
  *  in by addr.
  **/
-void
-e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
+void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
 {
        u32 rar_low, rar_high;
 
        DEBUGFUNC("e1000_rar_set_generic");
 
-       /* HW expects these in little endian so we reverse the byte order
+       /*
+        * HW expects these in little endian so we reverse the byte order
         * from network order (big endian) to little endian
         */
        rar_low = ((u32) addr[0] |
-                  ((u32) addr[1] << 8) |
-                   ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+                  ((u32) addr[1] << 8) |
+                  ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
 
        rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
 
-       if (!hw->mac.disable_av)
+       /* If MAC address zero, no need to set the AV bit */
+       if (rar_low || rar_high)
                rar_high |= E1000_RAH_AV;
 
-       E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
-       E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
+       E1000_WRITE_REG(hw, E1000_RAL(index), rar_low);
+       E1000_WRITE_REG(hw, E1000_RAH(index), rar_high);
 }
 
 /**
@@ -266,13 +481,13 @@
  *  current value is read, the new bit is OR'd in and the new value is
  *  written back into the register.
  **/
-void
-e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value)
+void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value)
 {
        u32 hash_bit, hash_reg, mta;
 
        DEBUGFUNC("e1000_mta_set_generic");
-       /* The MTA is a register array of 32-bit registers. It is
+       /*
+        * The MTA is a register array of 32-bit registers. It is
         * treated like an array of (32*mta_reg_count) bits.  We want to
         * set bit BitArray[hash_value]. So we figure out what register
         * the bit is in, read it, OR in the new bit, then write
@@ -293,7 +508,7 @@
 }
 
 /**
- *  e1000_mc_addr_list_update_generic - Update Multicast addresses
+ *  e1000_update_mc_addr_list_generic - Update Multicast addresses
  *  @hw: pointer to the HW structure
  *  @mc_addr_list: array of multicast addresses to program
  *  @mc_addr_count: number of multicast addresses to program
@@ -305,23 +520,23 @@
  *  The parameter rar_count will usually be hw->mac.rar_entry_count
  *  unless there are workarounds that change this.
  **/
-void
-e1000_mc_addr_list_update_generic(struct e1000_hw *hw,
-                                  u8 *mc_addr_list, u32 mc_addr_count,
-                                  u32 rar_used_count, u32 rar_count)
+void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
+                                       u8 *mc_addr_list, u32 mc_addr_count,
+                                       u32 rar_used_count, u32 rar_count)
 {
        u32 hash_value;
        u32 i;
 
-       DEBUGFUNC("e1000_mc_addr_list_update_generic");
+       DEBUGFUNC("e1000_update_mc_addr_list_generic");
 
-       /* Load the first set of multicast addresses into the exact
+       /*
+        * Load the first set of multicast addresses into the exact
         * filters (RAR).  If there are not enough to fill the RAR
         * array, clear the filters.
         */
        for (i = rar_used_count; i < rar_count; i++) {
                if (mc_addr_count) {
-                       e1000_rar_set(hw, mc_addr_list, i);
+                       hw->mac.ops.rar_set(hw, mc_addr_list, i);
                        mc_addr_count--;
                        mc_addr_list += ETH_ADDR_LEN;
                } else {
@@ -341,9 +556,9 @@
 
        /* Load any remaining multicast addresses into the hash table. */
        for (; mc_addr_count > 0; mc_addr_count--) {
-               hash_value = e1000_hash_mc_addr(hw, mc_addr_list);
+               hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
                DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
-               e1000_mta_set(hw, hash_value);
+               hw->mac.ops.mta_set(hw, hash_value);
                mc_addr_list += ETH_ADDR_LEN;
        }
 }
@@ -357,8 +572,7 @@
  *  the multicast filter table array address and new table value.  See
  *  e1000_mta_set_generic()
  **/
-u32
-e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
+u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
 {
        u32 hash_value, hash_mask;
        u8 bit_shift = 0;
@@ -368,12 +582,15 @@
        /* Register count multiplied by bits per register */
        hash_mask = (hw->mac.mta_reg_count * 32) - 1;
 
-       /* For a mc_filter_type of 0, bit_shift is the number of left-shifts
-        * where 0xFF would still fall within the hash mask. */
+       /*
+        * For a mc_filter_type of 0, 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++;
 
-       /* The portion of the address that is used for the hash table
+       /*
+        * The portion of the address that is used for the hash table
         * is determined by the mc_filter_type setting.
         * The algorithm is such that there is a total of 8 bits of shifting.
         * The bit_shift for a mc_filter_type of 0 represents the number of
@@ -384,8 +601,8 @@
         * cases are a variation of this algorithm...essentially raising the
         * number of bits to shift mc_addr[5] left, while still keeping the
         * 8-bit shifting total.
-        */
-       /* For example, given the following Destination MAC Address and an
+        *
+        * For example, given the following Destination MAC Address and an
         * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask),
         * we can see that the bit_shift for case 0 is 4.  These are the hash
         * values resulting from each mc_filter_type...
@@ -399,18 +616,18 @@
         * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634
         */
        switch (hw->mac.mc_filter_type) {
-               default:
-               case 0:
-                       break;
-               case 1:
-                       bit_shift += 1;
-                       break;
-               case 2:
-                       bit_shift += 2;
-                       break;
-               case 3:
-                       bit_shift += 4;
-                       break;
+       default:
+       case 0:
+               break;
+       case 1:
+               bit_shift += 1;
+               break;
+       case 2:
+               bit_shift += 2;
+               break;
+       case 3:
+               bit_shift += 4;
+               break;
        }
 
        hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
@@ -425,11 +642,10 @@
  *
  *  In certain situations, a system BIOS may report that the PCIx maximum
  *  memory read byte count (MMRBC) value is higher than than the actual
- *  value. We check the PCIx command regsiter with the current PCIx status
- *  regsiter.
+ *  value. We check the PCIx command register with the current PCIx status
+ *  register.
  **/
-void
-e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw)
+void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw)
 {
        u16 cmd_mmrbc;
        u16 pcix_cmd;
@@ -445,9 +661,9 @@
        e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd);
        e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word);
        cmd_mmrbc = (pcix_cmd & PCIX_COMMAND_MMRBC_MASK) >>
-                   PCIX_COMMAND_MMRBC_SHIFT;
+                    PCIX_COMMAND_MMRBC_SHIFT;
        stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
-                    PCIX_STATUS_HI_MMRBC_SHIFT;
+                     PCIX_STATUS_HI_MMRBC_SHIFT;
        if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
                stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;
        if (cmd_mmrbc > stat_mmrbc) {
@@ -463,50 +679,47 @@
  *
  *  Clears the base hardware counters by reading the counter registers.
  **/
-void
-e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw)
+void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw)
 {
-       volatile u32 temp;
-
        DEBUGFUNC("e1000_clear_hw_cntrs_base_generic");
 
-       temp = E1000_READ_REG(hw, E1000_CRCERRS);
-       temp = E1000_READ_REG(hw, E1000_SYMERRS);
-       temp = E1000_READ_REG(hw, E1000_MPC);
-       temp = E1000_READ_REG(hw, E1000_SCC);
-       temp = E1000_READ_REG(hw, E1000_ECOL);
-       temp = E1000_READ_REG(hw, E1000_MCC);
-       temp = E1000_READ_REG(hw, E1000_LATECOL);
-       temp = E1000_READ_REG(hw, E1000_COLC);
-       temp = E1000_READ_REG(hw, E1000_DC);
-       temp = E1000_READ_REG(hw, E1000_SEC);
-       temp = E1000_READ_REG(hw, E1000_RLEC);
-       temp = E1000_READ_REG(hw, E1000_XONRXC);
-       temp = E1000_READ_REG(hw, E1000_XONTXC);
-       temp = E1000_READ_REG(hw, E1000_XOFFRXC);
-       temp = E1000_READ_REG(hw, E1000_XOFFTXC);
-       temp = E1000_READ_REG(hw, E1000_FCRUC);
-       temp = E1000_READ_REG(hw, E1000_GPRC);
-       temp = E1000_READ_REG(hw, E1000_BPRC);
-       temp = E1000_READ_REG(hw, E1000_MPRC);
-       temp = E1000_READ_REG(hw, E1000_GPTC);
-       temp = E1000_READ_REG(hw, E1000_GORCL);
-       temp = E1000_READ_REG(hw, E1000_GORCH);
-       temp = E1000_READ_REG(hw, E1000_GOTCL);
-       temp = E1000_READ_REG(hw, E1000_GOTCH);
-       temp = E1000_READ_REG(hw, E1000_RNBC);
-       temp = E1000_READ_REG(hw, E1000_RUC);
-       temp = E1000_READ_REG(hw, E1000_RFC);
-       temp = E1000_READ_REG(hw, E1000_ROC);
-       temp = E1000_READ_REG(hw, E1000_RJC);
-       temp = E1000_READ_REG(hw, E1000_TORL);
-       temp = E1000_READ_REG(hw, E1000_TORH);
-       temp = E1000_READ_REG(hw, E1000_TOTL);
-       temp = E1000_READ_REG(hw, E1000_TOTH);
-       temp = E1000_READ_REG(hw, E1000_TPR);
-       temp = E1000_READ_REG(hw, E1000_TPT);
-       temp = E1000_READ_REG(hw, E1000_MPTC);
-       temp = E1000_READ_REG(hw, E1000_BPTC);
+       E1000_READ_REG(hw, E1000_CRCERRS);
+       E1000_READ_REG(hw, E1000_SYMERRS);
+       E1000_READ_REG(hw, E1000_MPC);
+       E1000_READ_REG(hw, E1000_SCC);
+       E1000_READ_REG(hw, E1000_ECOL);
+       E1000_READ_REG(hw, E1000_MCC);
+       E1000_READ_REG(hw, E1000_LATECOL);
+       E1000_READ_REG(hw, E1000_COLC);
+       E1000_READ_REG(hw, E1000_DC);
+       E1000_READ_REG(hw, E1000_SEC);
+       E1000_READ_REG(hw, E1000_RLEC);
+       E1000_READ_REG(hw, E1000_XONRXC);
+       E1000_READ_REG(hw, E1000_XONTXC);
+       E1000_READ_REG(hw, E1000_XOFFRXC);
+       E1000_READ_REG(hw, E1000_XOFFTXC);
+       E1000_READ_REG(hw, E1000_FCRUC);
+       E1000_READ_REG(hw, E1000_GPRC);
+       E1000_READ_REG(hw, E1000_BPRC);
+       E1000_READ_REG(hw, E1000_MPRC);
+       E1000_READ_REG(hw, E1000_GPTC);
+       E1000_READ_REG(hw, E1000_GORCL);
+       E1000_READ_REG(hw, E1000_GORCH);
+       E1000_READ_REG(hw, E1000_GOTCL);
+       E1000_READ_REG(hw, E1000_GOTCH);
+       E1000_READ_REG(hw, E1000_RNBC);
+       E1000_READ_REG(hw, E1000_RUC);
+       E1000_READ_REG(hw, E1000_RFC);
+       E1000_READ_REG(hw, E1000_ROC);
+       E1000_READ_REG(hw, E1000_RJC);
+       E1000_READ_REG(hw, E1000_TORL);
+       E1000_READ_REG(hw, E1000_TORH);
+       E1000_READ_REG(hw, E1000_TOTL);
+       E1000_READ_REG(hw, E1000_TOTH);
+       E1000_READ_REG(hw, E1000_TPR);
+       E1000_READ_REG(hw, E1000_TPT);
+       E1000_READ_REG(hw, E1000_MPTC);
+       E1000_READ_REG(hw, E1000_BPTC);
 }
 
 /**
@@ -517,16 +730,16 @@
  *  change in link status has been detected, then we read the PHY registers
  *  to get the current speed/duplex if link exists.
  **/
-s32
-e1000_check_for_copper_link_generic(struct e1000_hw *hw)
+s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_check_for_copper_link");
 
-       /* We only want to go out to the PHY registers to see if Auto-Neg
+       /*
+        * We only want to go out to the PHY registers to see if Auto-Neg
         * has completed and/or if our link status has changed.  The
         * get_link_status flag is set upon receiving a Link Status
         * Change or Rx Sequence Error interrupt.
@@ -536,7 +749,8 @@
                goto out;
        }
 
-       /* First we want to see if the MII Status Register reports
+       /*
+        * First we want to see if the MII Status Register reports
         * link.  If so, then we want to get the current speed/duplex
         * of the PHY.
         */
@@ -549,11 +763,14 @@
 
        mac->get_link_status = FALSE;
 
-       /* Check if there was DownShift, must be checked
-        * immediately after link-up */
+       /*
+        * Check if there was DownShift, must be checked
+        * immediately after link-up
+        */
        e1000_check_downshift_generic(hw);
 
-       /* If we are forcing speed/duplex, then we simply return since
+       /*
+        * If we are forcing speed/duplex, then we simply return since
         * we have already determined whether we have link or not.
         */
        if (!mac->autoneg) {
@@ -561,21 +778,22 @@
                goto out;
        }
 
-       /* Auto-Neg is enabled.  Auto Speed Detection takes care
+       /*
+        * Auto-Neg is enabled.  Auto Speed Detection takes care
         * of MAC speed/duplex configuration.  So we only need to
         * configure Collision Distance in the MAC.
         */
        e1000_config_collision_dist_generic(hw);
 
-       /* Configure Flow Control now that Auto-Neg has completed.
+       /*
+        * Configure Flow Control now that Auto-Neg has completed.
         * First, we need to restore the desired flow control
         * settings because we may have had to re-autoneg with a
         * different link partner.
         */
        ret_val = e1000_config_fc_after_link_up_generic(hw);
-       if (ret_val) {
+       if (ret_val)
                DEBUGOUT("Error configuring flow control\n");
-       }
 
 out:
        return ret_val;
@@ -588,8 +806,7 @@
  *  Checks for link up on the hardware.  If link is not up and we have
  *  a signal, then we need to force link up.
  **/
-s32
-e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
+s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 rxcw;
@@ -603,7 +820,8 @@
        status = E1000_READ_REG(hw, E1000_STATUS);
        rxcw = E1000_READ_REG(hw, E1000_RXCW);
 
-       /* If we don't have link (auto-negotiation failed or link partner
+       /*
+        * If we don't have link (auto-negotiation failed or link partner
         * cannot auto-negotiate), the cable is plugged in (we have signal),
         * and our link partner is not trying to auto-negotiate with us (we
         * are receiving idles or data), we need to force link up. We also
@@ -634,7 +852,8 @@
                        goto out;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-               /* If we are forcing link and we are receiving /C/ ordered
+               /*
+                * If we are forcing link and we are receiving /C/ ordered
                 * sets, re-enable auto-negotiation in the TXCW register
                 * and disable forced link in the Device Control register
                 * in an attempt to auto-negotiate with our link partner.
@@ -657,8 +876,7 @@
  *  Checks for link up on the hardware.  If link is not up and we have
  *  a signal, then we need to force link up.
  **/
-s32
-e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
+s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 rxcw;
@@ -672,7 +890,8 @@
        status = E1000_READ_REG(hw, E1000_STATUS);
        rxcw = E1000_READ_REG(hw, E1000_RXCW);
 
-       /* If we don't have link (auto-negotiation failed or link partner
+       /*
+        * If we don't have link (auto-negotiation failed or link partner
         * cannot auto-negotiate), and our link partner is not trying to
         * auto-negotiate with us (we are receiving idles or data),
         * we need to force link up. We also need to give auto-negotiation
@@ -701,7 +920,8 @@
                        goto out;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-               /* If we are forcing link and we are receiving /C/ ordered
+               /*
+                * If we are forcing link and we are receiving /C/ ordered
                 * sets, re-enable auto-negotiation in the TXCW register
                 * and disable forced link in the Device Control register
                 * in an attempt to auto-negotiate with our link partner.
@@ -712,28 +932,49 @@
 
                mac->serdes_has_link = TRUE;
        } else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) {
-               /* If we force link for non-auto-negotiation switch, check
+               /*
+                * If we force link for non-auto-negotiation switch, check
                 * link status based on MAC synchronization for internal
                 * serdes media type.
                 */
                /* SYNCH bit and IV bit are sticky. */
                usec_delay(10);
-               if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, E1000_RXCW)) {
+               rxcw = E1000_READ_REG(hw, E1000_RXCW);
+               if (rxcw & E1000_RXCW_SYNCH) {
                        if (!(rxcw & E1000_RXCW_IV)) {
                                mac->serdes_has_link = TRUE;
-                               DEBUGOUT("SERDES: Link is up.\n");
+                               DEBUGOUT("SERDES: Link up - forced.\n");
                        }
                } else {
                        mac->serdes_has_link = FALSE;
-                       DEBUGOUT("SERDES: Link is down.\n");
+                       DEBUGOUT("SERDES: Link down - force failed.\n");
                }
        }
 
        if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) {
                status = E1000_READ_REG(hw, E1000_STATUS);
-               mac->serdes_has_link = (status & E1000_STATUS_LU)
-                                       ? TRUE
-                                       : FALSE;
+               if (status & E1000_STATUS_LU) {
+                       /* SYNCH bit and IV bit are sticky, so reread rxcw. */
+                       usec_delay(10);
+                       rxcw = E1000_READ_REG(hw, E1000_RXCW);
+                       if (rxcw & E1000_RXCW_SYNCH) {
+                               if (!(rxcw & E1000_RXCW_IV)) {
+                                       mac->serdes_has_link = TRUE;
+                                       DEBUGOUT("SERDES: Link up - autoneg "
+                                          "completed sucessfully.\n");
+                               } else {
+                                       mac->serdes_has_link = FALSE;
+                                       DEBUGOUT("SERDES: Link down - invalid"
+                                          "codewords detected in autoneg.\n");
+                               }
+                       } else {
+                               mac->serdes_has_link = FALSE;
+                               DEBUGOUT("SERDES: Link down - no sync.\n");
+                       }
+               } else {
+                       mac->serdes_has_link = FALSE;
+                       DEBUGOUT("SERDES: Link down - autoneg failed\n");
+               }
        }
 
 out:
@@ -750,39 +991,46 @@
  *  should be established.  Assumes the hardware has previously been reset
  *  and the transmitter and receiver are not enabled.
  **/
-s32
-e1000_setup_link_generic(struct e1000_hw *hw)
+s32 e1000_setup_link_generic(struct e1000_hw *hw)
 {
-       struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_setup_link_generic");
 
-       /* In the case of the phy reset being blocked, we already have a link.
+       /*
+        * In the case of the phy reset being blocked, we already have a link.
         * We do not need to set it up again.
         */
-       if (e1000_check_reset_block(hw))
-               goto out;
+       if (hw->phy.ops.check_reset_block)
+               if (hw->phy.ops.check_reset_block(hw))
+                       goto out;
 
-       ret_val = e1000_set_default_fc_generic(hw);
-       if (ret_val)
-               goto out;
+       /*
+        * If requested flow control is set to default, set flow control
+        * based on the EEPROM flow control settings.
+        */
+       if (hw->fc.requested_mode == e1000_fc_default) {
+               ret_val = e1000_set_default_fc_generic(hw);
+               if (ret_val)
+                       goto out;
+       }
 
-       /* We want to save off the original Flow Control configuration just
-        * in case we get disconnected and then reconnected into a different
-        * hub or switch with different Flow Control capabilities.
+       /*
+        * Save off the requested flow control mode for use later.  Depending
+        * on the link partner's capabilities, we may or may not use this mode.
         */
-       mac->original_fc = mac->fc;
+       hw->fc.current_mode = hw->fc.requested_mode;
 
-       DEBUGOUT1("After fix-ups FlowControl is now = %x\n", mac->fc);
+       DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
+                                                    hw->fc.current_mode);
 
        /* Call the necessary media_type subroutine to configure the link. */
-       ret_val = func->setup_physical_interface(hw);
+       ret_val = hw->mac.ops.setup_physical_interface(hw);
        if (ret_val)
                goto out;
 
-       /* Initialize the flow control address, type, and PAUSE timer
+       /*
+        * Initialize the flow control address, type, and PAUSE timer
         * registers to their default values.  This is done even if flow
         * control is disabled, because it does not hurt anything to
         * initialize these registers.
@@ -792,7 +1040,7 @@
        E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH);
        E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW);
 
-       E1000_WRITE_REG(hw, E1000_FCTTV, mac->fc_pause_time);
+       E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
 
        ret_val = e1000_set_fc_watermarks_generic(hw);
 
@@ -807,8 +1055,7 @@
  *  Configures collision distance and flow control for fiber and serdes
  *  links.  Upon successful setup, poll for link.
  **/
-s32
-e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw)
+s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32 ret_val = E1000_SUCCESS;
@@ -826,7 +1073,8 @@
        if (ret_val)
                goto out;
 
-       /* Since auto-negotiation is enabled, take the link out of reset (the
+       /*
+        * Since auto-negotiation is enabled, take the link out of reset (the
         * link will be in reset, because we previously reset the chip). This
         * will restart auto-negotiation.  If auto-negotiation is successful
         * then the link-up status bit will be set and the flow control enable
@@ -838,11 +1086,12 @@
        E1000_WRITE_FLUSH(hw);
        msec_delay(1);
 
-       /* For these adapters, the SW defineable pin 1 is set when the optics
+       /*
+        * For these adapters, the SW definable pin 1 is set when the optics
         * detect a signal.  If we have a signal, then poll for a "Link-Up"
         * indication.
         */
-       if (hw->media_type == e1000_media_type_internal_serdes ||
+       if (hw->phy.media_type == e1000_media_type_internal_serdes ||
            (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
                ret_val = e1000_poll_fiber_serdes_link_generic(hw);
        } else {
@@ -861,8 +1110,7 @@
  *  during link setup. Currently no func pointer exists and all
  *  implementations are handled in the generic version of this function.
  **/
-void
-e1000_config_collision_dist_generic(struct e1000_hw *hw)
+void e1000_config_collision_dist_generic(struct e1000_hw *hw)
 {
        u32 tctl;
 
@@ -884,8 +1132,7 @@
  *  Polls for link up by reading the status register, if link fails to come
  *  up with auto-negotiation, then the link is forced if a signal is detected.
  **/
-s32
-e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
+s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 i, status;
@@ -893,7 +1140,8 @@
 
        DEBUGFUNC("e1000_poll_fiber_serdes_link_generic");
 
-       /* If we have a signal (the cable is plugged in, or assumed true for
+       /*
+        * If we have a signal (the cable is plugged in, or assumed TRUE for
         * serdes media) then poll for a "Link-Up" indication in the Device
         * Status Register.  Time-out if a link isn't seen in 500 milliseconds
         * seconds (Auto-negotiation should complete in less than 500
@@ -908,12 +1156,13 @@
        if (i == FIBER_LINK_UP_LIMIT) {
                DEBUGOUT("Never got a valid link from auto-neg!!!\n");
                mac->autoneg_failed = 1;
-               /* AutoNeg failed to achieve a link, so we'll call
+               /*
+                * AutoNeg failed to achieve a link, so we'll call
                 * mac->check_for_link. This routine will force the
                 * link up if we detect a signal. This will allow us to
                 * communicate with non-autonegotiating link partners.
                 */
-               ret_val = e1000_check_for_link(hw);
+               ret_val = hw->mac.ops.check_for_link(hw);
                if (ret_val) {
                        DEBUGOUT("Error while checking for link\n");
                        goto out;
@@ -935,8 +1184,7 @@
  *  Write the flow control settings to the Transmit Config Word Register (TXCW)
  *  base on the flow control settings in e1000_mac_info.
  **/
-s32
-e1000_commit_fc_settings_generic(struct e1000_hw *hw)
+s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 txcw;
@@ -944,7 +1192,8 @@
 
        DEBUGFUNC("e1000_commit_fc_settings_generic");
 
-       /* Check for a software override of the flow control settings, and
+       /*
+        * Check for a software override of the flow control settings, and
         * setup the device accordingly.  If auto-negotiation is enabled, then
         * software will have to set the "PAUSE" bits to the correct value in
         * the Transmit Config Word Register (TXCW) and re-start auto-
@@ -958,17 +1207,18 @@
         *          but not send pause frames).
         *      2:  Tx flow control is enabled (we can send pause frames but we
         *          do not support receiving pause frames).
-        *      3:  Both Rx and TX flow control (symmetric) are enabled.
+        *      3:  Both Rx and Tx flow control (symmetric) are enabled.
         */
-       switch (mac->fc) {
+       switch (hw->fc.current_mode) {
        case e1000_fc_none:
                /* Flow control completely disabled by a software over-ride. */
                txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
                break;
        case e1000_fc_rx_pause:
-               /* RX Flow control is enabled and TX Flow control is disabled
+               /*
+                * Rx Flow control is enabled and Tx Flow control is disabled
                 * by a software over-ride. Since there really isn't a way to
-                * advertise that we are capable of RX Pause ONLY, we will
+                * advertise that we are capable of Rx Pause ONLY, we will
                 * advertise that we support both symmetric and asymmetric RX
                 * PAUSE.  Later, we will disable the adapter's ability to send
                 * PAUSE frames.
@@ -976,13 +1226,15 @@
                txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
                break;
        case e1000_fc_tx_pause:
-               /* TX Flow control is enabled, and RX Flow control is disabled,
+               /*
+                * Tx Flow control is enabled, and Rx Flow control is disabled,
                 * by a software over-ride.
                 */
                txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
                break;
        case e1000_fc_full:
-               /* Flow control (both RX and TX) is enabled by a software
+               /*
+                * Flow control (both Rx and Tx) is enabled by a software
                 * over-ride.
                 */
                txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
@@ -1007,33 +1259,33 @@
  *
  *  Sets the flow control high/low threshold (watermark) registers.  If
  *  flow control XON frame transmission is enabled, then set XON frame
- *  tansmission as well.
+ *  transmission as well.
  **/
-s32
-e1000_set_fc_watermarks_generic(struct e1000_hw *hw)
+s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw)
 {
-       struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val = E1000_SUCCESS;
        u32 fcrtl = 0, fcrth = 0;
 
        DEBUGFUNC("e1000_set_fc_watermarks_generic");
 
-       /* Set the flow control receive threshold registers.  Normally,
+       /*
+        * Set the flow control receive threshold registers.  Normally,
         * these registers will be set to a default threshold that may be
         * adjusted later by the driver's runtime code.  However, if the
         * ability to transmit pause frames is not enabled, then these
         * registers will be set to 0.
         */
-       if (mac->fc & e1000_fc_tx_pause) {
-               /* We need to set up the Receive Threshold high and low water
+       if (hw->fc.current_mode & e1000_fc_tx_pause) {
+               /*
+                * We need to set up the Receive Threshold high and low water
                 * marks as well as (optionally) enabling the transmission of
                 * XON frames.
                 */
-               fcrtl = mac->fc_low_water;
-               if (mac->fc_send_xon)
+               fcrtl = hw->fc.low_water;
+               if (hw->fc.send_xon)
                        fcrtl |= E1000_FCRTL_XONE;
 
-               fcrth = mac->fc_high_water;
+               fcrth = hw->fc.high_water;
        }
        E1000_WRITE_REG(hw, E1000_FCRTL, fcrtl);
        E1000_WRITE_REG(hw, E1000_FCRTH, fcrth);
@@ -1048,19 +1300,15 @@
  *  Read the EEPROM for the default values for flow control and store the
  *  values.
  **/
-s32
-e1000_set_default_fc_generic(struct e1000_hw *hw)
+s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
 {
-       struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val = E1000_SUCCESS;
        u16 nvm_data;
 
        DEBUGFUNC("e1000_set_default_fc_generic");
 
-       if (mac->fc != e1000_fc_default)
-               goto out;
-
-       /* Read and store word 0x0F of the EEPROM. This word contains bits
+       /*
+        * Read and store word 0x0F of the EEPROM. This word contains bits
         * that determine the hardware's default PAUSE (flow control) mode,
         * a bit that determines whether the HW defaults to enabling or
         * disabling auto-negotiation, and the direction of the
@@ -1068,7 +1316,7 @@
         * control setting, then the variable hw->fc will
         * be initialized based on a value in the EEPROM.
         */
-       ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
+       ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
 
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
@@ -1076,12 +1324,12 @@
        }
 
        if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
-               mac->fc = e1000_fc_none;
+               hw->fc.requested_mode = e1000_fc_none;
        else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
                 NVM_WORD0F_ASM_DIR)
-               mac->fc = e1000_fc_tx_pause;
+               hw->fc.requested_mode = e1000_fc_tx_pause;
        else
-               mac->fc = e1000_fc_full;
+               hw->fc.requested_mode = e1000_fc_full;
 
 out:
        return ret_val;
@@ -1097,10 +1345,8 @@
  *  autonegotiation is managed by the PHY rather than the MAC.  Software must
  *  also configure these bits when link is forced on a fiber connection.
  **/
-s32
-e1000_force_mac_fc_generic(struct e1000_hw *hw)
+s32 e1000_force_mac_fc_generic(struct e1000_hw *hw)
 {
-       struct e1000_mac_info *mac = &hw->mac;
        u32 ctrl;
        s32 ret_val = E1000_SUCCESS;
 
@@ -1108,13 +1354,14 @@
 
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
 
-       /* Because we didn't get link via the internal auto-negotiation
+       /*
+        * Because we didn't get link via the internal auto-negotiation
         * mechanism (we either forced link or we got link via PHY
         * auto-neg), we have to manually enable/disable transmit an
         * receive flow control.
         *
         * The "Case" statement below enables/disable flow control
-        * according to the "mac->fc" parameter.
+        * according to the "hw->fc.current_mode" parameter.
         *
         * The possible values of the "fc" parameter are:
         *      0:  Flow control is completely disabled
@@ -1122,12 +1369,12 @@
         *          frames but not send pause frames).
         *      2:  Tx flow control is enabled (we can send pause frames
         *          frames but we do not receive pause frames).
-        *      3:  Both Rx and TX flow control (symmetric) is enabled.
+        *      3:  Both Rx and Tx flow control (symmetric) is enabled.
         *  other:  No other values should be possible at this point.
         */
-       DEBUGOUT1("mac->fc = %u\n", mac->fc);
+       DEBUGOUT1("hw->fc.current_mode = %u\n", hw->fc.current_mode);
 
-       switch (mac->fc) {
+       switch (hw->fc.current_mode) {
        case e1000_fc_none:
                ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
                break;
@@ -1164,8 +1411,7 @@
  *  and did not fail, then we configure flow control based on our link
  *  partner.
  **/
-s32
-e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
+s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val = E1000_SUCCESS;
@@ -1174,16 +1420,17 @@
 
        DEBUGFUNC("e1000_config_fc_after_link_up_generic");
 
-       /* Check for the case where we have fiber media and auto-neg failed
+       /*
+        * Check for the case where we have fiber media and auto-neg failed
         * so we had to force link.  In this case, we need to force the
         * configuration of the MAC to match the "fc" parameter.
         */
        if (mac->autoneg_failed) {
-               if (hw->media_type == e1000_media_type_fiber ||
-                   hw->media_type == e1000_media_type_internal_serdes)
+               if (hw->phy.media_type == e1000_media_type_fiber ||
+                   hw->phy.media_type == e1000_media_type_internal_serdes)
                        ret_val = e1000_force_mac_fc_generic(hw);
        } else {
-               if (hw->media_type == e1000_media_type_copper)
+               if (hw->phy.media_type == e1000_media_type_copper)
                        ret_val = e1000_force_mac_fc_generic(hw);
        }
 
@@ -1192,20 +1439,22 @@
                goto out;
        }
 
-       /* Check for the case where we have copper media and auto-neg is
+       /*
+        * Check for the case where we have copper media and auto-neg is
         * enabled.  In this case, we need to check and see if Auto-Neg
         * has completed, and if so, how the PHY and link partner has
         * flow control configured.
         */
-       if ((hw->media_type == e1000_media_type_copper) && mac->autoneg) {
-               /* Read the MII Status Register and check to see if AutoNeg
+       if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
+               /*
+                * Read the MII Status Register and check to see if AutoNeg
                 * has completed.  We read this twice because this reg has
                 * some "sticky" (latched) bits.
                 */
-               ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
                if (ret_val)
                        goto out;
-               ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
                if (ret_val)
                        goto out;
 
@@ -1215,22 +1464,24 @@
                        goto out;
                }
 
-               /* The AutoNeg process has completed, so we now need to
+               /*
+                * The AutoNeg process has completed, so we now need to
                 * read both the Auto Negotiation Advertisement
                 * Register (Address 4) and the Auto_Negotiation Base
                 * Page Ability Register (Address 5) to determine how
                 * flow control was negotiated.
                 */
-               ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
-                                           &mii_nway_adv_reg);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
+                                            &mii_nway_adv_reg);
                if (ret_val)
                        goto out;
-               ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
-                                           &mii_nway_lp_ability_reg);
+               ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
+                                            &mii_nway_lp_ability_reg);
                if (ret_val)
                        goto out;
 
-               /* Two bits in the Auto Negotiation Advertisement Register
+               /*
+                * Two bits in the Auto Negotiation Advertisement Register
                 * (Address 4) and two bits in the Auto Negotiation Base
                 * Page Ability Register (Address 5) determine flow control
                 * for both the PHY and the link partner.  The following
@@ -1251,8 +1502,7 @@
                 *   1   |    1    |   0   |    0    | e1000_fc_none
                 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
                 *
-                */
-               /* Are both PAUSE bits set to 1?  If so, this implies
+                * Are both PAUSE bits set to 1?  If so, this implies
                 * Symmetric Flow Control is enabled at both ends.  The
                 * ASM_DIR bits are irrelevant per the spec.
                 *
@@ -1266,95 +1516,76 @@
                 */
                if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
                    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
-                       /* Now we need to check if the user selected RX ONLY
+                       /*
+                        * Now we need to check if the user selected Rx ONLY
                         * of pause frames.  In this case, we had to advertise
                         * FULL flow control because we could not advertise RX
                         * ONLY. Hence, we must now check to see if we need to
                         * turn OFF  the TRANSMISSION of PAUSE frames.
                         */
-                       if (mac->original_fc == e1000_fc_full) {
-                               mac->fc = e1000_fc_full;
+                       if (hw->fc.requested_mode == e1000_fc_full) {
+                               hw->fc.current_mode = e1000_fc_full;
                                DEBUGOUT("Flow Control = FULL.\r\n");
                        } else {
-                               mac->fc = e1000_fc_rx_pause;
+                               hw->fc.current_mode = e1000_fc_rx_pause;
                                DEBUGOUT("Flow Control = "
                                         "RX PAUSE frames only.\r\n");
                        }
                }
-               /* For receiving PAUSE frames ONLY.
+               /*
+                * For receiving PAUSE frames ONLY.
                 *
                 *   LOCAL DEVICE  |   LINK PARTNER
                 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
                 *-------|---------|-------|---------|--------------------
                 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
-                *
                 */
                else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
                          (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
                          (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                          (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
-                       mac->fc = e1000_fc_tx_pause;
+                       hw->fc.current_mode = e1000_fc_tx_pause;
                        DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
                }
-               /* For transmitting PAUSE frames ONLY.
+               /*
+                * For transmitting PAUSE frames ONLY.
                 *
                 *   LOCAL DEVICE  |   LINK PARTNER
                 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
                 *-------|---------|-------|---------|--------------------
                 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
-                *
                 */
                else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
                         (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
                         !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                         (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
-                       mac->fc = e1000_fc_rx_pause;
+                       hw->fc.current_mode = e1000_fc_rx_pause;
                        DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
-               }
-               /* Per the IEEE spec, at this point flow control should be
-                * disabled.  However, we want to consider that we could
-                * be connected to a legacy switch that doesn't advertise
-                * desired flow control, but can be forced on the link
-                * partner.  So if we advertised no flow control, that is
-                * what we will resolve to.  If we advertised some kind of
-                * receive capability (Rx Pause Only or Full Flow Control)
-                * and the link partner advertised none, we will configure
-                * ourselves to enable Rx Flow Control only.  We can do
-                * this safely for two reasons:  If the link partner really
-                * didn't want flow control enabled, and we enable Rx, no
-                * harm done since we won't be receiving any PAUSE frames
-                * anyway.  If the intent on the link partner was to have
-                * flow control enabled, then by us enabling RX only, we
-                * can at least receive pause frames and process them.
-                * This is a good idea because in most cases, since we are
-                * predominantly a server NIC, more times than not we will
-                * be asked to delay transmission of packets than asking
-                * our link partner to pause transmission of frames.
-                */
-               else if ((mac->original_fc == e1000_fc_none ||
-                         mac->original_fc == e1000_fc_tx_pause) ||
-                        mac->fc_strict_ieee) {
-                       mac->fc = e1000_fc_none;
+               } else {
+                       /*
+                        * Per the IEEE spec, at this point flow control
+                        * should be disabled.
+                        */
+                       hw->fc.current_mode = e1000_fc_none;
                        DEBUGOUT("Flow Control = NONE.\r\n");
-               } else {
-                       mac->fc = e1000_fc_rx_pause;
-                       DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
                }
 
-               /* Now we need to do one last check...  If we auto-
+               /*
+                * Now we need to do one last check...  If we auto-
                 * negotiated to HALF DUPLEX, flow control should not be
                 * enabled per IEEE 802.3 spec.
                 */
-               ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+               ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
                if (ret_val) {
                        DEBUGOUT("Error getting link speed and duplex\n");
                        goto out;
                }
 
                if (duplex == HALF_DUPLEX)
-                       mac->fc = e1000_fc_none;
+                       hw->fc.current_mode = e1000_fc_none;
 
-               /* Now we call a subroutine to actually force the MAC
+               /*
+                * Now we call a subroutine to actually force the MAC
                 * controller to use the correct flow control settings.
                 */
                ret_val = e1000_force_mac_fc_generic(hw);
@@ -1369,7 +1600,7 @@
 }
 
 /**
- *  e1000_get_speed_and_duplex_copper_generic - Retreive current speed/duplex
+ *  e1000_get_speed_and_duplex_copper_generic - Retrieve current speed/duplex
  *  @hw: pointer to the HW structure
  *  @speed: stores the current speed
  *  @duplex: stores the current duplex
@@ -1377,9 +1608,8 @@
  *  Read the status register for the current speed/duplex and store the current
  *  speed and duplex for copper connections.
  **/
-s32
-e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
-                                          u16 *duplex)
+s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
+                                              u16 *duplex)
 {
        u32 status;
 
@@ -1409,7 +1639,7 @@
 }
 
 /**
- *  e1000_get_speed_and_duplex_fiber_generic - Retreive current speed/duplex
+ *  e1000_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex
  *  @hw: pointer to the HW structure
  *  @speed: stores the current speed
  *  @duplex: stores the current duplex
@@ -1417,9 +1647,8 @@
  *  Sets the speed and duplex to gigabit full duplex (the only possible option)
  *  for fiber/serdes links.
  **/
-s32
-e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, u16 
*speed,
-                                                u16 *duplex)
+s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
+                                                    u16 *speed, u16 *duplex)
 {
        DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic");
 
@@ -1435,8 +1664,7 @@
  *
  *  Acquire the HW semaphore to access the PHY or NVM
  **/
-s32
-e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
+s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
 {
        u32 swsm;
        s32 ret_val = E1000_SUCCESS;
@@ -1491,8 +1719,7 @@
  *
  *  Release hardware semaphore used to access the PHY or NVM
  **/
-void
-e1000_put_hw_semaphore_generic(struct e1000_hw *hw)
+void e1000_put_hw_semaphore_generic(struct e1000_hw *hw)
 {
        u32 swsm;
 
@@ -1511,8 +1738,7 @@
  *
  *  Check EEPROM for Auto Read done bit.
  **/
-s32
-e1000_get_auto_rd_done_generic(struct e1000_hw *hw)
+s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw)
 {
        s32 i = 0;
        s32 ret_val = E1000_SUCCESS;
@@ -1544,14 +1770,13 @@
  *  Read the EEPROM for the current default LED configuration.  If the
  *  LED configuration is not valid, set to a valid LED configuration.
  **/
-s32
-e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data)
+s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data)
 {
        s32 ret_val;
 
        DEBUGFUNC("e1000_valid_led_default_generic");
 
-       ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
+       ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
                goto out;
@@ -1569,8 +1794,7 @@
  *  @hw: pointer to the HW structure
  *
  **/
-s32
-e1000_id_led_init_generic(struct e1000_hw * hw)
+s32 e1000_id_led_init_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val;
@@ -1582,7 +1806,7 @@
 
        DEBUGFUNC("e1000_id_led_init_generic");
 
-       ret_val = hw->func.valid_led_default(hw, &data);
+       ret_val = hw->nvm.ops.valid_led_default(hw, &data);
        if (ret_val)
                goto out;
 
@@ -1639,20 +1863,19 @@
  *  This prepares the SW controllable LED for use and saves the current state
  *  of the LED so it can be later restored.
  **/
-s32
-e1000_setup_led_generic(struct e1000_hw *hw)
+s32 e1000_setup_led_generic(struct e1000_hw *hw)
 {
        u32 ledctl;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_setup_led_generic");
 
-       if (hw->func.setup_led != e1000_setup_led_generic) {
+       if (hw->mac.ops.setup_led != e1000_setup_led_generic) {
                ret_val = -E1000_ERR_CONFIG;
                goto out;
        }
 
-       if (hw->media_type == e1000_media_type_fiber) {
+       if (hw->phy.media_type == e1000_media_type_fiber) {
                ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
                hw->mac.ledctl_default = ledctl;
                /* Turn off LED0 */
@@ -1662,7 +1885,7 @@
                ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
                           E1000_LEDCTL_LED0_MODE_SHIFT);
                E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
-       } else if (hw->media_type == e1000_media_type_copper) {
+       } else if (hw->phy.media_type == e1000_media_type_copper) {
                E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
        }
 
@@ -1677,14 +1900,13 @@
  *  Remove the current LED configuration and set the LED configuration
  *  to the default value, saved from the EEPROM.
  **/
-s32
-e1000_cleanup_led_generic(struct e1000_hw *hw)
+s32 e1000_cleanup_led_generic(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_cleanup_led_generic");
 
-       if (hw->func.cleanup_led != e1000_cleanup_led_generic) {
+       if (hw->mac.ops.cleanup_led != e1000_cleanup_led_generic) {
                ret_val = -E1000_ERR_CONFIG;
                goto out;
        }
@@ -1699,23 +1921,24 @@
  *  e1000_blink_led_generic - Blink LED
  *  @hw: pointer to the HW structure
  *
- *  Blink the led's which are set to be on.
+ *  Blink the LEDs which are set to be on.
  **/
-s32
-e1000_blink_led_generic(struct e1000_hw *hw)
+s32 e1000_blink_led_generic(struct e1000_hw *hw)
 {
        u32 ledctl_blink = 0;
        u32 i;
 
        DEBUGFUNC("e1000_blink_led_generic");
 
-       if (hw->media_type == e1000_media_type_fiber) {
+       if (hw->phy.media_type == e1000_media_type_fiber) {
                /* always blink LED0 for PCI-E fiber */
                ledctl_blink = E1000_LEDCTL_LED0_BLINK |
                     (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
        } else {
-               /* set the blink bit for each LED that's "on" (0x0E)
-                * in ledctl_mode2 */
+               /*
+                * set the blink bit for each LED that's "on" (0x0E)
+                * in ledctl_mode2
+                */
                ledctl_blink = hw->mac.ledctl_mode2;
                for (i = 0; i < 4; i++)
                        if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
@@ -1735,14 +1958,13 @@
  *
  *  Turn LED on.
  **/
-s32
-e1000_led_on_generic(struct e1000_hw *hw)
+s32 e1000_led_on_generic(struct e1000_hw *hw)
 {
        u32 ctrl;
 
        DEBUGFUNC("e1000_led_on_generic");
 
-       switch (hw->media_type) {
+       switch (hw->phy.media_type) {
        case e1000_media_type_fiber:
                ctrl = E1000_READ_REG(hw, E1000_CTRL);
                ctrl &= ~E1000_CTRL_SWDPIN0;
@@ -1765,14 +1987,13 @@
  *
  *  Turn LED off.
  **/
-s32
-e1000_led_off_generic(struct e1000_hw *hw)
+s32 e1000_led_off_generic(struct e1000_hw *hw)
 {
        u32 ctrl;
 
        DEBUGFUNC("e1000_led_off_generic");
 
-       switch (hw->media_type) {
+       switch (hw->phy.media_type) {
        case e1000_media_type_fiber:
                ctrl = E1000_READ_REG(hw, E1000_CTRL);
                ctrl |= E1000_CTRL_SWDPIN0;
@@ -1796,8 +2017,7 @@
  *
  *  Set the PCI-express register to snoop for events enabled in 'no_snoop'.
  **/
-void
-e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop)
+void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop)
 {
        u32 gcr;
 
@@ -1821,14 +2041,13 @@
  *  @hw: pointer to the HW structure
  *
  *  Returns 0 (E1000_SUCCESS) if successful, else returns -10
- *  (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not casued
+ *  (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused
  *  the master requests to be disabled.
  *
  *  Disables PCI-Express master access and verifies there are no pending
  *  requests.
  **/
-s32
-e1000_disable_pcie_master_generic(struct e1000_hw *hw)
+s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32 timeout = MASTER_DISABLE_TIMEOUT;
@@ -1867,8 +2086,7 @@
  *
  *  Reset the Adaptive Interframe Spacing throttle to default values.
  **/
-void
-e1000_reset_adaptive_generic(struct e1000_hw *hw)
+void e1000_reset_adaptive_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
 
@@ -1879,13 +2097,11 @@
                goto out;
        }
 
-       if (!mac->ifs_params_forced) {
-               mac->current_ifs_val = 0;
-               mac->ifs_min_val = IFS_MIN;
-               mac->ifs_max_val = IFS_MAX;
-               mac->ifs_step_size = IFS_STEP;
-               mac->ifs_ratio = IFS_RATIO;
-       }
+       mac->current_ifs_val = 0;
+       mac->ifs_min_val = IFS_MIN;
+       mac->ifs_max_val = IFS_MAX;
+       mac->ifs_step_size = IFS_STEP;
+       mac->ifs_ratio = IFS_RATIO;
 
        mac->in_ifs_mode = FALSE;
        E1000_WRITE_REG(hw, E1000_AIT, 0);
@@ -1900,8 +2116,7 @@
  *  Update the Adaptive Interframe Spacing Throttle value based on the
  *  time between transmitted packets and time between collisions.
  **/
-void
-e1000_update_adaptive_generic(struct e1000_hw *hw)
+void e1000_update_adaptive_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
 
@@ -1940,11 +2155,10 @@
  *  e1000_validate_mdi_setting_generic - Verify MDI/MDIx settings
  *  @hw: pointer to the HW structure
  *
- *  Verify that when not using auto-negotitation that MDI/MDIx is correctly
+ *  Verify that when not using auto-negotiation that MDI/MDIx is correctly
  *  set, which is forced to MDI mode only.
  **/
-s32
-e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
+s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
 
@@ -1972,9 +2186,8 @@
  *  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)
+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;
Index: dev/em/e1000_phy.h
===================================================================
--- dev/em/e1000_phy.h  (Revision 28889)
+++ dev/em/e1000_phy.h  (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/*****************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,32 +29,22 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_phy.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_phy.h,v 1.2 2008/11/26 23:57:23 jfv Exp $*/
 
-
 #ifndef _E1000_PHY_H_
 #define _E1000_PHY_H_
 
-typedef enum {
-       e1000_ms_hw_default = 0,
-       e1000_ms_force_master,
-       e1000_ms_force_slave,
-       e1000_ms_auto
-} e1000_ms_type;
-
-typedef enum {
-       e1000_smart_speed_default = 0,
-       e1000_smart_speed_on,
-       e1000_smart_speed_off
-} e1000_smart_speed;
-
+void e1000_init_phy_ops_generic(struct e1000_hw *hw);
+s32  e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+void e1000_null_phy_generic(struct e1000_hw *hw);
+s32  e1000_null_lplu_state(struct e1000_hw *hw, bool active);
+s32  e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data);
 s32  e1000_check_downshift_generic(struct e1000_hw *hw);
 s32  e1000_check_polarity_m88(struct e1000_hw *hw);
 s32  e1000_check_polarity_igp(struct e1000_hw *hw);
 s32  e1000_check_reset_block_generic(struct e1000_hw *hw);
 s32  e1000_copper_link_autoneg(struct e1000_hw *hw);
-s32  e1000_phy_force_speed_duplex(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_phy_force_speed_duplex_igp(struct e1000_hw *hw);
@@ -73,7 +63,7 @@
 s32  e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
-s32  e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, boolean_t active);
+s32  e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active);
 s32  e1000_setup_copper_link_generic(struct e1000_hw *hw);
 s32  e1000_wait_autoneg_generic(struct e1000_hw *hw);
 s32  e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data);
@@ -81,9 +71,19 @@
 s32  e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data);
 s32  e1000_phy_reset_dsp(struct e1000_hw *hw);
 s32  e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
-                                u32 usec_interval, boolean_t *success);
+                                u32 usec_interval, bool *success);
 s32  e1000_phy_init_script_igp3(struct e1000_hw *hw);
-e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id);
+enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id);
+s32 e1000_determine_phy_address(struct e1000_hw *hw);
+s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
+void e1000_power_up_phy_copper(struct e1000_hw *hw);
+void e1000_power_down_phy_copper(struct e1000_hw *hw);
+s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
+
 #define E1000_MAX_PHY_ADDR                4
 
 /* IGP01E1000 Specific Registers */
@@ -95,18 +95,26 @@
 #define IGP01E1000_PHY_CHANNEL_QUALITY    0x15 /* PHY Channel Quality */
 #define IGP02E1000_PHY_POWER_MGMT         0x19 /* Power Management */
 #define IGP01E1000_PHY_PAGE_SELECT        0x1F /* Page Select */
-#define IGP4_PHY_PAGE_SELECT              22   /* Page Select for IGP 4 */
+#define BM_PHY_PAGE_SELECT                22   /* Page Select for BM */
 #define IGP_PAGE_SHIFT                    5
 #define PHY_REG_MASK                      0x1F
 
-#define IGP4_WUC_PAGE                     800
-#define IGP4_WUC_ADDRESS_OPCODE           0x11
-#define IGP4_WUC_DATA_OPCODE              0x12
-#define IGP4_WUC_ENABLE_PAGE              769
-#define IGP4_WUC_ENABLE_REG               17
-#define IGP4_WUC_ENABLE_BIT               (1 << 2)
-#define IGP4_WUC_HOST_WU_BIT              (1 << 4)
+#define BM_WUC_PAGE                       800
+#define BM_WUC_ADDRESS_OPCODE             0x11
+#define BM_WUC_DATA_OPCODE                0x12
+#define BM_WUC_ENABLE_PAGE                769
+#define BM_WUC_ENABLE_REG                 17
+#define BM_WUC_ENABLE_BIT                 (1 << 2)
+#define BM_WUC_HOST_WU_BIT                (1 << 4)
 
+/* BM PHY Copper Specific Control 1 */
+#define BM_CS_CTRL1                       16
+#define BM_CS_CTRL1_ENERGY_DETECT         0x0300 /* Enable Energy Detect */
+
+/* BM PHY Copper Specific States */
+#define BM_CS_STATUS                      17
+#define BM_CS_STATUS_ENERGY_DETECT        0x0010 /* Energy Detect Status */
+
 #define IGP01E1000_PHY_PCS_INIT_REG       0x00B4
 #define IGP01E1000_PHY_POLARITY_MASK      0x0078
 
@@ -115,8 +123,8 @@
 
 #define IGP01E1000_PSCFR_SMART_SPEED      0x0080
 
-#define IGP01E1000_GMII_FLEX_SPD          0x0010 /* Enable flexible speed
-                                                  * on link-up */
+/* Enable flexible speed on link-up */
+#define IGP01E1000_GMII_FLEX_SPD          0x0010
 #define IGP01E1000_GMII_SPD               0x0020 /* Enable SPD */
 
 #define IGP02E1000_PM_SPD                 0x0001 /* Smart Power Down */
Index: dev/em/e1000_nvm.h
===================================================================
--- dev/em/e1000_nvm.h  (Revision 28889)
+++ dev/em/e1000_nvm.h  (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,38 +29,40 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_nvm.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_nvm.h,v 1.1 2008/07/30 21:56:53 jfv Exp $*/
 
-
 #ifndef _E1000_NVM_H_
 #define _E1000_NVM_H_
 
+void e1000_init_nvm_ops_generic(struct e1000_hw *hw);
+s32  e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c);
+void e1000_null_nvm_generic(struct e1000_hw *hw);
+s32  e1000_null_led_default(struct e1000_hw *hw, u16 *data);
+s32  e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c);
 s32  e1000_acquire_nvm_generic(struct e1000_hw *hw);
 
 s32  e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
 s32  e1000_read_mac_addr_generic(struct e1000_hw *hw);
-s32  e1000_read_part_num_generic(struct e1000_hw *hw, u32 *part_num);
+s32  e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num);
 s32  e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset,
                               u16 words, u16 *data);
-s32  e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 
*data);
+s32  e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words,
+                         u16 *data);
 s32  e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data);
 s32  e1000_validate_nvm_checksum_generic(struct e1000_hw *hw);
 s32  e1000_write_nvm_eewr(struct e1000_hw *hw, u16 offset,
                           u16 words, u16 *data);
 s32  e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset,
                                u16 words, u16 *data);
-s32  e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 
*data);
+s32  e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words,
+                         u16 *data);
 s32  e1000_update_nvm_checksum_generic(struct e1000_hw *hw);
 void e1000_stop_nvm(struct e1000_hw *hw);
 void e1000_release_nvm_generic(struct e1000_hw *hw);
 void e1000_reload_nvm_generic(struct e1000_hw *hw);
 
-/* Function pointers */
-s32  e1000_acquire_nvm(struct e1000_hw *hw);
-void e1000_release_nvm(struct e1000_hw *hw);
-
 #define E1000_STM_OPCODE  0xDB00
 
 #endif
Index: dev/em/e1000_mac.h
===================================================================
--- dev/em/e1000_mac.h  (Revision 28889)
+++ dev/em/e1000_mac.h  (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,28 +29,41 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_mac.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_mac.h,v 1.2 2008/11/26 23:57:23 jfv Exp $*/
 
-
 #ifndef _E1000_MAC_H_
 #define _E1000_MAC_H_
 
-/* Functions that should not be called directly from drivers but can be used
+/*
+ * Functions that should not be called directly from drivers but can be used
  * by other files in this 'shared code'
  */
+void e1000_init_mac_ops_generic(struct e1000_hw *hw);
+void e1000_null_mac_generic(struct e1000_hw *hw);
+s32  e1000_null_ops_generic(struct e1000_hw *hw);
+s32  e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d);
+bool e1000_null_mng_mode(struct e1000_hw *hw);
+void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a, u32 b, u32 c);
+void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b);
+void e1000_null_mta_set(struct e1000_hw *hw, u32 a);
+void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a);
 s32  e1000_blink_led_generic(struct e1000_hw *hw);
 s32  e1000_check_for_copper_link_generic(struct e1000_hw *hw);
 s32  e1000_check_for_fiber_link_generic(struct e1000_hw *hw);
 s32  e1000_check_for_serdes_link_generic(struct e1000_hw *hw);
 s32  e1000_cleanup_led_generic(struct e1000_hw *hw);
 s32  e1000_commit_fc_settings_generic(struct e1000_hw *hw);
+s32  e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw);
 s32  e1000_config_fc_after_link_up_generic(struct e1000_hw *hw);
 s32  e1000_disable_pcie_master_generic(struct e1000_hw *hw);
 s32  e1000_force_mac_fc_generic(struct e1000_hw *hw);
 s32  e1000_get_auto_rd_done_generic(struct e1000_hw *hw);
 s32  e1000_get_bus_info_pci_generic(struct e1000_hw *hw);
 s32  e1000_get_bus_info_pcie_generic(struct e1000_hw *hw);
+void e1000_set_lan_id_single_port(struct e1000_hw *hw);
+void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw);
+void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
 s32  e1000_get_hw_semaphore_generic(struct e1000_hw *hw);
 s32  e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
                                                u16 *duplex);
@@ -59,16 +72,14 @@
 s32  e1000_id_led_init_generic(struct e1000_hw *hw);
 s32  e1000_led_on_generic(struct e1000_hw *hw);
 s32  e1000_led_off_generic(struct e1000_hw *hw);
-void e1000_mc_addr_list_update_generic(struct e1000_hw *hw,
+void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
                                       u8 *mc_addr_list, u32 mc_addr_count,
                                       u32 rar_used_count, u32 rar_count);
-s32  e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw);
 s32  e1000_set_default_fc_generic(struct e1000_hw *hw);
 s32  e1000_set_fc_watermarks_generic(struct e1000_hw *hw);
 s32  e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw);
 s32  e1000_setup_led_generic(struct e1000_hw *hw);
 s32  e1000_setup_link_generic(struct e1000_hw *hw);
-s32  e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
 s32  e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
                                        u32 offset, u8 data);
 
@@ -82,7 +93,7 @@
 void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw);
 void e1000_put_hw_semaphore_generic(struct e1000_hw *hw);
 void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
-void e1000_remove_device_generic(struct e1000_hw *hw);
+s32  e1000_check_alt_mac_addr_generic(struct e1000_hw *hw);
 void e1000_reset_adaptive_generic(struct e1000_hw *hw);
 void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop);
 void e1000_update_adaptive_generic(struct e1000_hw *hw);
Index: dev/em/README
===================================================================
--- dev/em/README       (Revision 28889)
+++ dev/em/README       (Arbeitskopie)
@@ -1,4 +1,4 @@
-$FreeBSD: src/sys/dev/em/README,v 1.15 2007/05/30 23:32:21 jfv Exp $
+$FreeBSD: src/sys/dev/e1000/README,v 1.1 2008/07/30 21:56:53 jfv Exp $
 FreeBSD* Driver for Intel Network Connection
 =============================================
 
Index: dev/em/e1000_osdep.c
===================================================================
--- dev/em/e1000_osdep.c        (Revision 0)
+++ dev/em/e1000_osdep.c        (Revision 0)
@@ -0,0 +1,81 @@
+/******************************************************************************
+
+  Copyright (c) 2001-2008, 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: src/sys/dev/e1000/e1000_osdep.c,v 1.1.2.2 2008/12/01 07:13:52 jfv 
Exp $*/
+
+#include "e1000_api.h"
+
+/*
+ * NOTE: the following routines using the e1000 
+ *     naming style are provided to the shared
+ *     code but are OS specific
+ */
+
+void
+e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
+{
+       pci_write_config(((struct e1000_osdep *)hw->back)->dev, reg, *value, 2);
+}
+
+void
+e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
+{
+       *value = pci_read_config(((struct e1000_osdep *)hw->back)->dev, reg, 2);
+}
+
+void
+e1000_pci_set_mwi(struct e1000_hw *hw)
+{
+       pci_write_config(((struct e1000_osdep *)hw->back)->dev, PCIR_COMMAND,
+           (hw->bus.pci_cmd_word | CMD_MEM_WRT_INVALIDATE), 2);
+}
+
+void
+e1000_pci_clear_mwi(struct e1000_hw *hw)
+{
+       pci_write_config(((struct e1000_osdep *)hw->back)->dev, PCIR_COMMAND,
+           (hw->bus.pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE), 2);
+}
+
+/*
+ * Read the PCI Express capabilities
+ */
+int32_t
+e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
+{
+       u32     result;
+
+       pci_find_extcap(((struct e1000_osdep *)hw->back)->dev,
+           reg, &result);
+       *value = (u16)result;
+       return (E1000_SUCCESS);
+}
Index: dev/em/if_em.c
===================================================================
--- dev/em/if_em.c      (Revision 28889)
+++ dev/em/if_em.c      (Arbeitskopie)
@@ -1,40 +1,40 @@
-/**************************************************************************
+/******************************************************************************
 
-Copyright (c) 2001-2007, Intel Corporation
-All rights reserved.
+  Copyright (c) 2001-2008, 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.
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/if_em.c,v 1.4 2008/12/07 21:32:56 thompsa Exp $*/
 
- 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: src/sys/dev/em/if_em.c,v 1.184 2007/09/10 21:50:40 jfv Exp $*/
-
 #ifdef HAVE_KERNEL_OPTION_HEADERS
 #include "opt_device_polling.h"
+#include "opt_inet.h"
 #endif
 
 #include <sys/param.h>
@@ -51,7 +51,11 @@
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
 #include <sys/taskqueue.h>
-
+#include <sys/eventhandler.h>
+#ifdef EM_TIMESYNC
+#include <sys/ioccom.h>
+#include <sys/time.h>
+#endif
 #include <machine/bus.h>
 #include <machine/resource.h>
 
@@ -78,7 +82,7 @@
 #include <dev/pci/pcireg.h>
 
 #include "e1000_api.h"
-#include "e1000_82575.h"
+#include "e1000_82571.h"
 #include "if_em.h"
 
 /*********************************************************************
@@ -89,7 +93,7 @@
 /*********************************************************************
  *  Driver version:
  *********************************************************************/
-char em_driver_version[] = "Version - 6.5.3";
+char em_driver_version[] = "6.9.6";
 
 
 /*********************************************************************
@@ -153,12 +157,18 @@
        { 0x8086, E1000_DEV_ID_82571EB_COPPER,  PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_82571EB_FIBER,   PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_82571EB_SERDES,  PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_82571EB_SERDES_DUAL,
+                                               PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_82571EB_SERDES_QUAD,
+                                               PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_82571EB_QUAD_COPPER,
                                                PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_82571EB_QUAD_COPPER_LP,
                                                PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_82571EB_QUAD_FIBER,
                                                PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_82571PT_QUAD_COPPER,
+                                               PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_82572EI_COPPER,  PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_82572EI_FIBER,   PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_82572EI_SERDES,  PCI_ANY_ID, PCI_ANY_ID, 0},
@@ -183,20 +193,21 @@
        { 0x8086, E1000_DEV_ID_ICH8_IFE_G,      PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_ICH8_IGP_M,      PCI_ANY_ID, PCI_ANY_ID, 0},
 
+       { 0x8086, E1000_DEV_ID_ICH9_IGP_M_AMT,  PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_ICH9_IGP_AMT,    PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_ICH9_IGP_C,      PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_ICH9_IGP_M,      PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_ICH9_IGP_M_V,    PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_ICH9_IFE,        PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_ICH9_IFE_GT,     PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_ICH9_IFE_G,      PCI_ANY_ID, PCI_ANY_ID, 0},
-
-       { 0x8086, E1000_DEV_ID_82575EB_COPPER,  PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82575EB_FIBER_SERDES,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82575EM_COPPER,  PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82575EM_FIBER_SERDES,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
-       { 0x8086, E1000_DEV_ID_82575GB_QUAD_COPPER,
-                                               PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_ICH9_BM,         PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_82574L,          PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_ICH10_R_BM_LM,   PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_ICH10_R_BM_LF,   PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_ICH10_R_BM_V,    PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_ICH10_D_BM_LM,   PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_ICH10_D_BM_LF,   PCI_ANY_ID, PCI_ANY_ID, 0},
        /* required last entry */
        { 0, 0, 0, 0, 0}
 };
@@ -229,13 +240,14 @@
 static int     em_media_change(struct ifnet *);
 static void    em_identify_hardware(struct adapter *);
 static int     em_allocate_pci_resources(struct adapter *);
-static int     em_allocate_intr(struct adapter *);
-static void    em_free_intr(struct adapter *);
+static int     em_allocate_legacy(struct adapter *adapter);
+static int     em_allocate_msix(struct adapter *adapter);
+static int     em_setup_msix(struct adapter *);
 static void    em_free_pci_resources(struct adapter *);
 static void    em_local_timer(void *);
 static int     em_hardware_init(struct adapter *);
 static void    em_setup_interface(device_t, struct adapter *);
-static int     em_setup_transmit_structures(struct adapter *);
+static void    em_setup_transmit_structures(struct adapter *);
 static void    em_initialize_transmit_unit(struct adapter *);
 static int     em_setup_receive_structures(struct adapter *);
 static void    em_initialize_receive_unit(struct adapter *);
@@ -245,6 +257,7 @@
 static void    em_free_receive_structures(struct adapter *);
 static void    em_update_stats_counters(struct adapter *);
 static void    em_txeof(struct adapter *);
+static void    em_tx_purge(struct adapter *);
 static int     em_allocate_receive_structures(struct adapter *);
 static int     em_allocate_transmit_structures(struct adapter *);
 static int     em_rxeof(struct adapter *, int);
@@ -254,20 +267,22 @@
 static void    em_receive_checksum(struct adapter *, struct e1000_rx_desc *,
                    struct mbuf *);
 static void    em_transmit_checksum_setup(struct adapter *, struct mbuf *,
-                   uint32_t *, uint32_t *);
-static boolean_t em_tx_adv_ctx_setup(struct adapter *, struct mbuf *);
-static boolean_t em_tso_setup(struct adapter *, struct mbuf *, uint32_t *,
-                   uint32_t *);
-static boolean_t em_tso_adv_setup(struct adapter *, struct mbuf *, uint32_t *);
+                   u32 *, u32 *);
+#if __FreeBSD_version >= 700000
+static bool    em_tso_setup(struct adapter *, struct mbuf *,
+                   u32 *, u32 *);
+#endif /* FreeBSD_version >= 700000 */
 static void    em_set_promisc(struct adapter *);
 static void    em_disable_promisc(struct adapter *);
 static void    em_set_multi(struct adapter *);
 static void    em_print_hw_stats(struct adapter *);
 static void    em_update_link_status(struct adapter *);
 static int     em_get_buf(struct adapter *, int);
-static void    em_enable_vlans(struct adapter *);
-static int     em_encap(struct adapter *, struct mbuf **);
-static int     em_adv_encap(struct adapter *, struct mbuf **);
+
+static void    em_register_vlan(void *, struct ifnet *, u16);
+static void    em_unregister_vlan(void *, struct ifnet *, u16);
+
+static int     em_xmit(struct adapter *, struct mbuf **);
 static void    em_smartspeed(struct adapter *);
 static int     em_82547_fifo_workaround(struct adapter *, int);
 static void    em_82547_update_fifo_head(struct adapter *, int);
@@ -277,10 +292,11 @@
                    struct em_dma_alloc *, int);
 static void    em_dma_free(struct adapter *, struct em_dma_alloc *);
 static void    em_print_debug_info(struct adapter *);
-static int     em_is_valid_ether_addr(uint8_t *);
+static void    em_print_nvm_info(struct adapter *);
+static int     em_is_valid_ether_addr(u8 *);
 static int     em_sysctl_stats(SYSCTL_HANDLER_ARGS);
 static int     em_sysctl_debug_info(SYSCTL_HANDLER_ARGS);
-static uint32_t        em_fill_descriptors (bus_addr_t address, uint32_t 
length,
+static u32     em_fill_descriptors (bus_addr_t address, u32 length,
                    PDESC_ARRAY desc_array);
 static int     em_sysctl_int_delay(SYSCTL_HANDLER_ARGS);
 static void    em_add_int_delay_sysctl(struct adapter *, const char *,
@@ -292,17 +308,36 @@
 static void     em_release_hw_control(struct adapter *);
 static void     em_enable_wakeup(device_t);
 
-#ifdef DEVICE_POLLING
-static poll_handler_t em_poll;
+#ifdef EM_TIMESYNC
+/* Precision Time sync support */
+static int     em_tsync_init(struct adapter *);
+static void    em_tsync_disable(struct adapter *);
+#endif
+
+#ifdef EM_LEGACY_IRQ
 static void    em_intr(void *);
+#else /* FAST IRQ */
+#if __FreeBSD_version < 700000
+static void    em_irq_fast(void *);
 #else
-static int     em_intr_fast(void *);
+static int     em_irq_fast(void *);
+#endif
+/* MSIX handlers */
+static void    em_msix_tx(void *);
+static void    em_msix_rx(void *);
+static void    em_msix_link(void *);
 static void    em_add_rx_process_limit(struct adapter *, const char *,
                    const char *, int *, int);
 static void    em_handle_rxtx(void *context, int pending);
+static void    em_handle_rx(void *context, int pending);
+static void    em_handle_tx(void *context, int pending);
 static void    em_handle_link(void *context, int pending);
-#endif
+#endif /* EM_LEGACY_IRQ */
 
+#ifdef DEVICE_POLLING
+static poll_handler_t em_poll;
+#endif /* POLLING */
+
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points
  *********************************************************************/
@@ -335,6 +370,11 @@
 #define EM_USECS_TO_TICKS(usecs)       ((1000 * (usecs) + 512) / 1024)
 #define M_TSO_LEN                      66
 
+/* Allow common code without TSO */
+#ifndef CSUM_TSO
+#define CSUM_TSO       0
+#endif
+
 static int em_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV);
 static int em_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR);
 static int em_tx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_TADV);
@@ -342,6 +382,10 @@
 static int em_rxd = EM_DEFAULT_RXD;
 static int em_txd = EM_DEFAULT_TXD;
 static int em_smart_pwr_down = FALSE;
+/* Controls whether promiscuous also shows bad packets */
+static int em_debug_sbp = FALSE;
+/* Local switch for MSI/MSIX */
+static int em_enable_msi = TRUE;
 
 TUNABLE_INT("hw.em.tx_int_delay", &em_tx_int_delay_dflt);
 TUNABLE_INT("hw.em.rx_int_delay", &em_rx_int_delay_dflt);
@@ -350,11 +394,15 @@
 TUNABLE_INT("hw.em.rxd", &em_rxd);
 TUNABLE_INT("hw.em.txd", &em_txd);
 TUNABLE_INT("hw.em.smart_pwr_down", &em_smart_pwr_down);
-#ifndef DEVICE_POLLING
+TUNABLE_INT("hw.em.sbp", &em_debug_sbp);
+TUNABLE_INT("hw.em.enable_msi", &em_enable_msi);
+
+#ifndef EM_LEGACY_IRQ
 /* How many packets rxeof tries to clean at a time */
 static int em_rx_process_limit = 100;
 TUNABLE_INT("hw.em.rx_process_limit", &em_rx_process_limit);
 #endif
+
 /* Global used in WOL setup with multiport cards */
 static int global_quad_port_a = 0;
 
@@ -371,10 +419,10 @@
 em_probe(device_t dev)
 {
        char            adapter_name[60];
-       uint16_t        pci_vendor_id = 0;
-       uint16_t        pci_device_id = 0;
-       uint16_t        pci_subvendor_id = 0;
-       uint16_t        pci_subdevice_id = 0;
+       u16             pci_vendor_id = 0;
+       u16             pci_device_id = 0;
+       u16             pci_subvendor_id = 0;
+       u16             pci_subdevice_id = 0;
        em_vendor_info_t *ent;
 
        INIT_DEBUGOUT("em_probe: begin");
@@ -431,12 +479,14 @@
 
        adapter = device_get_softc(dev);
        adapter->dev = adapter->osdep.dev = dev;
-       EM_LOCK_INIT(adapter, device_get_nameunit(dev));
+       EM_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
+       EM_TX_LOCK_INIT(adapter, device_get_nameunit(dev));
+       EM_RX_LOCK_INIT(adapter, device_get_nameunit(dev));
 
        /* SYSCTL stuff */
        SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
            SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-           OID_AUTO, "debug_info", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
+           OID_AUTO, "debug", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
            em_sysctl_debug_info, "I", "Debug Information");
 
        SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
@@ -444,8 +494,8 @@
            OID_AUTO, "stats", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
            em_sysctl_stats, "I", "Statistics");
 
-       callout_init_mtx(&adapter->timer, &adapter->mtx, 0);
-       callout_init_mtx(&adapter->tx_fifo_timer, &adapter->mtx, 0);
+       callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
+       callout_init_mtx(&adapter->tx_fifo_timer, &adapter->tx_mtx, 0);
 
        /* Determine hardware and mac info */
        em_identify_hardware(adapter);
@@ -464,16 +514,22 @@
        ** identified
        */
        if ((adapter->hw.mac.type == e1000_ich8lan) ||
+           (adapter->hw.mac.type == e1000_ich10lan) ||
            (adapter->hw.mac.type == e1000_ich9lan)) {
                int rid = EM_BAR_TYPE_FLASH;
-               adapter->flash_mem = bus_alloc_resource_any(dev,
+               adapter->flash = bus_alloc_resource_any(dev,
                    SYS_RES_MEMORY, &rid, RF_ACTIVE);
+               if (adapter->flash == NULL) {
+                       device_printf(dev, "Mapping of Flash failed\n");
+                       error = ENXIO;
+                       goto err_pci;
+               }
                /* This is used in the shared code */
-               adapter->hw.flash_address = (u8 *)adapter->flash_mem;
+               adapter->hw.flash_address = (u8 *)adapter->flash;
                adapter->osdep.flash_bus_space_tag =
-                   rman_get_bustag(adapter->flash_mem);
+                   rman_get_bustag(adapter->flash);
                adapter->osdep.flash_bus_space_handle =
-                   rman_get_bushandle(adapter->flash_mem);
+                   rman_get_bushandle(adapter->flash);
        }
 
        /* Do Shared Code initialization */
@@ -505,7 +561,7 @@
                    em_tx_abs_int_delay_dflt);
        }
 
-#ifndef DEVICE_POLLING
+#ifndef EM_LEGACY_IRQ
        /* Sysctls for limiting the amount of work done in the taskqueue */
        em_add_rx_process_limit(adapter, "rx_processing_limit",
            "max number of rx packets to process", &adapter->rx_process_limit,
@@ -537,7 +593,7 @@
                adapter->num_rx_desc = em_rxd;
 
        adapter->hw.mac.autoneg = DO_AUTO_NEG;
-       adapter->hw.phy.wait_for_link = FALSE;
+       adapter->hw.phy.autoneg_wait_to_complete = FALSE;
        adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT;
        adapter->rx_buffer_len = 2048;
 
@@ -545,21 +601,19 @@
        e1000_set_tbi_compatibility_82543(&adapter->hw, TRUE);
 
        /* Copper options */
-       if (adapter->hw.media_type == e1000_media_type_copper) {
+       if (adapter->hw.phy.media_type == e1000_media_type_copper) {
                adapter->hw.phy.mdix = AUTO_ALL_MODES;
                adapter->hw.phy.disable_polarity_correction = FALSE;
                adapter->hw.phy.ms_type = EM_MASTER_SLAVE;
        }
 
        /*
-        * Set the max frame size assuming standard ethernet
-        * sized frames.
+        * Set the frame limits assuming
+        * standard ethernet sized frames.
         */
-       adapter->hw.mac.max_frame_size =
-           ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE;
+       adapter->max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE;
+       adapter->min_frame_size = ETH_ZLEN + ETHERNET_FCS_SIZE;
 
-       adapter->hw.mac.min_frame_size = ETH_ZLEN + ETHERNET_FCS_SIZE;
-
        /*
         * This controls when hardware reports transmit completion
         * status.
@@ -605,13 +659,6 @@
                }
        }
 
-       if (e1000_read_part_num(&adapter->hw, &(adapter->part_num)) < 0) {
-               device_printf(dev, "EEPROM read error "
-                   "reading part number\n");
-               error = EIO;
-               goto err_hw_init;
-       }
-
        /* Initialize the hardware */
        if (em_hardware_init(adapter)) {
                device_printf(dev, "Unable to initialize the hardware\n");
@@ -633,11 +680,33 @@
                goto err_hw_init;
        }
 
+       /* Allocate transmit descriptors and buffers */
+       if (em_allocate_transmit_structures(adapter)) {
+               device_printf(dev, "Could not setup transmit structures\n");
+               error = ENOMEM;
+               goto err_tx_struct;
+       }
+
+       /* Allocate receive descriptors and buffers */
+       if (em_allocate_receive_structures(adapter)) {
+               device_printf(dev, "Could not setup receive structures\n");
+               error = ENOMEM;
+               goto err_rx_struct;
+       }
+
+       /*
+       **  Do interrupt configuration
+       */
+       if (adapter->msi > 1) /* Do MSI/X */
+               error = em_allocate_msix(adapter);
+       else  /* MSI or Legacy */
+               error = em_allocate_legacy(adapter);
+       if (error)
+               goto err_rx_struct;
+
        /* Setup OS specific network interface */
        em_setup_interface(dev, adapter);
 
-       em_allocate_intr(adapter);
-
        /* Initialize statistics */
        em_update_stats_counters(adapter);
 
@@ -719,6 +788,12 @@
        else
                adapter->pcix_82544 = FALSE;
 
+       /* Register for VLAN events */
+       adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
+           em_register_vlan, 0, EVENTHANDLER_PRI_FIRST);
+       adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
+           em_unregister_vlan, 0, EVENTHANDLER_PRI_FIRST); 
+
        /* Tell the stack that the interface is not active */
        adapter->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
@@ -726,17 +801,20 @@
 
        return (0);
 
+err_rx_struct:
+       em_free_transmit_structures(adapter);
+err_tx_struct:
 err_hw_init:
        em_release_hw_control(adapter);
-       e1000_remove_device(&adapter->hw);
        em_dma_free(adapter, &adapter->rxdma);
 err_rx_desc:
        em_dma_free(adapter, &adapter->txdma);
 err_tx_desc:
 err_pci:
-       em_free_intr(adapter);
        em_free_pci_resources(adapter);
-       EM_LOCK_DESTROY(adapter);
+       EM_TX_LOCK_DESTROY(adapter);
+       EM_RX_LOCK_DESTROY(adapter);
+       EM_CORE_LOCK_DESTROY(adapter);
 
        return (error);
 }
@@ -759,14 +837,23 @@
 
        INIT_DEBUGOUT("em_detach: begin");
 
+       /* Make sure VLANS are not using driver */
+#if __FreeBSD_version >= 700000
+       if (adapter->ifp->if_vlantrunk != NULL) {
+#else
+       if (adapter->ifp->if_nvlans != 0) {
+#endif   
+               device_printf(dev,"Vlan in use, detach first\n");
+               return (EBUSY);
+       }
+
 #ifdef DEVICE_POLLING
        if (ifp->if_capenable & IFCAP_POLLING)
                ether_poll_deregister(ifp);
 #endif
 
-       em_disable_intr(adapter);
-       em_free_intr(adapter);
-       EM_LOCK(adapter);
+       EM_CORE_LOCK(adapter);
+       EM_TX_LOCK(adapter);
        adapter->in_detach = 1;
        em_stop(adapter);
        e1000_phy_hw_reset(&adapter->hw);
@@ -775,6 +862,7 @@
 
        if (((adapter->hw.mac.type == e1000_82573) ||
            (adapter->hw.mac.type == e1000_ich8lan) ||
+           (adapter->hw.mac.type == e1000_ich10lan) ||
            (adapter->hw.mac.type == e1000_ich9lan)) &&
            e1000_check_mng_mode(&adapter->hw))
                em_release_hw_control(adapter);
@@ -785,9 +873,16 @@
                em_enable_wakeup(dev);
        }
 
-       EM_UNLOCK(adapter);
+       EM_TX_UNLOCK(adapter);
+       EM_CORE_UNLOCK(adapter);
+
+       /* Unregister VLAN events */
+       if (adapter->vlan_attach != NULL)
+               EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
+       if (adapter->vlan_detach != NULL)
+               EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); 
+
        ether_ifdetach(adapter->ifp);
-
        callout_drain(&adapter->timer);
        callout_drain(&adapter->tx_fifo_timer);
 
@@ -795,7 +890,6 @@
        bus_generic_detach(dev);
        if_free(ifp);
 
-       e1000_remove_device(&adapter->hw);
        em_free_transmit_structures(adapter);
        em_free_receive_structures(adapter);
 
@@ -811,7 +905,9 @@
                adapter->rx_desc_base = NULL;
        }
 
-       EM_LOCK_DESTROY(adapter);
+       EM_TX_LOCK_DESTROY(adapter);
+       EM_RX_LOCK_DESTROY(adapter);
+       EM_CORE_LOCK_DESTROY(adapter);
 
        return (0);
 }
@@ -836,13 +932,17 @@
 {
        struct adapter *adapter = device_get_softc(dev);
 
-       EM_LOCK(adapter);
+       EM_CORE_LOCK(adapter);
+
+       EM_TX_LOCK(adapter);
        em_stop(adapter);
+       EM_TX_UNLOCK(adapter);
 
         em_release_manageability(adapter);
 
         if (((adapter->hw.mac.type == e1000_82573) ||
             (adapter->hw.mac.type == e1000_ich8lan) ||
+            (adapter->hw.mac.type == e1000_ich10lan) ||
             (adapter->hw.mac.type == e1000_ich9lan)) &&
             e1000_check_mng_mode(&adapter->hw))
                 em_release_hw_control(adapter);
@@ -853,7 +953,7 @@
                 em_enable_wakeup(dev);
         }
 
-       EM_UNLOCK(adapter);
+       EM_CORE_UNLOCK(adapter);
 
        return bus_generic_suspend(dev);
 }
@@ -864,16 +964,12 @@
        struct adapter *adapter = device_get_softc(dev);
        struct ifnet *ifp = adapter->ifp;
 
-       EM_LOCK(adapter);
+       EM_CORE_LOCK(adapter);
        em_init_locked(adapter);
        em_init_manageability(adapter);
+       EM_CORE_UNLOCK(adapter);
+       em_start(ifp);
 
-       if ((ifp->if_flags & IFF_UP) &&
-           (ifp->if_drv_flags & IFF_DRV_RUNNING))
-               em_start_locked(ifp);
-
-       EM_UNLOCK(adapter);
-
        return bus_generic_resume(dev);
 }
 
@@ -894,7 +990,7 @@
        struct adapter  *adapter = ifp->if_softc;
        struct mbuf     *m_head;
 
-       EM_LOCK_ASSERT(adapter);
+       EM_TX_LOCK_ASSERT(adapter);
 
        if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
            IFF_DRV_RUNNING)
@@ -910,11 +1006,8 @@
                /*
                 *  Encapsulation can modify our pointer, and or make it
                 *  NULL on failure.  In that event, we can't requeue.
-                *
-                *  We now use a pointer to accomodate legacy and
-                *  advanced transmit functions.
                 */
-               if (adapter->em_xmit(adapter, &m_head)) {
+               if (em_xmit(adapter, &m_head)) {
                        if (m_head == NULL)
                                break;
                        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
@@ -935,10 +1028,10 @@
 {
        struct adapter *adapter = ifp->if_softc;
 
-       EM_LOCK(adapter);
+       EM_TX_LOCK(adapter);
        if (ifp->if_drv_flags & IFF_DRV_RUNNING)
                em_start_locked(ifp);
-       EM_UNLOCK(adapter);
+       EM_TX_UNLOCK(adapter);
 }
 
 /*********************************************************************
@@ -955,7 +1048,9 @@
 {
        struct adapter  *adapter = ifp->if_softc;
        struct ifreq *ifr = (struct ifreq *)data;
+#ifdef INET
        struct ifaddr *ifa = (struct ifaddr *)data;
+#endif
        int error = 0;
 
        if (adapter->in_detach)
@@ -963,6 +1058,7 @@
 
        switch (command) {
        case SIOCSIFADDR:
+#ifdef INET
                if (ifa->ifa_addr->sa_family == AF_INET) {
                        /*
                         * XXX
@@ -973,22 +1069,23 @@
                         */
                        ifp->if_flags |= IFF_UP;
                        if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-                               EM_LOCK(adapter);
+                               EM_CORE_LOCK(adapter);
                                em_init_locked(adapter);
-                               EM_UNLOCK(adapter);
+                               EM_CORE_UNLOCK(adapter);
                        }
                        arp_ifinit(ifp, ifa);
                } else
+#endif
                        error = ether_ioctl(ifp, command, data);
                break;
        case SIOCSIFMTU:
            {
                int max_frame_size;
-               uint16_t eeprom_data = 0;
+               u16 eeprom_data = 0;
 
                IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
 
-               EM_LOCK(adapter);
+               EM_CORE_LOCK(adapter);
                switch (adapter->hw.mac.type) {
                case e1000_82573:
                        /*
@@ -1005,7 +1102,8 @@
                case e1000_82571:
                case e1000_82572:
                case e1000_ich9lan:
-               case e1000_82575:
+               case e1000_ich10lan:
+               case e1000_82574:
                case e1000_80003es2lan: /* Limit Jumbo Frame size */
                        max_frame_size = 9234;
                        break;
@@ -1019,42 +1117,45 @@
                }
                if (ifr->ifr_mtu > max_frame_size - ETHER_HDR_LEN -
                    ETHER_CRC_LEN) {
-                       EM_UNLOCK(adapter);
+                       EM_CORE_UNLOCK(adapter);
                        error = EINVAL;
                        break;
                }
 
                ifp->if_mtu = ifr->ifr_mtu;
-               adapter->hw.mac.max_frame_size =
-               ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+               adapter->max_frame_size =
+                   ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
                em_init_locked(adapter);
-               EM_UNLOCK(adapter);
+               EM_CORE_UNLOCK(adapter);
                break;
            }
        case SIOCSIFFLAGS:
                IOCTL_DEBUGOUT("ioctl rcv'd:\
                    SIOCSIFFLAGS (Set Interface Flags)");
-               EM_LOCK(adapter);
+               EM_CORE_LOCK(adapter);
                if (ifp->if_flags & IFF_UP) {
                        if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
                                if ((ifp->if_flags ^ adapter->if_flags) &
-                                   IFF_PROMISC) {
+                                   (IFF_PROMISC | IFF_ALLMULTI)) {
                                        em_disable_promisc(adapter);
                                        em_set_promisc(adapter);
                                }
                        } else
                                em_init_locked(adapter);
                } else
-                       if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+                       if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+                               EM_TX_LOCK(adapter);
                                em_stop(adapter);
+                               EM_TX_UNLOCK(adapter);
+                       }
                adapter->if_flags = ifp->if_flags;
-               EM_UNLOCK(adapter);
+               EM_CORE_UNLOCK(adapter);
                break;
        case SIOCADDMULTI:
        case SIOCDELMULTI:
                IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI");
                if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-                       EM_LOCK(adapter);
+                       EM_CORE_LOCK(adapter);
                        em_disable_intr(adapter);
                        em_set_multi(adapter);
                        if (adapter->hw.mac.type == e1000_82542 && 
@@ -1065,19 +1166,19 @@
                        if (!(ifp->if_capenable & IFCAP_POLLING))
 #endif
                                em_enable_intr(adapter);
-                       EM_UNLOCK(adapter);
+                       EM_CORE_UNLOCK(adapter);
                }
                break;
        case SIOCSIFMEDIA:
                /* Check SOL/IDER usage */
-               EM_LOCK(adapter);
+               EM_CORE_LOCK(adapter);
                if (e1000_check_reset_block(&adapter->hw)) {
-                       EM_UNLOCK(adapter);
+                       EM_CORE_UNLOCK(adapter);
                        device_printf(adapter->dev, "Media change is"
                            " blocked due to SOL/IDER session.\n");
                        break;
                }
-               EM_UNLOCK(adapter);
+               EM_CORE_UNLOCK(adapter);
        case SIOCGIFMEDIA:
                IOCTL_DEBUGOUT("ioctl rcv'd: \
                    SIOCxIFMEDIA (Get/Set Interface Media)");
@@ -1096,17 +1197,17 @@
                                error = ether_poll_register(em_poll, ifp);
                                if (error)
                                        return (error);
-                               EM_LOCK(adapter);
+                               EM_CORE_LOCK(adapter);
                                em_disable_intr(adapter);
                                ifp->if_capenable |= IFCAP_POLLING;
-                               EM_UNLOCK(adapter);
+                               EM_CORE_UNLOCK(adapter);
                        } else {
                                error = ether_poll_deregister(ifp);
                                /* Enable interrupt even in error case */
-                               EM_LOCK(adapter);
+                               EM_CORE_LOCK(adapter);
                                em_enable_intr(adapter);
                                ifp->if_capenable &= ~IFCAP_POLLING;
-                               EM_UNLOCK(adapter);
+                               EM_CORE_UNLOCK(adapter);
                        }
                }
 #endif
@@ -1114,19 +1215,89 @@
                        ifp->if_capenable ^= IFCAP_HWCSUM;
                        reinit = 1;
                }
+#if __FreeBSD_version >= 700000
                if (mask & IFCAP_TSO4) {
                        ifp->if_capenable ^= IFCAP_TSO4;
                        reinit = 1;
                }
+#endif
+
                if (mask & IFCAP_VLAN_HWTAGGING) {
                        ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
                        reinit = 1;
                }
                if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING))
                        em_init(adapter);
+#if __FreeBSD_version >= 700000
                VLAN_CAPABILITIES(ifp);
+#endif
                break;
            }
+
+#ifdef EM_TIMESYNC
+       /*
+       ** IOCTL support for Precision Time (IEEE 1588) Support
+       */
+       case EM_TIMESYNC_READTS:
+           {
+               u32 rx_ctl, tx_ctl;
+               struct em_tsync_read *tdata;
+
+               tdata = (struct em_tsync_read *) ifr->ifr_data;
+
+               IOCTL_DEBUGOUT("Reading Timestamp\n");
+
+               if (tdata->read_current_time) {
+                       getnanotime(&tdata->system_time);
+                       tdata->network_time = E1000_READ_REG(&adapter->hw, 
E1000_SYSTIML);
+                       tdata->network_time |=
+                           (u64)E1000_READ_REG(&adapter->hw, E1000_SYSTIMH ) 
<< 32;
+               }
+ 
+               rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
+               tx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
+
+               IOCTL_DEBUGOUT1("RX_CTL value = %u\n", rx_ctl);
+               IOCTL_DEBUGOUT1("TX_CTL value = %u\n", tx_ctl);
+
+               if (rx_ctl & 0x1) {
+                       IOCTL_DEBUGOUT("RX timestamp is valid\n");
+                       u32 tmp;
+                       unsigned char *tmp_cp;
+
+                       tdata->rx_valid = 1;
+                       tdata->rx_stamp = E1000_READ_REG(&adapter->hw, 
E1000_RXSTMPL);
+                       tdata->rx_stamp |= (u64)E1000_READ_REG(&adapter->hw,
+                           E1000_RXSTMPH) << 32;
+
+                       tmp = E1000_READ_REG(&adapter->hw, E1000_RXSATRL);
+                       tmp_cp = (unsigned char *) &tmp;
+                       tdata->srcid[0] = tmp_cp[0];
+                       tdata->srcid[1] = tmp_cp[1];
+                       tdata->srcid[2] = tmp_cp[2];
+                       tdata->srcid[3] = tmp_cp[3];
+                       tmp = E1000_READ_REG(&adapter->hw, E1000_RXSATRH);
+                       tmp_cp = (unsigned char *) &tmp;
+                       tdata->srcid[4] = tmp_cp[0];
+                       tdata->srcid[5] = tmp_cp[1];
+                       tdata->seqid = tmp >> 16;
+                       tdata->seqid = htons(tdata->seqid);
+               } else
+                       tdata->rx_valid = 0;
+
+               if (tx_ctl & 0x1) {
+                       IOCTL_DEBUGOUT("TX timestamp is valid\n");
+                       tdata->tx_valid = 1;
+                       tdata->tx_stamp = E1000_READ_REG(&adapter->hw, 
E1000_TXSTMPL);
+                       tdata->tx_stamp |= (u64) E1000_READ_REG(&adapter->hw,
+                           E1000_TXSTMPH) << 32;
+               } else
+                       tdata->tx_valid = 0;
+
+               return (0);
+           }
+#endif /* EM_TIMESYNC */
+
        default:
                error = ether_ioctl(ifp, command, data);
                break;
@@ -1149,17 +1320,20 @@
 em_watchdog(struct adapter *adapter)
 {
 
-       EM_LOCK_ASSERT(adapter);
+       EM_CORE_LOCK_ASSERT(adapter);
 
        /*
        ** The timer is set to 5 every time start queues a packet.
-       ** Then txeof keeps resetting to 5 as long as it cleans at
+       ** Then txeof keeps resetting it as long as it cleans at
        ** least one descriptor.
        ** Finally, anytime all descriptors are clean the timer is
        ** set to 0.
        */
-       if (adapter->watchdog_timer == 0 || --adapter->watchdog_timer)
+       EM_TX_LOCK(adapter);
+       if ((adapter->watchdog_timer == 0) || (--adapter->watchdog_timer)) {
+               EM_TX_UNLOCK(adapter);
                return;
+       }
 
        /* If we are in this routine because of pause frames, then
         * don't reset the hardware.
@@ -1167,6 +1341,7 @@
        if (E1000_READ_REG(&adapter->hw, E1000_STATUS) &
            E1000_STATUS_TXOFF) {
                adapter->watchdog_timer = EM_TX_TIMEOUT;
+               EM_TX_UNLOCK(adapter);
                return;
        }
 
@@ -1174,6 +1349,7 @@
                device_printf(adapter->dev, "watchdog timeout -- resetting\n");
        adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
        adapter->watchdog_events++;
+       EM_TX_UNLOCK(adapter);
 
        em_init_locked(adapter);
 }
@@ -1194,13 +1370,15 @@
 {
        struct ifnet    *ifp = adapter->ifp;
        device_t        dev = adapter->dev;
-       uint32_t        pba;
+       u32             pba;
 
        INIT_DEBUGOUT("em_init: begin");
 
-       EM_LOCK_ASSERT(adapter);
+       EM_CORE_LOCK_ASSERT(adapter);
 
+       EM_TX_LOCK(adapter);
        em_stop(adapter);
+       EM_TX_UNLOCK(adapter);
 
        /*
         * Packet Buffer Allocation (PBA)
@@ -1216,7 +1394,7 @@
        switch (adapter->hw.mac.type) {
        case e1000_82547:
        case e1000_82547_rev_2: /* 82547: Total Packet Buffer is 40K */
-               if (adapter->hw.mac.max_frame_size > 8192)
+               if (adapter->max_frame_size > 8192)
                        pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */
                else
                        pba = E1000_PBA_30K; /* 30K for Rx, 10K for Tx */
@@ -1228,14 +1406,17 @@
        /* Total Packet Buffer on these is 48K */
        case e1000_82571:
        case e1000_82572:
-       case e1000_82575:
        case e1000_80003es2lan:
                        pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */
                break;
        case e1000_82573: /* 82573: Total Packet Buffer is 32K */
                        pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */
                break;
+       case e1000_82574:
+                       pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */
+               break;
        case e1000_ich9lan:
+       case e1000_ich10lan:
 #define E1000_PBA_10K  0x000A
                pba = E1000_PBA_10K;
                break;
@@ -1244,7 +1425,7 @@
                break;
        default:
                /* Devices before 82547 had a Packet Buffer of 64K.   */
-               if (adapter->hw.mac.max_frame_size > 8192)
+               if (adapter->max_frame_size > 8192)
                        pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */
                else
                        pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */
@@ -1261,11 +1442,16 @@
        e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
 
        /*
-        * With 82571 controllers, LAA may be overwritten
-        * due to controller reset from the other port.
+        * With the 82571 adapter, RAR[0] may be overwritten
+        * when the other port is reset, we make a duplicate
+        * in RAR[14] for that eventuality, this assures
+        * the interface continues to function.
         */
-       if (adapter->hw.mac.type == e1000_82571)
-                e1000_set_laa_state_82571(&adapter->hw, TRUE);
+       if (adapter->hw.mac.type == e1000_82571) {
+               e1000_set_laa_state_82571(&adapter->hw, TRUE);
+               e1000_rar_set(&adapter->hw, adapter->hw.mac.addr,
+                   E1000_RAR_ENTRIES - 1);
+       }
 
        /* Initialize the hardware */
        if (em_hardware_init(adapter)) {
@@ -1274,27 +1460,35 @@
        }
        em_update_link_status(adapter);
 
-       if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
-               em_enable_vlans(adapter);
+       /* Setup VLAN support, basic and offload if available */
+       E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
 
+       /* New register interface replaces this but
+          waiting on kernel support to be added */
+       if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) &&
+           ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)) {
+               u32 ctrl;
+               ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
+               ctrl |= E1000_CTRL_VME;
+               E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
+       }
+
        /* Set hardware offload abilities */
        ifp->if_hwassist = 0;
        if (adapter->hw.mac.type >= e1000_82543) {
                if (ifp->if_capenable & IFCAP_TXCSUM)
                        ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
+#if __FreeBSD_version >= 700000
                if (ifp->if_capenable & IFCAP_TSO4)
                        ifp->if_hwassist |= CSUM_TSO;
+#endif
        }
 
        /* Configure for OS presence */
        em_init_manageability(adapter);
 
        /* Prepare transmit descriptors and buffers */
-       if (em_setup_transmit_structures(adapter)) {
-               device_printf(dev, "Could not setup transmit structures\n");
-               em_stop(adapter);
-               return;
-       }
+       em_setup_transmit_structures(adapter);
        em_initialize_transmit_unit(adapter);
 
        /* Setup Multicast table */
@@ -1303,7 +1497,9 @@
        /* Prepare receive descriptors and buffers */
        if (em_setup_receive_structures(adapter)) {
                device_printf(dev, "Could not setup receive structures\n");
+               EM_TX_LOCK(adapter);
                em_stop(adapter);
+               EM_TX_UNLOCK(adapter);
                return;
        }
        em_initialize_receive_unit(adapter);
@@ -1317,6 +1513,22 @@
        callout_reset(&adapter->timer, hz, em_local_timer, adapter);
        e1000_clear_hw_cntrs_base_generic(&adapter->hw);
 
+       /* MSI/X configuration for 82574 */
+       if (adapter->hw.mac.type == e1000_82574) {
+               int tmp;
+               tmp = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
+               tmp |= E1000_CTRL_EXT_PBA_CLR;
+               E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, tmp);
+               /*
+               ** Set the IVAR - interrupt vector routing.
+               ** Each nibble represents a vector, high bit
+               ** is enable, other 3 bits are the MSIX table
+               ** entry, we map RXQ0 to 0, TXQ0 to 1, and
+               ** Link (other) to 2, hence the magic number.
+               */
+               E1000_WRITE_REG(&adapter->hw, E1000_IVAR, 0x800A0908);
+       }
+
 #ifdef DEVICE_POLLING
        /*
         * Only enable interrupts if we are not polling, make sure
@@ -1328,6 +1540,13 @@
 #endif /* DEVICE_POLLING */
                em_enable_intr(adapter);
 
+#ifdef EM_TIMESYNC
+       /* Initializae IEEE 1588 Precision Time hardware */
+       if ((adapter->hw.mac.type == e1000_82574) ||
+           (adapter->hw.mac.type == e1000_ich10lan))
+               em_tsync_init(adapter);
+#endif
+
        /* Don't reset the phy next time init gets called */
        adapter->hw.phy.reset_disable = TRUE;
 }
@@ -1337,9 +1556,9 @@
 {
        struct adapter *adapter = arg;
 
-       EM_LOCK(adapter);
+       EM_CORE_LOCK(adapter);
        em_init_locked(adapter);
-       EM_UNLOCK(adapter);
+       EM_CORE_UNLOCK(adapter);
 }
 
 
@@ -1353,11 +1572,11 @@
 em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
 {
        struct adapter *adapter = ifp->if_softc;
-       uint32_t reg_icr;
+       u32             reg_icr;
 
-       EM_LOCK(adapter);
+       EM_CORE_LOCK(adapter);
        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
-               EM_UNLOCK(adapter);
+               EM_CORE_UNLOCK(adapter);
                return;
        }
 
@@ -1366,20 +1585,25 @@
                if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
                        callout_stop(&adapter->timer);
                        adapter->hw.mac.get_link_status = 1;
-                       e1000_check_for_link(&adapter->hw);
                        em_update_link_status(adapter);
                        callout_reset(&adapter->timer, hz,
                            em_local_timer, adapter);
                }
        }
+       EM_CORE_UNLOCK(adapter);
+
        em_rxeof(adapter, count);
+
+       EM_TX_LOCK(adapter);
        em_txeof(adapter);
 
        if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
                em_start_locked(ifp);
-       EM_UNLOCK(adapter);
+       EM_TX_UNLOCK(adapter);
 }
+#endif /* DEVICE_POLLING */
 
+#ifdef EM_LEGACY_IRQ 
 /*********************************************************************
  *
  *  Legacy Interrupt Service routine  
@@ -1390,17 +1614,14 @@
 em_intr(void *arg)
 {
        struct adapter  *adapter = arg;
-       struct ifnet    *ifp;
-       uint32_t        reg_icr;
+       struct ifnet    *ifp = adapter->ifp;
+       u32             reg_icr;
 
-       EM_LOCK(adapter);
-       ifp = adapter->ifp;
 
-       if (ifp->if_capenable & IFCAP_POLLING) {
-               EM_UNLOCK(adapter);
+       if (ifp->if_capenable & IFCAP_POLLING)
                return;
-       }
 
+       EM_CORE_LOCK(adapter);
        for (;;) {
                reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
 
@@ -1419,17 +1640,22 @@
                if (reg_icr == 0xffffffff)
                        break;
 
+               EM_CORE_UNLOCK(adapter);
                if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
                        em_rxeof(adapter, -1);
+                       EM_TX_LOCK(adapter);
                        em_txeof(adapter);
+                       EM_TX_UNLOCK(adapter);
                }
+               EM_CORE_LOCK(adapter);
 
                /* Link status change */
                if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
                        callout_stop(&adapter->timer);
                        adapter->hw.mac.get_link_status = 1;
-                       e1000_check_for_link(&adapter->hw);
                        em_update_link_status(adapter);
+                       /* Deal with TX cruft when link lost */
+                       em_tx_purge(adapter);
                        callout_reset(&adapter->timer, hz,
                            em_local_timer, adapter);
                }
@@ -1437,74 +1663,100 @@
                if (reg_icr & E1000_ICR_RXO)
                        adapter->rx_overruns++;
        }
+       EM_CORE_UNLOCK(adapter);
 
        if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
            !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-               em_start_locked(ifp);
-       EM_UNLOCK(adapter);
+               em_start(ifp);
 }
 
-#else /* if not DEVICE_POLLING, then fast interrupt routines only */
+#else /* EM_FAST_IRQ, then fast interrupt routines only */
 
 static void
 em_handle_link(void *context, int pending)
 {
        struct adapter  *adapter = context;
-       struct ifnet *ifp;
+       struct ifnet *ifp = adapter->ifp;
 
-       ifp = adapter->ifp;
-
-       EM_LOCK(adapter);
-       if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-               EM_UNLOCK(adapter);
+       if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
                return;
-       }
 
+       EM_CORE_LOCK(adapter);
        callout_stop(&adapter->timer);
-       adapter->hw.mac.get_link_status = 1;
-       e1000_check_for_link(&adapter->hw);
        em_update_link_status(adapter);
+       /* Deal with TX cruft when link lost */
+       em_tx_purge(adapter);
        callout_reset(&adapter->timer, hz, em_local_timer, adapter);
-       EM_UNLOCK(adapter);
+       EM_CORE_UNLOCK(adapter);
 }
 
+
+/* Combined RX/TX handler, used by Legacy and MSI */
 static void
 em_handle_rxtx(void *context, int pending)
 {
        struct adapter  *adapter = context;
-       struct ifnet    *ifp;
+       struct ifnet    *ifp = adapter->ifp;
 
-       ifp = adapter->ifp;
 
-       /*
-        * TODO:
-        * It should be possible to run the tx clean loop without the lock.
-        */
        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
                if (em_rxeof(adapter, adapter->rx_process_limit) != 0)
                        taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
-               EM_LOCK(adapter);
+               EM_TX_LOCK(adapter);
                em_txeof(adapter);
 
                if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
                        em_start_locked(ifp);
-               EM_UNLOCK(adapter);
+               EM_TX_UNLOCK(adapter);
        }
 
        em_enable_intr(adapter);
 }
 
+static void
+em_handle_rx(void *context, int pending)
+{
+       struct adapter  *adapter = context;
+       struct ifnet    *ifp = adapter->ifp;
+
+       if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
+           (em_rxeof(adapter, adapter->rx_process_limit) != 0))
+               taskqueue_enqueue(adapter->tq, &adapter->rx_task);
+
+}
+
+static void
+em_handle_tx(void *context, int pending)
+{
+       struct adapter  *adapter = context;
+       struct ifnet    *ifp = adapter->ifp;
+
+       if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+               EM_TX_LOCK(adapter);
+               em_txeof(adapter);
+               if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+                       em_start_locked(ifp);
+               EM_TX_UNLOCK(adapter);
+       }
+}
+
 /*********************************************************************
  *
- *  Fast Interrupt Service routine  
+ *  Fast Legacy/MSI Combined Interrupt Service routine  
  *
  *********************************************************************/
+#if __FreeBSD_version < 700000
+#define FILTER_STRAY
+#define FILTER_HANDLED
+static void
+#else
 static int
-em_intr_fast(void *arg)
+#endif
+em_irq_fast(void *arg)
 {
        struct adapter  *adapter = arg;
        struct ifnet    *ifp;
-       uint32_t        reg_icr;
+       u32             reg_icr;
 
        ifp = adapter->ifp;
 
@@ -1512,11 +1764,11 @@
 
        /* Hot eject?  */
        if (reg_icr == 0xffffffff)
-               return (FILTER_STRAY);
+               return FILTER_STRAY;
 
        /* Definitely not our interrupt.  */
        if (reg_icr == 0x0)
-               return (FILTER_STRAY);
+               return FILTER_STRAY;
 
        /*
         * Starting with the 82571 chip, bit 31 should be used to
@@ -1524,7 +1776,7 @@
         */
        if (adapter->hw.mac.type >= e1000_82571 &&
            (reg_icr & E1000_ICR_INT_ASSERTED) == 0)
-               return (FILTER_STRAY);
+               return FILTER_STRAY;
 
        /*
         * Mask interrupts until the taskqueue is finished running.  This is
@@ -1535,17 +1787,91 @@
        taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
 
        /* Link status change */
-       if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))
+       if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+               adapter->hw.mac.get_link_status = 1;
                taskqueue_enqueue(taskqueue_fast, &adapter->link_task);
+       }
 
        if (reg_icr & E1000_ICR_RXO)
                adapter->rx_overruns++;
-       return (FILTER_HANDLED);
+       return FILTER_HANDLED;
 }
-#endif /* ! DEVICE_POLLING */
 
 /*********************************************************************
  *
+ *  MSIX Interrupt Service Routines
+ *
+ **********************************************************************/
+#define EM_MSIX_TX     0x00040000
+#define EM_MSIX_RX     0x00010000
+#define EM_MSIX_LINK   0x00100000
+
+static void
+em_msix_tx(void *arg)
+{
+       struct adapter *adapter = arg;
+       struct ifnet    *ifp = adapter->ifp;
+
+       ++adapter->tx_irq;
+       if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+               EM_TX_LOCK(adapter);
+               em_txeof(adapter);
+               EM_TX_UNLOCK(adapter);
+               taskqueue_enqueue(adapter->tq, &adapter->tx_task);
+       }
+       /* Reenable this interrupt */
+       E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_TX);
+       return;
+}
+
+/*********************************************************************
+ *
+ *  MSIX RX Interrupt Service routine
+ *
+ **********************************************************************/
+
+static void
+em_msix_rx(void *arg)
+{
+       struct adapter *adapter = arg;
+       struct ifnet    *ifp = adapter->ifp;
+
+       ++adapter->rx_irq;
+       if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
+           (em_rxeof(adapter, adapter->rx_process_limit) != 0))
+               taskqueue_enqueue(adapter->tq, &adapter->rx_task);
+       /* Reenable this interrupt */
+       E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_RX);
+       return;
+}
+
+/*********************************************************************
+ *
+ *  MSIX Link Fast Interrupt Service routine
+ *
+ **********************************************************************/
+
+static void
+em_msix_link(void *arg)
+{
+       struct adapter  *adapter = arg;
+       u32             reg_icr;
+
+       ++adapter->link_irq;
+       reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
+
+       if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+               adapter->hw.mac.get_link_status = 1;
+               taskqueue_enqueue(taskqueue_fast, &adapter->link_task);
+       }
+       E1000_WRITE_REG(&adapter->hw, E1000_IMS,
+           EM_MSIX_LINK | E1000_IMS_LSC);
+       return;
+}
+#endif /* EM_FAST_IRQ */
+
+/*********************************************************************
+ *
  *  Media Ioctl callback
  *
  *  This routine is called whenever the user queries the status of
@@ -1560,22 +1886,21 @@
 
        INIT_DEBUGOUT("em_media_status: begin");
 
-       EM_LOCK(adapter);
-       e1000_check_for_link(&adapter->hw);
+       EM_CORE_LOCK(adapter);
        em_update_link_status(adapter);
 
        ifmr->ifm_status = IFM_AVALID;
        ifmr->ifm_active = IFM_ETHER;
 
        if (!adapter->link_active) {
-               EM_UNLOCK(adapter);
+               EM_CORE_UNLOCK(adapter);
                return;
        }
 
        ifmr->ifm_status |= IFM_ACTIVE;
 
-       if ((adapter->hw.media_type == e1000_media_type_fiber) ||
-           (adapter->hw.media_type == e1000_media_type_internal_serdes)) {
+       if ((adapter->hw.phy.media_type == e1000_media_type_fiber) ||
+           (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) {
                if (adapter->hw.mac.type == e1000_82545)
                        fiber_type = IFM_1000_LX;
                ifmr->ifm_active |= fiber_type | IFM_FDX;
@@ -1596,7 +1921,7 @@
                else
                        ifmr->ifm_active |= IFM_HDX;
        }
-       EM_UNLOCK(adapter);
+       EM_CORE_UNLOCK(adapter);
 }
 
 /*********************************************************************
@@ -1618,7 +1943,7 @@
        if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
                return (EINVAL);
 
-       EM_LOCK(adapter);
+       EM_CORE_LOCK(adapter);
        switch (IFM_SUBTYPE(ifm->ifm_media)) {
        case IFM_AUTO:
                adapter->hw.mac.autoneg = DO_AUTO_NEG;
@@ -1656,7 +1981,7 @@
        adapter->hw.phy.reset_disable = FALSE;
 
        em_init_locked(adapter);
-       EM_UNLOCK(adapter);
+       EM_CORE_UNLOCK(adapter);
 
        return (0);
 }
@@ -1669,21 +1994,27 @@
  **********************************************************************/
 
 static int
-em_encap(struct adapter *adapter, struct mbuf **m_headp)
+em_xmit(struct adapter *adapter, struct mbuf **m_headp)
 {
        bus_dma_segment_t       segs[EM_MAX_SCATTER];
        bus_dmamap_t            map;
        struct em_buffer        *tx_buffer, *tx_buffer_mapped;
        struct e1000_tx_desc    *ctxd = NULL;
        struct mbuf             *m_head;
-       uint32_t                txd_upper, txd_lower, txd_used, txd_saved;
+       u32                     txd_upper, txd_lower, txd_used, txd_saved;
        int                     nsegs, i, j, first, last = 0;
        int                     error, do_tso, tso_desc = 0;
-
+#if __FreeBSD_version < 700000
+       struct m_tag            *mtag;
+#endif
        m_head = *m_headp;
        txd_upper = txd_lower = txd_used = txd_saved = 0;
 
+#if __FreeBSD_version >= 700000
        do_tso = ((m_head->m_pkthdr.csum_flags & CSUM_TSO) != 0);
+#else
+       do_tso = 0;
+#endif
 
         /*
          * Force a cleanup if number of TX descriptors
@@ -1791,10 +2122,23 @@
        m_head = *m_headp;
 
        /* Do hardware assists */
-       if (em_tso_setup(adapter, m_head, &txd_upper, &txd_lower))
+#if __FreeBSD_version >= 700000
+       if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
+               error = em_tso_setup(adapter, m_head, &txd_upper, &txd_lower);
+               if (error != TRUE)
+                       return (ENXIO); /* something foobar */
                /* we need to make a final sentinel transmit desc */
                tso_desc = TRUE;
-       else if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD)
+       } else
+#endif
+#ifndef EM_TIMESYNC
+       /*
+       ** Timesync needs to check the packet header 
+       ** so call checksum code to do so, but don't
+       ** penalize the code if not defined.
+       */
+       if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD)
+#endif
                em_transmit_checksum_setup(adapter,  m_head,
                    &txd_upper, &txd_lower);
 
@@ -1809,7 +2153,7 @@
                /* If adapter is 82544 and on PCIX bus */
                if(adapter->pcix_82544) {
                        DESC_ARRAY      desc_array;
-                       uint32_t        array_elements, counter;
+                       u32             array_elements, counter;
                        /*
                         * Check the Address and Length combination and
                         * split the data accordingly
@@ -1828,7 +2172,7 @@
                                ctxd->buffer_addr = htole64(
                                    desc_array.descriptor[counter].address);
                                ctxd->lower.data = htole32(
-                                   (adapter->txd_cmd | txd_lower | (uint16_t) 
+                                   (adapter->txd_cmd | txd_lower | (u16)
                                    desc_array.descriptor[counter].length));
                                ctxd->upper.data =
                                    htole32((txd_upper));
@@ -1895,10 +2239,23 @@
                        adapter->num_tx_desc_avail -= txd_used;
        }
 
+        /*
+       ** Handle VLAN tag, this is the
+       ** biggest difference between 
+       ** 6.x and 7
+       */
+#if __FreeBSD_version < 700000
+        /* Find out if we are in vlan mode. */
+        mtag = VLAN_OUTPUT_TAG(ifp, m_head);
+        if (mtag != NULL) {
+                ctxd->upper.fields.special =
+                    htole16(VLAN_TAG_VALUE(mtag));
+#else /* FreeBSD 7 */
        if (m_head->m_flags & M_VLANTAG) {
                /* Set the vlan id. */
                ctxd->upper.fields.special =
                    htole16(m_head->m_pkthdr.ether_vtag);
+#endif
                 /* Tell hardware to add tag */
                 ctxd->lower.data |= htole32(E1000_TXD_CMD_VLE);
         }
@@ -1932,188 +2289,22 @@
            adapter->link_duplex == HALF_DUPLEX)
                em_82547_move_tail(adapter);
        else {
-               E1000_WRITE_REG(&adapter->hw, E1000_TDT, i);
+               E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), i);
                if (adapter->hw.mac.type == e1000_82547)
                        em_82547_update_fifo_head(adapter,
                            m_head->m_pkthdr.len);
        }
 
+#ifdef EM_TIMESYNC
+       if (ctxd->upper.data & E1000_TXD_EXTCMD_TSTAMP) {
+               HW_DEBUGOUT( "@@@ Timestamp bit is set in transmit 
descriptor\n" );
+       } 
+#endif
        return (0);
 }
 
 /*********************************************************************
  *
- *  This routine maps the mbufs to Advanced TX descriptors.
- *  used by the 82575 adapter. It also needs no workarounds.
- *  
- **********************************************************************/
-
-static int
-em_adv_encap(struct adapter *adapter, struct mbuf **m_headp)
-{
-       bus_dma_segment_t       segs[EM_MAX_SCATTER];
-       bus_dmamap_t            map;
-       struct em_buffer        *tx_buffer, *tx_buffer_mapped;
-       union e1000_adv_tx_desc *txd = NULL;
-       struct mbuf             *m_head;
-       u32                     olinfo_status = 0, cmd_type_len = 0;
-       u32                     paylen = 0;
-       int                     nsegs, i, j, error, first, last = 0;
-
-       m_head = *m_headp;
-
-
-       /* Set basic descriptor constants */
-       cmd_type_len |= E1000_ADVTXD_DTYP_DATA;
-       cmd_type_len |= E1000_ADVTXD_DCMD_IFCS | E1000_ADVTXD_DCMD_DEXT;
-
-        /*
-         * Force a cleanup if number of TX descriptors
-         * available hits the threshold
-         */
-       if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) {
-               em_txeof(adapter);
-               /* Now do we at least have a minimal? */
-               if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) {
-                       adapter->no_tx_desc_avail1++;
-                       return (ENOBUFS);
-               }
-       }
-
-       /*
-         * Map the packet for DMA.
-        *
-        * Capture the first descriptor index,
-        * this descriptor will have the index
-        * of the EOP which is the only one that
-        * now gets a DONE bit writeback.
-        */
-       first = adapter->next_avail_tx_desc;
-       tx_buffer = &adapter->tx_buffer_area[first];
-       tx_buffer_mapped = tx_buffer;
-       map = tx_buffer->map;
-
-       error = bus_dmamap_load_mbuf_sg(adapter->txtag, map,
-           *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
-       if (error == EFBIG) {
-               struct mbuf *m;
-
-               m = m_defrag(*m_headp, M_DONTWAIT);
-               if (m == NULL) {
-                       adapter->mbuf_alloc_failed++;
-                       m_freem(*m_headp);
-                       *m_headp = NULL;
-                       return (ENOBUFS);
-               }
-               *m_headp = m;
-
-               /* Try it again */
-               error = bus_dmamap_load_mbuf_sg(adapter->txtag, map,
-                   *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
-               if (error == ENOMEM) {
-                       adapter->no_tx_dma_setup++;
-                       return (error);
-               } else if (error != 0) {
-                       adapter->no_tx_dma_setup++;
-                       m_freem(*m_headp);
-                       *m_headp = NULL;
-                       return (error);
-               }
-       } else if (error == ENOMEM) {
-               adapter->no_tx_dma_setup++;
-               return (error);
-       } else if (error != 0) {
-               adapter->no_tx_dma_setup++;
-               m_freem(*m_headp);
-               *m_headp = NULL;
-               return (error);
-       }
-
-       /* Check again to be sure we have enough descriptors */
-        if (nsegs > (adapter->num_tx_desc_avail - 2)) {
-                adapter->no_tx_desc_avail2++;
-               bus_dmamap_unload(adapter->txtag, map);
-               return (ENOBUFS);
-        }
-       m_head = *m_headp;
-
-        /*
-         * Set up the context descriptor:
-         * used when any hardware offload is done.
-        * This includes CSUM, VLAN, and TSO. It
-        * will use the first descriptor.
-         */
-       /* First try TSO */
-       if (em_tso_adv_setup(adapter, m_head, &paylen)) {
-               cmd_type_len |= E1000_ADVTXD_DCMD_TSE;
-               olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
-               olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
-               olinfo_status |= paylen << E1000_ADVTXD_PAYLEN_SHIFT;
-       } else if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) {
-               if (em_tx_adv_ctx_setup(adapter, m_head))
-                       olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
-       }
-
-       /* Set up our transmit descriptors */
-       i = adapter->next_avail_tx_desc;
-       for (j = 0; j < nsegs; j++) {
-               bus_size_t seg_len;
-               bus_addr_t seg_addr;
-
-               tx_buffer = &adapter->tx_buffer_area[i];
-               txd = (union e1000_adv_tx_desc *)&adapter->tx_desc_base[i];
-               seg_addr = segs[j].ds_addr;
-               seg_len  = segs[j].ds_len;
-
-               txd->read.buffer_addr = htole64(seg_addr);
-               txd->read.cmd_type_len = htole32(
-                   adapter->txd_cmd | cmd_type_len | seg_len);
-               txd->read.olinfo_status = htole32(olinfo_status);
-               last = i;
-               if (++i == adapter->num_tx_desc)
-                       i = 0;
-               tx_buffer->m_head = NULL;
-               tx_buffer->next_eop = -1;
-       }
-
-       adapter->next_avail_tx_desc = i;
-       adapter->num_tx_desc_avail -= nsegs;
-
-        tx_buffer->m_head = m_head;
-       tx_buffer_mapped->map = tx_buffer->map;
-       tx_buffer->map = map;
-        bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE);
-
-        /*
-         * Last Descriptor of Packet
-        * needs End Of Packet (EOP)
-        * and Report Status (RS)
-         */
-        txd->read.cmd_type_len |=
-           htole32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS);
-       /*
-        * Keep track in the first buffer which
-        * descriptor will be written back
-        */
-       tx_buffer = &adapter->tx_buffer_area[first];
-       tx_buffer->next_eop = last;
-
-       /*
-        * Advance the Transmit Descriptor Tail (TDT), this tells the E1000
-        * that this frame is available to transmit.
-        */
-       bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
-           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-       E1000_WRITE_REG(&adapter->hw, E1000_TDT, i);
-
-       return (0);
-
-}
-
-/*********************************************************************
- *
  * 82547 workaround to avoid controller hang in half-duplex environment.
  * The workaround is to avoid queuing a large packet that would span
  * the internal Tx FIFO ring boundary. We need to reset the FIFO pointers
@@ -2124,15 +2315,13 @@
 em_82547_move_tail(void *arg)
 {
        struct adapter *adapter = arg;
-       uint16_t hw_tdt;
-       uint16_t sw_tdt;
        struct e1000_tx_desc *tx_desc;
-       uint16_t length = 0;
-       boolean_t eop = 0;
+       u16     hw_tdt, sw_tdt, length = 0;
+       bool    eop = 0;
 
-       EM_LOCK_ASSERT(adapter);
+       EM_TX_LOCK_ASSERT(adapter);
 
-       hw_tdt = E1000_READ_REG(&adapter->hw, E1000_TDT);
+       hw_tdt = E1000_READ_REG(&adapter->hw, E1000_TDT(0));
        sw_tdt = adapter->next_avail_tx_desc;
        
        while (hw_tdt != sw_tdt) {
@@ -2149,7 +2338,7 @@
                                        em_82547_move_tail, adapter);
                                break;
                        }
-                       E1000_WRITE_REG(&adapter->hw, E1000_TDT, hw_tdt);
+                       E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), hw_tdt);
                        em_82547_update_fifo_head(adapter, length);
                        length = 0;
                }
@@ -2193,10 +2382,10 @@
 static int
 em_82547_tx_fifo_reset(struct adapter *adapter)
 {
-       uint32_t tctl;
+       u32 tctl;
 
-       if ((E1000_READ_REG(&adapter->hw, E1000_TDT) ==
-           E1000_READ_REG(&adapter->hw, E1000_TDH)) &&
+       if ((E1000_READ_REG(&adapter->hw, E1000_TDT(0)) ==
+           E1000_READ_REG(&adapter->hw, E1000_TDH(0))) &&
            (E1000_READ_REG(&adapter->hw, E1000_TDFT) == 
            E1000_READ_REG(&adapter->hw, E1000_TDFH)) &&
            (E1000_READ_REG(&adapter->hw, E1000_TDFTS) ==
@@ -2235,12 +2424,15 @@
 em_set_promisc(struct adapter *adapter)
 {
        struct ifnet    *ifp = adapter->ifp;
-       uint32_t        reg_rctl;
+       u32             reg_rctl;
 
        reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
 
        if (ifp->if_flags & IFF_PROMISC) {
                reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
+               /* Turn this on if you want to see bad packets */
+               if (em_debug_sbp)
+                       reg_rctl |= E1000_RCTL_SBP;
                E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
        } else if (ifp->if_flags & IFF_ALLMULTI) {
                reg_rctl |= E1000_RCTL_MPE;
@@ -2252,12 +2444,13 @@
 static void
 em_disable_promisc(struct adapter *adapter)
 {
-       uint32_t        reg_rctl;
+       u32     reg_rctl;
 
        reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
 
        reg_rctl &=  (~E1000_RCTL_UPE);
        reg_rctl &=  (~E1000_RCTL_MPE);
+       reg_rctl &=  (~E1000_RCTL_SBP);
        E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
 }
 
@@ -2274,8 +2467,8 @@
 {
        struct ifnet    *ifp = adapter->ifp;
        struct ifmultiaddr *ifma;
-       uint32_t reg_rctl = 0;
-       uint8_t  mta[512]; /* Largest MTS is 4096 bits */
+       u32 reg_rctl = 0;
+       u8  mta[512]; /* Largest MTS is 4096 bits */
        int mcnt = 0;
 
        IOCTL_DEBUGOUT("em_set_multi: begin");
@@ -2309,7 +2502,7 @@
                reg_rctl |= E1000_RCTL_MPE;
                E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
        } else
-               e1000_mc_addr_list_update(&adapter->hw, mta,
+               e1000_update_mc_addr_list(&adapter->hw, mta,
                    mcnt, 1, adapter->hw.mac.rar_entry_count);
 
        if (adapter->hw.mac.type == e1000_82542 && 
@@ -2337,14 +2530,13 @@
        struct adapter  *adapter = arg;
        struct ifnet    *ifp = adapter->ifp;
 
-       EM_LOCK_ASSERT(adapter);
+       EM_CORE_LOCK_ASSERT(adapter);
 
-       e1000_check_for_link(&adapter->hw);
        em_update_link_status(adapter);
        em_update_stats_counters(adapter);
 
-       /* Check for 82571 LAA reset by other port */
-       if (e1000_get_laa_state_82571(&adapter->hw) == TRUE)  
+       /* Reset LAA into RAR[0] on 82571 */
+       if (e1000_get_laa_state_82571(&adapter->hw) == TRUE)
                e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
 
        if (em_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -2359,50 +2551,74 @@
        em_watchdog(adapter);
 
        callout_reset(&adapter->timer, hz, em_local_timer, adapter);
+
 }
 
 static void
 em_update_link_status(struct adapter *adapter)
 {
+       struct e1000_hw *hw = &adapter->hw;
        struct ifnet *ifp = adapter->ifp;
        device_t dev = adapter->dev;
+       u32 link_check = 0;
 
-       if (E1000_READ_REG(&adapter->hw, E1000_STATUS) &
-           E1000_STATUS_LU) {
-               if (adapter->link_active == 0) {
-                       e1000_get_speed_and_duplex(&adapter->hw, 
-                           &adapter->link_speed, &adapter->link_duplex);
-                       /* Check if we must disable SPEED_MODE bit on PCI-E */
-                       if ((adapter->link_speed != SPEED_1000) &&
-                           ((adapter->hw.mac.type == e1000_82571) ||
-                           (adapter->hw.mac.type == e1000_82572))) {
-                               int tarc0;
+       /* Get the cached link value or read phy for real */
+       switch (hw->phy.media_type) {
+       case e1000_media_type_copper:
+               if (hw->mac.get_link_status) {
+                       /* Do the work to read phy */
+                       e1000_check_for_link(hw);
+                       link_check = !hw->mac.get_link_status;
+                       if (link_check) /* ESB2 fix */
+                               e1000_cfg_on_link_up(hw);
+               } else
+                       link_check = TRUE;
+               break;
+       case e1000_media_type_fiber:
+               e1000_check_for_link(hw);
+               link_check = (E1000_READ_REG(hw, E1000_STATUS) &
+                                 E1000_STATUS_LU);
+               break;
+       case e1000_media_type_internal_serdes:
+               e1000_check_for_link(hw);
+               link_check = adapter->hw.mac.serdes_has_link;
+               break;
+       default:
+       case e1000_media_type_unknown:
+               break;
+       }
 
-                               tarc0 = E1000_READ_REG(&adapter->hw,
-                                   E1000_TARC0);
-                               tarc0 &= ~SPEED_MODE_BIT;
-                               E1000_WRITE_REG(&adapter->hw,
-                                   E1000_TARC0, tarc0);
-                       }
-                       if (bootverbose)
-                               device_printf(dev, "Link is up %d Mbps %s\n",
-                                   adapter->link_speed,
-                                   ((adapter->link_duplex == FULL_DUPLEX) ?
-                                   "Full Duplex" : "Half Duplex"));
-                       adapter->link_active = 1;
-                       adapter->smartspeed = 0;
-                       ifp->if_baudrate = adapter->link_speed * 1000000;
-                       if_link_state_change(ifp, LINK_STATE_UP);
+       /* Now check for a transition */
+       if (link_check && (adapter->link_active == 0)) {
+               e1000_get_speed_and_duplex(hw, &adapter->link_speed,
+                   &adapter->link_duplex);
+               /* Check if we must disable SPEED_MODE bit on PCI-E */
+               if ((adapter->link_speed != SPEED_1000) &&
+                   ((hw->mac.type == e1000_82571) ||
+                   (hw->mac.type == e1000_82572))) {
+                       int tarc0;
+                       tarc0 = E1000_READ_REG(hw, E1000_TARC(0));
+                       tarc0 &= ~SPEED_MODE_BIT;
+                       E1000_WRITE_REG(hw, E1000_TARC(0), tarc0);
                }
-       } else {
-               if (adapter->link_active == 1) {
-                       ifp->if_baudrate = adapter->link_speed = 0;
-                       adapter->link_duplex = 0;
-                       if (bootverbose)
-                               device_printf(dev, "Link is Down\n");
-                       adapter->link_active = 0;
-                       if_link_state_change(ifp, LINK_STATE_DOWN);
-               }
+               if (bootverbose)
+                       device_printf(dev, "Link is up %d Mbps %s\n",
+                           adapter->link_speed,
+                           ((adapter->link_duplex == FULL_DUPLEX) ?
+                           "Full Duplex" : "Half Duplex"));
+               adapter->link_active = 1;
+               adapter->smartspeed = 0;
+               ifp->if_baudrate = adapter->link_speed * 1000000;
+               if_link_state_change(ifp, LINK_STATE_UP);
+       } else if (!link_check && (adapter->link_active == 1)) {
+               ifp->if_baudrate = adapter->link_speed = 0;
+               adapter->link_duplex = 0;
+               if (bootverbose)
+                       device_printf(dev, "Link is Down\n");
+               adapter->link_active = 0;
+               /* Link down, disable watchdog */
+               adapter->watchdog_timer = FALSE;
+               if_link_state_change(ifp, LINK_STATE_DOWN);
        }
 }
 
@@ -2411,6 +2627,8 @@
  *  This routine disables all traffic on the adapter by issuing a
  *  global reset on the MAC and deallocates TX/RX buffers.
  *
+ *  This routine should always be called with BOTH the CORE
+ *  and TX locks.
  **********************************************************************/
 
 static void
@@ -2419,19 +2637,25 @@
        struct adapter  *adapter = arg;
        struct ifnet    *ifp = adapter->ifp;
 
-       EM_LOCK_ASSERT(adapter);
+       EM_CORE_LOCK_ASSERT(adapter);
+       EM_TX_LOCK_ASSERT(adapter);
 
        INIT_DEBUGOUT("em_stop: begin");
 
        em_disable_intr(adapter);
        callout_stop(&adapter->timer);
        callout_stop(&adapter->tx_fifo_timer);
-       em_free_transmit_structures(adapter);
-       em_free_receive_structures(adapter);
 
        /* Tell the stack that the interface is no longer active */
        ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
+#ifdef EM_TIMESYNC
+       /* Disable IEEE 1588 Time hardware */
+       if ((adapter->hw.mac.type == e1000_82574) ||
+           (adapter->hw.mac.type == e1000_ich10lan))
+               em_tsync_disable(adapter);
+#endif
+
        e1000_reset_hw(&adapter->hw);
        if (adapter->hw.mac.type >= e1000_82544)
                E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0);
@@ -2466,7 +2690,8 @@
        adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1);
        adapter->hw.subsystem_vendor_id =
            pci_read_config(dev, PCIR_SUBVEND_0, 2);
-       adapter->hw.subsystem_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 
2);
+       adapter->hw.subsystem_device_id =
+           pci_read_config(dev, PCIR_SUBDEV_0, 2);
 
        /* Do Shared Code Init and Setup */
        if (e1000_set_mac_type(&adapter->hw)) {
@@ -2479,20 +2704,21 @@
 em_allocate_pci_resources(struct adapter *adapter)
 {
        device_t        dev = adapter->dev;
-       int             val, rid;
+       int             val, rid, error = E1000_SUCCESS;
+       int             i = 0;
 
        rid = PCIR_BAR(0);
-       adapter->res_memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+       adapter->memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
            &rid, RF_ACTIVE);
-       if (adapter->res_memory == NULL) {
+       if (adapter->memory == NULL) {
                device_printf(dev, "Unable to allocate bus resource: memory\n");
                return (ENXIO);
        }
        adapter->osdep.mem_bus_space_tag =
-           rman_get_bustag(adapter->res_memory);
+           rman_get_bustag(adapter->memory);
        adapter->osdep.mem_bus_space_handle =
-           rman_get_bushandle(adapter->res_memory);
-       adapter->hw.hw_addr = (uint8_t *)&adapter->osdep.mem_bus_space_handle;
+           rman_get_bushandle(adapter->memory);
+       adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle;
 
        /* Only older adapters use IO mapping */
        if ((adapter->hw.mac.type > e1000_82543) &&
@@ -2513,77 +2739,48 @@
                        device_printf(dev, "Unable to locate IO BAR\n");
                        return (ENXIO);
                }
-               adapter->res_ioport = bus_alloc_resource_any(dev,
+               adapter->ioport = bus_alloc_resource_any(dev,
                    SYS_RES_IOPORT, &adapter->io_rid, RF_ACTIVE);
-               if (adapter->res_ioport == NULL) {
+               if (adapter->ioport == NULL) {
                        device_printf(dev, "Unable to allocate bus resource: "
                            "ioport\n");
                        return (ENXIO);
                }
                adapter->hw.io_base = 0;
                adapter->osdep.io_bus_space_tag =
-                   rman_get_bustag(adapter->res_ioport);
+                   rman_get_bustag(adapter->ioport);
                adapter->osdep.io_bus_space_handle =
-                   rman_get_bushandle(adapter->res_ioport);
+                   rman_get_bushandle(adapter->ioport);
        }
 
        /*
+       ** Init the resource arrays
+       **  used by MSIX setup 
+       */
+       for (i = 0; i < 3; i++) {
+               adapter->rid[i] = i + 1; /* MSI/X RID starts at 1 */
+               adapter->tag[i] = NULL;
+               adapter->res[i] = NULL;
+       }
+
+       /*
         * Setup MSI/X or MSI if PCI Express
-        * only the latest can use MSI/X and
-        * real support for it is forthcoming
         */
-       adapter->msi = 0; /* Set defaults */
-       rid = 0x0;
-       if (adapter->hw.mac.type >= e1000_82575) {
-               /*
-                * Setup MSI/X
-                */
-               rid = PCIR_BAR(EM_MSIX_BAR);
-               adapter->msix_mem = bus_alloc_resource_any(dev,
-                   SYS_RES_MEMORY, &rid, RF_ACTIVE);
-               if (!adapter->msix_mem) {
-                       device_printf(dev,"Unable to map MSIX table \n");
-                        return (ENXIO);
-               }
-               /*
-                * Eventually this may be used
-                * for Multiqueue, for now we will
-                * just use one vector.
-                * 
-                * val = pci_msix_count(dev); 
-                */
-               val = 1;
-               if ((val) && pci_alloc_msix(dev, &val) == 0) {
-                       rid = 1;
-                       adapter->msi = 1;
-               }
-       } else if (adapter->hw.mac.type >= e1000_82571) {
-               val = pci_msi_count(dev);
-               if (val == 1 && pci_alloc_msi(dev, &val) == 0) {
-                       rid = 1;
-                       adapter->msi = 1;
-               } 
-       } 
-       adapter->res_interrupt = bus_alloc_resource_any(dev,
-           SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
-       if (adapter->res_interrupt == NULL) {
-               device_printf(dev, "Unable to allocate bus resource: "
-                   "interrupt\n");
-               return (ENXIO);
-       }
+       if (em_enable_msi)
+               adapter->msi = em_setup_msix(adapter);
 
        adapter->hw.back = &adapter->osdep;
 
-       return (0);
+       return (error);
 }
 
 /*********************************************************************
  *
- *  Setup the appropriate Interrupt handlers.
+ *  Setup the Legacy or MSI Interrupt handler
  *
  **********************************************************************/
 int
-em_allocate_intr(struct adapter *adapter)
+em_allocate_legacy(struct adapter *adapter)
 {
        device_t dev = adapter->dev;
        int error;
@@ -2591,17 +2788,33 @@
        /* Manually turn off all interrupts */
        E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff);
 
-#ifdef DEVICE_POLLING
+       /* Legacy RID is 0 */
+       if (adapter->msi == 0)
+               adapter->rid[0] = 0;
+
+       /* We allocate a single interrupt resource */
+       adapter->res[0] = bus_alloc_resource_any(dev,
+           SYS_RES_IRQ, &adapter->rid[0], RF_SHAREABLE | RF_ACTIVE);
+       if (adapter->res[0] == NULL) {
+               device_printf(dev, "Unable to allocate bus resource: "
+                   "interrupt\n");
+               return (ENXIO);
+       }
+
+#ifdef EM_LEGACY_IRQ
        /* We do Legacy setup */
-       if (adapter->int_handler_tag == NULL &&
-           (error = bus_setup_intr(dev, adapter->res_interrupt,
+       if ((error = bus_setup_intr(dev, adapter->res[0],
+#if __FreeBSD_version > 700000
            INTR_TYPE_NET | INTR_MPSAFE, NULL, em_intr, adapter,
-           &adapter->int_handler_tag)) != 0) {
+#else /* 6.X */
+           INTR_TYPE_NET | INTR_MPSAFE, em_intr, adapter,
+#endif
+           &adapter->tag[0])) != 0) {
                device_printf(dev, "Failed to register interrupt handler");
                return (error);
        }
 
-#else
+#else /* FAST_IRQ */
        /*
         * Try allocating a fast interrupt and the associated deferred
         * processing contexts.
@@ -2612,68 +2825,200 @@
            taskqueue_thread_enqueue, &adapter->tq);
        taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq",
            device_get_nameunit(adapter->dev));
-       if ((error = bus_setup_intr(dev, adapter->res_interrupt,
-           INTR_TYPE_NET, em_intr_fast, NULL, adapter,
-           &adapter->int_handler_tag)) != 0) {
+#if __FreeBSD_version < 700000
+       if ((error = bus_setup_intr(dev, adapter->res[0],
+           INTR_TYPE_NET | INTR_FAST, em_irq_fast, adapter,
+#else
+       if ((error = bus_setup_intr(dev, adapter->res[0],
+           INTR_TYPE_NET, em_irq_fast, NULL, adapter,
+#endif
+           &adapter->tag[0])) != 0) {
                device_printf(dev, "Failed to register fast interrupt "
                            "handler: %d\n", error);
                taskqueue_free(adapter->tq);
                adapter->tq = NULL;
                return (error);
        }
-#endif 
-
-       em_enable_intr(adapter);
+#endif  /* EM_LEGACY_IRQ */
+       
        return (0);
 }
 
-static void
-em_free_intr(struct adapter *adapter)
+/*********************************************************************
+ *
+ *  Setup the MSIX Interrupt handlers
+ *   This is not really Multiqueue, rather
+ *   its just multiple interrupt vectors.
+ *
+ **********************************************************************/
+int
+em_allocate_msix(struct adapter *adapter)
 {
        device_t dev = adapter->dev;
+       int error, i = 0;
 
-       if (adapter->res_interrupt != NULL) {
-               bus_teardown_intr(dev, adapter->res_interrupt,
-                       adapter->int_handler_tag);
-               adapter->int_handler_tag = NULL;
+       /* Make sure all interrupts are disabled */
+       E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff);
+
+       /* First get the resources */
+       for (i = 0; i < adapter->msi; i++) {
+               adapter->res[i] = bus_alloc_resource_any(dev,
+                   SYS_RES_IRQ, &adapter->rid[i], RF_ACTIVE);
+               if (adapter->res[i] == NULL) {
+                       device_printf(dev,
+                           "Unable to allocate bus resource: "
+                           "MSIX Interrupt\n");
+                       return (ENXIO);
+               }
        }
-       if (adapter->tq != NULL) {
-               taskqueue_drain(adapter->tq, &adapter->rxtx_task);
-               taskqueue_drain(taskqueue_fast, &adapter->link_task);
-               taskqueue_free(adapter->tq);
-               adapter->tq = NULL;
+
+       /*
+        * Now allocate deferred processing contexts.
+        */
+       TASK_INIT(&adapter->rx_task, 0, em_handle_rx, adapter);
+       TASK_INIT(&adapter->tx_task, 0, em_handle_tx, adapter);
+       TASK_INIT(&adapter->link_task, 0, em_handle_link, adapter);
+       adapter->tq = taskqueue_create_fast("em_taskq", M_NOWAIT,
+           taskqueue_thread_enqueue, &adapter->tq);
+       taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq",
+           device_get_nameunit(adapter->dev));
+
+       /*
+        * And setup the interrupt handlers
+        */
+
+       /* First slot to RX */
+       if ((error = bus_setup_intr(dev, adapter->res[0],
+#if __FreeBSD_version > 700000
+           INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_rx, adapter,
+#else /* 6.X */
+           INTR_TYPE_NET | INTR_MPSAFE, em_msix_rx, adapter,
+#endif
+           &adapter->tag[0])) != 0) {
+               device_printf(dev, "Failed to register RX handler");
+               return (error);
        }
+
+       /* Next TX */
+       if ((error = bus_setup_intr(dev, adapter->res[1],
+#if __FreeBSD_version > 700000
+           INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_tx, adapter,
+#else /* 6.X */
+           INTR_TYPE_NET | INTR_MPSAFE, em_msix_tx, adapter,
+#endif
+           &adapter->tag[1])) != 0) {
+               device_printf(dev, "Failed to register TX handler");
+               return (error);
+       }
+
+       /* And Link */
+       if ((error = bus_setup_intr(dev, adapter->res[2],
+#if __FreeBSD_version > 700000
+           INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_link, adapter,
+#else /* 6.X */
+           INTR_TYPE_NET | INTR_MPSAFE, em_msix_link, adapter,
+#endif
+           &adapter->tag[2])) != 0) {
+               device_printf(dev, "Failed to register TX handler");
+               return (error);
+       }
+
+       return (0);
 }
 
 static void
 em_free_pci_resources(struct adapter *adapter)
 {
        device_t dev = adapter->dev;
+       int i = 0;
 
-       if (adapter->res_interrupt != NULL)
-               bus_release_resource(dev, SYS_RES_IRQ,
-                   adapter->msi ? 1 : 0, adapter->res_interrupt);
+       /* Make sure the for loop below runs once */
+       if (adapter->msi == 0)
+               adapter->msi = 1;
 
-       if (adapter->msix_mem != NULL)
-               bus_release_resource(dev, SYS_RES_MEMORY,
-                   PCIR_BAR(EM_MSIX_BAR), adapter->msix_mem);
+       /*
+        * First release all the interrupt resources:
+        *      notice that since these are just kept
+        *      in an array we can do the same logic
+        *      whether its MSIX or just legacy.
+        */
+       for (i = 0; i < adapter->msi; i++) {
+               if (adapter->tag[i] != NULL) {
+                       bus_teardown_intr(dev, adapter->res[i],
+                           adapter->tag[i]);
+                       adapter->tag[i] = NULL;
+               }
+               if (adapter->res[i] != NULL) {
+                       bus_release_resource(dev, SYS_RES_IRQ,
+                           adapter->rid[i], adapter->res[i]);
+               }
+       }
 
        if (adapter->msi)
                pci_release_msi(dev);
 
-       if (adapter->res_memory != NULL)
+       if (adapter->msix != NULL)
                bus_release_resource(dev, SYS_RES_MEMORY,
-                   PCIR_BAR(0), adapter->res_memory);
+                   PCIR_BAR(EM_MSIX_BAR), adapter->msix);
 
-       if (adapter->flash_mem != NULL)
+       if (adapter->memory != NULL)
                bus_release_resource(dev, SYS_RES_MEMORY,
-                   EM_FLASH, adapter->flash_mem);
+                   PCIR_BAR(0), adapter->memory);
 
-       if (adapter->res_ioport != NULL)
+       if (adapter->flash != NULL)
+               bus_release_resource(dev, SYS_RES_MEMORY,
+                   EM_FLASH, adapter->flash);
+
+       if (adapter->ioport != NULL)
                bus_release_resource(dev, SYS_RES_IOPORT,
-                   adapter->io_rid, adapter->res_ioport);
+                   adapter->io_rid, adapter->ioport);
 }
 
+/*
+ * Setup MSI/X
+ */
+static int
+em_setup_msix(struct adapter *adapter)
+{
+       device_t dev = adapter->dev;
+       int val = 0;
+
+       if (adapter->hw.mac.type < e1000_82571)
+               return (0);
+
+       /* Setup MSI/X for Hartwell */
+       if (adapter->hw.mac.type == e1000_82574) {
+               /* Map the MSIX BAR */
+               int rid = PCIR_BAR(EM_MSIX_BAR);
+               adapter->msix = bus_alloc_resource_any(dev,
+                   SYS_RES_MEMORY, &rid, RF_ACTIVE);
+                       if (!adapter->msix) {
+                       /* May not be enabled */
+                               device_printf(adapter->dev,
+                           "Unable to map MSIX table \n");
+                       goto msi;
+                       }
+               val = pci_msix_count(dev); 
+               /*
+               ** 82574 can be configured for 5 but
+               ** we limit use to 3.
+               */
+               if (val > 3) val = 3;
+               if ((val) && pci_alloc_msix(dev, &val) == 0) {
+                               device_printf(adapter->dev,"Using MSIX 
interrupts\n");
+                       return (val);
+               }
+       }
+msi:
+               val = pci_msi_count(dev);
+               if (val == 1 && pci_alloc_msi(dev, &val) == 0) {
+                       adapter->msi = 1;
+                       device_printf(adapter->dev,"Using MSI interrupt\n");
+               return (val);
+       } 
+       return (0);
+}
+
 /*********************************************************************
  *
  *  Initialize the hardware to a configuration
@@ -2684,7 +3029,7 @@
 em_hardware_init(struct adapter *adapter)
 {
        device_t dev = adapter->dev;
-       uint16_t rx_buffer_size;
+       u16     rx_buffer_size;
 
        INIT_DEBUGOUT("em_hardware_init: begin");
 
@@ -2694,6 +3039,7 @@
        /* Get control from any management/hw control */
        if (((adapter->hw.mac.type == e1000_82573) ||
            (adapter->hw.mac.type == e1000_ich8lan) ||
+           (adapter->hw.mac.type == e1000_ich10lan) ||
            (adapter->hw.mac.type == e1000_ich9lan)) &&
            e1000_check_mng_mode(&adapter->hw))
                em_get_hw_control(adapter);
@@ -2704,7 +3050,7 @@
        /* Set up smart power down as default off on newer adapters. */
        if (!em_smart_pwr_down && (adapter->hw.mac.type == e1000_82571 ||
            adapter->hw.mac.type == e1000_82572)) {
-               uint16_t phy_tmp = 0;
+               u16 phy_tmp = 0;
 
                /* Speed up time to link by disabling smart power down. */
                e1000_read_phy_reg(&adapter->hw,
@@ -2731,15 +3077,16 @@
        rx_buffer_size = ((E1000_READ_REG(&adapter->hw, E1000_PBA) &
            0xffff) << 10 );
 
-       adapter->hw.mac.fc_high_water = rx_buffer_size -
-           roundup2(adapter->hw.mac.max_frame_size, 1024);
-       adapter->hw.mac.fc_low_water = adapter->hw.mac.fc_high_water - 1500;
+       adapter->hw.fc.high_water = rx_buffer_size -
+           roundup2(adapter->max_frame_size, 1024);
+       adapter->hw.fc.low_water = adapter->hw.fc.high_water - 1500;
+
        if (adapter->hw.mac.type == e1000_80003es2lan)
-               adapter->hw.mac.fc_pause_time = 0xFFFF;
+               adapter->hw.fc.pause_time = 0xFFFF;
        else
-               adapter->hw.mac.fc_pause_time = EM_FC_PAUSE_TIME;
-       adapter->hw.mac.fc_send_xon = TRUE;
-       adapter->hw.mac.fc = e1000_fc_full;
+               adapter->hw.fc.pause_time = EM_FC_PAUSE_TIME;
+       adapter->hw.fc.send_xon = TRUE;
+       adapter->hw.fc.requested_mode = e1000_fc_full;
 
        if (e1000_init_hw(&adapter->hw) < 0) {
                device_printf(dev, "Hardware Initialization Failed\n");
@@ -2782,10 +3129,17 @@
        ifp->if_capabilities = ifp->if_capenable = 0;
 
        if (adapter->hw.mac.type >= e1000_82543) {
-               ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
-               ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
+               int version_cap;
+#if __FreeBSD_version < 700000
+               version_cap = IFCAP_HWCSUM;
+#else
+               version_cap = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
+#endif
+               ifp->if_capabilities |= version_cap;
+               ifp->if_capenable |= version_cap;
        }
 
+#if __FreeBSD_version >= 700000
        /* Identify TSO capable adapters */
        if ((adapter->hw.mac.type > e1000_82544) &&
            (adapter->hw.mac.type != e1000_82547))
@@ -2796,13 +3150,14 @@
         */
        if (adapter->hw.mac.type >= e1000_82571)
                ifp->if_capenable |= IFCAP_TSO4;
+#endif
 
        /*
         * Tell the upper layer(s) we support long frames.
         */
        ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
        ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
-       ifp->if_capenable |= IFCAP_VLAN_MTU;
+       ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
 
 #ifdef DEVICE_POLLING
        ifp->if_capabilities |= IFCAP_POLLING;
@@ -2814,8 +3169,8 @@
         */
        ifmedia_init(&adapter->media, IFM_IMASK,
            em_media_change, em_media_status);
-       if ((adapter->hw.media_type == e1000_media_type_fiber) ||
-           (adapter->hw.media_type == e1000_media_type_internal_serdes)) {
+       if ((adapter->hw.phy.media_type == e1000_media_type_fiber) ||
+           (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) {
                u_char fiber_type = IFM_1000_SX;        /* default type */
 
                if (adapter->hw.mac.type == e1000_82545)
@@ -2851,7 +3206,7 @@
 static void
 em_smartspeed(struct adapter *adapter)
 {
-       uint16_t phy_tmp;
+       u16 phy_tmp;
 
        if (adapter->link_active || (adapter->hw.phy.type != e1000_phy_igp) ||
            adapter->hw.mac.autoneg == 0 ||
@@ -2866,20 +3221,21 @@
                        return;
                e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp);
                if (phy_tmp & SR_1000T_MS_CONFIG_FAULT) {
-                       e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, 
&phy_tmp);
+                       e1000_read_phy_reg(&adapter->hw,
+                           PHY_1000T_CTRL, &phy_tmp);
                        if(phy_tmp & CR_1000T_MS_ENABLE) {
                                phy_tmp &= ~CR_1000T_MS_ENABLE;
-                               e1000_write_phy_reg(&adapter->hw, 
PHY_1000T_CTRL,
-                                   phy_tmp);
+                               e1000_write_phy_reg(&adapter->hw,
+                                   PHY_1000T_CTRL, phy_tmp);
                                adapter->smartspeed++;
                                if(adapter->hw.mac.autoneg &&
                                   !e1000_phy_setup_autoneg(&adapter->hw) &&
-                                  !e1000_read_phy_reg(&adapter->hw, 
PHY_CONTROL,
-                                   &phy_tmp)) {
+                                  !e1000_read_phy_reg(&adapter->hw,
+                                   PHY_CONTROL, &phy_tmp)) {
                                        phy_tmp |= (MII_CR_AUTO_NEG_EN |
                                                    MII_CR_RESTART_AUTO_NEG);
-                                       e1000_write_phy_reg(&adapter->hw, 
PHY_CONTROL,
-                                           phy_tmp);
+                                       e1000_write_phy_reg(&adapter->hw,
+                                           PHY_CONTROL, phy_tmp);
                                }
                        }
                }
@@ -2920,7 +3276,11 @@
 {
        int error;
 
+#if __FreeBSD_version >= 700000
        error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */
+#else
+       error = bus_dma_tag_create(NULL,                 /* parent */
+#endif
                                EM_DBA_ALIGN, 0,        /* alignment, bounds */
                                BUS_SPACE_MAXADDR,      /* lowaddr */
                                BUS_SPACE_MAXADDR,      /* highaddr */
@@ -2939,16 +3299,11 @@
                goto fail_0;
        }
 
-#ifdef __arm__
        error = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr,
            BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
-#else
-       error = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr,
-           BUS_DMA_NOWAIT, &dma->dma_map);
-#endif
        if (error) {
                device_printf(adapter->dev,
-                   "%s: bus_dmamem_alloc(%Lu) failed: %d\n",
+                   "%s: bus_dmamem_alloc(%ju) failed: %d\n",
                    __func__, (uintmax_t)size, error);
                goto fail_2;
        }
@@ -3004,36 +3359,17 @@
 em_allocate_transmit_structures(struct adapter *adapter)
 {
        device_t dev = adapter->dev;
-
-       adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) *
-           adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO);
-       if (adapter->tx_buffer_area == NULL) {
-               device_printf(dev, "Unable to allocate tx_buffer memory\n");
-               return (ENOMEM);
-       }
-
-       bzero(adapter->tx_buffer_area,
-           (sizeof(struct em_buffer)) * adapter->num_tx_desc);
-
-       return (0);
-}
-
-/*********************************************************************
- *
- *  Initialize transmit structures.
- *
- **********************************************************************/
-static int
-em_setup_transmit_structures(struct adapter *adapter)
-{
-       device_t dev = adapter->dev;
        struct em_buffer *tx_buffer;
-       int error, i;
+       int error, i = 0;
 
        /*
         * Create DMA tags for tx descriptors
         */
+#if __FreeBSD_version >= 700000
        if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
+#else
+       if ((error = bus_dma_tag_create(NULL,            /* parent */
+#endif
                                1, 0,                   /* alignment, bounds */
                                BUS_SPACE_MAXADDR,      /* lowaddr */
                                BUS_SPACE_MAXADDR,      /* highaddr */
@@ -3049,39 +3385,66 @@
                goto fail;
        }
 
-       if ((error = em_allocate_transmit_structures(adapter)) != 0)
+       adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) *
+           adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO);
+       if (adapter->tx_buffer_area == NULL) {
+               device_printf(dev, "Unable to allocate tx_buffer memory\n");
+               error = ENOMEM;
                goto fail;
+       }
 
-       /* Clear the old ring contents */
-       bzero(adapter->tx_desc_base,
-           (sizeof(struct e1000_tx_desc)) * adapter->num_tx_desc);
-
        /* Create the descriptor buffer dma maps */
-       tx_buffer = adapter->tx_buffer_area;
        for (i = 0; i < adapter->num_tx_desc; i++) {
+               tx_buffer = &adapter->tx_buffer_area[i];
                error = bus_dmamap_create(adapter->txtag, 0, &tx_buffer->map);
                if (error != 0) {
                        device_printf(dev, "Unable to create TX DMA map\n");
                        goto fail;
                }
                tx_buffer->next_eop = -1;
-               tx_buffer++;
        }
 
+       return (0);
+fail:
+       em_free_transmit_structures(adapter);
+       return (error);
+}
+
+/*********************************************************************
+ *
+ *  (Re)Initialize transmit structures.
+ *
+ **********************************************************************/
+static void
+em_setup_transmit_structures(struct adapter *adapter)
+{
+       struct em_buffer *tx_buffer;
+       int i;
+
+       /* Clear the old ring contents */
+       bzero(adapter->tx_desc_base,
+           (sizeof(struct e1000_tx_desc)) * adapter->num_tx_desc);
+
+       /* Free any existing TX buffers */
+       for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
+               tx_buffer = &adapter->tx_buffer_area[i];
+               bus_dmamap_sync(adapter->txtag, tx_buffer->map,
+                   BUS_DMASYNC_POSTWRITE);
+               bus_dmamap_unload(adapter->txtag, tx_buffer->map);
+               m_freem(tx_buffer->m_head);
+               tx_buffer->m_head = NULL;
+               tx_buffer->next_eop = -1;
+       }
+
+       /* Reset state */
        adapter->next_avail_tx_desc = 0;
        adapter->next_tx_to_clean = 0;
-
-       /* Set number of descriptors available */
        adapter->num_tx_desc_avail = adapter->num_tx_desc;
 
        bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
-       return (0);
-
-fail:
-       em_free_transmit_structures(adapter);
-       return (error);
+       return;
 }
 
 /*********************************************************************
@@ -3092,24 +3455,25 @@
 static void
 em_initialize_transmit_unit(struct adapter *adapter)
 {
-       uint32_t        tctl, tarc, tipg = 0;
-       uint64_t        bus_addr;
+       u32     tctl, tarc, tipg = 0;
+       u64     bus_addr;
 
         INIT_DEBUGOUT("em_initialize_transmit_unit: begin");
        /* Setup the Base and Length of the Tx Descriptor Ring */
        bus_addr = adapter->txdma.dma_paddr;
-       E1000_WRITE_REG(&adapter->hw, E1000_TDLEN,
+       E1000_WRITE_REG(&adapter->hw, E1000_TDLEN(0),
            adapter->num_tx_desc * sizeof(struct e1000_tx_desc));
-       E1000_WRITE_REG(&adapter->hw, E1000_TDBAH, (uint32_t)(bus_addr >> 32));
-       E1000_WRITE_REG(&adapter->hw, E1000_TDBAL, (uint32_t)bus_addr);
-
+       E1000_WRITE_REG(&adapter->hw, E1000_TDBAH(0),
+           (u32)(bus_addr >> 32));
+       E1000_WRITE_REG(&adapter->hw, E1000_TDBAL(0),
+           (u32)bus_addr);
        /* Setup the HW Tx Head and Tail descriptor pointers */
-       E1000_WRITE_REG(&adapter->hw, E1000_TDT, 0);
-       E1000_WRITE_REG(&adapter->hw, E1000_TDH, 0);
+       E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0);
+       E1000_WRITE_REG(&adapter->hw, E1000_TDH(0), 0);
 
        HW_DEBUGOUT2("Base = %x, Length = %x\n",
-           E1000_READ_REG(&adapter->hw, E1000_TDBAL),
-           E1000_READ_REG(&adapter->hw, E1000_TDLEN));
+           E1000_READ_REG(&adapter->hw, E1000_TDBAL(0)),
+           E1000_READ_REG(&adapter->hw, E1000_TDLEN(0)));
 
        /* Set the default values for the Tx Inter Packet Gap timer */
        switch (adapter->hw.mac.type) {
@@ -3124,8 +3488,8 @@
                    E1000_TIPG_IPGR2_SHIFT;
                break;
        default:
-               if ((adapter->hw.media_type == e1000_media_type_fiber) ||
-                   (adapter->hw.media_type ==
+               if ((adapter->hw.phy.media_type == e1000_media_type_fiber) ||
+                   (adapter->hw.phy.media_type ==
                    e1000_media_type_internal_serdes))
                        tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
                else
@@ -3142,16 +3506,16 @@
 
        if ((adapter->hw.mac.type == e1000_82571) ||
            (adapter->hw.mac.type == e1000_82572)) {
-               tarc = E1000_READ_REG(&adapter->hw, E1000_TARC0);
+               tarc = E1000_READ_REG(&adapter->hw, E1000_TARC(0));
                tarc |= SPEED_MODE_BIT;
-               E1000_WRITE_REG(&adapter->hw, E1000_TARC0, tarc);
+               E1000_WRITE_REG(&adapter->hw, E1000_TARC(0), tarc);
        } else if (adapter->hw.mac.type == e1000_80003es2lan) {
-               tarc = E1000_READ_REG(&adapter->hw, E1000_TARC0);
+               tarc = E1000_READ_REG(&adapter->hw, E1000_TARC(0));
                tarc |= 1;
-               E1000_WRITE_REG(&adapter->hw, E1000_TARC0, tarc);
-               tarc = E1000_READ_REG(&adapter->hw, E1000_TARC1);
+               E1000_WRITE_REG(&adapter->hw, E1000_TARC(0), tarc);
+               tarc = E1000_READ_REG(&adapter->hw, E1000_TARC(1));
                tarc |= 1;
-               E1000_WRITE_REG(&adapter->hw, E1000_TARC1, tarc);
+               E1000_WRITE_REG(&adapter->hw, E1000_TARC(1), tarc);
        }
 
        /* Program the Transmit Control Register */
@@ -3169,15 +3533,8 @@
        /* Setup Transmit Descriptor Base Settings */   
        adapter->txd_cmd = E1000_TXD_CMD_IFCS;
 
-       if ((adapter->tx_int_delay.value > 0) &&
-           (adapter->hw.mac.type != e1000_82575))
+       if (adapter->tx_int_delay.value > 0)
                adapter->txd_cmd |= E1000_TXD_CMD_IDE;
-
-        /* Set the function pointer for the transmit routine */
-        if (adapter->hw.mac.type >= e1000_82575)
-                adapter->em_xmit = em_adv_encap;
-        else
-                adapter->em_xmit = em_encap;
 }
 
 /*********************************************************************
@@ -3189,13 +3546,13 @@
 em_free_transmit_structures(struct adapter *adapter)
 {
        struct em_buffer *tx_buffer;
-       int i;
+       int i = 0;
 
        INIT_DEBUGOUT("free_transmit_structures: begin");
 
        if (adapter->tx_buffer_area != NULL) {
-               tx_buffer = adapter->tx_buffer_area;
-               for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
+               for (i = 0; i < adapter->num_tx_desc; i++) {
+                       tx_buffer = &adapter->tx_buffer_area[i];
                        if (tx_buffer->m_head != NULL) {
                                bus_dmamap_sync(adapter->txtag, tx_buffer->map,
                                    BUS_DMASYNC_POSTWRITE);
@@ -3232,27 +3589,25 @@
  **********************************************************************/
 static void
 em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp,
-    uint32_t *txd_upper, uint32_t *txd_lower)
+    u32 *txd_upper, u32 *txd_lower)
 {
        struct e1000_context_desc *TXD;
        struct em_buffer *tx_buffer;
        struct ether_vlan_header *eh;
-       struct ip *ip;
+       struct ip *ip = NULL;
        struct ip6_hdr *ip6;
        struct tcp_hdr *th;
-       int curr_txd, ehdrlen, hdr_len, ip_hlen;
-       uint32_t cmd = 0;
-       uint16_t etype;
-       uint8_t ipproto;
+       int curr_txd, ehdrlen;
+       u32 cmd, hdr_len, ip_hlen;
+       u16 etype;
+       u8 ipproto;
 
+       cmd = hdr_len = ipproto = 0;
        /* Setup checksum offload context. */
        curr_txd = adapter->next_avail_tx_desc;
        tx_buffer = &adapter->tx_buffer_area[curr_txd];
        TXD = (struct e1000_context_desc *) &adapter->tx_desc_base[curr_txd];
 
-       *txd_lower = E1000_TXD_CMD_DEXT |       /* Extended descr type */
-                    E1000_TXD_DTYP_D;          /* Data descr */
-
        /*
         * Determine where frame payload starts.
         * Jump over vlan headers if already present,
@@ -3312,6 +3667,11 @@
                ipproto = ip6->ip6_nxt;
 
                break;
+#ifdef EM_TIMESYNC
+       case ETHERTYPE_IEEE1588:
+               *txd_upper |= E1000_TXD_EXTCMD_TSTAMP;
+               break;
+#endif
        default:
                *txd_upper = 0;
                *txd_lower = 0;
@@ -3336,6 +3696,16 @@
                }
                break;
        case IPPROTO_UDP:
+       {
+#ifdef EM_TIMESYNC
+               void *hdr = (caddr_t) ip + ip_hlen;
+               struct udphdr *uh = (struct udphdr *)hdr;
+
+               if (uh->uh_dport == htons(TSYNC_PORT)) {
+                       *txd_upper |= E1000_TXD_EXTCMD_TSTAMP;
+                       IOCTL_DEBUGOUT("@@@ Sending Event Packet\n");
+               }
+#endif
                if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
                        /*
                         * Start offset for header checksum calculation.
@@ -3348,11 +3718,23 @@
                            hdr_len + offsetof(struct udphdr, uh_sum);
                        *txd_upper |= E1000_TXD_POPTS_TXSM << 8;
                }
-               break;
+               /* Fall Thru */
+       }
        default:
                break;
        }
 
+#ifdef EM_TIMESYNC
+       /*
+       ** We might be here just for TIMESYNC
+       ** which means we don't need the context
+       ** descriptor.
+       */
+       if (!mp->m_pkthdr.csum_flags & CSUM_OFFLOAD)
+               return;
+#endif
+       *txd_lower = E1000_TXD_CMD_DEXT |       /* Extended descr type */
+                    E1000_TXD_DTYP_D;          /* Data descr */
        TXD->tcp_seg_setup.data = htole32(0);
        TXD->cmd_and_length =
            htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd);
@@ -3366,14 +3748,16 @@
        adapter->next_avail_tx_desc = curr_txd;
 }
 
+
+#if __FreeBSD_version >= 700000
 /**********************************************************************
  *
  *  Setup work for hardware segmentation offload (TSO)
  *
  **********************************************************************/
-static boolean_t
-em_tso_setup(struct adapter *adapter, struct mbuf *mp, uint32_t *txd_upper,
-   uint32_t *txd_lower)
+static bool
+em_tso_setup(struct adapter *adapter, struct mbuf *mp, u32 *txd_upper,
+   u32 *txd_lower)
 {
        struct e1000_context_desc *TXD;
        struct em_buffer *tx_buffer;
@@ -3382,20 +3766,9 @@
        struct ip6_hdr *ip6;
        struct tcphdr *th;
        int curr_txd, ehdrlen, hdr_len, ip_hlen, isip6;
-       uint16_t etype;
+       u16 etype;
 
        /*
-        * XXX: This is not really correct as the stack would not have
-        * set up all checksums.
-        * XXX: Return FALSE is not sufficient as we may have to return
-        * in true failure cases as well.  Should do -1 (failure), 0 (no)
-        * and 1 (success).
-        */
-       if (((mp->m_pkthdr.csum_flags & CSUM_TSO) == 0) ||
-            (mp->m_pkthdr.len <= EM_TX_BUFFER_SIZE))
-               return FALSE;
-
-       /*
         * This function could/should be extended to support IP/IPv6
         * fragmentation as well.  But as they say, one step at a time.
         */
@@ -3526,203 +3899,10 @@
        return TRUE;
 }
 
+#endif /* __FreeBSD_version >= 700000 */
 
 /**********************************************************************
  *
- *  Setup work for hardware segmentation offload (TSO) on
- *  adapters using advanced tx descriptors
- *
- **********************************************************************/
-static boolean_t
-em_tso_adv_setup(struct adapter *adapter, struct mbuf *mp, u32 *paylen)
-{
-       struct e1000_adv_tx_context_desc *TXD;
-       struct em_buffer        *tx_buffer;
-       u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
-       u32 mss_l4len_idx = 0;
-       u16 vtag = 0;
-       int ctxd, ehdrlen, hdrlen, ip_hlen, tcp_hlen;
-       struct ether_vlan_header *eh;
-       struct ip *ip;
-       struct tcphdr *th;
-
-       if (((mp->m_pkthdr.csum_flags & CSUM_TSO) == 0) ||
-            (mp->m_pkthdr.len <= EM_TX_BUFFER_SIZE))
-               return FALSE;
-
-       /*
-        * Determine where frame payload starts.
-        * Jump over vlan headers if already present
-        */
-       eh = mtod(mp, struct ether_vlan_header *);
-       if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))
-               ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
-       else
-               ehdrlen = ETHER_HDR_LEN;
-
-       /* Ensure we have at least the IP+TCP header in the first mbuf. */
-       if (mp->m_len < ehdrlen + sizeof(struct ip) + sizeof(struct tcphdr))
-               return FALSE;
-
-       /* Only supports IPV4 for now */
-       ctxd = adapter->next_avail_tx_desc;
-       tx_buffer = &adapter->tx_buffer_area[ctxd];
-       TXD = (struct e1000_adv_tx_context_desc *) &adapter->tx_desc_base[ctxd];
-
-       ip = (struct ip *)(mp->m_data + ehdrlen);
-       if (ip->ip_p != IPPROTO_TCP)
-                return FALSE;   /* 0 */
-       ip->ip_len = 0;
-       ip->ip_sum = 0;
-       ip_hlen = ip->ip_hl << 2;
-       th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
-       th->th_sum = in_pseudo(ip->ip_src.s_addr,
-           ip->ip_dst.s_addr, htons(IPPROTO_TCP));
-       tcp_hlen = th->th_off << 2;
-       hdrlen = ehdrlen + ip_hlen + tcp_hlen;
-       /* Calculate payload, this is used in the transmit desc in encap */
-       *paylen = mp->m_pkthdr.len - hdrlen;
-
-       /* VLAN MACLEN IPLEN */
-       if (mp->m_flags & M_VLANTAG) {
-               vtag = htole16(mp->m_pkthdr.ether_vtag);
-               vlan_macip_lens |= (vtag << E1000_ADVTXD_VLAN_SHIFT);
-       }
-       vlan_macip_lens |= (ehdrlen << E1000_ADVTXD_MACLEN_SHIFT);
-       vlan_macip_lens |= ip_hlen;
-       TXD->vlan_macip_lens |= htole32(vlan_macip_lens);
-
-       /* ADV DTYPE TUCMD */
-       type_tucmd_mlhl |= E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
-       type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP;
-       type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
-       TXD->type_tucmd_mlhl |= htole32(type_tucmd_mlhl);
-
-       /* MSS L4LEN IDX */
-       mss_l4len_idx |= (mp->m_pkthdr.tso_segsz << E1000_ADVTXD_MSS_SHIFT);
-       mss_l4len_idx |= (tcp_hlen << E1000_ADVTXD_L4LEN_SHIFT);
-       TXD->mss_l4len_idx = htole32(mss_l4len_idx);
-
-       TXD->seqnum_seed = htole32(0);
-       tx_buffer->m_head = NULL;
-       tx_buffer->next_eop = -1;
-
-       if (++ctxd == adapter->num_tx_desc)
-               ctxd = 0;
-
-       adapter->num_tx_desc_avail--;
-       adapter->next_avail_tx_desc = ctxd;
-       return TRUE;
-}
-
-
-/*********************************************************************
- *
- *  Advanced Context Descriptor setup for VLAN or CSUM
- *
- **********************************************************************/
-
-static boolean_t
-em_tx_adv_ctx_setup(struct adapter *adapter, struct mbuf *mp)
-{
-       struct e1000_adv_tx_context_desc *TXD;
-       struct em_buffer        *tx_buffer;
-       uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0;
-       struct ether_vlan_header *eh;
-       struct ip *ip;
-       struct ip6_hdr *ip6;
-       int  ehdrlen, ip_hlen;
-       u16     etype;
-       u8      ipproto;
-
-       int ctxd = adapter->next_avail_tx_desc;
-       u16 vtag = 0;
-
-       tx_buffer = &adapter->tx_buffer_area[ctxd];
-       TXD = (struct e1000_adv_tx_context_desc *) &adapter->tx_desc_base[ctxd];
-
-       /*
-       ** In advanced descriptors the vlan tag must 
-       ** be placed into the descriptor itself.
-       */
-       if (mp->m_flags & M_VLANTAG) {
-               vtag = htole16(mp->m_pkthdr.ether_vtag);
-               vlan_macip_lens |= (vtag << E1000_ADVTXD_VLAN_SHIFT);
-       }
-
-       /*
-        * Determine where frame payload starts.
-        * Jump over vlan headers if already present,
-        * helpful for QinQ too.
-        */
-       eh = mtod(mp, struct ether_vlan_header *);
-       if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
-               etype = ntohs(eh->evl_proto);
-               ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
-       } else {
-               etype = ntohs(eh->evl_encap_proto);
-               ehdrlen = ETHER_HDR_LEN;
-       }
-
-       /* Set the ether header length */
-       vlan_macip_lens |= ehdrlen << E1000_ADVTXD_MACLEN_SHIFT;
-
-       switch (etype) {
-               case ETHERTYPE_IP:
-                       ip = (struct ip *)(mp->m_data + ehdrlen);
-                       ip_hlen = ip->ip_hl << 2;
-                       if (mp->m_len < ehdrlen + ip_hlen)
-                               return FALSE; /* failure */
-                       ipproto = ip->ip_p;
-                       type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
-                       break;
-               case ETHERTYPE_IPV6:
-                       ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
-                       ip_hlen = sizeof(struct ip6_hdr);
-                       if (mp->m_len < ehdrlen + ip_hlen)
-                               return FALSE; /* failure */
-                       ipproto = ip6->ip6_nxt;
-                       type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV6;
-                       break;
-               default:
-                       return FALSE;
-       }
-
-       vlan_macip_lens |= ip_hlen;
-       type_tucmd_mlhl |= E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
-
-       switch (ipproto) {
-               case IPPROTO_TCP:
-                       if (mp->m_pkthdr.csum_flags & CSUM_TCP)
-                               type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP;
-                       break;
-               case IPPROTO_UDP:
-                       if (mp->m_pkthdr.csum_flags & CSUM_UDP)
-                               type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_UDP;
-                       break;
-       }
-
-       /* Now copy bits into descriptor */
-       TXD->vlan_macip_lens |= htole32(vlan_macip_lens);
-       TXD->type_tucmd_mlhl |= htole32(type_tucmd_mlhl);
-       TXD->seqnum_seed = htole32(0);
-       TXD->mss_l4len_idx = htole32(0);
-
-       tx_buffer->m_head = NULL;
-       tx_buffer->next_eop = -1;
-
-       /* We've consumed the first desc, adjust counters */
-       if (++ctxd == adapter->num_tx_desc)
-               ctxd = 0;
-       adapter->next_avail_tx_desc = ctxd;
-       --adapter->num_tx_desc_avail;
-
-        return TRUE;
-}
-
-
-/**********************************************************************
- *
  *  Examine each tx_buffer in the used queue. If the hardware is done
  *  processing the packet then free associated resources. The
  *  tx_buffer is put back on the free queue.
@@ -3736,7 +3916,7 @@
         struct e1000_tx_desc   *tx_desc, *eop_desc;
        struct ifnet   *ifp = adapter->ifp;
 
-       EM_LOCK_ASSERT(adapter);
+       EM_TX_LOCK_ASSERT(adapter);
 
         if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
                 return;
@@ -3812,18 +3992,41 @@
         if (num_avail > EM_TX_CLEANUP_THRESHOLD) {                
                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
                /* All clean, turn off the timer */
-                if (num_avail == adapter->num_tx_desc)
+                if (num_avail == adapter->num_tx_desc) {
                        adapter->watchdog_timer = 0;
+               } else
                /* Some cleaned, reset the timer */
-                else if (num_avail != adapter->num_tx_desc_avail)
+                if (num_avail != adapter->num_tx_desc_avail)
                        adapter->watchdog_timer = EM_TX_TIMEOUT;
         }
         adapter->num_tx_desc_avail = num_avail;
-        return;
+       return;
 }
 
 /*********************************************************************
  *
+ *  When Link is lost sometimes there is work still in the TX ring
+ *  which will result in a watchdog, rather than allow that do an
+ *  attempted cleanup and then reinit here. Note that this has been
+ *  seens mostly with fiber adapters.
+ *
+ **********************************************************************/
+static void
+em_tx_purge(struct adapter *adapter)
+{
+       if ((!adapter->link_active) && (adapter->watchdog_timer)) {
+               EM_TX_LOCK(adapter);
+               em_txeof(adapter);
+               EM_TX_UNLOCK(adapter);
+               if (adapter->watchdog_timer) { /* Still not clean? */
+                       adapter->watchdog_timer = 0;
+                       em_init_locked(adapter);
+               }
+       }
+}
+
+/*********************************************************************
+ *
  *  Get a buffer from system mbuf buffer pool.
  *
  **********************************************************************/
@@ -3843,7 +4046,7 @@
        }
        m->m_len = m->m_pkthdr.len = MCLBYTES;
 
-       if (adapter->hw.mac.max_frame_size <= (MCLBYTES - ETHER_ALIGN))
+       if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN))
                m_adj(m, ETHER_ALIGN);
 
        /*
@@ -3890,16 +4093,17 @@
        int i, error;
 
        adapter->rx_buffer_area = malloc(sizeof(struct em_buffer) *
-           adapter->num_rx_desc, M_DEVBUF, M_NOWAIT);
+           adapter->num_rx_desc, M_DEVBUF, M_NOWAIT | M_ZERO);
        if (adapter->rx_buffer_area == NULL) {
                device_printf(dev, "Unable to allocate rx_buffer memory\n");
                return (ENOMEM);
        }
 
-       bzero(adapter->rx_buffer_area,
-           sizeof(struct em_buffer) * adapter->num_rx_desc);
-
-       error = bus_dma_tag_create(bus_get_dma_tag(dev),        /* parent */
+#if __FreeBSD_version >= 700000
+       error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
+#else
+       error = bus_dma_tag_create(NULL,                 /* parent */
+#endif
                                1, 0,                   /* alignment, bounds */
                                BUS_SPACE_MAXADDR,      /* lowaddr */
                                BUS_SPACE_MAXADDR,      /* highaddr */
@@ -3937,15 +4141,6 @@
                }
        }
 
-       /* Setup the initial buffers */
-       for (i = 0; i < adapter->num_rx_desc; i++) {
-               error = em_get_buf(adapter, i);
-               if (error)
-                       goto fail;
-       }
-       bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
-           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
        return (0);
 
 fail:
@@ -3955,22 +4150,42 @@
 
 /*********************************************************************
  *
- *  Allocate and initialize receive structures.
+ *  (Re)initialize receive structures.
  *
  **********************************************************************/
 static int
 em_setup_receive_structures(struct adapter *adapter)
 {
-       int error;
+       struct em_buffer *rx_buffer;
+       int i, error;
 
+       /* Reset descriptor ring */
        bzero(adapter->rx_desc_base,
            (sizeof(struct e1000_rx_desc)) * adapter->num_rx_desc);
 
-       if ((error = em_allocate_receive_structures(adapter)) !=0)
-               return (error);
+       /* Free current RX buffers. */
+       rx_buffer = adapter->rx_buffer_area;
+       for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
+               if (rx_buffer->m_head != NULL) {
+                       bus_dmamap_sync(adapter->rxtag, rx_buffer->map,
+                           BUS_DMASYNC_POSTREAD);
+                       bus_dmamap_unload(adapter->rxtag, rx_buffer->map);
+                       m_freem(rx_buffer->m_head);
+                       rx_buffer->m_head = NULL;
+               }
+        }
 
+       /* Allocate new ones. */
+       for (i = 0; i < adapter->num_rx_desc; i++) {
+               error = em_get_buf(adapter, i);
+               if (error)
+                        return (error);
+       }
+
        /* Setup our descriptor pointers */
        adapter->next_rx_desc_to_check = 0;
+       bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
+           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
        return (0);
 }
@@ -3980,13 +4195,16 @@
  *  Enable receive unit.
  *
  **********************************************************************/
+#define MAX_INTS_PER_SEC       8000
+#define DEFAULT_ITR         1000000000/(MAX_INTS_PER_SEC * 256)
+
 static void
 em_initialize_receive_unit(struct adapter *adapter)
 {
        struct ifnet    *ifp = adapter->ifp;
-       uint64_t        bus_addr;
-       uint32_t        reg_rctl;
-       uint32_t        reg_rxcsum;
+       u64     bus_addr;
+       u32     rctl, rxcsum;
+       int i = 0;
 
        INIT_DEBUGOUT("em_initialize_receive_unit: begin");
 
@@ -3994,69 +4212,86 @@
         * Make sure receives are disabled while setting
         * up the descriptor ring
         */
-       reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
-       E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl & ~E1000_RCTL_EN);
+       rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
+       E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
 
-       if(adapter->hw.mac.type >= e1000_82540) {
+       if (adapter->hw.mac.type >= e1000_82540) {
                E1000_WRITE_REG(&adapter->hw, E1000_RADV,
                    adapter->rx_abs_int_delay.value);
                /*
                 * Set the interrupt throttling rate. Value is calculated
                 * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns)
                 */
-#define MAX_INTS_PER_SEC       8000
-#define DEFAULT_ITR         1000000000/(MAX_INTS_PER_SEC * 256)
                E1000_WRITE_REG(&adapter->hw, E1000_ITR, DEFAULT_ITR);
        }
 
+       /*
+       ** When using MSIX interrupts we need to throttle
+       ** using the EITR register (82574 only)
+       */
+       if (adapter->msix)
+               for (i = 0; i < 4; i++)
+                       E1000_WRITE_REG(&adapter->hw,
+                           E1000_EITR_82574(i), DEFAULT_ITR);
+
+       /* Disable accelerated ackknowledge */
+       if (adapter->hw.mac.type == e1000_82574)
+               E1000_WRITE_REG(&adapter->hw,
+                   E1000_RFCTL, E1000_RFCTL_ACK_DIS);
+
        /* Setup the Base and Length of the Rx Descriptor Ring */
        bus_addr = adapter->rxdma.dma_paddr;
-       E1000_WRITE_REG(&adapter->hw, E1000_RDLEN, adapter->num_rx_desc *
-                       sizeof(struct e1000_rx_desc));
-       E1000_WRITE_REG(&adapter->hw, E1000_RDBAH, (uint32_t)(bus_addr >> 32));
-       E1000_WRITE_REG(&adapter->hw, E1000_RDBAL, (uint32_t)bus_addr);
+       E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0),
+           adapter->num_rx_desc * sizeof(struct e1000_rx_desc));
+       E1000_WRITE_REG(&adapter->hw, E1000_RDBAH(0),
+           (u32)(bus_addr >> 32));
+       E1000_WRITE_REG(&adapter->hw, E1000_RDBAL(0),
+           (u32)bus_addr);
 
        /* Setup the Receive Control Register */
-       reg_rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
-       reg_rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
+       rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
+       rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
                   E1000_RCTL_RDMTS_HALF |
                   (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
 
+       /* Make sure VLAN Filters are off */
+       rctl &= ~E1000_RCTL_VFE;
+
        if (e1000_tbi_sbp_enabled_82543(&adapter->hw))
-               reg_rctl |= E1000_RCTL_SBP;
+               rctl |= E1000_RCTL_SBP;
        else
-               reg_rctl &= ~E1000_RCTL_SBP;
+               rctl &= ~E1000_RCTL_SBP;
 
        switch (adapter->rx_buffer_len) {
        default:
        case 2048:
-               reg_rctl |= E1000_RCTL_SZ_2048;
+               rctl |= E1000_RCTL_SZ_2048;
                break;
        case 4096:
-               reg_rctl |= E1000_RCTL_SZ_4096 |
+               rctl |= E1000_RCTL_SZ_4096 |
                    E1000_RCTL_BSEX | E1000_RCTL_LPE;
                break;
        case 8192:
-               reg_rctl |= E1000_RCTL_SZ_8192 |
+               rctl |= E1000_RCTL_SZ_8192 |
                    E1000_RCTL_BSEX | E1000_RCTL_LPE;
                break;
        case 16384:
-               reg_rctl |= E1000_RCTL_SZ_16384 |
+               rctl |= E1000_RCTL_SZ_16384 |
                    E1000_RCTL_BSEX | E1000_RCTL_LPE;
                break;
        }
 
        if (ifp->if_mtu > ETHERMTU)
-               reg_rctl |= E1000_RCTL_LPE;
+               rctl |= E1000_RCTL_LPE;
        else
-               reg_rctl &= ~E1000_RCTL_LPE;
+               rctl &= ~E1000_RCTL_LPE;
 
        /* Enable 82543 Receive Checksum Offload for TCP and UDP */
        if ((adapter->hw.mac.type >= e1000_82543) &&
            (ifp->if_capenable & IFCAP_RXCSUM)) {
-               reg_rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM);
-               reg_rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL);
-               E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, reg_rxcsum);
+               rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM);
+               rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL);
+               E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum);
        }
 
        /*
@@ -4070,14 +4305,14 @@
                E1000_WRITE_REG(&adapter->hw, E1000_RDTR, 0x20);
 
        /* Enable Receives */
-       E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
+       E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
 
        /*
         * Setup the HW Rx Head and
         * Tail Descriptor Pointers
         */
-       E1000_WRITE_REG(&adapter->hw, E1000_RDH, 0);
-       E1000_WRITE_REG(&adapter->hw, E1000_RDT, adapter->num_rx_desc - 1);
+       E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0);
+       E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), adapter->num_rx_desc - 1);
 
        return;
 }
@@ -4146,25 +4381,23 @@
 static int
 em_rxeof(struct adapter *adapter, int count)
 {
-       struct ifnet    *ifp;
+       struct ifnet    *ifp = adapter->ifp;
        struct mbuf     *mp;
-       uint8_t         accept_frame = 0;
-       uint8_t         eop = 0;
-       uint16_t        len, desc_len, prev_len_adj;
+       u8              status, accept_frame = 0, eop = 0;
+       u16             len, desc_len, prev_len_adj;
        int             i;
-
-       /* Pointer to the receive descriptor being examined. */
        struct e1000_rx_desc   *current_desc;
-       uint8_t         status;
 
-       ifp = adapter->ifp;
+       EM_RX_LOCK(adapter);
        i = adapter->next_rx_desc_to_check;
        current_desc = &adapter->rx_desc_base[i];
        bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
            BUS_DMASYNC_POSTREAD);
 
-       if (!((current_desc->status) & E1000_RXD_STAT_DD))
+       if (!((current_desc->status) & E1000_RXD_STAT_DD)) {
+               EM_RX_UNLOCK(adapter);
                return (0);
+       }
 
        while ((current_desc->status & E1000_RXD_STAT_DD) &&
            (count != 0) &&
@@ -4197,18 +4430,20 @@
                }
 
                if (current_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
-                       uint8_t         last_byte;
-                       uint32_t        pkt_len = desc_len;
+                       u8      last_byte;
+                       u32     pkt_len = desc_len;
 
                        if (adapter->fmp != NULL)
                                pkt_len += adapter->fmp->m_pkthdr.len;
 
                        last_byte = *(mtod(mp, caddr_t) + desc_len - 1);        
                
                        if (TBI_ACCEPT(&adapter->hw, status,
-                           current_desc->errors, pkt_len, last_byte)) {
+                           current_desc->errors, pkt_len, last_byte,
+                           adapter->min_frame_size, adapter->max_frame_size)) {
                                e1000_tbi_adjust_stats_82543(&adapter->hw,
                                    &adapter->stats, pkt_len,
-                                   adapter->hw.mac.addr);
+                                   adapter->hw.mac.addr,
+                                   adapter->max_frame_size);
                                if (len > 0)
                                        len--;
                        } else
@@ -4252,16 +4487,22 @@
                                em_receive_checksum(adapter, current_desc,
                                    adapter->fmp);
 #ifndef __NO_STRICT_ALIGNMENT
-                               if (adapter->hw.mac.max_frame_size >
+                               if (adapter->max_frame_size >
                                    (MCLBYTES - ETHER_ALIGN) &&
                                    em_fixup_rx(adapter) != 0)
                                        goto skip;
 #endif
                                if (status & E1000_RXD_STAT_VP) {
+#if __FreeBSD_version < 700000
+                                       VLAN_INPUT_TAG_NEW(ifp, adapter->fmp,
+                                           (le16toh(current_desc->special) &
+                                           E1000_RXD_SPC_VLAN_MASK));
+#else
                                        adapter->fmp->m_pkthdr.ether_vtag =
                                            (le16toh(current_desc->special) &
                                            E1000_RXD_SPC_VLAN_MASK);
                                        adapter->fmp->m_flags |= M_VLANTAG;
+#endif
                                }
 #ifndef __NO_STRICT_ALIGNMENT
 skip:
@@ -4278,7 +4519,7 @@
                        mp->m_len = mp->m_pkthdr.len = MCLBYTES;
                        mp->m_data = mp->m_ext.ext_buf;
                        mp->m_next = NULL;
-                       if (adapter->hw.mac.max_frame_size <=
+                       if (adapter->max_frame_size <=
                            (MCLBYTES - ETHER_ALIGN))
                                m_adj(mp, ETHER_ALIGN);
                        if (adapter->fmp != NULL) {
@@ -4299,14 +4540,10 @@
                        i = 0;
                if (m != NULL) {
                        adapter->next_rx_desc_to_check = i;
-#ifdef DEVICE_POLLING
-                       EM_UNLOCK(adapter);
+                       /* Unlock for call into stack */
+                       EM_RX_UNLOCK(adapter);
                        (*ifp->if_input)(ifp, m);
-                       EM_LOCK(adapter);
-#else
-                       /* Already running unlocked */
-                       (*ifp->if_input)(ifp, m);
-#endif
+                       EM_RX_LOCK(adapter);
                        i = adapter->next_rx_desc_to_check;
                }
                current_desc = &adapter->rx_desc_base[i];
@@ -4316,7 +4553,8 @@
        /* Advance the E1000's Receive Queue #0  "Tail Pointer". */
        if (--i < 0)
                i = adapter->num_rx_desc - 1;
-       E1000_WRITE_REG(&adapter->hw, E1000_RDT, i);
+       E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i);
+       EM_RX_UNLOCK(adapter);
        if (!((current_desc->status) & E1000_RXD_STAT_DD))
                return (0);
 
@@ -4412,29 +4650,87 @@
        }
 }
 
-
+/*
+ * This routine is run via an vlan
+ * config EVENT
+ */
 static void
-em_enable_vlans(struct adapter *adapter)
+em_register_vlan(void *unused, struct ifnet *ifp, u16 vtag)
 {
-       uint32_t ctrl;
+       struct adapter  *adapter = ifp->if_softc;
+       u32             ctrl, rctl, index, vfta;
 
-       E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
-
        ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
        ctrl |= E1000_CTRL_VME;
        E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
+
+       /* Setup for Hardware Filter */
+       rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
+       rctl |= E1000_RCTL_VFE;
+       rctl &= ~E1000_RCTL_CFIEN;
+       E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
+
+       /* Make entry in the hardware filter table */
+       index = ((vtag >> 5) & 0x7F);
+       vfta = E1000_READ_REG_ARRAY(&adapter->hw, E1000_VFTA, index);
+       vfta |= (1 << (vtag & 0x1F));
+       E1000_WRITE_REG_ARRAY(&adapter->hw, E1000_VFTA, index, vfta);
+
+       /* Update the frame size */
+       E1000_WRITE_REG(&adapter->hw, E1000_RLPML,
+           adapter->max_frame_size + VLAN_TAG_SIZE);
+
 }
 
+/*
+ * This routine is run via an vlan
+ * unconfig EVENT
+ */
 static void
+em_unregister_vlan(void *unused, struct ifnet *ifp, u16 vtag)
+{
+       struct adapter  *adapter = ifp->if_softc;
+       u32             index, vfta;
+
+       /* Remove entry in the hardware filter table */
+       index = ((vtag >> 5) & 0x7F);
+       vfta = E1000_READ_REG_ARRAY(&adapter->hw, E1000_VFTA, index);
+       vfta &= ~(1 << (vtag & 0x1F));
+       E1000_WRITE_REG_ARRAY(&adapter->hw, E1000_VFTA, index, vfta);
+       /* Have all vlans unregistered? */
+       if (adapter->ifp->if_vlantrunk == NULL) {
+               u32 rctl;
+               /* Turn off the filter table */
+               rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
+               rctl &= ~E1000_RCTL_VFE;
+               rctl |= E1000_RCTL_CFIEN;
+               E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
+               /* Reset the frame size */
+               E1000_WRITE_REG(&adapter->hw, E1000_RLPML,
+                   adapter->max_frame_size);
+       }
+}
+
+static void
 em_enable_intr(struct adapter *adapter)
 {
-       E1000_WRITE_REG(&adapter->hw, E1000_IMS,
-           (IMS_ENABLE_MASK));
+       struct e1000_hw *hw = &adapter->hw;
+       u32 ims_mask = IMS_ENABLE_MASK;
+
+       if (adapter->msix) {
+               E1000_WRITE_REG(hw, EM_EIAC, EM_MSIX_MASK);
+               ims_mask |= EM_MSIX_MASK;
+       } 
+       E1000_WRITE_REG(hw, E1000_IMS, ims_mask);
 }
 
 static void
 em_disable_intr(struct adapter *adapter)
 {
+       struct e1000_hw *hw = &adapter->hw;
+
+       if (adapter->msix)
+               E1000_WRITE_REG(hw, EM_EIAC, 0);
        E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff);
 }
 
@@ -4513,6 +4809,7 @@
        case e1000_80003es2lan:
        case e1000_ich8lan:
        case e1000_ich9lan:
+       case e1000_ich10lan:
                ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
                E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
                    ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
@@ -4546,6 +4843,7 @@
        case e1000_80003es2lan:
        case e1000_ich8lan:
        case e1000_ich9lan:
+       case e1000_ich10lan:
                ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
                E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
                    ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
@@ -4557,7 +4855,7 @@
 }
 
 static int
-em_is_valid_ether_addr(uint8_t *addr)
+em_is_valid_ether_addr(u8 *addr)
 {
        char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
 
@@ -4569,84 +4867,6 @@
 }
 
 /*
- * NOTE: the following routines using the e1000 
- *     naming style are provided to the shared
- *     code which expects that rather than 'em'
- */
-
-void
-e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
-{
-       pci_write_config(((struct e1000_osdep *)hw->back)->dev, reg, *value, 2);
-}
-
-void
-e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
-{
-       *value = pci_read_config(((struct e1000_osdep *)hw->back)->dev, reg, 2);
-}
-
-void
-e1000_pci_set_mwi(struct e1000_hw *hw)
-{
-       pci_write_config(((struct e1000_osdep *)hw->back)->dev, PCIR_COMMAND,
-           (hw->bus.pci_cmd_word | CMD_MEM_WRT_INVALIDATE), 2);
-}
-
-void
-e1000_pci_clear_mwi(struct e1000_hw *hw)
-{
-       pci_write_config(((struct e1000_osdep *)hw->back)->dev, PCIR_COMMAND,
-           (hw->bus.pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE), 2);
-}
-
-/*
- * Read the PCI Express capabilities
- */
-int32_t
-e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
-{
-       int32_t         error = E1000_SUCCESS;
-       uint16_t        cap_off;
-
-       switch (hw->mac.type) {
-
-               case e1000_82571:
-               case e1000_82572:
-               case e1000_82573:
-               case e1000_80003es2lan:
-                       cap_off = 0xE0;
-                       e1000_read_pci_cfg(hw, cap_off + reg, value);
-                       break;
-               default:
-                       error = ~E1000_NOT_IMPLEMENTED;
-                       break;
-       }
-
-       return (error); 
-}
-
-int32_t
-e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, uint32_t size)
-{
-       int32_t error = 0;
-
-       hw->dev_spec = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
-       if (hw->dev_spec == NULL)
-               error = ENOMEM;
-
-       return (error);
-}
-
-void
-e1000_free_dev_spec_struct(struct e1000_hw *hw)
-{
-       if (hw->dev_spec != NULL)
-               free(hw->dev_spec, M_DEVBUF);
-       return;
-}
-
-/*
  * Enable PCI Wake On Lan capability
  */
 void
@@ -4690,20 +4910,21 @@
 *        as 1,2,3,4(Hang) or 9,a,b,c (DAC)
 *
 *************************************************************************/
-static uint32_t
-em_fill_descriptors (bus_addr_t address, uint32_t length,
+static u32
+em_fill_descriptors (bus_addr_t address, u32 length,
                PDESC_ARRAY desc_array)
 {
+       u32 safe_terminator;
+
        /* Since issue is sensitive to length and address.*/
        /* Let us first check the address...*/
-       uint32_t safe_terminator;
        if (length <= 4) {
                desc_array->descriptor[0].address = address;
                desc_array->descriptor[0].length = length;
                desc_array->elements = 1;
                return (desc_array->elements);
        }
-       safe_terminator = (uint32_t)((((uint32_t)address & 0x7) +
+       safe_terminator = (u32)((((u32)address & 0x7) +
            (length & 0xF)) & 0xF);
        /* if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then return */
        if (safe_terminator == 0   ||
@@ -4735,7 +4956,7 @@
 {
        struct ifnet   *ifp;
 
-       if(adapter->hw.media_type == e1000_media_type_copper ||
+       if(adapter->hw.phy.media_type == e1000_media_type_copper ||
           (E1000_READ_REG(&adapter->hw, E1000_STATUS) & E1000_STATUS_LU)) {
                adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, 
E1000_SYMERRS);
                adapter->stats.sec += E1000_READ_REG(&adapter->hw, E1000_SEC);
@@ -4769,10 +4990,8 @@
        /* For the 64-bit byte counters the low dword must be read first. */
        /* Both registers clear on the read of the high dword */
 
-       adapter->stats.gorcl += E1000_READ_REG(&adapter->hw, E1000_GORCL);
-       adapter->stats.gorch += E1000_READ_REG(&adapter->hw, E1000_GORCH);
-       adapter->stats.gotcl += E1000_READ_REG(&adapter->hw, E1000_GOTCL);
-       adapter->stats.gotch += E1000_READ_REG(&adapter->hw, E1000_GOTCH);
+       adapter->stats.gorc += E1000_READ_REG(&adapter->hw, E1000_GORCH);
+       adapter->stats.gotc += E1000_READ_REG(&adapter->hw, E1000_GOTCH);
 
        adapter->stats.rnbc += E1000_READ_REG(&adapter->hw, E1000_RNBC);
        adapter->stats.ruc += E1000_READ_REG(&adapter->hw, E1000_RUC);
@@ -4780,10 +4999,8 @@
        adapter->stats.roc += E1000_READ_REG(&adapter->hw, E1000_ROC);
        adapter->stats.rjc += E1000_READ_REG(&adapter->hw, E1000_RJC);
 
-       adapter->stats.torl += E1000_READ_REG(&adapter->hw, E1000_TORL);
-       adapter->stats.torh += E1000_READ_REG(&adapter->hw, E1000_TORH);
-       adapter->stats.totl += E1000_READ_REG(&adapter->hw, E1000_TOTL);
-       adapter->stats.toth += E1000_READ_REG(&adapter->hw, E1000_TOTH);
+       adapter->stats.tor += E1000_READ_REG(&adapter->hw, E1000_TORH);
+       adapter->stats.tot += E1000_READ_REG(&adapter->hw, E1000_TOTH);
 
        adapter->stats.tpr += E1000_READ_REG(&adapter->hw, E1000_TPR);
        adapter->stats.tpt += E1000_READ_REG(&adapter->hw, E1000_TPT);
@@ -4837,7 +5054,7 @@
 em_print_debug_info(struct adapter *adapter)
 {
        device_t dev = adapter->dev;
-       uint8_t *hw_addr = adapter->hw.hw_addr;
+       u8 *hw_addr = adapter->hw.hw_addr;
 
        device_printf(dev, "Adapter hardware address = %p \n", hw_addr);
        device_printf(dev, "CTRL = 0x%x RCTL = 0x%x \n",
@@ -4847,8 +5064,8 @@
            ((E1000_READ_REG(&adapter->hw, E1000_PBA) & 0xffff0000) >> 16),\
            (E1000_READ_REG(&adapter->hw, E1000_PBA) & 0xffff) );
        device_printf(dev, "Flow control watermarks high = %d low = %d\n",
-           adapter->hw.mac.fc_high_water,
-           adapter->hw.mac.fc_low_water);
+           adapter->hw.fc.high_water,
+           adapter->hw.fc.low_water);
        device_printf(dev, "tx_int_delay = %d, tx_abs_int_delay = %d\n",
            E1000_READ_REG(&adapter->hw, E1000_TIDV),
            E1000_READ_REG(&adapter->hw, E1000_TADV));
@@ -4859,11 +5076,11 @@
            (long long)adapter->tx_fifo_wrk_cnt,
            (long long)adapter->tx_fifo_reset_cnt);
        device_printf(dev, "hw tdh = %d, hw tdt = %d\n",
-           E1000_READ_REG(&adapter->hw, E1000_TDH),
-           E1000_READ_REG(&adapter->hw, E1000_TDT));
+           E1000_READ_REG(&adapter->hw, E1000_TDH(0)),
+           E1000_READ_REG(&adapter->hw, E1000_TDT(0)));
        device_printf(dev, "hw rdh = %d, hw rdt = %d\n",
-           E1000_READ_REG(&adapter->hw, E1000_RDH),
-           E1000_READ_REG(&adapter->hw, E1000_RDT));
+           E1000_READ_REG(&adapter->hw, E1000_RDH(0)),
+           E1000_READ_REG(&adapter->hw, E1000_RDT(0)));
        device_printf(dev, "Num Tx descriptors avail = %d\n",
            adapter->num_tx_desc_avail);
        device_printf(dev, "Tx Descriptors not avail1 = %ld\n",
@@ -4908,11 +5125,14 @@
            (long long)adapter->stats.crcerrs);
        device_printf(dev, "Alignment errors = %lld\n",
            (long long)adapter->stats.algnerrc);
-       device_printf(dev, "Carrier extension errors = %lld\n",
+       device_printf(dev, "Collision/Carrier extension errors = %lld\n",
            (long long)adapter->stats.cexterr);
        device_printf(dev, "RX overruns = %ld\n", adapter->rx_overruns);
        device_printf(dev, "watchdog timeouts = %ld\n",
            adapter->watchdog_events);
+       device_printf(dev, "RX MSIX IRQ = %ld TX MSIX IRQ = %ld"
+           " LINK MSIX IRQ = %ld\n", adapter->rx_irq,
+           adapter->tx_irq , adapter->link_irq);
        device_printf(dev, "XON Rcvd = %lld\n",
            (long long)adapter->stats.xonrxc);
        device_printf(dev, "XON Xmtd = %lld\n",
@@ -4931,6 +5151,33 @@
            (long long)adapter->stats.tsctfc);
 }
 
+/**********************************************************************
+ *
+ *  This routine provides a way to dump out the adapter eeprom,
+ *  often a useful debug/service tool. This only dumps the first
+ *  32 words, stuff that matters is in that extent.
+ *
+ **********************************************************************/
+static void
+em_print_nvm_info(struct adapter *adapter)
+{
+       u16     eeprom_data;
+       int     i, j, row = 0;
+
+       /* Its a bit crude, but it gets the job done */
+       printf("\nInterface EEPROM Dump:\n");
+       printf("Offset\n0x0000  ");
+       for (i = 0, j = 0; i < 32; i++, j++) {
+               if (j == 8) { /* Make the offset block */
+                       j = 0; ++row;
+                       printf("\n0x00%x0  ",row);
+               }
+               e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data);
+               printf("%04x ", eeprom_data);
+       }
+       printf("\n");
+}
+
 static int
 em_sysctl_debug_info(SYSCTL_HANDLER_ARGS)
 {
@@ -4948,6 +5195,15 @@
                adapter = (struct adapter *)arg1;
                em_print_debug_info(adapter);
        }
+       /*
+        * This value will cause a hex dump of the
+        * first 32 16-bit words of the EEPROM to
+        * the screen.
+        */
+       if (result == 2) {
+               adapter = (struct adapter *)arg1;
+               em_print_nvm_info(adapter);
+        }
 
        return (error);
 }
@@ -4979,7 +5235,7 @@
 {
        struct em_int_delay_info *info;
        struct adapter *adapter;
-       uint32_t regval;
+       u32 regval;
        int error;
        int usecs;
        int ticks;
@@ -4996,7 +5252,7 @@
 
        adapter = info->adapter;
        
-       EM_LOCK(adapter);
+       EM_CORE_LOCK(adapter);
        regval = E1000_READ_OFFSET(&adapter->hw, info->offset);
        regval = (regval & ~0xffff) | (ticks & 0xffff);
        /* Handle a few special cases. */
@@ -5009,12 +5265,11 @@
                        /* Don't write 0 into the TIDV register. */
                        regval++;
                } else
-                       if (adapter->hw.mac.type != e1000_82575)
-                               adapter->txd_cmd |= E1000_TXD_CMD_IDE;
+                       adapter->txd_cmd |= E1000_TXD_CMD_IDE;
                break;
        }
        E1000_WRITE_OFFSET(&adapter->hw, info->offset, regval);
-       EM_UNLOCK(adapter);
+       EM_CORE_UNLOCK(adapter);
        return (0);
 }
 
@@ -5032,7 +5287,7 @@
            info, 0, em_sysctl_int_delay, "I", description);
 }
 
-#ifndef DEVICE_POLLING
+#ifndef EM_LEGACY_IRQ
 static void
 em_add_rx_process_limit(struct adapter *adapter, const char *name,
        const char *description, int *limit, int value)
@@ -5043,3 +5298,101 @@
            OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
 }
 #endif
+
+#ifdef EM_TIMESYNC
+/*
+ * Initialize the Time Sync Feature
+ */
+static int
+em_tsync_init(struct adapter *adapter)
+{
+       device_t        dev = adapter->dev;
+       u32             tx_ctl, rx_ctl;
+
+
+       E1000_WRITE_REG(&adapter->hw, E1000_TIMINCA, (1<<24) |
+           20833/PICOSECS_PER_TICK);
+
+       adapter->last_stamp =  E1000_READ_REG(&adapter->hw, E1000_SYSTIML);
+       adapter->last_stamp |= (u64)E1000_READ_REG(&adapter->hw,
+           E1000_SYSTIMH) << 32ULL;
+
+       /* Enable the TX side */
+       tx_ctl =  E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
+       tx_ctl |= 0x10;
+       E1000_WRITE_REG(&adapter->hw, E1000_TSYNCTXCTL, tx_ctl);
+       E1000_WRITE_FLUSH(&adapter->hw);
+
+       tx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
+       if ((tx_ctl & 0x10) == 0) {
+               device_printf(dev, "Failed to enable TX timestamping\n");
+               return (ENXIO);
+       } 
+
+       /* Enable RX */
+       rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
+       rx_ctl |= 0x10; /* Enable the feature */
+       rx_ctl |= 0x0a; /* This value turns on Ver 1 and 2 */
+       E1000_WRITE_REG(&adapter->hw, E1000_TSYNCRXCTL, rx_ctl);
+
+       /*
+        * Ethertype Stamping (Ethertype = 0x88F7)
+        */
+       E1000_WRITE_REG(&adapter->hw, E1000_RXMTRL, htonl(0x440088f7));
+
+       /*
+        * Source Port Queue Filter Setup:
+        *  this is for UDP port filtering 
+        */
+       E1000_WRITE_REG(&adapter->hw, E1000_RXUDP, htons(TSYNC_PORT));
+       /* Protocol = UDP, enable Timestamp, and filter on source/protocol */
+
+       E1000_WRITE_FLUSH(&adapter->hw);
+
+       rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
+       if ((rx_ctl & 0x10) == 0) {
+               device_printf(dev, "Failed to enable RX timestamping\n");
+               return (ENXIO);
+       } 
+
+       device_printf(dev, "IEEE 1588 Precision Time Protocol enabled\n");
+
+       return (0);
+}
+
+/*
+ * Disable the Time Sync Feature
+ */
+static void
+em_tsync_disable(struct adapter *adapter)
+{
+       u32             tx_ctl, rx_ctl;
+ 
+       tx_ctl =  E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
+       tx_ctl &= ~0x10;
+       E1000_WRITE_REG(&adapter->hw, E1000_TSYNCTXCTL, tx_ctl);
+       E1000_WRITE_FLUSH(&adapter->hw);
+   
+       /* Invalidate TX Timestamp */
+       E1000_READ_REG(&adapter->hw, E1000_TXSTMPH);
+ 
+       tx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
+       if (tx_ctl & 0x10)
+               HW_DEBUGOUT("Failed to disable TX timestamping\n");
+   
+       rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
+       rx_ctl &= ~0x10;
+   
+       E1000_WRITE_REG(&adapter->hw, E1000_TSYNCRXCTL, rx_ctl);
+       E1000_WRITE_FLUSH(&adapter->hw);
+   
+       /* Invalidate RX Timestamp */
+       E1000_READ_REG(&adapter->hw, E1000_RXSATRH);
+ 
+       rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
+       if (rx_ctl & 0x10)
+               HW_DEBUGOUT("Failed to disable RX timestamping\n");
+ 
+       return;
+}
+#endif /* EM_TIMESYNC */
Index: dev/em/if_em.h
===================================================================
--- dev/em/if_em.h      (Revision 28889)
+++ dev/em/if_em.h      (Arbeitskopie)
@@ -1,37 +1,38 @@
-/**************************************************************************
+/******************************************************************************
 
-Copyright (c) 2001-2007, Intel Corporation
-All rights reserved.
+  Copyright (c) 2001-2008, 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.
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/if_em.h,v 1.2 2008/11/26 23:57:23 jfv Exp $*/
 
- 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: src/sys/dev/em/if_em.h,v 1.62 2007/09/10 21:50:40 jfv Exp $*/
-
 #ifndef _EM_H_DEFINED_
 #define _EM_H_DEFINED_
 
@@ -135,7 +136,7 @@
 /*
  * This parameter controls the duration of transmit watchdog timer.
  */
-#define EM_TX_TIMEOUT                   5    /* set to 5 seconds */
+#define EM_TX_TIMEOUT                   5
 
 /*
  * This parameter controls when the driver calls the routine to reclaim
@@ -185,10 +186,14 @@
 #define MAX_NUM_MULTICAST_ADDRESSES     128
 #define PCI_ANY_ID                      (~0U)
 #define ETHER_ALIGN                     2
-#define EM_TX_BUFFER_SIZE              ((uint32_t) 1514)
 #define EM_FC_PAUSE_TIME               0x0680
 #define EM_EEPROM_APME                 0x400;
 
+/* Code compatilbility between 6 and 7 */
+#ifndef ETHER_BPF_MTAP
+#define ETHER_BPF_MTAP                 BPF_MTAP
+#endif
+
 /*
  * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
  * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will
@@ -226,12 +231,52 @@
 #define HW_DEBUGOUT2(S, A, B)       if (DEBUG_HW) printf(S "\n", A, B)
 
 #define EM_MAX_SCATTER         64
-#define EM_TSO_SIZE            65535   /* maxsize of a dma transfer */
+#define EM_TSO_SIZE            (65535 + sizeof(struct ether_vlan_header))
 #define EM_TSO_SEG_SIZE                4096    /* Max dma segment size */
+#define EM_MSIX_MASK           0x01F00000 /* For 82574 use */
 #define ETH_ZLEN               60
 #define ETH_ADDR_LEN           6
-#define CSUM_OFFLOAD           7       /* Offload bits in csum flags */
+#define CSUM_OFFLOAD           7       /* Offload bits in mbuf flag */
 
+/*
+ * 82574 has a nonstandard address for EIAC
+ * and since its only used in MSIX, and in
+ * the em driver only 82574 uses MSIX we can
+ * solve it just using this define.
+ */
+#define EM_EIAC 0x000DC
+
+/* Used in for 82547 10Mb Half workaround */
+#define EM_PBA_BYTES_SHIFT     0xA
+#define EM_TX_HEAD_ADDR_SHIFT  7
+#define EM_PBA_TX_MASK         0xFFFF0000
+#define EM_FIFO_HDR            0x10
+#define EM_82547_PKT_THRESH    0x3e0
+
+#ifdef EM_TIMESYNC
+/* Precision Time Sync (IEEE 1588) defines */
+#define ETHERTYPE_IEEE1588     0x88F7
+#define PICOSECS_PER_TICK      20833
+#define TSYNC_PORT             319 /* UDP port for the protocol */
+
+/* TIMESYNC IOCTL defines */
+#define EM_TIMESYNC_READTS     _IOWR('i', 127, struct em_tsync_read)
+  
+/* Used in the READTS IOCTL */
+struct em_tsync_read {
+       int read_current_time;
+       struct timespec system_time;
+       u64 network_time;
+       u64 rx_stamp;
+       u64 tx_stamp;
+       u16 seqid;
+       unsigned char srcid[6];
+       int rx_valid;
+       int tx_valid;
+};
+
+#endif /* EM_TIMESYNC */
+
 struct adapter;
 
 struct em_int_delay_info {
@@ -261,30 +306,47 @@
        /* FreeBSD operating-system-specific structures. */
        struct e1000_osdep osdep;
        struct device   *dev;
-       struct resource *res_memory;
-       struct resource *flash_mem;
-       struct resource *msix_mem;
-       struct resource *res_ioport;
-       struct resource *res_interrupt;
-       void            *int_handler_tag;
+
+       struct resource *memory;
+       struct resource *flash;
+       struct resource *msix;
+
+       struct resource *ioport;
+       int             io_rid;
+
+       /* 82574 uses 3 int vectors */
+       struct resource *res[3];
+       void            *tag[3];
+       int             rid[3];
+
        struct ifmedia  media;
        struct callout  timer;
        struct callout  tx_fifo_timer;
        int             watchdog_timer;
-       int             io_rid;
        int             msi;
        int             if_flags;
-       struct mtx      mtx;
+       int             max_frame_size;
+       int             min_frame_size;
+       struct mtx      core_mtx;
+       struct mtx      tx_mtx;
+       struct mtx      rx_mtx;
        int             em_insert_vlan_header;
+
+       /* Task for FAST handling */
        struct task     link_task;
        struct task     rxtx_task;
+       struct task     rx_task;
+       struct task     tx_task;
        struct taskqueue *tq;           /* private task queue */
+
+       eventhandler_tag vlan_attach;
+       eventhandler_tag vlan_detach;
+
        /* Management and WOL features */
        int             wol;
        int             has_manage;
 
        /* Info about the board itself */
-       uint32_t        part_num;
        uint8_t         link_active;
        uint16_t        link_speed;
        uint16_t        link_duplex;
@@ -314,12 +376,6 @@
        bus_dma_tag_t           txtag;          /* dma tag for tx */
        uint32_t                tx_tso;         /* last tx was tso */
 
-       /*
-        * Transmit function pointer:
-        *      legacy or advanced (82575 and later)
-        */
-       int (*em_xmit) (struct adapter *adapter, struct mbuf **m_headp);
-
        /* 
         * Receive definitions
         *
@@ -355,15 +411,11 @@
         unsigned long  no_tx_dma_setup;
        unsigned long   watchdog_events;
        unsigned long   rx_overruns;
+       unsigned long   rx_irq;
+       unsigned long   tx_irq;
+       unsigned long   link_irq;
 
-       /* Used in for 82547 10Mb Half workaround */
-       #define EM_PBA_BYTES_SHIFT      0xA
-       #define EM_TX_HEAD_ADDR_SHIFT   7
-       #define EM_PBA_TX_MASK          0xFFFF0000
-       #define EM_FIFO_HDR             0x10
-
-       #define EM_82547_PKT_THRESH     0x3e0
-
+       /* 82547 workaround */
        uint32_t        tx_fifo_size;
        uint32_t        tx_fifo_head;
        uint32_t        tx_fifo_head_addr;
@@ -375,6 +427,12 @@
        boolean_t       pcix_82544;
        boolean_t       in_detach;
 
+#ifdef EM_TIMESYNC
+       u64             last_stamp;
+       u64             last_sec;
+       u32             last_ns;
+#endif
+
        struct e1000_hw_stats stats;
 };
 
@@ -413,11 +471,22 @@
        uint32_t   elements;
 } DESC_ARRAY, *PDESC_ARRAY;
 
-#define        EM_LOCK_INIT(_sc, _name) \
-       mtx_init(&(_sc)->mtx, _name, MTX_NETWORK_LOCK, MTX_DEF)
-#define        EM_LOCK_DESTROY(_sc)    mtx_destroy(&(_sc)->mtx)
-#define        EM_LOCK(_sc)            mtx_lock(&(_sc)->mtx)
-#define        EM_UNLOCK(_sc)          mtx_unlock(&(_sc)->mtx)
-#define        EM_LOCK_ASSERT(_sc)     mtx_assert(&(_sc)->mtx, MA_OWNED)
+#define        EM_CORE_LOCK_INIT(_sc, _name) \
+       mtx_init(&(_sc)->core_mtx, _name, "EM Core Lock", MTX_DEF)
+#define        EM_TX_LOCK_INIT(_sc, _name) \
+       mtx_init(&(_sc)->tx_mtx, _name, "EM TX Lock", MTX_DEF)
+#define        EM_RX_LOCK_INIT(_sc, _name) \
+       mtx_init(&(_sc)->rx_mtx, _name, "EM RX Lock", MTX_DEF)
+#define        EM_CORE_LOCK_DESTROY(_sc)       mtx_destroy(&(_sc)->core_mtx)
+#define        EM_TX_LOCK_DESTROY(_sc)         mtx_destroy(&(_sc)->tx_mtx)
+#define        EM_RX_LOCK_DESTROY(_sc)         mtx_destroy(&(_sc)->rx_mtx)
+#define        EM_CORE_LOCK(_sc)               mtx_lock(&(_sc)->core_mtx)
+#define        EM_TX_LOCK(_sc)                 mtx_lock(&(_sc)->tx_mtx)
+#define        EM_RX_LOCK(_sc)                 mtx_lock(&(_sc)->rx_mtx)
+#define        EM_CORE_UNLOCK(_sc)             mtx_unlock(&(_sc)->core_mtx)
+#define        EM_TX_UNLOCK(_sc)               mtx_unlock(&(_sc)->tx_mtx)
+#define        EM_RX_UNLOCK(_sc)               mtx_unlock(&(_sc)->rx_mtx)
+#define        EM_CORE_LOCK_ASSERT(_sc)        mtx_assert(&(_sc)->core_mtx, 
MA_OWNED)
+#define        EM_TX_LOCK_ASSERT(_sc)          mtx_assert(&(_sc)->tx_mtx, 
MA_OWNED)
 
 #endif /* _EM_H_DEFINED_ */
Index: dev/em/e1000_osdep.h
===================================================================
--- dev/em/e1000_osdep.h        (Revision 28889)
+++ dev/em/e1000_osdep.h        (Arbeitskopie)
@@ -1,38 +1,38 @@
-/**************************************************************************
+/******************************************************************************
 
-Copyright (c) 2001-2007, Intel Corporation
-All rights reserved.
+  Copyright (c) 2001-2008, 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.
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_osdep.h,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
- 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: src/sys/dev/em/e1000_osdep.h,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
-
-
 #ifndef _FREEBSD_OS_H_
 #define _FREEBSD_OS_H_
 
@@ -71,11 +71,13 @@
        #define DEBUGOUT3(S,A,B,C)
        #define DEBUGOUT7(S,A,B,C,D,E,F,G)
 
-#define STATIC                         static
-#define FALSE               0
-#define TRUE                1
-#define CMD_MEM_WRT_INVALIDATE          0x0010  /* BIT_4 */
-#define PCI_COMMAND_REGISTER            PCIR_COMMAND
+#define STATIC                 static
+#define FALSE                  0
+//#define false                        FALSE /* shared code stupidity */
+#define TRUE                   1
+//#define true                 TRUE
+#define CMD_MEM_WRT_INVALIDATE 0x0010  /* BIT_4 */
+#define PCI_COMMAND_REGISTER   PCIR_COMMAND
 
 /*
 ** These typedefs are necessary due to the new
@@ -89,7 +91,12 @@
 typedef int32_t                s32;
 typedef int16_t                s16;
 typedef int8_t         s8;
+//typedef boolean_t    bool;
 
+#define __le16         u16
+#define __le32         u32
+#define __le64         u64
+
 struct e1000_osdep
 {
        bus_space_tag_t    mem_bus_space_tag;
@@ -101,12 +108,8 @@
        struct device     *dev;
 };
 
-#ifdef NO_82542_SUPPORT
-#define E1000_REGISTER(hw, reg) reg
-#else
 #define E1000_REGISTER(hw, reg) (((hw)->mac.type >= e1000_82543) \
     ? reg : e1000_translate_register_82542(reg))
-#endif
 
 #define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS)
 
Index: dev/em/e1000_ich8lan.c
===================================================================
--- dev/em/e1000_ich8lan.c      (Revision 28889)
+++ dev/em/e1000_ich8lan.c      (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,71 +29,90 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_ich8lan.c,v 1.3 2007/05/16 00:14:23 jfv Exp 
$*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_ich8lan.c,v 1.2 2008/11/26 23:57:23 jfv 
Exp $*/
 
-
-/* e1000_ich8lan
- * e1000_ich9lan
+/*
+ * 82562G 10/100 Network Connection
+ * 82562G-2 10/100 Network Connection
+ * 82562GT 10/100 Network Connection
+ * 82562GT-2 10/100 Network Connection
+ * 82562V 10/100 Network Connection
+ * 82562V-2 10/100 Network Connection
+ * 82566DC-2 Gigabit Network Connection
+ * 82566DC Gigabit Network Connection
+ * 82566DM-2 Gigabit Network Connection
+ * 82566DM Gigabit Network Connection
+ * 82566MC Gigabit Network Connection
+ * 82566MM Gigabit Network Connection
+ * 82567LM Gigabit Network Connection
+ * 82567LF Gigabit Network Connection
+ * 82567V Gigabit Network Connection
+ * 82567LM-2 Gigabit Network Connection
+ * 82567LF-2 Gigabit Network Connection
+ * 82567V-2 Gigabit Network Connection
+ * 82567LF-3 Gigabit Network Connection
+ * 82567LM-3 Gigabit Network Connection
+ * 82567LM-4 Gigabit Network Connection
  */
 
 #include "e1000_api.h"
-#include "e1000_ich8lan.h"
 
-void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw);
+static s32  e1000_init_phy_params_ich8lan(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_ich8lan(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_ich8lan(struct e1000_hw *hw);
+static s32  e1000_acquire_swflag_ich8lan(struct e1000_hw *hw);
+static void e1000_release_swflag_ich8lan(struct e1000_hw *hw);
+static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
+static s32  e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw);
+static s32  e1000_check_reset_block_ich8lan(struct e1000_hw *hw);
+static s32  e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw);
+static s32  e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw);
+static s32  e1000_get_phy_info_ich8lan(struct e1000_hw *hw);
+static s32  e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw,
+                                            bool active);
+static s32  e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw,
+                                            bool active);
+static s32  e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
+                                   u16 words, u16 *data);
+static s32  e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
+                                    u16 words, u16 *data);
+static s32  e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw);
+static s32  e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw);
+static s32  e1000_valid_led_default_ich8lan(struct e1000_hw *hw,
+                                            u16 *data);
+static s32  e1000_get_bus_info_ich8lan(struct e1000_hw *hw);
+static s32  e1000_reset_hw_ich8lan(struct e1000_hw *hw);
+static s32  e1000_init_hw_ich8lan(struct e1000_hw *hw);
+static s32  e1000_setup_link_ich8lan(struct e1000_hw *hw);
+static s32  e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
+static s32  e1000_get_link_up_info_ich8lan(struct e1000_hw *hw,
+                                           u16 *speed, u16 *duplex);
+static s32  e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
+static s32  e1000_led_on_ich8lan(struct e1000_hw *hw);
+static s32  e1000_led_off_ich8lan(struct e1000_hw *hw);
+static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
+static s32  e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank);
+static s32  e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout);
+static s32  e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw);
+static s32  e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw);
+static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
+static s32  e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
+static s32  e1000_read_flash_byte_ich8lan(struct e1000_hw *hw,
+                                          u32 offset, u8 *data);
+static s32  e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+                                          u8 size, u16 *data);
+static s32  e1000_read_flash_word_ich8lan(struct e1000_hw *hw,
+                                          u32 offset, u16 *data);
+static s32  e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
+                                                 u32 offset, u8 byte);
+static s32  e1000_write_flash_byte_ich8lan(struct e1000_hw *hw,
+                                           u32 offset, u8 data);
+static s32  e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+                                           u8 size, u16 data);
+static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);
+static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);
 
-STATIC s32       e1000_init_phy_params_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_init_nvm_params_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_init_mac_params_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_acquire_swflag_ich8lan(struct e1000_hw *hw);
-STATIC void      e1000_release_swflag_ich8lan(struct e1000_hw *hw);
-STATIC boolean_t e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_check_reset_block_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_get_phy_info_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw,
-                                                 boolean_t active);
-STATIC s32       e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw,
-                                                 boolean_t active);
-STATIC s32       e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
-                                        u16 words, u16 *data);
-STATIC s32       e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
-                                         u16 words, u16 *data);
-STATIC s32       e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_valid_led_default_ich8lan(struct e1000_hw *hw,
-                                                 u16 *data);
-STATIC s32       e1000_get_bus_info_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_reset_hw_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_init_hw_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_setup_link_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_get_link_up_info_ich8lan(struct e1000_hw *hw,
-                                                u16 *speed, u16 *duplex);
-STATIC s32       e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_led_on_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_led_off_ich8lan(struct e1000_hw *hw);
-STATIC void      e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
-STATIC s32       e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank);
-static s32       e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout);
-static s32       e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw);
-static s32       e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw);
-static void      e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
-static s32       e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
-static s32       e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
-                                               u8 size, u16* data);
-STATIC s32       e1000_read_flash_word_ich8lan(struct e1000_hw *hw,
-                                               u32 offset, u16 *data);
-static s32       e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
-                                                      u32 offset, u8 byte);
-STATIC s32       e1000_write_flash_byte_ich8lan(struct e1000_hw *hw,
-                                                u32 offset, u8 data);
-static s32       e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 
offset,
-                                                u8 size, u16 data);
-STATIC s32      e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);
-
 /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
 /* Offset 04h HSFSTS */
 union ich8_hws_flash_status {
@@ -135,49 +154,53 @@
        u16 regval;
 };
 
-struct e1000_shadow_ram {
-       u16  value;
-       boolean_t modified;
-};
-
-struct e1000_dev_spec_ich8lan {
-       boolean_t kmrn_lock_loss_workaround_enabled;
-       struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS];
-};
-
 /**
  *  e1000_init_phy_params_ich8lan - Initialize PHY function pointers
  *  @hw: pointer to the HW structure
  *
  *  Initialize family-specific PHY parameters and function pointers.
  **/
-STATIC s32
-e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
+static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
        u16 i = 0;
 
        DEBUGFUNC("e1000_init_phy_params_ich8lan");
 
-       phy->addr                       = 1;
-       phy->reset_delay_us             = 100;
+       phy->addr                     = 1;
+       phy->reset_delay_us           = 100;
 
-       func->acquire_phy               = e1000_acquire_swflag_ich8lan;
-       func->check_polarity            = e1000_check_polarity_ife_ich8lan;
-       func->check_reset_block         = e1000_check_reset_block_ich8lan;
-       func->force_speed_duplex        = e1000_phy_force_speed_duplex_ich8lan;
-       func->get_cable_length          = e1000_get_cable_length_igp_2;
-       func->get_cfg_done              = e1000_get_cfg_done_ich8lan;
-       func->get_phy_info              = e1000_get_phy_info_ich8lan;
-       func->read_phy_reg              = e1000_read_phy_reg_igp;
-       func->release_phy               = e1000_release_swflag_ich8lan;
-       func->reset_phy                 = e1000_phy_hw_reset_ich8lan;
-       func->set_d0_lplu_state         = e1000_set_d0_lplu_state_ich8lan;
-       func->set_d3_lplu_state         = e1000_set_d3_lplu_state_ich8lan;
-       func->write_phy_reg             = e1000_write_phy_reg_igp;
+       phy->ops.acquire              = e1000_acquire_swflag_ich8lan;
+       phy->ops.check_polarity       = e1000_check_polarity_ife_ich8lan;
+       phy->ops.check_reset_block    = e1000_check_reset_block_ich8lan;
+       phy->ops.force_speed_duplex   = e1000_phy_force_speed_duplex_ich8lan;
+       phy->ops.get_cable_length     = e1000_get_cable_length_igp_2;
+       phy->ops.get_cfg_done         = e1000_get_cfg_done_ich8lan;
+       phy->ops.get_info             = e1000_get_phy_info_ich8lan;
+       phy->ops.read_reg             = e1000_read_phy_reg_igp;
+       phy->ops.release              = e1000_release_swflag_ich8lan;
+       phy->ops.reset                = e1000_phy_hw_reset_ich8lan;
+       phy->ops.set_d0_lplu_state    = e1000_set_d0_lplu_state_ich8lan;
+       phy->ops.set_d3_lplu_state    = e1000_set_d3_lplu_state_ich8lan;
+       phy->ops.write_reg            = e1000_write_phy_reg_igp;
+       phy->ops.power_up             = e1000_power_up_phy_copper;
+       phy->ops.power_down           = e1000_power_down_phy_copper_ich8lan;
 
+       /*
+        * We may need to do this twice - once for IGP and if that fails,
+        * we'll set BM func pointers and try again
+        */
+       ret_val = e1000_determine_phy_address(hw);
+       if (ret_val) {
+               phy->ops.write_reg = e1000_write_phy_reg_bm;
+               phy->ops.read_reg  = e1000_read_phy_reg_bm;
+               ret_val = e1000_determine_phy_address(hw);
+               if (ret_val) {
+                       DEBUGOUT("Cannot determine PHY address. Erroring 
out\n");
+                       goto out;
+               }
+       }
 
        phy->id = 0;
        while ((e1000_phy_unknown == e1000_get_phy_type_from_id(phy->id)) &&
@@ -200,6 +223,13 @@
                phy->type = e1000_phy_ife;
                phy->autoneg_mask = E1000_ALL_NOT_GIG;
                break;
+       case BME1000_E_PHY_ID:
+               phy->type = e1000_phy_bm;
+               phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+               phy->ops.read_reg = e1000_read_phy_reg_bm;
+               phy->ops.write_reg = e1000_write_phy_reg_bm;
+               phy->ops.commit = e1000_phy_sw_reset_generic;
+               break;
        default:
                ret_val = -E1000_ERR_PHY;
                goto out;
@@ -216,57 +246,50 @@
  *  Initialize family-specific NVM parameters and function
  *  pointers.
  **/
-STATIC s32
-e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
+static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_functions *func = &hw->func;
-       struct e1000_dev_spec_ich8lan *dev_spec;
+       struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
        u32 gfpreg, sector_base_addr, sector_end_addr;
-       s32  ret_val = E1000_SUCCESS;
+       s32 ret_val = E1000_SUCCESS;
        u16 i;
 
        DEBUGFUNC("e1000_init_nvm_params_ich8lan");
 
-       /* Can't read flash registers if the register set isn't mapped.
-        */
+       /* Can't read flash registers if the register set isn't mapped. */
        if (!hw->flash_address) {
                DEBUGOUT("ERROR: Flash registers not mapped\n");
                ret_val = -E1000_ERR_CONFIG;
                goto out;
        }
 
-       nvm->type               = e1000_nvm_flash_sw;
+       nvm->type = e1000_nvm_flash_sw;
 
        gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG);
 
-       /* sector_X_addr is a "sector"-aligned address (4096 bytes)
+       /*
+        * sector_X_addr is a "sector"-aligned address (4096 bytes)
         * Add 1 to sector_end_addr since this sector is included in
-        * the overall size. */
+        * the overall size.
+        */
        sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
        sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
 
        /* flash_base_addr is byte-aligned */
-       nvm->flash_base_addr    = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
+       nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
 
-       /* find total size of the NVM, then cut in half since the total
-        * size represents two separate NVM banks. */
-       nvm->flash_bank_size    = (sector_end_addr - sector_base_addr)
+       /*
+        * find total size of the NVM, then cut in half since the total
+        * size represents two separate NVM banks.
+        */
+       nvm->flash_bank_size = (sector_end_addr - sector_base_addr)
                                  << FLASH_SECTOR_ADDR_SHIFT;
-       nvm->flash_bank_size    /= 2;
+       nvm->flash_bank_size /= 2;
        /* Adjust to word count */
-       nvm->flash_bank_size    /= sizeof(u16);
+       nvm->flash_bank_size /= sizeof(u16);
 
-       nvm->word_size          = E1000_SHADOW_RAM_WORDS;
+       nvm->word_size = E1000_SHADOW_RAM_WORDS;
 
-       dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-       }
-
        /* Clear shadow ram */
        for (i = 0; i < nvm->word_size; i++) {
                dev_spec->shadow_ram[i].modified = FALSE;
@@ -274,13 +297,13 @@
        }
 
        /* Function Pointers */
-       func->acquire_nvm       = e1000_acquire_swflag_ich8lan;
-       func->read_nvm          = e1000_read_nvm_ich8lan;
-       func->release_nvm       = e1000_release_swflag_ich8lan;
-       func->update_nvm        = e1000_update_nvm_checksum_ich8lan;
-       func->valid_led_default = e1000_valid_led_default_ich8lan;
-       func->validate_nvm      = e1000_validate_nvm_checksum_ich8lan;
-       func->write_nvm         = e1000_write_nvm_ich8lan;
+       nvm->ops.acquire       = e1000_acquire_swflag_ich8lan;
+       nvm->ops.read          = e1000_read_nvm_ich8lan;
+       nvm->ops.release       = e1000_release_swflag_ich8lan;
+       nvm->ops.update        = e1000_update_nvm_checksum_ich8lan;
+       nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan;
+       nvm->ops.validate      = e1000_validate_nvm_checksum_ich8lan;
+       nvm->ops.write         = e1000_write_nvm_ich8lan;
 
 out:
        return ret_val;
@@ -293,17 +316,14 @@
  *  Initialize family-specific MAC parameters and function
  *  pointers.
  **/
-STATIC s32
-e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
+static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_mac_params_ich8lan");
 
        /* Set media type function pointer */
-       hw->media_type = e1000_media_type_copper;
+       hw->phy.media_type = e1000_media_type_copper;
 
        /* Set mta register count */
        mac->mta_reg_count = 32;
@@ -319,53 +339,45 @@
        /* Function pointers */
 
        /* bus type/speed/width */
-       func->get_bus_info = e1000_get_bus_info_ich8lan;
+       mac->ops.get_bus_info = e1000_get_bus_info_ich8lan;
+       /* function id */
+       mac->ops.set_lan_id = e1000_set_lan_id_single_port;
        /* reset */
-       func->reset_hw = e1000_reset_hw_ich8lan;
+       mac->ops.reset_hw = e1000_reset_hw_ich8lan;
        /* hw initialization */
-       func->init_hw = e1000_init_hw_ich8lan;
+       mac->ops.init_hw = e1000_init_hw_ich8lan;
        /* link setup */
-       func->setup_link = e1000_setup_link_ich8lan;
+       mac->ops.setup_link = e1000_setup_link_ich8lan;
        /* physical interface setup */
-       func->setup_physical_interface = e1000_setup_copper_link_ich8lan;
+       mac->ops.setup_physical_interface = e1000_setup_copper_link_ich8lan;
        /* check for link */
-       func->check_for_link = e1000_check_for_copper_link_generic;
+       mac->ops.check_for_link = e1000_check_for_copper_link_generic;
        /* check management mode */
-       func->check_mng_mode = e1000_check_mng_mode_ich8lan;
+       mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan;
        /* link info */
-       func->get_link_up_info = e1000_get_link_up_info_ich8lan;
+       mac->ops.get_link_up_info = e1000_get_link_up_info_ich8lan;
        /* multicast address update */
-       func->mc_addr_list_update = e1000_mc_addr_list_update_generic;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
        /* setting MTA */
-       func->mta_set = e1000_mta_set_generic;
+       mac->ops.mta_set = e1000_mta_set_generic;
        /* blink LED */
-       func->blink_led = e1000_blink_led_generic;
+       mac->ops.blink_led = e1000_blink_led_generic;
        /* setup LED */
-       func->setup_led = e1000_setup_led_generic;
+       mac->ops.setup_led = e1000_setup_led_generic;
        /* cleanup LED */
-       func->cleanup_led = e1000_cleanup_led_ich8lan;
+       mac->ops.cleanup_led = e1000_cleanup_led_ich8lan;
        /* turn on/off LED */
-       func->led_on = e1000_led_on_ich8lan;
-       func->led_off = e1000_led_off_ich8lan;
-       /* remove device */
-       func->remove_device = e1000_remove_device_generic;
+       mac->ops.led_on = e1000_led_on_ich8lan;
+       mac->ops.led_off = e1000_led_off_ich8lan;
        /* clear hardware counters */
-       func->clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan;
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan;
 
-       hw->dev_spec_size = sizeof(struct e1000_dev_spec_ich8lan);
-
-       /* Device-specific structure allocation */
-       ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size);
-       if (ret_val)
-               goto out;
-
        /* Enable PCS Lock-loss workaround for ICH8 */
        if (mac->type == e1000_ich8lan)
                e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, TRUE);
 
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -374,14 +386,13 @@
  *
  *  Initialize family-specific function pointers for PHY, MAC, and NVM.
  **/
-void
-e1000_init_function_pointers_ich8lan(struct e1000_hw *hw)
+void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_init_function_pointers_ich8lan");
 
-       hw->func.init_mac_params = e1000_init_mac_params_ich8lan;
-       hw->func.init_nvm_params = e1000_init_nvm_params_ich8lan;
-       hw->func.init_phy_params = e1000_init_phy_params_ich8lan;
+       hw->mac.ops.init_params = e1000_init_mac_params_ich8lan;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_ich8lan;
+       hw->phy.ops.init_params = e1000_init_phy_params_ich8lan;
 }
 
 /**
@@ -392,8 +403,7 @@
  *  operations.  This is a function pointer entry point only called by
  *  read/write routines for the PHY and NVM parts.
  **/
-STATIC s32
-e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
+static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
 {
        u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT;
        s32 ret_val = E1000_SUCCESS;
@@ -414,6 +424,8 @@
 
        if (!timeout) {
                DEBUGOUT("FW or HW has locked the resource for too long.\n");
+               extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
+               E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
                ret_val = -E1000_ERR_CONFIG;
                goto out;
        }
@@ -430,8 +442,7 @@
  *  This is a function pointer entry point only called by read/write
  *  routines for the PHY and NVM parts.
  **/
-STATIC void
-e1000_release_swflag_ich8lan(struct e1000_hw *hw)
+static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
 {
        u32 extcnf_ctrl;
 
@@ -452,8 +463,7 @@
  *  This is a function pointer entry point only called by read/write
  *  routines for the PHY and NVM parts.
  **/
-STATIC boolean_t
-e1000_check_mng_mode_ich8lan(struct e1000_hw *hw)
+static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw)
 {
        u32 fwsm;
 
@@ -461,8 +471,8 @@
 
        fwsm = E1000_READ_REG(hw, E1000_FWSM);
 
-       return ((fwsm & E1000_FWSM_MODE_MASK) ==
-               (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
+       return (fwsm & E1000_FWSM_MODE_MASK) ==
+               (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
 }
 
 /**
@@ -473,8 +483,7 @@
  *  This is a function pointer entry point only called by
  *  reset routines.
  **/
-STATIC s32
-e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
+static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
 {
        u32 fwsm;
 
@@ -494,13 +503,12 @@
  *  This is a function pointer entry point only called by
  *  PHY setup routines.
  **/
-STATIC s32
-e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
+static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
        u16 data;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_phy_force_speed_duplex_ich8lan");
 
@@ -509,25 +517,25 @@
                goto out;
        }
 
-       ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &data);
+       ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data);
        if (ret_val)
                goto out;
 
        e1000_phy_force_speed_duplex_setup(hw, &data);
 
-       ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, data);
+       ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data);
        if (ret_val)
                goto out;
 
        /* Disable MDI-X support for 10/100 */
-       ret_val = e1000_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
+       ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
        if (ret_val)
                goto out;
 
        data &= ~IFE_PMC_AUTO_MDIX;
        data &= ~IFE_PMC_FORCE_MDIX;
 
-       ret_val = e1000_write_phy_reg(hw, IFE_PHY_MDIX_CONTROL, data);
+       ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data);
        if (ret_val)
                goto out;
 
@@ -535,7 +543,7 @@
 
        usec_delay(1);
 
-       if (phy->wait_for_link) {
+       if (phy->autoneg_wait_to_complete) {
                DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n");
 
                ret_val = e1000_phy_has_link_generic(hw,
@@ -545,9 +553,8 @@
                if (ret_val)
                        goto out;
 
-               if (!link) {
+               if (!link)
                        DEBUGOUT("Link taking longer than expected.\n");
-               }
 
                /* Try once more */
                ret_val = e1000_phy_has_link_generic(hw,
@@ -570,8 +577,7 @@
  *  This is a function pointer entry point called by drivers
  *  or other shared routines.
  **/
-STATIC s32
-e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
@@ -585,7 +591,8 @@
        if (ret_val)
                goto out;
 
-       /* Initialize the PHY from the NVM on ICH platforms.  This
+       /*
+        * Initialize the PHY from the NVM on ICH platforms.  This
         * is needed due to an issue where the NVM configuration is
         * not properly autoloaded after power transitions.
         * Therefore, after each PHY reset, we will load the
@@ -610,21 +617,23 @@
                        usec_delay(100);
                } while ((!data) && --loop);
 
-               /* If basic configuration is incomplete before the above loop
+               /*
+                * If basic configuration is incomplete before the above loop
                 * count reaches 0, loading the configuration from NVM will
                 * leave the PHY in a bad state possibly resulting in no link.
                 */
-               if (loop == 0) {
+               if (loop == 0)
                        DEBUGOUT("LAN_INIT_DONE not set, increase timeout\n");
-               }
 
                /* Clear the Init Done bit for the next init event */
                data = E1000_READ_REG(hw, E1000_STATUS);
                data &= ~E1000_STATUS_LAN_INIT_DONE;
                E1000_WRITE_REG(hw, E1000_STATUS, data);
 
-               /* Make sure HW does not configure LCD from PHY
-                * extended configuration before SW configuration */
+               /*
+                * Make sure HW does not configure LCD from PHY
+                * extended configuration before SW configuration
+                */
                data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
                if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
                        goto out;
@@ -638,24 +647,19 @@
                cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
                cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
 
-               /* Configure LCD from extended configuration
-                * region. */
+               /* Configure LCD from extended configuration region. */
 
                /* cnf_base_addr is in DWORD */
                word_addr = (u16)(cnf_base_addr << 1);
 
                for (i = 0; i < cnf_size; i++) {
-                       ret_val = e1000_read_nvm(hw,
-                                               (word_addr + i * 2),
-                                               1,
-                                               &reg_data);
+                       ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2), 1,
+                                                  &reg_data);
                        if (ret_val)
                                goto out;
 
-                       ret_val = e1000_read_nvm(hw,
-                                               (word_addr + i * 2 + 1),
-                                               1,
-                                               &reg_addr);
+                       ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2 + 1),
+                                                  1, &reg_addr);
                        if (ret_val)
                                goto out;
 
@@ -667,9 +671,7 @@
 
                        reg_addr |= phy_page;
 
-                       ret_val = e1000_write_phy_reg(hw,
-                                                    (u32)reg_addr,
-                                                    reg_data);
+                       ret_val = phy->ops.write_reg(hw, (u32)reg_addr, 
reg_data);
                        if (ret_val)
                                goto out;
                }
@@ -684,11 +686,8 @@
  *  @hw: pointer to the HW structure
  *
  *  Wrapper for calling the get_phy_info routines for the appropriate phy type.
- *  This is a function pointer entry point called by drivers
- *  or other shared routines.
  **/
-STATIC s32
-e1000_get_phy_info_ich8lan(struct e1000_hw *hw)
+static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw)
 {
        s32 ret_val = -E1000_ERR_PHY_TYPE;
 
@@ -699,6 +698,7 @@
                ret_val = e1000_get_phy_info_ife_ich8lan(hw);
                break;
        case e1000_phy_igp_3:
+       case e1000_phy_bm:
                ret_val = e1000_get_phy_info_igp(hw);
                break;
        default:
@@ -716,13 +716,12 @@
  *  This function is only called by other family-specific
  *  routines.
  **/
-static s32
-e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw)
+static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
        u16 data;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_get_phy_info_ife_ich8lan");
 
@@ -736,7 +735,7 @@
                goto out;
        }
 
-       ret_val = e1000_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data);
+       ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data);
        if (ret_val)
                goto out;
        phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE)
@@ -753,7 +752,7 @@
                                      : e1000_rev_polarity_normal;
        }
 
-       ret_val = e1000_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
+       ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
        if (ret_val)
                goto out;
 
@@ -772,12 +771,11 @@
  *  e1000_check_polarity_ife_ich8lan - Check cable polarity for IFE PHY
  *  @hw: pointer to the HW structure
  *
- *  Polarity is determined on the polarity reveral feature being enabled.
+ *  Polarity is determined on the polarity reversal feature being enabled.
  *  This function is only called by other family-specific
  *  routines.
  **/
-STATIC s32
-e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw)
+static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -785,8 +783,8 @@
 
        DEBUGFUNC("e1000_check_polarity_ife_ich8lan");
 
-       /* Polarity is determined based on the reversal feature
-        * being enabled.
+       /*
+        * Polarity is determined based on the reversal feature being enabled.
         */
        if (phy->polarity_correction) {
                offset  = IFE_PHY_EXTENDED_STATUS_CONTROL;
@@ -796,7 +794,7 @@
                mask    = IFE_PSC_FORCE_POLARITY;
        }
 
-       ret_val = e1000_read_phy_reg(hw, offset, &phy_data);
+       ret_val = phy->ops.read_reg(hw, offset, &phy_data);
 
        if (!ret_val)
                phy->cable_polarity = (phy_data & mask)
@@ -819,8 +817,7 @@
  *  This is a function pointer entry point only called by
  *  PHY setup routines.
  **/
-STATIC s32
-e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, boolean_t active)
+static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 phy_ctrl;
@@ -829,7 +826,7 @@
 
        DEBUGFUNC("e1000_set_d0_lplu_state_ich8lan");
 
-       if (phy->type != e1000_phy_igp_3)
+       if (phy->type == e1000_phy_ife)
                goto out;
 
        phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
@@ -838,18 +835,20 @@
                phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
                E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
 
-               /* Call gig speed drop workaround on LPLU before accessing
-                * any PHY registers */
+               /*
+                * Call gig speed drop workaround on LPLU before accessing
+                * any PHY registers
+                */
                if ((hw->mac.type == e1000_ich8lan) &&
                    (hw->phy.type == e1000_phy_igp_3))
                        e1000_gig_downshift_workaround_ich8lan(hw);
 
                /* When LPLU is enabled, we should disable SmartSpeed */
-               ret_val = e1000_read_phy_reg(hw,
+               ret_val = phy->ops.read_reg(hw,
                                            IGP01E1000_PHY_PORT_CONFIG,
                                            &data);
                data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-               ret_val = e1000_write_phy_reg(hw,
+               ret_val = phy->ops.write_reg(hw,
                                             IGP01E1000_PHY_PORT_CONFIG,
                                             data);
                if (ret_val)
@@ -858,32 +857,34 @@
                phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
                E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
 
-               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               /*
+                * 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. */
+                * SmartSpeed, so performance is maintained.
+                */
                if (phy->smart_speed == e1000_smart_speed_on) {
-                       ret_val = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                    IGP01E1000_PHY_PORT_CONFIG,
                                                    &data);
                        if (ret_val)
                                goto out;
 
                        data |= IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       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 = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                    IGP01E1000_PHY_PORT_CONFIG,
                                                    &data);
                        if (ret_val)
                                goto out;
 
                        data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
@@ -908,8 +909,7 @@
  *  This is a function pointer entry point only called by
  *  PHY setup routines.
  **/
-STATIC s32
-e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, boolean_t active)
+static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 phy_ctrl;
@@ -923,32 +923,34 @@
        if (!active) {
                phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
                E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
-               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               /*
+                * 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. */
+                * SmartSpeed, so performance is maintained.
+                */
                if (phy->smart_speed == e1000_smart_speed_on) {
-                       ret_val = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                    IGP01E1000_PHY_PORT_CONFIG,
                                                    &data);
                        if (ret_val)
                                goto out;
 
                        data |= IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       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 = e1000_read_phy_reg(hw,
+                       ret_val = phy->ops.read_reg(hw,
                                                    IGP01E1000_PHY_PORT_CONFIG,
                                                    &data);
                        if (ret_val)
                                goto out;
 
                        data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
@@ -960,21 +962,23 @@
                phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
                E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
 
-               /* Call gig speed drop workaround on LPLU before accessing
-                * any PHY registers */
+               /*
+                * Call gig speed drop workaround on LPLU before accessing
+                * any PHY registers
+                */
                if ((hw->mac.type == e1000_ich8lan) &&
                    (hw->phy.type == e1000_phy_igp_3))
                        e1000_gig_downshift_workaround_ich8lan(hw);
 
                /* When LPLU is enabled, we should disable SmartSpeed */
-               ret_val = e1000_read_phy_reg(hw,
+               ret_val = phy->ops.read_reg(hw,
                                            IGP01E1000_PHY_PORT_CONFIG,
                                            &data);
                if (ret_val)
                        goto out;
 
                data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-               ret_val = e1000_write_phy_reg(hw,
+               ret_val = phy->ops.write_reg(hw,
                                             IGP01E1000_PHY_PORT_CONFIG,
                                             data);
        }
@@ -984,6 +988,57 @@
 }
 
 /**
+ *  e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1
+ *  @hw: pointer to the HW structure
+ *  @bank:  pointer to the variable that returns the active bank
+ *
+ *  Reads signature byte from the NVM using the flash access registers.
+ **/
+static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
+{
+       s32 ret_val = E1000_SUCCESS;
+       struct e1000_nvm_info *nvm = &hw->nvm;
+       /* flash bank size is in words */
+       u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
+       u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
+       u8 bank_high_byte = 0;
+
+       if (hw->mac.type != e1000_ich10lan) {
+               if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL)
+                       *bank = 1;
+               else
+                       *bank = 0;
+       } else {
+               /*
+                * Make sure the signature for bank 0 is valid,
+                * if not check for bank1
+                */
+               e1000_read_flash_byte_ich8lan(hw, act_offset, &bank_high_byte);
+               if ((bank_high_byte & 0xC0) == 0x80) {
+                       *bank = 0;
+               } else {
+                       /*
+                        * find if segment 1 is valid by verifying
+                        * bit 15:14 = 10b in word 0x13
+                        */
+                       e1000_read_flash_byte_ich8lan(hw,
+                                                     act_offset + bank1_offset,
+                                                     &bank_high_byte);
+
+                       /* bank1 has a valid signature equivalent to SEC1V */
+                       if ((bank_high_byte & 0xC0) == 0x80) {
+                               *bank = 1;
+                       } else {
+                               DEBUGOUT("ERROR: EEPROM not present\n");
+                               ret_val = -E1000_ERR_NVM;
+                       }
+               }
+       }
+
+       return ret_val;
+}
+
+/**
  *  e1000_read_nvm_ich8lan - Read word(s) from the NVM
  *  @hw: pointer to the HW structure
  *  @offset: The offset (in bytes) of the word(s) to read.
@@ -992,25 +1047,18 @@
  *
  *  Reads a word(s) from the NVM using the flash access registers.
  **/
-STATIC s32
-e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
+                                  u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_dev_spec_ich8lan *dev_spec;
+       struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
        u32 act_offset;
        s32 ret_val = E1000_SUCCESS;
+       u32 bank = 0;
        u16 i, word;
 
        DEBUGFUNC("e1000_read_nvm_ich8lan");
 
-       dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-       }
-
        if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
@@ -1018,19 +1066,20 @@
                goto out;
        }
 
-       ret_val = e1000_acquire_nvm(hw);
+       ret_val = nvm->ops.acquire(hw);
        if (ret_val)
                goto out;
 
-       /* Start with the bank offset, then add the relative offset. */
-       act_offset = (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL)
-                    ? nvm->flash_bank_size
-                    : 0;
+       ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+       if (ret_val != E1000_SUCCESS)
+               goto out;
+
+       act_offset = (bank) ? nvm->flash_bank_size : 0;
        act_offset += offset;
 
        for (i = 0; i < words; i++) {
-               if ((dev_spec->shadow_ram != NULL) &&
-                   (dev_spec->shadow_ram[offset+i].modified == TRUE)) {
+               if ((dev_spec->shadow_ram) &&
+                   (dev_spec->shadow_ram[offset+i].modified)) {
                        data[i] = dev_spec->shadow_ram[offset+i].value;
                } else {
                        ret_val = e1000_read_flash_word_ich8lan(hw,
@@ -1042,7 +1091,7 @@
                }
        }
 
-       e1000_release_nvm(hw);
+       nvm->ops.release(hw);
 
 out:
        return ret_val;
@@ -1055,8 +1104,7 @@
  *  This function does initial flash setup so that a new read/write/erase cycle
  *  can be started.
  **/
-static s32
-e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
+static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
 {
        union ich8_hws_flash_status hsfsts;
        s32 ret_val = -E1000_ERR_NVM;
@@ -1079,24 +1127,29 @@
 
        E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
 
-       /* Either we should have a hardware SPI cycle in progress
+       /*
+        * Either we should have a hardware SPI cycle in progress
         * bit to check against, in order to start a new cycle or
         * FDONE bit should be changed in the hardware so that it
-        * is 1 after harware reset, which can then be used as an
+        * is 1 after hardware reset, which can then be used as an
         * indication whether a cycle is in progress or has been
         * completed.
         */
 
        if (hsfsts.hsf_status.flcinprog == 0) {
-               /* There is no cycle running at present,
-                * so we can start a cycle */
-               /* Begin by setting Flash Cycle Done. */
+               /*
+                * There is no cycle running at present,
+                * so we can start a cycle.
+                * Begin by setting Flash Cycle Done.
+                */
                hsfsts.hsf_status.flcdone = 1;
                E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
                ret_val = E1000_SUCCESS;
        } else {
-               /* otherwise poll for sometime so the current
-                * cycle has a chance to end before giving up. */
+               /*
+                * Otherwise poll for sometime so the current
+                * cycle has a chance to end before giving up.
+                */
                for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
                        hsfsts.regval = E1000_READ_FLASH_REG16(hw,
                                                              ICH_FLASH_HSFSTS);
@@ -1107,11 +1160,12 @@
                        usec_delay(1);
                }
                if (ret_val == E1000_SUCCESS) {
-                       /* Successful in waiting for previous cycle to timeout,
-                        * now set the Flash Cycle Done. */
+                       /*
+                        * Successful in waiting for previous cycle to timeout,
+                        * now set the Flash Cycle Done.
+                        */
                        hsfsts.hsf_status.flcdone = 1;
-                       E1000_WRITE_FLASH_REG16(hw,
-                                               ICH_FLASH_HSFSTS,
+                       E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
                                                hsfsts.regval);
                } else {
                        DEBUGOUT("Flash controller busy, cannot get access");
@@ -1129,8 +1183,7 @@
  *
  *  This function starts a flash cycle and waits for its completion.
  **/
-static s32
-e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
+static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
 {
        union ich8_hws_flash_ctrl hsflctl;
        union ich8_hws_flash_status hsfsts;
@@ -1167,14 +1220,14 @@
  *  Reads the flash word at offset into data.  Offset is converted
  *  to bytes before read.
  **/
-STATIC s32
-e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
+                                         u16 *data)
 {
        s32 ret_val;
 
        DEBUGFUNC("e1000_read_flash_word_ich8lan");
 
-       if (data == NULL) {
+       if (!data) {
                ret_val = -E1000_ERR_NVM;
                goto out;
        }
@@ -1189,6 +1242,30 @@
 }
 
 /**
+ *  e1000_read_flash_byte_ich8lan - Read byte from flash
+ *  @hw: pointer to the HW structure
+ *  @offset: The offset of the byte to read.
+ *  @data: Pointer to a byte to store the value read.
+ *
+ *  Reads a single byte from the NVM using the flash access registers.
+ **/
+static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
+                                         u8 *data)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 word = 0;
+
+       ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
+       if (ret_val)
+               goto out;
+
+       *data = (u8)word;
+
+out:
+       return ret_val;
+}
+
+/**
  *  e1000_read_flash_data_ich8lan - Read byte or word from NVM
  *  @hw: pointer to the HW structure
  *  @offset: The offset (in bytes) of the byte or word to read.
@@ -1197,9 +1274,8 @@
  *
  *  Reads a byte or word from the NVM using the flash access registers.
  **/
-static s32
-e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
-                              u8 size, u16* data)
+static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+                                         u8 size, u16 *data)
 {
        union ich8_hws_flash_status hsfsts;
        union ich8_hws_flash_ctrl hsflctl;
@@ -1210,8 +1286,7 @@
 
        DEBUGFUNC("e1000_read_flash_data_ich8lan");
 
-       if (size < 1  || size > 2 || data == 0x0 ||
-           offset > ICH_FLASH_LINEAR_ADDR_MASK)
+       if (size < 1  || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
                goto out;
 
        flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
@@ -1235,20 +1310,22 @@
                ret_val = e1000_flash_cycle_ich8lan(hw,
                                                ICH_FLASH_READ_COMMAND_TIMEOUT);
 
-               /* Check if FCERR is set to 1, if set to 1, clear it
+               /*
+                * Check if FCERR is set to 1, if set to 1, clear it
                 * and try the whole sequence a few more times, else
                 * read in (shift in) the Flash Data0, the order is
-                * least significant byte first msb to lsb */
+                * least significant byte first msb to lsb
+                */
                if (ret_val == E1000_SUCCESS) {
                        flash_data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0);
-                       if (size == 1) {
+                       if (size == 1)
                                *data = (u8)(flash_data & 0x000000FF);
-                       } else if (size == 2) {
+                       else if (size == 2)
                                *data = (u16)(flash_data & 0x0000FFFF);
-                       }
                        break;
                } else {
-                       /* If we've gotten here, then things are probably
+                       /*
+                        * If we've gotten here, then things are probably
                         * completely hosed, but if the error condition is
                         * detected, it won't hurt to give it another try...
                         * ICH_FLASH_CYCLE_REPEAT_COUNT times.
@@ -1279,24 +1356,16 @@
  *
  *  Writes a byte or word to the NVM using the flash access registers.
  **/
-STATIC s32
-e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
+                                   u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_dev_spec_ich8lan *dev_spec;
+       struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
        s32 ret_val = E1000_SUCCESS;
        u16 i;
 
        DEBUGFUNC("e1000_write_nvm_ich8lan");
 
-       dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-       }
-
        if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
@@ -1304,7 +1373,7 @@
                goto out;
        }
 
-       ret_val = e1000_acquire_nvm(hw);
+       ret_val = nvm->ops.acquire(hw);
        if (ret_val)
                goto out;
 
@@ -1313,7 +1382,7 @@
                dev_spec->shadow_ram[offset+i].value = data[i];
        }
 
-       e1000_release_nvm(hw);
+       nvm->ops.release(hw);
 
 out:
        return ret_val;
@@ -1327,22 +1396,19 @@
  *  which writes the checksum to the shadow ram.  The changes in the shadow
  *  ram are then committed to the EEPROM by processing each bank at a time
  *  checking for the modified bit and writing only the pending changes.
- *  After a succesful commit, the shadow ram is cleared and is ready for
+ *  After a successful commit, the shadow ram is cleared and is ready for
  *  future writes.
  **/
-STATIC s32
-e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_dev_spec_ich8lan *dev_spec;
-       u32 i, act_offset, new_bank_offset, old_bank_offset;
+       struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+       u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
        s32 ret_val;
        u16 data;
 
        DEBUGFUNC("e1000_update_nvm_checksum_ich8lan");
 
-       dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec;
-
        ret_val = e1000_update_nvm_checksum_generic(hw);
        if (ret_val)
                goto out;
@@ -1350,14 +1416,20 @@
        if (nvm->type != e1000_nvm_flash_sw)
                goto out;
 
-       ret_val = e1000_acquire_nvm(hw);
+       ret_val = nvm->ops.acquire(hw);
        if (ret_val)
                goto out;
 
-       /* We're writing to the opposite bank so if we're on bank 1,
+       /*
+        * We're writing to the opposite bank so if we're on bank 1,
         * write to bank 0 etc.  We also need to erase the segment that
-        * is going to be written */
-       if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL)) {
+        * is going to be written
+        */
+       ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+       if (ret_val != E1000_SUCCESS)
+               goto out;
+
+       if (bank == 0) {
                new_bank_offset = nvm->flash_bank_size;
                old_bank_offset = 0;
                e1000_erase_flash_bank_ich8lan(hw, 1);
@@ -1368,10 +1440,12 @@
        }
 
        for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
-               /* Determine whether to write the value stored
+               /*
+                * Determine whether to write the value stored
                 * in the other NVM bank or a modified value stored
-                * in the shadow RAM */
-               if (dev_spec->shadow_ram[i].modified == TRUE) {
+                * in the shadow RAM
+                */
+               if (dev_spec->shadow_ram[i].modified) {
                        data = dev_spec->shadow_ram[i].value;
                } else {
                        e1000_read_flash_word_ich8lan(hw,
@@ -1379,12 +1453,14 @@
                                                      &data);
                }
 
-               /* If the word is 0x13, then make sure the signature bits
+               /*
+                * If the word is 0x13, then make sure the signature bits
                 * (15:14) are 11b until the commit has completed.
                 * This will allow us to write 10b which indicates the
                 * signature is valid.  We want to do this after the write
                 * has completed so that we don't mark the segment valid
-                * while the write is still in progress */
+                * while the write is still in progress
+                */
                if (i == E1000_ICH_NVM_SIG_WORD)
                        data |= E1000_ICH_NVM_SIG_MASK;
 
@@ -1407,18 +1483,22 @@
                        break;
        }
 
-       /* Don't bother writing the segment valid bits if sector
-        * programming failed. */
+       /*
+        * Don't bother writing the segment valid bits if sector
+        * programming failed.
+        */
        if (ret_val) {
                DEBUGOUT("Flash commit failed.\n");
-               e1000_release_nvm(hw);
+               nvm->ops.release(hw);
                goto out;
        }
 
-       /* Finally validate the new segment by setting bit 15:14
+       /*
+        * Finally validate the new segment by setting bit 15:14
         * to 10b in word 0x13 , this can be done without an
         * erase as well since these bits are 11 to start with
-        * and we need to change bit 14 to 0b */
+        * and we need to change bit 14 to 0b
+        */
        act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
        e1000_read_flash_word_ich8lan(hw, act_offset, &data);
        data &= 0xBFFF;
@@ -1426,18 +1506,20 @@
                                                       act_offset * 2 + 1,
                                                       (u8)(data >> 8));
        if (ret_val) {
-               e1000_release_nvm(hw);
+               nvm->ops.release(hw);
                goto out;
        }
 
-       /* And invalidate the previously valid segment by setting
+       /*
+        * And invalidate the previously valid segment by setting
         * its signature word (0x13) high_byte to 0b. This can be
         * done without an erase because flash erase sets all bits
-        * to 1's. We can write 1's to 0's without an erase */
+        * to 1's. We can write 1's to 0's without an erase
+        */
        act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
        ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
        if (ret_val) {
-               e1000_release_nvm(hw);
+               nvm->ops.release(hw);
                goto out;
        }
 
@@ -1447,12 +1529,13 @@
                dev_spec->shadow_ram[i].value = 0xFFFF;
        }
 
-       e1000_release_nvm(hw);
+       nvm->ops.release(hw);
 
-       /* Reload the EEPROM, or else modifications will not appear
+       /*
+        * Reload the EEPROM, or else modifications will not appear
         * until after the next adapter reset.
         */
-       e1000_reload_nvm(hw);
+       nvm->ops.reload(hw);
        msec_delay(10);
 
 out:
@@ -1467,29 +1550,29 @@
  *  If the bit is 0, that the EEPROM had been modified, but the checksum was 
not
  *  calculated, in which case we need to calculate the checksum and set bit 6.
  **/
-STATIC s32
-e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
+static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
        u16 data;
 
        DEBUGFUNC("e1000_validate_nvm_checksum_ich8lan");
 
-       /* Read 0x19 and check bit 6.  If this bit is 0, the checksum
+       /*
+        * Read 0x19 and check bit 6.  If this bit is 0, the checksum
         * needs to be fixed.  This bit is an indication that the NVM
         * was prepared by OEM software and did not calculate the
         * checksum...a likely scenario.
         */
-       ret_val = e1000_read_nvm(hw, 0x19, 1, &data);
+       ret_val = hw->nvm.ops.read(hw, 0x19, 1, &data);
        if (ret_val)
                goto out;
 
        if ((data & 0x40) == 0) {
                data |= 0x40;
-               ret_val = e1000_write_nvm(hw, 0x19, 1, &data);
+               ret_val = hw->nvm.ops.write(hw, 0x19, 1, &data);
                if (ret_val)
                        goto out;
-               ret_val = e1000_update_nvm_checksum(hw);
+               ret_val = hw->nvm.ops.update(hw);
                if (ret_val)
                        goto out;
        }
@@ -1509,9 +1592,8 @@
  *
  *  Writes one/two bytes to the NVM using the flash access registers.
  **/
-static s32
-e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
-                               u8 size, u16 data)
+static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+                                          u8 size, u16 data)
 {
        union ich8_hws_flash_status hsfsts;
        union ich8_hws_flash_ctrl hsflctl;
@@ -1538,7 +1620,7 @@
 
                hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
                /* 0b/1b corresponds to 1 or 2 byte size, respectively. */
-               hsflctl.hsf_ctrl.fldbcount = size -1;
+               hsflctl.hsf_ctrl.fldbcount = size - 1;
                hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
                E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
 
@@ -1551,28 +1633,29 @@
 
                E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
 
-               /* check if FCERR is set to 1 , if set to 1, clear it
-                * and try the whole sequence a few more times else done */
+               /*
+                * check if FCERR is set to 1 , if set to 1, clear it
+                * and try the whole sequence a few more times else done
+                */
                ret_val = e1000_flash_cycle_ich8lan(hw,
                                               ICH_FLASH_WRITE_COMMAND_TIMEOUT);
-               if (ret_val == E1000_SUCCESS) {
+               if (ret_val == E1000_SUCCESS)
                        break;
-               } else {
-                       /* If we're here, then things are most likely
-                        * completely hosed, but if the error condition
-                        * is detected, it won't hurt to give it another
-                        * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
-                        */
-                       hsfsts.regval = E1000_READ_FLASH_REG16(hw,
-                                                             ICH_FLASH_HSFSTS);
-                       if (hsfsts.hsf_status.flcerr == 1) {
-                               /* Repeat for some time before giving up. */
-                               continue;
-                       } else if (hsfsts.hsf_status.flcdone == 0) {
-                               DEBUGOUT("Timeout error - flash cycle "
-                                        "did not complete.");
-                               break;
-                       }
+
+               /*
+                * If we're here, then things are most likely
+                * completely hosed, but if the error condition
+                * is detected, it won't hurt to give it another
+                * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
+                */
+               hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
+               if (hsfsts.hsf_status.flcerr == 1) {
+                       /* Repeat for some time before giving up. */
+                       continue;
+               } else if (hsfsts.hsf_status.flcdone == 0) {
+                       DEBUGOUT("Timeout error - flash cycle "
+                                "did not complete.");
+                       break;
                }
        } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
 
@@ -1588,8 +1671,8 @@
  *
  *  Writes a single byte to the NVM using the flash access registers.
  **/
-STATIC s32
-e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 data)
+static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
+                                          u8 data)
 {
        u16 word = (u16)data;
 
@@ -1607,8 +1690,8 @@
  *  Writes a single byte to the NVM using the flash access registers.
  *  Goes through a retry algorithm before giving up.
  **/
-static s32
-e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 byte)
+static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
+                                                u32 offset, u8 byte)
 {
        s32 ret_val;
        u16 program_retries;
@@ -1616,11 +1699,9 @@
        DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan");
 
        ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);
-       if (ret_val)
+       if (ret_val == E1000_SUCCESS)
                goto out;
 
-       usec_delay(100);
-
        for (program_retries = 0; program_retries < 100; program_retries++) {
                DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset);
                usec_delay(100);
@@ -1645,25 +1726,26 @@
  *  Erases the bank specified. Each bank is a 4k block. Banks are 0 based.
  *  bank N is 4096 * N + flash_reg_addr.
  **/
-STATIC s32
-e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
+static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        union ich8_hws_flash_status hsfsts;
        union ich8_hws_flash_ctrl hsflctl;
        u32 flash_linear_addr;
-       u32 flash_bank_size = nvm->flash_bank_size * 2; /* bank size is in 
16bit words - adjust to bytes */
-       s32  ret_val = E1000_SUCCESS;
-       s32  count = 0;
-       s32  j, iteration, sector_size;
+       /* bank size is in 16bit words - adjust to bytes */
+       u32 flash_bank_size = nvm->flash_bank_size * 2;
+       s32 ret_val = E1000_SUCCESS;
+       s32 count = 0;
+       s32 j, iteration, sector_size;
 
        DEBUGFUNC("e1000_erase_flash_bank_ich8lan");
 
        hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
 
-       /* Determine HW Sector size: Read BERASE bits of hw flash status
-        * register */
-       /* 00: The Hw sector is 256 bytes, hence we need to erase 16
+       /*
+        * Determine HW Sector size: Read BERASE bits of hw flash status
+        * register
+        * 00: The Hw sector is 256 bytes, hence we need to erase 16
         *     consecutive sectors.  The start index for the nth Hw sector
         *     can be calculated as = bank * 4096 + n * 256
         * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.
@@ -1712,41 +1794,42 @@
                        if (ret_val)
                                goto out;
 
-                       /* Write a value 11 (block Erase) in Flash
-                        * Cycle field in hw flash control */
+                       /*
+                        * Write a value 11 (block Erase) in Flash
+                        * Cycle field in hw flash control
+                        */
                        hsflctl.regval = E1000_READ_FLASH_REG16(hw,
                                                              ICH_FLASH_HSFCTL);
                        hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
-                       E1000_WRITE_FLASH_REG16(hw,
-                                               ICH_FLASH_HSFCTL,
+                       E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
                                                hsflctl.regval);
 
-                       /* Write the last 24 bits of an index within the
+                       /*
+                        * Write the last 24 bits of an index within the
                         * block into Flash Linear address field in Flash
                         * Address.
                         */
                        flash_linear_addr += (j * sector_size);
-                       E1000_WRITE_FLASH_REG(hw,
-                                             ICH_FLASH_FADDR,
+                       E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR,
                                              flash_linear_addr);
 
                        ret_val = e1000_flash_cycle_ich8lan(hw,
                                               ICH_FLASH_ERASE_COMMAND_TIMEOUT);
-                       if (ret_val == E1000_SUCCESS) {
+                       if (ret_val == E1000_SUCCESS)
                                break;
-                       } else {
-                               /* Check if FCERR is set to 1.  If 1,
-                                * clear it and try the whole sequence
-                                * a few more times else Done */
-                               hsfsts.regval = E1000_READ_FLASH_REG16(hw,
-                                                             ICH_FLASH_HSFSTS);
-                               if (hsfsts.hsf_status.flcerr == 1) {
-                                       /* repeat for some time before
-                                        * giving up */
-                                       continue;
-                               } else if (hsfsts.hsf_status.flcdone == 0)
-                                       goto out;
-                       }
+
+                       /*
+                        * Check if FCERR is set to 1.  If 1,
+                        * clear it and try the whole sequence
+                        * a few more times else Done
+                        */
+                       hsfsts.regval = E1000_READ_FLASH_REG16(hw,
+                                                     ICH_FLASH_HSFSTS);
+                       if (hsfsts.hsf_status.flcerr == 1)
+                               /* repeat for some time before giving up */
+                               continue;
+                       else if (hsfsts.hsf_status.flcdone == 0)
+                               goto out;
                } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT);
        }
 
@@ -1763,14 +1846,13 @@
  *  settings is all 0's or F's, set the LED default to a valid LED default
  *  setting.
  **/
-STATIC s32
-e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data)
+static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data)
 {
        s32 ret_val;
 
        DEBUGFUNC("e1000_valid_led_default_ich8lan");
 
-       ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
+       ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
                goto out;
@@ -1791,8 +1873,7 @@
  *  ICH8 use the PCI Express bus, but does not contain a PCI Express Capability
  *  register, so the the bus width is hard coded.
  **/
-STATIC s32
-e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
+static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_bus_info *bus = &hw->bus;
        s32 ret_val;
@@ -1801,7 +1882,8 @@
 
        ret_val = e1000_get_bus_info_pcie_generic(hw);
 
-       /* ICH devices are "PCI Express"-ish.  They have
+       /*
+        * ICH devices are "PCI Express"-ish.  They have
         * a configuration space, but do not contain
         * PCI Express Capability registers, so bus width
         * must be hardcoded.
@@ -1819,26 +1901,26 @@
  *  Does a full reset of the hardware which includes a reset of the PHY and
  *  MAC.
  **/
-STATIC s32
-e1000_reset_hw_ich8lan(struct e1000_hw *hw)
+static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
 {
        u32 ctrl, icr, kab;
        s32 ret_val;
 
        DEBUGFUNC("e1000_reset_hw_ich8lan");
 
-       /* Prevent the PCI-E bus from sticking if there is no TLP connection
+       /*
+        * 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) {
+       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);
 
-       /* Disable the Transmit and Receive units.  Then delay to allow
+       /*
+        * Disable the Transmit and Receive units.  Then delay to allow
         * any pending transactions to complete before we hit the MAC
         * with the global reset.
         */
@@ -1858,15 +1940,16 @@
 
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
 
-       if (!e1000_check_reset_block(hw) && !hw->phy.reset_disable) {
-               /* PHY HW reset requires MAC CORE reset at the same
+       if (!hw->phy.ops.check_reset_block(hw) && !hw->phy.reset_disable) {
+               /*
+                * PHY HW reset requires MAC CORE reset at the same
                 * time to make sure the interface between MAC and the
                 * external PHY is reset.
                 */
                ctrl |= E1000_CTRL_PHY_RST;
        }
        ret_val = e1000_acquire_swflag_ich8lan(hw);
-       DEBUGOUT("Issuing a global reset to ich8lan");
+       DEBUGOUT("Issuing a global reset to ich8lan\n");
        E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_RST));
        msec_delay(20);
 
@@ -1899,11 +1982,10 @@
  *   - initialize LED identification
  *   - setup receive address registers
  *   - setup flow control
- *   - setup transmit discriptors
+ *   - setup transmit descriptors
  *   - clear statistics
  **/
-STATIC s32
-e1000_init_hw_ich8lan(struct e1000_hw *hw)
+static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 ctrl_ext, txdctl, snoop;
@@ -1918,7 +2000,7 @@
        ret_val = e1000_id_led_init_generic(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
-               goto out;
+               /* This is not fatal and we should not stop init due to this */
        }
 
        /* Setup the receive address. */
@@ -1930,24 +2012,26 @@
                E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
 
        /* Setup link and flow control */
-       ret_val = e1000_setup_link(hw);
+       ret_val = mac->ops.setup_link(hw);
 
        /* Set the transmit descriptor write-back policy for both queues */
-       txdctl = E1000_READ_REG(hw, E1000_TXDCTL);
+       txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
        txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
                 E1000_TXDCTL_FULL_TX_DESC_WB;
        txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
                 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
-       E1000_WRITE_REG(hw, E1000_TXDCTL, txdctl);
-       txdctl = E1000_READ_REG(hw, E1000_TXDCTL1);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
+       txdctl = E1000_READ_REG(hw, E1000_TXDCTL(1));
        txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
                 E1000_TXDCTL_FULL_TX_DESC_WB;
        txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
                 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
-       E1000_WRITE_REG(hw, E1000_TXDCTL1, txdctl);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(1), txdctl);
 
-       /* ICH8 has opposite polarity of no_snoop bits.
-        * By default, we should use snoop behavior. */
+       /*
+        * ICH8 has opposite polarity of no_snoop bits.
+        * By default, we should use snoop behavior.
+        */
        if (mac->type == e1000_ich8lan)
                snoop = PCIE_ICH8_SNOOP_ALL;
        else
@@ -1958,14 +2042,14 @@
        ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
        E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
 
-       /* Clear all of the statistics registers (clear on read).  It is
+       /*
+        * 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_ich8lan(hw);
 
-out:
        return ret_val;
 }
 /**
@@ -1975,46 +2059,42 @@
  *  Sets/Clears required hardware bits necessary for correctly setting up the
  *  hardware for transmit and receive.
  **/
-static void
-e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
+static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
 {
        u32 reg;
 
        DEBUGFUNC("e1000_initialize_hw_bits_ich8lan");
 
-       if (hw->mac.disable_hw_init_bits)
-               goto out;
-
        /* Extended Device Control */
        reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
        reg |= (1 << 22);
        E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
 
        /* Transmit Descriptor Control 0 */
-       reg = E1000_READ_REG(hw, E1000_TXDCTL);
+       reg = E1000_READ_REG(hw, E1000_TXDCTL(0));
        reg |= (1 << 22);
-       E1000_WRITE_REG(hw, E1000_TXDCTL, reg);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg);
 
        /* Transmit Descriptor Control 1 */
-       reg = E1000_READ_REG(hw, E1000_TXDCTL1);
+       reg = E1000_READ_REG(hw, E1000_TXDCTL(1));
        reg |= (1 << 22);
-       E1000_WRITE_REG(hw, E1000_TXDCTL1, reg);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg);
 
        /* Transmit Arbitration Control 0 */
-       reg = E1000_READ_REG(hw, E1000_TARC0);
+       reg = E1000_READ_REG(hw, E1000_TARC(0));
        if (hw->mac.type == e1000_ich8lan)
                reg |= (1 << 28) | (1 << 29);
        reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27);
-       E1000_WRITE_REG(hw, E1000_TARC0, reg);
+       E1000_WRITE_REG(hw, E1000_TARC(0), reg);
 
        /* Transmit Arbitration Control 1 */
-       reg = E1000_READ_REG(hw, E1000_TARC1);
+       reg = E1000_READ_REG(hw, E1000_TARC(1));
        if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR)
                reg &= ~(1 << 28);
        else
                reg |= (1 << 28);
        reg |= (1 << 24) | (1 << 26) | (1 << 30);
-       E1000_WRITE_REG(hw, E1000_TARC1, reg);
+       E1000_WRITE_REG(hw, E1000_TARC(1), reg);
 
        /* Device Status */
        if (hw->mac.type == e1000_ich8lan) {
@@ -2023,7 +2103,6 @@
                E1000_WRITE_REG(hw, E1000_STATUS, reg);
        }
 
-out:
        return;
 }
 
@@ -2037,35 +2116,38 @@
  *  should be established.  Assumes the hardware has previously been reset
  *  and the transmitter and receiver are not enabled.
  **/
-STATIC s32
-e1000_setup_link_ich8lan(struct e1000_hw *hw)
+static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
 {
-       struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_setup_link_ich8lan");
 
-       if (e1000_check_reset_block(hw))
+       if (hw->phy.ops.check_reset_block(hw))
                goto out;
 
-       /* ICH parts do not have a word in the NVM to determine
+       /*
+        * ICH parts do not have a word in the NVM to determine
         * the default flow control setting, so we explicitly
         * set it to full.
         */
-       if (mac->fc == e1000_fc_default)
-               mac->fc = e1000_fc_full;
+       if (hw->fc.requested_mode == e1000_fc_default)
+               hw->fc.requested_mode = e1000_fc_full;
 
-       mac->original_fc = mac->fc;
+       /*
+        * Save off the requested flow control mode for use later.  Depending
+        * on the link partner's capabilities, we may or may not use this mode.
+        */
+       hw->fc.current_mode = hw->fc.requested_mode;
 
-       DEBUGOUT1("After fix-ups FlowControl is now = %x\n", mac->fc);
+       DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
+                                                    hw->fc.current_mode);
 
        /* Continue to configure the copper link. */
-       ret_val = func->setup_physical_interface(hw);
+       ret_val = hw->mac.ops.setup_physical_interface(hw);
        if (ret_val)
                goto out;
 
-       E1000_WRITE_REG(hw, E1000_FCTTV, mac->fc_pause_time);
+       E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
 
        ret_val = e1000_set_fc_watermarks_generic(hw);
 
@@ -2081,8 +2163,7 @@
  *  when polling the PHY, then call the generic setup_copper_link to finish
  *  configuring the copper link.
  **/
-STATIC s32
-e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
+static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32 ret_val;
@@ -2095,17 +2176,22 @@
        ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
 
-       /* Set the mac to wait the maximum time between each iteration
+       /*
+        * Set the mac to wait the maximum time between each iteration
         * and increase the max iterations when polling the phy;
-        * this fixes erroneous timeouts at 10Mbps. */
-       ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+        * this fixes erroneous timeouts at 10Mbps.
+        */
+       ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 4),
+                                              0xFFFF);
        if (ret_val)
                goto out;
-       ret_val = e1000_read_kmrn_reg(hw, GG82563_REG(0x34, 9), &reg_data);
+       ret_val = e1000_read_kmrn_reg_generic(hw, GG82563_REG(0x34, 9),
+                                             &reg_data);
        if (ret_val)
                goto out;
        reg_data |= 0x3F;
-       ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data);
+       ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 9),
+                                              reg_data);
        if (ret_val)
                goto out;
 
@@ -2113,8 +2199,37 @@
                ret_val = e1000_copper_link_setup_igp(hw);
                if (ret_val)
                        goto out;
+       } else if (hw->phy.type == e1000_phy_bm) {
+               ret_val = e1000_copper_link_setup_m88(hw);
+               if (ret_val)
+                       goto out;
        }
 
+       if (hw->phy.type == e1000_phy_ife) {
+               ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL,
+                                              &reg_data);
+               if (ret_val)
+                       goto out;
+
+               reg_data &= ~IFE_PMC_AUTO_MDIX;
+
+               switch (hw->phy.mdix) {
+               case 1:
+                       reg_data &= ~IFE_PMC_FORCE_MDIX;
+                       break;
+               case 2:
+                       reg_data |= IFE_PMC_FORCE_MDIX;
+                       break;
+               case 0:
+               default:
+                       reg_data |= IFE_PMC_AUTO_MDIX;
+                       break;
+               }
+               ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_MDIX_CONTROL,
+                                               reg_data);
+               if (ret_val)
+                       goto out;
+       }
        ret_val = e1000_setup_copper_link_generic(hw);
 
 out:
@@ -2127,12 +2242,12 @@
  *  @speed: pointer to store current link speed
  *  @duplex: pointer to store the current link duplex
  *
- *  Calls the generic get_speed_and_duplex to retreive the current link
+ *  Calls the generic get_speed_and_duplex to retrieve the current link
  *  information and then calls the Kumeran lock loss workaround for links at
  *  gigabit speeds.
  **/
-STATIC s32
-e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, u16 *duplex)
+static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
+                                          u16 *duplex)
 {
        s32 ret_val;
 
@@ -2167,31 +2282,24 @@
  *    5) repeat up to 10 times
  *  Note: this is only called for IGP3 copper when speed is 1gb.
  **/
-static s32
-e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
+static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
 {
-       struct e1000_dev_spec_ich8lan *dev_spec;
+       struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
        u32 phy_ctrl;
        s32 ret_val = E1000_SUCCESS;
        u16 i, data;
-       boolean_t link;
+       bool link;
 
        DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan");
 
-       dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               ret_val = -E1000_ERR_CONFIG;
+       if (!(dev_spec->kmrn_lock_loss_workaround_enabled))
                goto out;
-       }
 
-       if (dev_spec->kmrn_lock_loss_workaround_enabled == FALSE)
-               goto out;
-
-       /* Make sure link is up before proceeding.  If not just return.
+       /*
+        * Make sure link is up before proceeding.  If not just return.
         * Attempting this while link is negotiating fouled up link
-        * stability */
+        * stability
+        */
        ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
        if (!link) {
                ret_val = E1000_SUCCESS;
@@ -2200,11 +2308,11 @@
 
        for (i = 0; i < 10; i++) {
                /* read once to clear */
-               ret_val = e1000_read_phy_reg(hw, IGP3_KMRN_DIAG, &data);
+               ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data);
                if (ret_val)
                        goto out;
                /* and again to get new status */
-               ret_val = e1000_read_phy_reg(hw, IGP3_KMRN_DIAG, &data);
+               ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data);
                if (ret_val)
                        goto out;
 
@@ -2215,7 +2323,7 @@
                }
 
                /* Issue PHY reset */
-               e1000_phy_hw_reset(hw);
+               hw->phy.ops.reset(hw);
                msec_delay_irq(5);
        }
        /* Disable GigE link negotiation */
@@ -2224,8 +2332,10 @@
                     E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
        E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
 
-       /* Call gig speed drop workaround on Giga disable before accessing
-        * any PHY registers */
+       /*
+        * Call gig speed drop workaround on Gig disable before accessing
+        * any PHY registers
+        */
        e1000_gig_downshift_workaround_ich8lan(hw);
 
        /* unable to acquire PCS lock */
@@ -2236,36 +2346,27 @@
 }
 
 /**
- *  e1000_set_kmrn_lock_loss_workaound_ich8lan - Set Kumeran workaround state
+ *  e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state
  *  @hw: pointer to the HW structure
- *  @state: boolean value used to set the current Kumaran workaround state
+ *  @state: boolean value used to set the current Kumeran workaround state
  *
  *  If ICH8, set the current Kumeran workaround state (enabled - TRUE
  *  /disabled - FALSE).
  **/
-void
-e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
-                                            boolean_t state)
+void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
+                                                 bool state)
 {
-       struct e1000_dev_spec_ich8lan *dev_spec;
+       struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
 
        DEBUGFUNC("e1000_set_kmrn_lock_loss_workaround_ich8lan");
 
        if (hw->mac.type != e1000_ich8lan) {
                DEBUGOUT("Workaround applies to ICH8 only.\n");
-               goto out;
+               return;
        }
 
-       dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec;
-
-       if (dev_spec == NULL) {
-               DEBUGOUT("dev_spec pointer is set to NULL.\n");
-               goto out;
-       }
-
        dev_spec->kmrn_lock_loss_workaround_enabled = state;
 
-out:
        return;
 }
 
@@ -2279,8 +2380,7 @@
  *    3) read it back
  *  Continue if successful, else issue LCD reset and repeat
  **/
-void
-e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
+void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
 {
        u32 reg;
        u16 data;
@@ -2299,20 +2399,21 @@
                        E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
                E1000_WRITE_REG(hw, E1000_PHY_CTRL, reg);
 
-               /* Call gig speed drop workaround on Giga disable before
-                * accessing any PHY registers */
+               /*
+                * Call gig speed drop workaround on Gig disable before
+                * accessing any PHY registers
+                */
                if (hw->mac.type == e1000_ich8lan)
                        e1000_gig_downshift_workaround_ich8lan(hw);
 
                /* Write VR power-down enable */
-               e1000_read_phy_reg(hw, IGP3_VR_CTRL, &data);
+               hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data);
                data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK;
-               e1000_write_phy_reg(hw,
-                                  IGP3_VR_CTRL,
+               hw->phy.ops.write_reg(hw, IGP3_VR_CTRL,
                                   data | IGP3_VR_CTRL_MODE_SHUTDOWN);
 
                /* Read it back and test */
-               e1000_read_phy_reg(hw, IGP3_VR_CTRL, &data);
+               hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data);
                data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK;
                if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry)
                        break;
@@ -2332,13 +2433,12 @@
  *  @hw: pointer to the HW structure
  *
  *  Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC),
- *  LPLU, Giga disable, MDIC PHY reset):
+ *  LPLU, Gig disable, MDIC PHY reset):
  *    1) Set Kumeran Near-end loopback
  *    2) Clear Kumeran Near-end loopback
  *  Should only be called for ICH8[m] devices with IGP_3 Phy.
  **/
-void
-e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
+void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
        u16 reg_data;
@@ -2349,39 +2449,65 @@
            (hw->phy.type != e1000_phy_igp_3))
                goto out;
 
-       ret_val = e1000_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
-                                     &reg_data);
+       ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
+                                             &reg_data);
        if (ret_val)
                goto out;
        reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK;
-       ret_val = e1000_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
-                                      reg_data);
+       ret_val = e1000_write_kmrn_reg_generic(hw,
+                                              E1000_KMRNCTRLSTA_DIAG_OFFSET,
+                                              reg_data);
        if (ret_val)
                goto out;
        reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK;
-       ret_val = e1000_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
-                                      reg_data);
+       ret_val = e1000_write_kmrn_reg_generic(hw,
+                                              E1000_KMRNCTRLSTA_DIAG_OFFSET,
+                                              reg_data);
 out:
        return;
 }
 
 /**
+ *  e1000_disable_gig_wol_ich8lan - disable gig during WoL
+ *  @hw: pointer to the HW structure
+ *
+ *  During S0 to Sx transition, it is possible the link remains at gig
+ *  instead of negotiating to a lower speed.  Before going to Sx, set
+ *  'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
+ *  to a lower speed.
+ *
+ *  Should only be called for ICH9 and ICH10 devices.
+ **/
+void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw)
+{
+       u32 phy_ctrl;
+
+       if ((hw->mac.type == e1000_ich10lan) ||
+           (hw->mac.type == e1000_ich9lan)) {
+               phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
+               phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU |
+                           E1000_PHY_CTRL_GBE_DISABLE;
+               E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
+       }
+
+       return;
+}
+
+/**
  *  e1000_cleanup_led_ich8lan - Restore the default LED operation
  *  @hw: pointer to the HW structure
  *
  *  Return the LED back to the default configuration.
  **/
-STATIC s32
-e1000_cleanup_led_ich8lan(struct e1000_hw *hw)
+static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_cleanup_led_ich8lan");
 
        if (hw->phy.type == e1000_phy_ife)
-               ret_val = e1000_write_phy_reg(hw,
-                                               IFE_PHY_SPECIAL_CONTROL_LED,
-                                               0);
+               ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
+                                             0);
        else
                E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);
 
@@ -2389,21 +2515,19 @@
 }
 
 /**
- *  e1000_led_on_ich8lan - Turn LED's on
+ *  e1000_led_on_ich8lan - Turn LEDs on
  *  @hw: pointer to the HW structure
  *
- *  Turn on the LED's.
+ *  Turn on the LEDs.
  **/
-STATIC s32
-e1000_led_on_ich8lan(struct e1000_hw *hw)
+static s32 e1000_led_on_ich8lan(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_led_on_ich8lan");
 
        if (hw->phy.type == e1000_phy_ife)
-               ret_val = e1000_write_phy_reg(hw,
-                               IFE_PHY_SPECIAL_CONTROL_LED,
+               ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
                                (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
        else
                E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2);
@@ -2412,20 +2536,19 @@
 }
 
 /**
- *  e1000_led_off_ich8lan - Turn LED's off
+ *  e1000_led_off_ich8lan - Turn LEDs off
  *  @hw: pointer to the HW structure
  *
- *  Turn off the LED's.
+ *  Turn off the LEDs.
  **/
-STATIC s32
-e1000_led_off_ich8lan(struct e1000_hw *hw)
+static s32 e1000_led_off_ich8lan(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_led_off_ich8lan");
 
        if (hw->phy.type == e1000_phy_ife)
-               ret_val = e1000_write_phy_reg(hw,
+               ret_val = hw->phy.ops.write_reg(hw,
                               IFE_PHY_SPECIAL_CONTROL_LED,
                               (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
        else
@@ -2444,48 +2567,72 @@
  *  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_ich8lan(struct e1000_hw *hw)
+static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
 {
+       s32 ret_val = E1000_SUCCESS;
+       u32 bank = 0;
+
        e1000_get_cfg_done_generic(hw);
 
        /* If EEPROM is not marked present, init the IGP 3 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);
+       if (hw->mac.type != e1000_ich10lan) {
+               if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) &&
+                   (hw->phy.type == e1000_phy_igp_3)) {
+                       e1000_phy_init_script_igp3(hw);
+               }
+       } else {
+               if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) {
+                       /* Maybe we should do a basic PHY config */
+                       DEBUGOUT("EEPROM not present\n");
+                       ret_val = -E1000_ERR_CONFIG;
+               }
        }
 
-       return E1000_SUCCESS;
+       return ret_val;
 }
 
 /**
+ * e1000_power_down_phy_copper_ich8lan - 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_ich8lan(struct e1000_hw *hw)
+{
+       /* If the management interface is not enabled, then power down */
+       if (!(hw->mac.ops.check_mng_mode(hw) ||
+             hw->phy.ops.check_reset_block(hw)))
+               e1000_power_down_phy_copper(hw);
+
+       return;
+}
+
+/**
  *  e1000_clear_hw_cntrs_ich8lan - Clear statistical counters
  *  @hw: pointer to the HW structure
  *
  *  Clears hardware counters specific to the silicon family and calls
  *  clear_hw_cntrs_generic to clear all general purpose counters.
  **/
-STATIC void
-e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
 {
-       volatile u32 temp;
-
        DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan");
 
        e1000_clear_hw_cntrs_base_generic(hw);
 
-       temp = E1000_READ_REG(hw, E1000_ALGNERRC);
-       temp = E1000_READ_REG(hw, E1000_RXERRC);
-       temp = E1000_READ_REG(hw, E1000_TNCRS);
-       temp = E1000_READ_REG(hw, E1000_CEXTERR);
-       temp = E1000_READ_REG(hw, E1000_TSCTC);
-       temp = E1000_READ_REG(hw, E1000_TSCTFC);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_MGTPRC);
-       temp = E1000_READ_REG(hw, E1000_MGTPDC);
-       temp = E1000_READ_REG(hw, E1000_MGTPTC);
+       E1000_READ_REG(hw, E1000_MGTPRC);
+       E1000_READ_REG(hw, E1000_MGTPDC);
+       E1000_READ_REG(hw, E1000_MGTPTC);
 
-       temp = E1000_READ_REG(hw, E1000_IAC);
-       temp = E1000_READ_REG(hw, E1000_ICRXOC);
+       E1000_READ_REG(hw, E1000_IAC);
+       E1000_READ_REG(hw, E1000_ICRXOC);
 }
 
Index: dev/em/e1000_82571.c
===================================================================
--- dev/em/e1000_82571.c        (Revision 28889)
+++ dev/em/e1000_82571.c        (Arbeitskopie)
@@ -1,6 +1,6 @@
-/*******************************************************************************
+/******************************************************************************
 
-  Copyright (c) 2001-2007, Intel Corporation 
+  Copyright (c) 2001-2008, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -29,43 +29,52 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
-*******************************************************************************/
-/*$FreeBSD: src/sys/dev/em/e1000_82571.c,v 1.3 2007/05/16 00:14:23 jfv Exp $*/
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/e1000/e1000_82571.c,v 1.2 2008/11/26 23:57:23 jfv Exp 
$*/
 
-
-/* e1000_82571
- * e1000_82572
- * e1000_82573
+/*
+ * 82571EB Gigabit Ethernet Controller
+ * 82571EB Gigabit Ethernet Controller (Copper)
+ * 82571EB Gigabit Ethernet Controller (Fiber)
+ * 82571EB Dual Port Gigabit Mezzanine Adapter
+ * 82571EB Quad Port Gigabit Mezzanine Adapter
+ * 82571PT Gigabit PT Quad Port Server ExpressModule
+ * 82572EI Gigabit Ethernet Controller (Copper)
+ * 82572EI Gigabit Ethernet Controller (Fiber)
+ * 82572EI Gigabit Ethernet Controller
+ * 82573V Gigabit Ethernet Controller (Copper)
+ * 82573E Gigabit Ethernet Controller (Copper)
+ * 82573L Gigabit Ethernet Controller
+ * 82574L Gigabit Network Connection
  */
 
 #include "e1000_api.h"
-#include "e1000_82571.h"
 
-void e1000_init_function_pointers_82571(struct e1000_hw *hw);
-
-STATIC s32  e1000_init_phy_params_82571(struct e1000_hw *hw);
-STATIC s32  e1000_init_nvm_params_82571(struct e1000_hw *hw);
-STATIC s32  e1000_init_mac_params_82571(struct e1000_hw *hw);
-STATIC s32  e1000_acquire_nvm_82571(struct e1000_hw *hw);
-STATIC void e1000_release_nvm_82571(struct e1000_hw *hw);
-STATIC s32  e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset,
+static s32  e1000_init_phy_params_82571(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_82571(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82571(struct e1000_hw *hw);
+static s32  e1000_acquire_nvm_82571(struct e1000_hw *hw);
+static void e1000_release_nvm_82571(struct e1000_hw *hw);
+static s32  e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset,
                                   u16 words, u16 *data);
-STATIC s32  e1000_update_nvm_checksum_82571(struct e1000_hw *hw);
-STATIC s32  e1000_validate_nvm_checksum_82571(struct e1000_hw *hw);
-STATIC s32  e1000_get_cfg_done_82571(struct e1000_hw *hw);
-STATIC s32  e1000_set_d0_lplu_state_82571(struct e1000_hw *hw,
-                                          boolean_t active);
-STATIC s32  e1000_reset_hw_82571(struct e1000_hw *hw);
-STATIC s32  e1000_init_hw_82571(struct e1000_hw *hw);
-STATIC void e1000_clear_vfta_82571(struct e1000_hw *hw);
-STATIC void e1000_mc_addr_list_update_82571(struct e1000_hw *hw,
-                                            u8 *mc_addr_list, u32 
mc_addr_count,
-                                            u32 rar_used_count, u32 rar_count);
-STATIC s32  e1000_setup_link_82571(struct e1000_hw *hw);
-STATIC s32  e1000_setup_copper_link_82571(struct e1000_hw *hw);
-STATIC s32  e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
-STATIC s32  e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data);
-STATIC void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
+static s32  e1000_update_nvm_checksum_82571(struct e1000_hw *hw);
+static s32  e1000_validate_nvm_checksum_82571(struct e1000_hw *hw);
+static s32  e1000_get_cfg_done_82571(struct e1000_hw *hw);
+static s32  e1000_set_d0_lplu_state_82571(struct e1000_hw *hw,
+                                          bool active);
+static s32  e1000_reset_hw_82571(struct e1000_hw *hw);
+static s32  e1000_init_hw_82571(struct e1000_hw *hw);
+static void e1000_clear_vfta_82571(struct e1000_hw *hw);
+static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
+static s32 e1000_led_on_82574(struct e1000_hw *hw);
+static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw,
+                                           u8 *mc_addr_list, u32 mc_addr_count,
+                                           u32 rar_used_count, u32 rar_count);
+static s32  e1000_setup_link_82571(struct e1000_hw *hw);
+static s32  e1000_setup_copper_link_82571(struct e1000_hw *hw);
+static s32  e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
+static s32  e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data);
+static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
 static s32  e1000_get_hw_semaphore_82571(struct e1000_hw *hw);
 static s32  e1000_fix_nvm_checksum_82571(struct e1000_hw *hw);
 static s32  e1000_get_phy_id_82571(struct e1000_hw *hw);
@@ -73,28 +82,22 @@
 static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw);
 static s32  e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
                                        u16 words, u16 *data);
+static s32  e1000_read_mac_addr_82571(struct e1000_hw *hw);
+static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw);
 
-struct e1000_dev_spec_82571 {
-       boolean_t laa_is_present;
-};
-
 /**
  *  e1000_init_phy_params_82571 - Init PHY func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_phy_params_82571(struct e1000_hw *hw)
+static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_phy_params_82571");
 
-       if (hw->media_type != e1000_media_type_copper) {
-               phy->type        = e1000_phy_none;
+       if (hw->phy.media_type != e1000_media_type_copper) {
+               phy->type = e1000_phy_none;
                goto out;
        }
 
@@ -102,59 +105,75 @@
        phy->autoneg_mask                = AUTONEG_ADVERTISE_SPEED_DEFAULT;
        phy->reset_delay_us              = 100;
 
-       func->acquire_phy                = e1000_get_hw_semaphore_82571;
-       func->check_polarity             = e1000_check_polarity_igp;
-       func->check_reset_block          = e1000_check_reset_block_generic;
-       func->release_phy                = e1000_put_hw_semaphore_82571;
-       func->reset_phy                  = e1000_phy_hw_reset_generic;
-       func->set_d0_lplu_state          = e1000_set_d0_lplu_state_82571;
-       func->set_d3_lplu_state          = e1000_set_d3_lplu_state_generic;
+       phy->ops.acquire                 = e1000_get_hw_semaphore_82571;
+       phy->ops.check_polarity          = e1000_check_polarity_igp;
+       phy->ops.check_reset_block       = e1000_check_reset_block_generic;
+       phy->ops.release                 = e1000_put_hw_semaphore_82571;
+       phy->ops.reset                   = e1000_phy_hw_reset_generic;
+       phy->ops.set_d0_lplu_state       = e1000_set_d0_lplu_state_82571;
+       phy->ops.set_d3_lplu_state       = e1000_set_d3_lplu_state_generic;
+       phy->ops.power_up                = e1000_power_up_phy_copper;
+       phy->ops.power_down              = e1000_power_down_phy_copper_82571;
 
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
-               phy->type                = e1000_phy_igp_2;
-               func->get_cfg_done       = e1000_get_cfg_done_82571;
-               func->get_phy_info       = e1000_get_phy_info_igp;
-               func->force_speed_duplex = e1000_phy_force_speed_duplex_igp;
-               func->get_cable_length   = e1000_get_cable_length_igp_2;
-               func->read_phy_reg       = e1000_read_phy_reg_igp;
-               func->write_phy_reg      = e1000_write_phy_reg_igp;
-               break;
-       case e1000_82573:
-               phy->type                = e1000_phy_m88;
-               func->get_cfg_done       = e1000_get_cfg_done_generic;
-               func->get_phy_info       = e1000_get_phy_info_m88;
-               func->commit_phy         = e1000_phy_sw_reset_generic;
-               func->force_speed_duplex = e1000_phy_force_speed_duplex_m88;
-               func->get_cable_length   = e1000_get_cable_length_m88;
-               func->read_phy_reg       = e1000_read_phy_reg_m88;
-               func->write_phy_reg      = e1000_write_phy_reg_m88;
-               break;
-       default:
-               ret_val = -E1000_ERR_PHY;
-               goto out;
-               break;
-       }
+               phy->type                   = e1000_phy_igp_2;
+               phy->ops.get_cfg_done       = e1000_get_cfg_done_82571;
+               phy->ops.get_info           = e1000_get_phy_info_igp;
+               phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
+               phy->ops.get_cable_length   = e1000_get_cable_length_igp_2;
+               phy->ops.read_reg           = e1000_read_phy_reg_igp;
+               phy->ops.write_reg          = e1000_write_phy_reg_igp;
 
-       /* This can only be done after all function pointers are setup. */
-       ret_val = e1000_get_phy_id_82571(hw);
+               /* This uses above function pointers */
+               ret_val = e1000_get_phy_id_82571(hw);
 
-       /* Verify phy id */
-       switch (hw->mac.type) {
-       case e1000_82571:
-       case e1000_82572:
+               /* Verify PHY ID */
                if (phy->id != IGP01E1000_I_PHY_ID) {
                        ret_val = -E1000_ERR_PHY;
                        goto out;
                }
                break;
        case e1000_82573:
+               phy->type                   = e1000_phy_m88;
+               phy->ops.get_cfg_done       = e1000_get_cfg_done_generic;
+               phy->ops.get_info           = e1000_get_phy_info_m88;
+               phy->ops.commit             = e1000_phy_sw_reset_generic;
+               phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
+               phy->ops.get_cable_length   = e1000_get_cable_length_m88;
+               phy->ops.read_reg           = e1000_read_phy_reg_m88;
+               phy->ops.write_reg          = e1000_write_phy_reg_m88;
+
+               /* This uses above function pointers */
+               ret_val = e1000_get_phy_id_82571(hw);
+
+               /* Verify PHY ID */
                if (phy->id != M88E1111_I_PHY_ID) {
                        ret_val = -E1000_ERR_PHY;
+                       DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
                        goto out;
                }
                break;
+       case e1000_82574:
+               phy->type                   = e1000_phy_bm;
+               phy->ops.get_cfg_done       = e1000_get_cfg_done_generic;
+               phy->ops.get_info           = e1000_get_phy_info_m88;
+               phy->ops.commit             = e1000_phy_sw_reset_generic;
+               phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
+               phy->ops.get_cable_length   = e1000_get_cable_length_m88;
+               phy->ops.read_reg           = e1000_read_phy_reg_bm2;
+               phy->ops.write_reg          = e1000_write_phy_reg_bm2;
+
+               /* This uses above function pointers */
+               ret_val = e1000_get_phy_id_82571(hw);
+               /* Verify PHY ID */
+               if (phy->id != BME1000_E_PHY_ID_R2) {
+                       ret_val = -E1000_ERR_PHY;
+                       DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
+                       goto out;
+               }
+               break;
        default:
                ret_val = -E1000_ERR_PHY;
                goto out;
@@ -168,42 +187,40 @@
 /**
  *  e1000_init_nvm_params_82571 - Init NVM func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_nvm_params_82571(struct e1000_hw *hw)
+static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       struct e1000_functions *func = &hw->func;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
        u16 size;
 
        DEBUGFUNC("e1000_init_nvm_params_82571");
 
-       nvm->opcode_bits          = 8;
-       nvm->delay_usec           = 1;
+       nvm->opcode_bits = 8;
+       nvm->delay_usec = 1;
        switch (nvm->override) {
        case e1000_nvm_override_spi_large:
-               nvm->page_size    = 32;
+               nvm->page_size = 32;
                nvm->address_bits = 16;
                break;
        case e1000_nvm_override_spi_small:
-               nvm->page_size    = 8;
+               nvm->page_size = 8;
                nvm->address_bits = 8;
                break;
        default:
-               nvm->page_size    = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
+               nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
                nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
                break;
        }
 
        switch (hw->mac.type) {
        case e1000_82573:
+       case e1000_82574:
                if (((eecd >> 15) & 0x3) == 0x3) {
                        nvm->type = e1000_nvm_flash_hw;
                        nvm->word_size = 2048;
-                       /* Autonomous Flash update bit must be cleared due
+                       /*
+                        * Autonomous Flash update bit must be cleared due
                         * to Flash update issue.
                         */
                        eecd &= ~E1000_EECD_AUPDEN;
@@ -212,27 +229,30 @@
                }
                /* Fall Through */
        default:
-               nvm->type       = e1000_nvm_eeprom_spi;
+               nvm->type = e1000_nvm_eeprom_spi;
                size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
                                  E1000_EECD_SIZE_EX_SHIFT);
-               /* Added to a constant, "size" becomes the left-shift value
+               /*
+                * Added to a constant, "size" becomes the left-shift value
                 * for setting word_size.
                 */
                size += NVM_WORD_SIZE_BASE_SHIFT;
+
+               /* EEPROM access above 16k is unsupported */
+               if (size > 14)
+                       size = 14;
                nvm->word_size  = 1 << size;
                break;
        }
 
        /* Function Pointers */
-       func->acquire_nvm       = e1000_acquire_nvm_82571;
-       func->read_nvm          = (hw->mac.type == e1000_82573)
-                                 ? e1000_read_nvm_eerd
-                                 : e1000_read_nvm_spi;
-       func->release_nvm       = e1000_release_nvm_82571;
-       func->update_nvm        = e1000_update_nvm_checksum_82571;
-       func->validate_nvm      = e1000_validate_nvm_checksum_82571;
-       func->valid_led_default = e1000_valid_led_default_82571;
-       func->write_nvm         = e1000_write_nvm_82571;
+       nvm->ops.acquire       = e1000_acquire_nvm_82571;
+       nvm->ops.read          = e1000_read_nvm_eerd;
+       nvm->ops.release       = e1000_release_nvm_82571;
+       nvm->ops.update        = e1000_update_nvm_checksum_82571;
+       nvm->ops.validate      = e1000_validate_nvm_checksum_82571;
+       nvm->ops.valid_led_default = e1000_valid_led_default_82571;
+       nvm->ops.write         = e1000_write_nvm_82571;
 
        return E1000_SUCCESS;
 }
@@ -240,14 +260,10 @@
 /**
  *  e1000_init_mac_params_82571 - Init MAC func ptrs.
  *  @hw: pointer to the HW structure
- *
- *  This is a function pointer entry point called by the api module.
  **/
-STATIC s32
-e1000_init_mac_params_82571(struct e1000_hw *hw)
+static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       struct e1000_functions *func = &hw->func;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_mac_params_82571");
@@ -257,16 +273,16 @@
        case E1000_DEV_ID_82571EB_FIBER:
        case E1000_DEV_ID_82572EI_FIBER:
        case E1000_DEV_ID_82571EB_QUAD_FIBER:
-               hw->media_type = e1000_media_type_fiber;
+               hw->phy.media_type = e1000_media_type_fiber;
                break;
        case E1000_DEV_ID_82571EB_SERDES:
        case E1000_DEV_ID_82571EB_SERDES_DUAL:
        case E1000_DEV_ID_82571EB_SERDES_QUAD:
        case E1000_DEV_ID_82572EI_SERDES:
-               hw->media_type = e1000_media_type_internal_serdes;
+               hw->phy.media_type = e1000_media_type_internal_serdes;
                break;
        default:
-               hw->media_type = e1000_media_type_copper;
+               hw->phy.media_type = e1000_media_type_copper;
                break;
        }
 
@@ -284,28 +300,37 @@
        /* Function pointers */
 
        /* bus type/speed/width */
-       func->get_bus_info = e1000_get_bus_info_pcie_generic;
+       mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
+       /* function id */
+       switch (hw->mac.type) {
+       case e1000_82573:
+       case e1000_82574:
+               mac->ops.set_lan_id = e1000_set_lan_id_single_port;
+               break;
+       default:
+               break;
+       }
        /* reset */
-       func->reset_hw = e1000_reset_hw_82571;
+       mac->ops.reset_hw = e1000_reset_hw_82571;
        /* hw initialization */
-       func->init_hw = e1000_init_hw_82571;
+       mac->ops.init_hw = e1000_init_hw_82571;
        /* link setup */
-       func->setup_link = e1000_setup_link_82571;
+       mac->ops.setup_link = e1000_setup_link_82571;
        /* physical interface link setup */
-       func->setup_physical_interface =
-               (hw->media_type == e1000_media_type_copper)
+       mac->ops.setup_physical_interface =
+               (hw->phy.media_type == e1000_media_type_copper)
                        ? e1000_setup_copper_link_82571
                        : e1000_setup_fiber_serdes_link_82571;
        /* check for link */
-       switch (hw->media_type) {
+       switch (hw->phy.media_type) {
        case e1000_media_type_copper:
-               func->check_for_link = e1000_check_for_copper_link_generic;
+               mac->ops.check_for_link = e1000_check_for_copper_link_generic;
                break;
        case e1000_media_type_fiber:
-               func->check_for_link = e1000_check_for_fiber_link_generic;
+               mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
                break;
        case e1000_media_type_internal_serdes:
-               func->check_for_link = e1000_check_for_serdes_link_generic;
+               mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
                break;
        default:
                ret_val = -E1000_ERR_CONFIG;
@@ -313,39 +338,48 @@
                break;
        }
        /* check management mode */
-       func->check_mng_mode = e1000_check_mng_mode_generic;
+       switch (hw->mac.type) {
+       case e1000_82574:
+               mac->ops.check_mng_mode = e1000_check_mng_mode_82574;
+               break;
+       default:
+               mac->ops.check_mng_mode = e1000_check_mng_mode_generic;
+               break;
+       }
        /* multicast address update */
-       func->mc_addr_list_update = e1000_mc_addr_list_update_82571;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82571;
        /* writing VFTA */
-       func->write_vfta = e1000_write_vfta_generic;
+       mac->ops.write_vfta = e1000_write_vfta_generic;
        /* clearing VFTA */
-       func->clear_vfta = e1000_clear_vfta_82571;
+       mac->ops.clear_vfta = e1000_clear_vfta_82571;
        /* setting MTA */
-       func->mta_set = e1000_mta_set_generic;
+       mac->ops.mta_set = e1000_mta_set_generic;
+       /* read mac address */
+       mac->ops.read_mac_addr = e1000_read_mac_addr_82571;
        /* blink LED */
-       func->blink_led = e1000_blink_led_generic;
+       mac->ops.blink_led = e1000_blink_led_generic;
        /* setup LED */
-       func->setup_led = e1000_setup_led_generic;
+       mac->ops.setup_led = e1000_setup_led_generic;
        /* cleanup LED */
-       func->cleanup_led = e1000_cleanup_led_generic;
+       mac->ops.cleanup_led = e1000_cleanup_led_generic;
        /* turn on/off LED */
-       func->led_on = e1000_led_on_generic;
-       func->led_off = e1000_led_off_generic;
-       /* remove device */
-       func->remove_device = e1000_remove_device_generic;
+       switch (hw->mac.type) {
+       case e1000_82574:
+               mac->ops.led_on = e1000_led_on_82574;
+               break;
+       default:
+               mac->ops.led_on = e1000_led_on_generic;
+               break;
+       }
+       mac->ops.led_off = e1000_led_off_generic;
        /* clear hardware counters */
-       func->clear_hw_cntrs = e1000_clear_hw_cntrs_82571;
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82571;
        /* link info */
-       func->get_link_up_info =
-               (hw->media_type == e1000_media_type_copper)
+       mac->ops.get_link_up_info =
+               (hw->phy.media_type == e1000_media_type_copper)
                        ? e1000_get_speed_and_duplex_copper_generic
                        : e1000_get_speed_and_duplex_fiber_serdes_generic;
 
-       hw->dev_spec_size = sizeof(struct e1000_dev_spec_82571);
-
-       /* Device-specific structure allocation */
-       ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size);
-
 out:
        return ret_val;
 }
@@ -354,17 +388,15 @@
  *  e1000_init_function_pointers_82571 - Init func ptrs.
  *  @hw: pointer to the HW structure
  *
- *  The only function explicitly called by the api module to initialize
- *  all function pointers and parameters.
+ *  Called to initialize all function pointers and parameters.
  **/
-void
-e1000_init_function_pointers_82571(struct e1000_hw *hw)
+void e1000_init_function_pointers_82571(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_init_function_pointers_82571");
 
-       hw->func.init_mac_params = e1000_init_mac_params_82571;
-       hw->func.init_nvm_params = e1000_init_nvm_params_82571;
-       hw->func.init_phy_params = e1000_init_phy_params_82571;
+       hw->mac.ops.init_params = e1000_init_mac_params_82571;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82571;
+       hw->phy.ops.init_params = e1000_init_phy_params_82571;
 }
 
 /**
@@ -374,31 +406,48 @@
  *  Reads the PHY registers and stores the PHY ID and possibly the PHY
  *  revision in the hardware structure.
  **/
-static s32
-e1000_get_phy_id_82571(struct e1000_hw *hw)
+static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val = E1000_SUCCESS;
+       u16 phy_id = 0;
 
        DEBUGFUNC("e1000_get_phy_id_82571");
 
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
-               /* The 82571 firmware may still be configuring the PHY.
+               /*
+                * The 82571 firmware may still be configuring the PHY.
                 * In this case, we cannot access the PHY until the
                 * configuration is done.  So we explicitly set the
-                * PHY ID. */
+                * PHY ID.
+                */
                phy->id = IGP01E1000_I_PHY_ID;
                break;
        case e1000_82573:
                ret_val = e1000_get_phy_id(hw);
                break;
+       case e1000_82574:
+               ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
+               if (ret_val)
+                       goto out;
+
+               phy->id = (u32)(phy_id << 16);
+               usec_delay(20);
+               ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
+               if (ret_val)
+                       goto out;
+
+               phy->id |= (u32)(phy_id);
+               phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
+               break;
        default:
                ret_val = -E1000_ERR_PHY;
                break;
        }
 
+out:
        return ret_val;
 }
 
@@ -408,8 +457,7 @@
  *
  *  Acquire the HW semaphore to access the PHY or NVM
  **/
-s32
-e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
+static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
 {
        u32 swsm;
        s32 ret_val = E1000_SUCCESS;
@@ -448,8 +496,7 @@
  *
  *  Release hardware semaphore used to access the PHY or NVM
  **/
-void
-e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
+static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
 {
        u32 swsm;
 
@@ -471,8 +518,7 @@
  *  for EEPROM access grant bit.  If the access grant bit is not set, release
  *  hardware semaphore.
  **/
-STATIC s32
-e1000_acquire_nvm_82571(struct e1000_hw *hw)
+static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
 {
        s32 ret_val;
 
@@ -482,7 +528,7 @@
        if (ret_val)
                goto out;
 
-       if (hw->mac.type != e1000_82573)
+       if (hw->mac.type != e1000_82573 && hw->mac.type != e1000_82574)
                ret_val = e1000_acquire_nvm_generic(hw);
 
        if (ret_val)
@@ -498,8 +544,7 @@
  *
  *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
  **/
-STATIC void
-e1000_release_nvm_82571(struct e1000_hw *hw)
+static void e1000_release_nvm_82571(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_release_nvm_82571");
 
@@ -517,10 +562,10 @@
  *  For non-82573 silicon, write data to EEPROM at offset using SPI interface.
  *
  *  If e1000_update_nvm_checksum is not called after this function, the
- *  EEPROM will most likley contain an invalid checksum.
+ *  EEPROM will most likely contain an invalid checksum.
  **/
-STATIC s32
-e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words,
+                                 u16 *data)
 {
        s32 ret_val = E1000_SUCCESS;
 
@@ -528,6 +573,7 @@
 
        switch (hw->mac.type) {
        case e1000_82573:
+       case e1000_82574:
                ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data);
                break;
        case e1000_82571:
@@ -550,8 +596,7 @@
  *  up to the checksum.  Then calculates the EEPROM checksum and writes the
  *  value to the EEPROM.
  **/
-STATIC s32
-e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
+static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
 {
        u32 eecd;
        s32 ret_val;
@@ -563,8 +608,10 @@
        if (ret_val)
                goto out;
 
-       /* If our nvm is an EEPROM, then we're done
-        * otherwise, commit the checksum to the flash NVM. */
+       /*
+        * If our nvm is an EEPROM, then we're done
+        * otherwise, commit the checksum to the flash NVM.
+        */
        if (hw->nvm.type != e1000_nvm_flash_hw)
                goto out;
 
@@ -582,7 +629,8 @@
 
        /* Reset the firmware if using STM opcode. */
        if ((E1000_READ_REG(hw, E1000_FLOP) & 0xFF00) == E1000_STM_OPCODE) {
-               /* The enabling of and the actual reset must be done
+               /*
+                * The enabling of and the actual reset must be done
                 * in two write cycles.
                 */
                E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET_ENABLE);
@@ -616,8 +664,7 @@
  *  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.
  **/
-STATIC s32
-e1000_validate_nvm_checksum_82571(struct e1000_hw *hw)
+static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_validate_nvm_checksum_82571");
 
@@ -639,11 +686,10 @@
  *  poll for completion.
  *
  *  If e1000_update_nvm_checksum is not called after this function, the
- *  EEPROM will most likley contain an invalid checksum.
+ *  EEPROM will most likely contain an invalid checksum.
  **/
-static s32
-e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, u16 words,
-                           u16 *data)
+static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
+                                      u16 words, u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        u32 i, eewr = 0;
@@ -651,8 +697,10 @@
 
        DEBUGFUNC("e1000_write_nvm_eewr_82571");
 
-       /* A check for invalid values:  offset too large, too many words,
-        * and not enough words. */
+       /*
+        * A check for invalid values:  offset too large, too many words,
+        * and not enough words.
+        */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                DEBUGOUT("nvm parameter(s) out of bounds\n");
@@ -686,8 +734,7 @@
  *
  *  Reads the management control register for the config done bit to be set.
  **/
-STATIC s32
-e1000_get_cfg_done_82571(struct e1000_hw *hw)
+static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw)
 {
        s32 timeout = PHY_CFG_TIMEOUT;
        s32 ret_val = E1000_SUCCESS;
@@ -721,68 +768,68 @@
  *  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_82571(struct e1000_hw *hw, boolean_t active)
+static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32 ret_val;
+       s32 ret_val = E1000_SUCCESS;
        u16 data;
 
        DEBUGFUNC("e1000_set_d0_lplu_state_82571");
 
-       ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
+       if (!(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 = e1000_write_phy_reg(hw,
-                                             IGP02E1000_PHY_POWER_MGMT,
-                                             data);
+               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 = e1000_read_phy_reg(hw,
-                                            IGP01E1000_PHY_PORT_CONFIG,
-                                            &data);
+               ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+                                           &data);
                data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-               ret_val = e1000_write_phy_reg(hw,
-                                             IGP01E1000_PHY_PORT_CONFIG,
-                                             data);
+               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 = e1000_write_phy_reg(hw,
-                                             IGP02E1000_PHY_POWER_MGMT,
-                                             data);
-               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               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. */
+                * SmartSpeed, so performance is maintained.
+                */
                if (phy->smart_speed == e1000_smart_speed_on) {
-                       ret_val = e1000_read_phy_reg(hw,
-                                                    IGP01E1000_PHY_PORT_CONFIG,
-                                                    &data);
+                       ret_val = phy->ops.read_reg(hw,
+                                                   IGP01E1000_PHY_PORT_CONFIG,
+                                                   &data);
                        if (ret_val)
                                goto out;
 
                        data |= IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       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 = e1000_read_phy_reg(hw,
-                                                    IGP01E1000_PHY_PORT_CONFIG,
-                                                    &data);
+                       ret_val = phy->ops.read_reg(hw,
+                                                   IGP01E1000_PHY_PORT_CONFIG,
+                                                   &data);
                        if (ret_val)
                                goto out;
 
                        data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-                       ret_val = e1000_write_phy_reg(hw,
+                       ret_val = phy->ops.write_reg(hw,
                                                     IGP01E1000_PHY_PORT_CONFIG,
                                                     data);
                        if (ret_val)
@@ -798,11 +845,9 @@
  *  e1000_reset_hw_82571 - Reset hardware
  *  @hw: pointer to the HW structure
  *
- *  This resets the hardware into a known state.  This is a
- *  function pointer entry point called by the api module.
+ *  This resets the hardware into a known state.
  **/
-STATIC s32
-e1000_reset_hw_82571(struct e1000_hw *hw)
+static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
 {
        u32 ctrl, extcnf_ctrl, ctrl_ext, icr;
        s32 ret_val;
@@ -810,13 +855,13 @@
 
        DEBUGFUNC("e1000_reset_hw_82571");
 
-       /* Prevent the PCI-E bus from sticking if there is no TLP connection
+       /*
+        * 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) {
+       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);
@@ -827,9 +872,11 @@
 
        msec_delay(10);
 
-       /* Must acquire the MDIO ownership before MAC reset.
-        * Ownership defaults to firmware after a reset. */
-       if (hw->mac.type == e1000_82573) {
+       /*
+        * Must acquire the MDIO ownership before MAC reset.
+        * Ownership defaults to firmware after a reset.
+        */
+       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
                extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
                extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
 
@@ -865,17 +912,21 @@
                /* We don't want to continue accessing MAC registers. */
                goto out;
 
-       /* Phy configuration from NVM just starts after EECD_AUTO_RD is set.
+       /*
+        * Phy configuration from NVM just starts after EECD_AUTO_RD is set.
         * Need to wait for Phy configuration completion before accessing
         * NVM and Phy.
         */
-       if (hw->mac.type == e1000_82573)
+       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574)
                msec_delay(25);
 
        /* Clear any pending interrupt events. */
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
        icr = E1000_READ_REG(hw, E1000_ICR);
 
+       if (!(e1000_check_alt_mac_addr_generic(hw)))
+               e1000_set_laa_state_82571(hw, TRUE);
+
 out:
        return ret_val;
 }
@@ -886,8 +937,7 @@
  *
  *  This inits the hardware readying it for operation.
  **/
-STATIC s32
-e1000_init_hw_82571(struct e1000_hw *hw)
+static s32 e1000_init_hw_82571(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 reg_data;
@@ -902,19 +952,20 @@
        ret_val = e1000_id_led_init_generic(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
-               goto out;
+               /* This is not fatal and we should not stop init due to this */
        }
 
        /* Disabling VLAN filtering */
        DEBUGOUT("Initializing the IEEE VLAN\n");
-       e1000_clear_vfta(hw);
+       mac->ops.clear_vfta(hw);
 
        /* Setup the receive address. */
-       /* If, however, a locally administered address was assigned to the
+       /*
+        * If, however, a locally administered address was assigned to the
         * 82571, we must reserve a RAR for it to work around an issue where
         * resetting one port will reload the MAC on the other port.
         */
-       if (e1000_get_laa_state_82571(hw) == TRUE)
+       if (e1000_get_laa_state_82571(hw))
                rar_count--;
        e1000_init_rx_addrs_generic(hw, rar_count);
 
@@ -924,37 +975,37 @@
                E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
 
        /* Setup link and flow control */
-       ret_val = e1000_setup_link(hw);
+       ret_val = mac->ops.setup_link(hw);
 
        /* Set the transmit descriptor write-back policy */
-       reg_data = E1000_READ_REG(hw, E1000_TXDCTL);
+       reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
        reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
                   E1000_TXDCTL_FULL_TX_DESC_WB |
                   E1000_TXDCTL_COUNT_DESC;
-       E1000_WRITE_REG(hw, E1000_TXDCTL, reg_data);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
 
        /* ...for both queues. */
-       if (mac->type != e1000_82573) {
-               reg_data = E1000_READ_REG(hw, E1000_TXDCTL1);
+       if (mac->type != e1000_82573 && mac->type != e1000_82574) {
+               reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
                reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
                           E1000_TXDCTL_FULL_TX_DESC_WB |
                           E1000_TXDCTL_COUNT_DESC;
-               E1000_WRITE_REG(hw, E1000_TXDCTL1, reg_data);
+               E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
        } else {
-               e1000_enable_tx_pkt_filtering(hw);
+               e1000_enable_tx_pkt_filtering_generic(hw);
                reg_data = E1000_READ_REG(hw, E1000_GCR);
                reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
                E1000_WRITE_REG(hw, E1000_GCR, reg_data);
        }
 
-       /* Clear all of the statistics registers (clear on read).  It is
+       /*
+        * 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_82571(hw);
 
-out:
        return ret_val;
 }
 
@@ -964,28 +1015,24 @@
  *
  *  Initializes required hardware-dependent bits needed for normal operation.
  **/
-static void
-e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
+static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
 {
        u32 reg;
 
        DEBUGFUNC("e1000_initialize_hw_bits_82571");
 
-       if (hw->mac.disable_hw_init_bits)
-               goto out;
-
        /* Transmit Descriptor Control 0 */
-       reg = E1000_READ_REG(hw, E1000_TXDCTL);
+       reg = E1000_READ_REG(hw, E1000_TXDCTL(0));
        reg |= (1 << 22);
-       E1000_WRITE_REG(hw, E1000_TXDCTL, reg);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg);
 
        /* Transmit Descriptor Control 1 */
-       reg = E1000_READ_REG(hw, E1000_TXDCTL1);
+       reg = E1000_READ_REG(hw, E1000_TXDCTL(1));
        reg |= (1 << 22);
-       E1000_WRITE_REG(hw, E1000_TXDCTL1, reg);
+       E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg);
 
        /* Transmit Arbitration Control 0 */
-       reg = E1000_READ_REG(hw, E1000_TARC0);
+       reg = E1000_READ_REG(hw, E1000_TARC(0));
        reg &= ~(0xF << 27); /* 30:27 */
        switch (hw->mac.type) {
        case e1000_82571:
@@ -995,10 +1042,10 @@
        default:
                break;
        }
-       E1000_WRITE_REG(hw, E1000_TARC0, reg);
+       E1000_WRITE_REG(hw, E1000_TARC(0), reg);
 
        /* Transmit Arbitration Control 1 */
-       reg = E1000_READ_REG(hw, E1000_TARC1);
+       reg = E1000_READ_REG(hw, E1000_TARC(1));
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
@@ -1008,28 +1055,34 @@
                        reg &= ~(1 << 28);
                else
                        reg |= (1 << 28);
-               E1000_WRITE_REG(hw, E1000_TARC1, reg);
+               E1000_WRITE_REG(hw, E1000_TARC(1), reg);
                break;
        default:
                break;
        }
 
        /* Device Control */
-       if (hw->mac.type == e1000_82573) {
+       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
                reg = E1000_READ_REG(hw, E1000_CTRL);
                reg &= ~(1 << 29);
                E1000_WRITE_REG(hw, E1000_CTRL, reg);
        }
 
        /* Extended Device Control */
-       if (hw->mac.type == e1000_82573) {
+       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
                reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
                reg &= ~(1 << 23);
                reg |= (1 << 22);
                E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
        }
 
-out:
+       /* PCI-Ex Control Register */
+       if (hw->mac.type == e1000_82574) {
+               reg = E1000_READ_REG(hw, E1000_GCR);
+               reg |= (1 << 22);
+               E1000_WRITE_REG(hw, E1000_GCR, reg);
+       }
+
        return;
 }
 
@@ -1040,8 +1093,7 @@
  *  Clears the register array which contains the VLAN filter table by
  *  setting all the values to 0.
  **/
-STATIC void
-e1000_clear_vfta_82571(struct e1000_hw *hw)
+static void e1000_clear_vfta_82571(struct e1000_hw *hw)
 {
        u32 offset;
        u32 vfta_value = 0;
@@ -1050,9 +1102,10 @@
 
        DEBUGFUNC("e1000_clear_vfta_82571");
 
-       if (hw->mac.type == e1000_82573) {
+       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
                if (hw->mng_cookie.vlan_id != 0) {
-                       /* The VFTA is a 4096b bit-field, each identifying
+                       /*
+                        * The VFTA is a 4096b bit-field, each identifying
                         * a single VLAN ID.  The following operations
                         * determine which 32b entry (i.e. offset) into the
                         * array we want to set the VLAN ID (i.e. bit) of
@@ -1066,7 +1119,8 @@
                }
        }
        for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
-               /* If the offset we want to clear is the same offset of the
+               /*
+                * If the offset we want to clear is the same offset of the
                 * manageability VLAN ID, then clear all bits except that of
                 * the manageability unit.
                 */
@@ -1077,8 +1131,54 @@
 }
 
 /**
- *  e1000_mc_addr_list_update_82571 - Update Multicast addresses
+ *  e1000_check_mng_mode_82574 - Check manageability is enabled
  *  @hw: pointer to the HW structure
+ *
+ *  Reads the NVM Initialization Control Word 2 and returns TRUE
+ *  (>0) if any manageability is enabled, else FALSE (0).
+ **/
+static bool e1000_check_mng_mode_82574(struct e1000_hw *hw)
+{
+       u16 data;
+
+       DEBUGFUNC("e1000_check_mng_mode_82574");
+
+       hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+       return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0;
+}
+
+/**
+ *  e1000_led_on_82574 - Turn LED on
+ *  @hw: pointer to the HW structure
+ *
+ *  Turn LED on.
+ **/
+static s32 e1000_led_on_82574(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       u32 i;
+
+       DEBUGFUNC("e1000_led_on_82574");
+
+       ctrl = hw->mac.ledctl_mode2;
+       if (!(E1000_STATUS_LU & E1000_READ_REG(hw, E1000_STATUS))) {
+               /*
+                * If no link, then turn LED on by setting the invert bit
+                * for each LED that's "on" (0x0E) in ledctl_mode2.
+                */
+               for (i = 0; i < 4; i++)
+                       if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
+                           E1000_LEDCTL_MODE_LED_ON)
+                               ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8));
+       }
+       E1000_WRITE_REG(hw, E1000_LEDCTL, ctrl);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_update_mc_addr_list_82571 - 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
  *  @rar_used_count: the first RAR register free to program
@@ -1089,17 +1189,16 @@
  *  The parameter rar_count will usually be hw->mac.rar_entry_count
  *  unless there are workarounds that change this.
  **/
-STATIC void
-e1000_mc_addr_list_update_82571(struct e1000_hw *hw,
-                                u8 *mc_addr_list, u32 mc_addr_count,
-                                u32 rar_used_count, u32 rar_count)
+static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw,
+                                           u8 *mc_addr_list, u32 mc_addr_count,
+                                           u32 rar_used_count, u32 rar_count)
 {
-       DEBUGFUNC("e1000_mc_addr_list_update_82571");
+       DEBUGFUNC("e1000_update_mc_addr_list_82571");
 
        if (e1000_get_laa_state_82571(hw))
                rar_count--;
 
-       e1000_mc_addr_list_update_generic(hw, mc_addr_list, mc_addr_count,
+       e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count,
                                          rar_used_count, rar_count);
 }
 
@@ -1113,17 +1212,18 @@
  *  should be established.  Assumes the hardware has previously been reset
  *  and the transmitter and receiver are not enabled.
  **/
-STATIC s32
-e1000_setup_link_82571(struct e1000_hw *hw)
+static s32 e1000_setup_link_82571(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_setup_link_82571");
 
-       /* 82573 does not have a word in the NVM to determine
+       /*
+        * 82573 does not have a word in the NVM to determine
         * the default flow control setting, so we explicitly
         * set it to full.
         */
-       if (hw->mac.type == e1000_82573)
-               hw->mac.fc = e1000_fc_full;
+       if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
+           hw->fc.requested_mode == e1000_fc_default)
+               hw->fc.requested_mode = e1000_fc_full;
 
        return e1000_setup_link_generic(hw);
 }
@@ -1136,8 +1236,7 @@
  *  for link, once link is established calls to configure collision distance
  *  and flow control are called.
  **/
-STATIC s32
-e1000_setup_copper_link_82571(struct e1000_hw *hw)
+static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
 {
        u32 ctrl, led_ctrl;
        s32  ret_val;
@@ -1151,6 +1250,7 @@
 
        switch (hw->phy.type) {
        case e1000_phy_m88:
+       case e1000_phy_bm:
                ret_val = e1000_copper_link_setup_m88(hw);
                break;
        case e1000_phy_igp_2:
@@ -1182,18 +1282,18 @@
  *  Configures collision distance and flow control for fiber and serdes links.
  *  Upon successful setup, poll for link.
  **/
-STATIC s32
-e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
+static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_setup_fiber_serdes_link_82571");
 
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
-               /* If SerDes loopback mode is entered, there is no form
+               /*
+                * If SerDes loopback mode is entered, there is no form
                 * of reset to take the adapter out of that mode.  So we
                 * have to explicitly take the adapter out of loopback
-                * mode.  This prevents drivers from twidling their thumbs
+                * mode.  This prevents drivers from twiddling their thumbs
                 * if another tool failed to take it out of loopback mode.
                 */
                E1000_WRITE_REG(hw, E1000_SCTL, 
E1000_SCTL_DISABLE_SERDES_LOOPBACK);
@@ -1213,26 +1313,23 @@
  *  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_82571(struct e1000_hw *hw, u16 *data)
+static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data)
 {
        s32 ret_val;
 
        DEBUGFUNC("e1000_valid_led_default_82571");
 
-       ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
+       ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
                goto out;
        }
 
-       if (hw->mac.type == e1000_82573 &&
+       if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
            *data == ID_LED_RESERVED_F746)
                *data = ID_LED_DEFAULT_82573;
-       else if (*data == ID_LED_RESERVED_0000 ||
-                *data == ID_LED_RESERVED_FFFF)
+       else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
                *data = ID_LED_DEFAULT;
-
 out:
        return ret_val;
 }
@@ -1241,25 +1338,16 @@
  *  e1000_get_laa_state_82571 - Get locally administered address state
  *  @hw: pointer to the HW structure
  *
- *  Retrieve and return the current locally administed address state.
+ *  Retrieve and return the current locally administered address state.
  **/
-boolean_t
-e1000_get_laa_state_82571(struct e1000_hw *hw)
+bool e1000_get_laa_state_82571(struct e1000_hw *hw)
 {
-       struct e1000_dev_spec_82571 *dev_spec;
-       boolean_t state = FALSE;
-
        DEBUGFUNC("e1000_get_laa_state_82571");
 
        if (hw->mac.type != e1000_82571)
-               goto out;
+               return FALSE;
 
-       dev_spec = (struct e1000_dev_spec_82571 *)hw->dev_spec;
-
-       state = dev_spec->laa_is_present;
-
-out:
-       return state;
+       return hw->dev_spec._82571.laa_is_present;
 }
 
 /**
@@ -1267,25 +1355,21 @@
  *  @hw: pointer to the HW structure
  *  @state: enable/disable locally administered address
  *
- *  Enable/Disable the current locally administed address state.
+ *  Enable/Disable the current locally administered address state.
  **/
-void
-e1000_set_laa_state_82571(struct e1000_hw *hw, boolean_t state)
+void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state)
 {
-       struct e1000_dev_spec_82571 *dev_spec;
-
        DEBUGFUNC("e1000_set_laa_state_82571");
 
        if (hw->mac.type != e1000_82571)
-               goto out;
+               return;
 
-       dev_spec = (struct e1000_dev_spec_82571 *)hw->dev_spec;
+       hw->dev_spec._82571.laa_is_present = state;
 
-       dev_spec->laa_is_present = state;
-
        /* If workaround is activated... */
-       if (state == TRUE) {
-               /* Hold a copy of the LAA in RAR[14] This is done so that
+       if (state)
+               /*
+                * Hold a copy of the LAA in RAR[14] This is done so that
                 * between the time RAR[0] gets clobbered and the time it
                 * gets fixed, the actual LAA is in one of the RARs and no
                 * incoming packets directed to this port are dropped.
@@ -1293,9 +1377,6 @@
                 */
                e1000_rar_set_generic(hw, hw->mac.addr,
                                      hw->mac.rar_entry_count - 1);
-       }
-
-out:
        return;
 }
 
@@ -1309,8 +1390,7 @@
  *  the checksum.  Otherwise, if bit 15 is set and the checksum is incorrect,
  *  we need to return bad checksum.
  **/
-static s32
-e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
+static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        s32 ret_val = E1000_SUCCESS;
@@ -1321,31 +1401,33 @@
        if (nvm->type != e1000_nvm_flash_hw)
                goto out;
 
-       /* Check bit 4 of word 10h.  If it is 0, firmware is done updating
+       /*
+        * Check bit 4 of word 10h.  If it is 0, firmware is done updating
         * 10h-12h.  Checksum may need to be fixed.
         */
-       ret_val = e1000_read_nvm(hw, 0x10, 1, &data);
+       ret_val = nvm->ops.read(hw, 0x10, 1, &data);
        if (ret_val)
                goto out;
 
        if (!(data & 0x10)) {
-               /* Read 0x23 and check bit 15.  This bit is a 1
+               /*
+                * Read 0x23 and check bit 15.  This bit is a 1
                 * when the checksum has already been fixed.  If
                 * the checksum is still wrong and this bit is a
                 * 1, we need to return bad checksum.  Otherwise,
                 * we need to set this bit to a 1 and update the
                 * checksum.
                 */
-               ret_val = e1000_read_nvm(hw, 0x23, 1, &data);
+               ret_val = nvm->ops.read(hw, 0x23, 1, &data);
                if (ret_val)
                        goto out;
 
                if (!(data & 0x8000)) {
                        data |= 0x8000;
-                       ret_val = e1000_write_nvm(hw, 0x23, 1, &data);
+                       ret_val = nvm->ops.write(hw, 0x23, 1, &data);
                        if (ret_val)
                                goto out;
-                       ret_val = e1000_update_nvm_checksum(hw);
+                       ret_val = nvm->ops.update(hw);
                }
        }
 
@@ -1354,52 +1436,86 @@
 }
 
 /**
+ *  e1000_read_mac_addr_82571 - Read device MAC address
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_read_mac_addr_82571");
+       if (e1000_check_alt_mac_addr_generic(hw))
+               ret_val = e1000_read_mac_addr_generic(hw);
+
+       return ret_val;
+}
+
+/**
+ * e1000_power_down_phy_copper_82571 - 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_82571(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       struct e1000_mac_info *mac = &hw->mac;
+
+       if (!(phy->ops.check_reset_block))
+               return;
+
+       /* If the management interface is not enabled, then power down */
+       if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw)))
+               e1000_power_down_phy_copper(hw);
+
+       return;
+}
+
+/**
  *  e1000_clear_hw_cntrs_82571 - 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_82571(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw)
 {
-       volatile u32 temp;
-
        DEBUGFUNC("e1000_clear_hw_cntrs_82571");
 
        e1000_clear_hw_cntrs_base_generic(hw);
 
-       temp = E1000_READ_REG(hw, E1000_PRC64);
-       temp = E1000_READ_REG(hw, E1000_PRC127);
-       temp = E1000_READ_REG(hw, E1000_PRC255);
-       temp = E1000_READ_REG(hw, E1000_PRC511);
-       temp = E1000_READ_REG(hw, E1000_PRC1023);
-       temp = E1000_READ_REG(hw, E1000_PRC1522);
-       temp = E1000_READ_REG(hw, E1000_PTC64);
-       temp = E1000_READ_REG(hw, E1000_PTC127);
-       temp = E1000_READ_REG(hw, E1000_PTC255);
-       temp = E1000_READ_REG(hw, E1000_PTC511);
-       temp = E1000_READ_REG(hw, E1000_PTC1023);
-       temp = E1000_READ_REG(hw, E1000_PTC1522);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_ALGNERRC);
-       temp = E1000_READ_REG(hw, E1000_RXERRC);
-       temp = E1000_READ_REG(hw, E1000_TNCRS);
-       temp = E1000_READ_REG(hw, E1000_CEXTERR);
-       temp = E1000_READ_REG(hw, E1000_TSCTC);
-       temp = E1000_READ_REG(hw, E1000_TSCTFC);
+       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);
 
-       temp = E1000_READ_REG(hw, E1000_MGTPRC);
-       temp = E1000_READ_REG(hw, E1000_MGTPDC);
-       temp = E1000_READ_REG(hw, E1000_MGTPTC);
+       E1000_READ_REG(hw, E1000_MGTPRC);
+       E1000_READ_REG(hw, E1000_MGTPDC);
+       E1000_READ_REG(hw, E1000_MGTPTC);
 
-       temp = E1000_READ_REG(hw, E1000_IAC);
-       temp = E1000_READ_REG(hw, E1000_ICRXOC);
+       E1000_READ_REG(hw, E1000_IAC);
+       E1000_READ_REG(hw, E1000_ICRXOC);
 
-       temp = E1000_READ_REG(hw, E1000_ICRXPTC);
-       temp = E1000_READ_REG(hw, E1000_ICRXATC);
-       temp = E1000_READ_REG(hw, E1000_ICTXPTC);
-       temp = E1000_READ_REG(hw, E1000_ICTXATC);
-       temp = E1000_READ_REG(hw, E1000_ICTXQEC);
-       temp = E1000_READ_REG(hw, E1000_ICTXQMTC);
-       temp = E1000_READ_REG(hw, E1000_ICRXDMTC);
+       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);
 }

Other related posts: