Imported Upstream version 16.04
[deb_dpdk.git] / drivers / net / e1000 / base / e1000_82543.c
diff --git a/drivers/net/e1000/base/e1000_82543.c b/drivers/net/e1000/base/e1000_82543.c
new file mode 100644 (file)
index 0000000..fc96199
--- /dev/null
@@ -0,0 +1,1553 @@
+/*******************************************************************************
+
+Copyright (c) 2001-2015, 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.
+
+***************************************************************************/
+
+/*
+ * 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"
+
+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_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);
+
+/**
+ *  e1000_init_phy_params_82543 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 e1000_init_phy_params_82543(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_init_phy_params_82543");
+
+       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;
+       phy->autoneg_mask       = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us     = 10000;
+       phy->type               = e1000_phy_m88;
+
+       /* Function Pointers */
+       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;
+       phy->ops.reset          = (hw->mac.type == e1000_82543)
+                                 ? e1000_phy_hw_reset_82543
+                                 : e1000_phy_hw_reset_generic;
+       phy->ops.write_reg      = (hw->mac.type == e1000_82543)
+                                 ? e1000_write_phy_reg_82543
+                                 : e1000_write_phy_reg_m88;
+       phy->ops.get_info       = e1000_get_phy_info_m88;
+
+       /*
+        * 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 = phy->ops.reset(hw);
+               if (ret_val) {
+                       DEBUGOUT("Resetting PHY during init failed.\n");
+                       goto out;
+               }
+               msec_delay(20);
+       }
+
+       ret_val = e1000_get_phy_id(hw);
+       if (ret_val)
+               goto out;
+
+       /* Verify phy id */
+       switch (hw->mac.type) {
+       case e1000_82543:
+               if (phy->id != M88E1000_E_PHY_ID) {
+                       ret_val = -E1000_ERR_PHY;
+                       goto out;
+               }
+               break;
+       case e1000_82544:
+               if (phy->id != M88E1000_I_PHY_ID) {
+                       ret_val = -E1000_ERR_PHY;
+                       goto out;
+               }
+               break;
+       default:
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+               break;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_nvm_params_82543 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 e1000_init_nvm_params_82543(struct e1000_hw *hw)
+{
+       struct e1000_nvm_info *nvm = &hw->nvm;
+
+       DEBUGFUNC("e1000_init_nvm_params_82543");
+
+       nvm->type               = e1000_nvm_eeprom_microwire;
+       nvm->word_size          = 64;
+       nvm->delay_usec         = 50;
+       nvm->address_bits       =  6;
+       nvm->opcode_bits        =  3;
+
+       /* Function Pointers */
+       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;
+}
+
+/**
+ *  e1000_init_mac_params_82543 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 e1000_init_mac_params_82543(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+
+       DEBUGFUNC("e1000_init_mac_params_82543");
+
+       /* Set media type */
+       switch (hw->device_id) {
+       case E1000_DEV_ID_82543GC_FIBER:
+       case E1000_DEV_ID_82544EI_FIBER:
+               hw->phy.media_type = e1000_media_type_fiber;
+               break;
+       default:
+               hw->phy.media_type = e1000_media_type_copper;
+               break;
+       }
+
+       /* Set mta register count */
+       mac->mta_reg_count = 128;
+       /* Set rar entry count */
+       mac->rar_entry_count = E1000_RAR_ENTRIES;
+
+       /* Function pointers */
+
+       /* bus type/speed/width */
+       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 */
+       mac->ops.reset_hw = e1000_reset_hw_82543;
+       /* hw initialization */
+       mac->ops.init_hw = e1000_init_hw_82543;
+       /* link setup */
+       mac->ops.setup_link = e1000_setup_link_82543;
+       /* physical interface setup */
+       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 */
+       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 */
+       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 */
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
+       /* writing VFTA */
+       mac->ops.write_vfta = e1000_write_vfta_82543;
+       /* clearing VFTA */
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
+       /* turn on/off LED */
+       mac->ops.led_on = e1000_led_on_82543;
+       mac->ops.led_off = e1000_led_off_82543;
+       /* clear hardware counters */
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82543;
+
+       /* Set tbi compatibility */
+       if ((hw->mac.type != e1000_82543) ||
+           (hw->phy.media_type == e1000_media_type_fiber))
+               e1000_set_tbi_compatibility_82543(hw, false);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_function_pointers_82543 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void e1000_init_function_pointers_82543(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_function_pointers_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 current status of 10-bit Interface (TBI) compatibility
+ *  (enabled/disabled).
+ **/
+STATIC bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       bool state = false;
+
+       DEBUGFUNC("e1000_tbi_compatibility_enabled_82543");
+
+       if (hw->mac.type != e1000_82543) {
+               DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
+               goto out;
+       }
+
+       state = !!(dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED);
+
+out:
+       return state;
+}
+
+/**
+ *  e1000_set_tbi_compatibility_82543 - Set TBI compatibility
+ *  @hw: pointer to the HW structure
+ *  @state: enable/disable TBI compatibility
+ *
+ *  Enables or disabled 10-bit Interface (TBI) compatibility.
+ **/
+void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+
+       DEBUGFUNC("e1000_set_tbi_compatibility_82543");
+
+       if (hw->mac.type != e1000_82543) {
+               DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
+               goto out;
+       }
+
+       if (state)
+               dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED;
+       else
+               dev_spec->tbi_compatibility &= ~TBI_COMPAT_ENABLED;
+
+out:
+       return;
+}
+
+/**
+ *  e1000_tbi_sbp_enabled_82543 - Returns TBI SBP status
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns the current status of 10-bit Interface (TBI) store bad packet (SBP)
+ *  (enabled/disabled).
+ **/
+bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       bool state = false;
+
+       DEBUGFUNC("e1000_tbi_sbp_enabled_82543");
+
+       if (hw->mac.type != e1000_82543) {
+               DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
+               goto out;
+       }
+
+       state = !!(dev_spec->tbi_compatibility & TBI_SBP_ENABLED);
+
+out:
+       return state;
+}
+
+/**
+ *  e1000_set_tbi_sbp_82543 - Set TBI SBP
+ *  @hw: pointer to the HW structure
+ *  @state: enable/disable TBI store bad packet
+ *
+ *  Enables or disabled 10-bit Interface (TBI) store bad packet (SBP).
+ **/
+STATIC void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+
+       DEBUGFUNC("e1000_set_tbi_sbp_82543");
+
+       if (state && e1000_tbi_compatibility_enabled_82543(hw))
+               dev_spec->tbi_compatibility |= TBI_SBP_ENABLED;
+       else
+               dev_spec->tbi_compatibility &= ~TBI_SBP_ENABLED;
+
+       return;
+}
+
+/**
+ *  e1000_init_phy_disabled_82543 - Returns init PHY status
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns the current status of whether PHY initialization is disabled.
+ *  True if PHY initialization is disabled else false.
+ **/
+STATIC bool e1000_init_phy_disabled_82543(struct e1000_hw *hw)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       bool ret_val;
+
+       DEBUGFUNC("e1000_init_phy_disabled_82543");
+
+       if (hw->mac.type != e1000_82543) {
+               ret_val = false;
+               goto out;
+       }
+
+       ret_val = dev_spec->init_phy_disabled;
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_tbi_adjust_stats_82543 - Adjust stats when TBI enabled
+ *  @hw: pointer to the HW structure
+ *  @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, u32 max_frame_size)
+{
+       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
+        * counters overcount this packet as a CRC error and undercount
+        * the packet as a good packet
+        */
+       /* This packet should not be counted as a CRC error. */
+       stats->crcerrs--;
+       /* This packet does count as a Good Packet Received. */
+       stats->gprc++;
+
+       /* Adjust the Good Octets received counters */
+       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.
+        */
+       if ((mac_addr[0] == 0xff) && (mac_addr[1] == 0xff))
+               /* Broadcast packet */
+               stats->bprc++;
+       else if (*mac_addr & 0x01)
+               /* Multicast packet */
+               stats->mprc++;
+
+       /*
+        * In this case, the hardware has over counted the number of
+        * oversize frames.
+        */
+       if ((frame_len == max_frame_size) && (stats->roc > 0))
+               stats->roc--;
+
+       /*
+        * 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) {
+               stats->prc64++;
+               stats->prc127--;
+       } else if (frame_len == 127) {
+               stats->prc127++;
+               stats->prc255--;
+       } else if (frame_len == 255) {
+               stats->prc255++;
+               stats->prc511--;
+       } else if (frame_len == 511) {
+               stats->prc511++;
+               stats->prc1023--;
+       } else if (frame_len == 1023) {
+               stats->prc1023++;
+               stats->prc1522--;
+       } else if (frame_len == 1522) {
+               stats->prc1522++;
+       }
+
+out:
+       return;
+}
+
+/**
+ *  e1000_read_phy_reg_82543 - Read PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  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)
+{
+       u32 mdic;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_read_phy_reg_82543");
+
+       if (offset > MAX_PHY_REG_ADDRESS) {
+               DEBUGOUT1("PHY Address %d is out of range\n", offset);
+               ret_val = -E1000_ERR_PARAM;
+               goto out;
+       }
+
+       /*
+        * 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
+        * 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
+        * is defined as follows:
+        *         <Preamble><SOF><Op Code><Phy Addr><Offset>
+        * followed by a shift in of 18 bits.  This first two bits shifted in
+        * are TurnAround bits used to avoid contention on the MDIO pin when a
+        * READ operation is performed.  These two bits are thrown away
+        * followed by a shift in of 16 bits which contains the desired data.
+        */
+       mdic = (offset | (hw->phy.addr << 5) |
+               (PHY_OP_READ << 10) | (PHY_SOF << 12));
+
+       e1000_shift_out_mdi_bits_82543(hw, mdic, 14);
+
+       /*
+        * 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.
+        */
+       *data = e1000_shift_in_mdi_bits_82543(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_write_phy_reg_82543 - Write PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be written
+ *  @data: pointer to the data to be written at offset
+ *
+ *  Writes data to the PHY at offset.
+ **/
+STATIC s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       u32 mdic;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_write_phy_reg_82543");
+
+       if (offset > MAX_PHY_REG_ADDRESS) {
+               DEBUGOUT1("PHY Address %d is out of range\n", offset);
+               ret_val = -E1000_ERR_PARAM;
+               goto out;
+       }
+
+       /*
+        * 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
+        * 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:
+        * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
+        */
+       mdic = ((PHY_TURNAROUND) | (offset << 2) | (hw->phy.addr << 7) |
+               (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+       mdic <<= 16;
+       mdic |= (u32)data;
+
+       e1000_shift_out_mdi_bits_82543(hw, mdic, 32);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_raise_mdi_clk_82543 - Raise Management Data Input clock
+ *  @hw: pointer to the HW structure
+ *  @ctrl: pointer to the control register
+ *
+ *  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)
+{
+       /*
+        * 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));
+       E1000_WRITE_FLUSH(hw);
+       usec_delay(10);
+}
+
+/**
+ *  e1000_lower_mdi_clk_82543 - Lower Management Data Input clock
+ *  @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.
+ **/
+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
+        * MDC bit), and then delay a sufficient amount of time.
+        */
+       E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl & ~E1000_CTRL_MDC));
+       E1000_WRITE_FLUSH(hw);
+       usec_delay(10);
+}
+
+/**
+ *  e1000_shift_out_mdi_bits_82543 - Shift data bits our to the PHY
+ *  @hw: pointer to the HW structure
+ *  @data: data to send to the PHY
+ *  @count: number of bits to shift out
+ *
+ *  We need to shift 'count' 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.
+ **/
+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
+        * 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.
+        */
+       mask = 0x01;
+       mask <<= (count - 1);
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
+       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
+                * "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.
+                */
+               if (data & mask)
+                       ctrl |= E1000_CTRL_MDIO;
+               else
+                       ctrl &= ~E1000_CTRL_MDIO;
+
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+               E1000_WRITE_FLUSH(hw);
+
+               usec_delay(10);
+
+               e1000_raise_mdi_clk_82543(hw, &ctrl);
+               e1000_lower_mdi_clk_82543(hw, &ctrl);
+
+               mask >>= 1;
+       }
+}
+
+/**
+ *  e1000_shift_in_mdi_bits_82543 - Shift data bits in from the PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  In order to read a register from the PHY, we need to shift 18 bits
+ *  in from the PHY.  Bits are "shifted in" by raising the clock input to
+ *  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)
+{
+       u32 ctrl;
+       u16 data = 0;
+       u8 i;
+
+       /*
+        * 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
+        * thrown away.  Bits are "shifted in" by raising the input to the
+        * Management Data Clock (setting the MDC bit) and then reading the
+        * value of the MDIO bit.
+        */
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /*
+        * Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
+        * input.
+        */
+       ctrl &= ~E1000_CTRL_MDIO_DIR;
+       ctrl &= ~E1000_CTRL_MDIO;
+
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       E1000_WRITE_FLUSH(hw);
+
+       /*
+        * 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.
+        */
+       e1000_raise_mdi_clk_82543(hw, &ctrl);
+       e1000_lower_mdi_clk_82543(hw, &ctrl);
+
+       for (data = 0, i = 0; i < 16; i++) {
+               data <<= 1;
+               e1000_raise_mdi_clk_82543(hw, &ctrl);
+               ctrl = E1000_READ_REG(hw, E1000_CTRL);
+               /* Check to see if we shifted in a "1". */
+               if (ctrl & E1000_CTRL_MDIO)
+                       data |= 1;
+               e1000_lower_mdi_clk_82543(hw, &ctrl);
+       }
+
+       e1000_raise_mdi_clk_82543(hw, &ctrl);
+       e1000_lower_mdi_clk_82543(hw, &ctrl);
+
+       return data;
+}
+
+/**
+ *  e1000_phy_force_speed_duplex_82543 - Force speed/duplex for PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the function to force speed and duplex for the m88 PHY, and
+ *  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)
+{
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_phy_force_speed_duplex_82543");
+
+       ret_val = e1000_phy_force_speed_duplex_m88(hw);
+       if (ret_val)
+               goto out;
+
+       if (!hw->mac.autoneg && (hw->mac.forced_speed_duplex &
+           E1000_ALL_10_SPEED))
+               ret_val = e1000_polarity_reversal_workaround_82543(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_polarity_reversal_workaround_82543 - Workaround polarity reversal
+ *  @hw: pointer to the HW structure
+ *
+ *  When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity
+ *  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)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 mii_status_reg;
+       u16 i;
+       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 = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+       if (ret_val)
+               goto out;
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
+       if (ret_val)
+               goto out;
+
+       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.
+        * 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
+                * to be clear.
+                */
+
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
+               if (ret_val)
+                       goto out;
+
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
+               if (ret_val)
+                       goto out;
+
+               if (!(mii_status_reg & ~MII_SR_LINK_STATUS))
+                       break;
+               msec_delay_irq(100);
+       }
+
+       /* Recommended delay time after link has been lost */
+       msec_delay_irq(1000);
+
+       /* Now we will re-enable the transmitter on the PHY */
+
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+       if (ret_val)
+               goto out;
+       msec_delay_irq(50);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
+       if (ret_val)
+               goto out;
+       msec_delay_irq(50);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
+       if (ret_val)
+               goto out;
+       msec_delay_irq(50);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
+       if (ret_val)
+               goto out;
+
+       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
+        * to be set.
+        */
+       ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_TIME, 100000, &link);
+       if (ret_val)
+               goto out;
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_phy_hw_reset_82543 - PHY hardware reset
+ *  @hw: pointer to the HW structure
+ *
+ *  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.
+ **/
+STATIC s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw)
+{
+       u32 ctrl_ext;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_phy_hw_reset_82543");
+
+       /*
+        * 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);
+       ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
+       ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       E1000_WRITE_FLUSH(hw);
+
+       msec_delay(10);
+
+       /* ...then take it out of reset. */
+       ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       E1000_WRITE_FLUSH(hw);
+
+       usec_delay(150);
+
+       if (!(hw->phy.ops.get_cfg_done))
+               return E1000_SUCCESS;
+
+       ret_val = hw->phy.ops.get_cfg_done(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_reset_hw_82543 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+STATIC s32 e1000_reset_hw_82543(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_reset_hw_82543");
+
+       DEBUGOUT("Masking off all interrupts\n");
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+
+       E1000_WRITE_REG(hw, E1000_RCTL, 0);
+       E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+       E1000_WRITE_FLUSH(hw);
+
+       e1000_set_tbi_sbp_82543(hw, false);
+
+       /*
+        * Delay to allow any outstanding PCI transactions to complete before
+        * resetting the device
+        */
+       msec_delay(10);
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       DEBUGOUT("Issuing a global reset to 82543/82544 MAC\n");
+       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
+                * 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
+        * settings to device.
+        */
+       hw->nvm.ops.reload(hw);
+       msec_delay(2);
+
+       /* Masking off and clearing any pending interrupts */
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+       E1000_READ_REG(hw, E1000_ICR);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_init_hw_82543 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+STATIC s32 e1000_init_hw_82543(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       u32 ctrl;
+       s32 ret_val;
+       u16 i;
+
+       DEBUGFUNC("e1000_init_hw_82543");
+
+       /* Disabling VLAN filtering */
+       E1000_WRITE_REG(hw, E1000_VET, 0);
+       mac->ops.clear_vfta(hw);
+
+       /* Setup the receive address. */
+       e1000_init_rx_addrs_generic(hw, mac->rar_entry_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);
+               E1000_WRITE_FLUSH(hw);
+       }
+
+       /*
+        * 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.
+        */
+       if (hw->mac.type == e1000_82543 && dev_spec->dma_fairness) {
+               ctrl = E1000_READ_REG(hw, E1000_CTRL);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR);
+       }
+
+       e1000_pcix_mmrbc_workaround_generic(hw);
+
+       /* Setup link and flow control */
+       ret_val = mac->ops.setup_link(hw);
+
+       /*
+        * Clear all of the statistics registers (clear on read).  It is
+        * important that we do this after we have tried to establish link
+        * because the symbol error count will increment wildly if there
+        * is no link.
+        */
+       e1000_clear_hw_cntrs_82543(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_link_82543 - Setup flow control and link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Read the EEPROM to determine the initial polarity value and write the
+ *  extended device control register with the information before calling
+ *  the generic setup link function, which does the following:
+ *  Determines which flow control settings to use, then configures flow
+ *  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.
+ **/
+STATIC s32 e1000_setup_link_82543(struct e1000_hw *hw)
+{
+       u32 ctrl_ext;
+       s32  ret_val;
+       u16 data;
+
+       DEBUGFUNC("e1000_setup_link_82543");
+
+       /*
+        * 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 = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+               if (ret_val) {
+                       DEBUGOUT("NVM Read Error\n");
+                       ret_val = -E1000_ERR_NVM;
+                       goto out;
+               }
+               ctrl_ext = ((data & NVM_WORD0F_SWPDIO_EXT_MASK) <<
+                           NVM_SWDPIO_EXT_SHIFT);
+               E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       }
+
+       ret_val = e1000_setup_link_generic(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_copper_link_82543 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the link for auto-neg or forced speed and duplex.  Then we check
+ *  for link, once link is established calls to configure collision distance
+ *  and flow control are called.
+ **/
+STATIC s32 e1000_setup_copper_link_82543(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32 ret_val;
+       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
+        * 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.
+        */
+       if (hw->mac.type == e1000_82543) {
+               ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+               ret_val = hw->phy.ops.reset(hw);
+               if (ret_val)
+                       goto out;
+       } else {
+               ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       }
+
+       /* Set MDI/MDI-X, Polarity Reversal, and downshift settings */
+       ret_val = e1000_copper_link_setup_m88(hw);
+       if (ret_val)
+               goto out;
+
+       if (hw->mac.autoneg) {
+               /*
+                * 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.
+                */
+               DEBUGOUT("Forcing Speed and Duplex\n");
+               ret_val = e1000_phy_force_speed_duplex_82543(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
+        * valid.
+        */
+       ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
+                                            &link);
+       if (ret_val)
+               goto out;
+
+
+       if (link) {
+               DEBUGOUT("Valid link established!!!\n");
+               /* Config the MAC and PHY after link is up */
+               if (hw->mac.type == e1000_82544) {
+                       hw->mac.ops.config_collision_dist(hw);
+               } else {
+                       ret_val = e1000_config_mac_to_phy_82543(hw);
+                       if (ret_val)
+                               goto out;
+               }
+               ret_val = e1000_config_fc_after_link_up_generic(hw);
+       } else {
+               DEBUGOUT("Unable to establish link!!!\n");
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_fiber_link_82543 - Setup link for fiber
+ *  @hw: pointer to the HW structure
+ *
+ *  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)
+{
+       u32 ctrl;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_setup_fiber_link_82543");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /* Take the link out of reset */
+       ctrl &= ~E1000_CTRL_LRST;
+
+       hw->mac.ops.config_collision_dist(hw);
+
+       ret_val = e1000_commit_fc_settings_generic(hw);
+       if (ret_val)
+               goto out;
+
+       DEBUGOUT("Auto-negotiation enabled\n");
+
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       E1000_WRITE_FLUSH(hw);
+       msec_delay(1);
+
+       /*
+        * For these adapters, the SW definable pin 1 is cleared when the
+        * optics detect a signal.  If we have a signal, then poll for a
+        * "Link-Up" indication.
+        */
+       if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1))
+               ret_val = e1000_poll_fiber_serdes_link_generic(hw);
+       else
+               DEBUGOUT("No signal detected\n");
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_copper_link_82543 - Check for link (Copper)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks the phy for link, if link exists, do the following:
+ *   - check for downshift
+ *   - do polarity workaround (if necessary)
+ *   - configure collision distance
+ *   - configure flow control after link up
+ *   - configure tbi compatibility
+ **/
+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;
+       bool link;
+
+       DEBUGFUNC("e1000_check_for_copper_link_82543");
+
+       if (!mac->get_link_status) {
+               ret_val = E1000_SUCCESS;
+               goto out;
+       }
+
+       ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
+       if (ret_val)
+               goto out;
+
+       if (!link)
+               goto out; /* No link detected */
+
+       mac->get_link_status = false;
+
+       e1000_check_downshift_generic(hw);
+
+       /*
+        * 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
+                * 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
+                * status change interrupt which will happened due to the
+                * execution of this workaround.
+                */
+               if (mac->forced_speed_duplex & E1000_ALL_10_SPEED) {
+                       E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
+                       ret_val = e1000_polarity_reversal_workaround_82543(hw);
+                       icr = E1000_READ_REG(hw, E1000_ICR);
+                       E1000_WRITE_REG(hw, E1000_ICS, (icr & ~E1000_ICS_LSC));
+                       E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK);
+               }
+
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+       }
+
+       /*
+        * 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
+        * Distance in the MAC.  Otherwise, we need to force
+        * speed/duplex on the MAC to the current PHY speed/duplex
+        * settings.
+        */
+       if (mac->type == e1000_82544)
+               hw->mac.ops.config_collision_dist(hw);
+       else {
+               ret_val = e1000_config_mac_to_phy_82543(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error configuring MAC to PHY settings\n");
+                       goto out;
+               }
+       }
+
+       /*
+        * Configure Flow Control now that Auto-Neg has completed.
+        * First, we need to restore the desired flow control
+        * settings because we may have had to re-autoneg with a
+        * different link partner.
+        */
+       ret_val = e1000_config_fc_after_link_up_generic(hw);
+       if (ret_val)
+               DEBUGOUT("Error configuring flow control\n");
+
+       /*
+        * 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
+        * at gigabit speed, then TBI compatibility is not needed.  If we are
+        * at gigabit speed, we turn on TBI compatibility.
+        */
+       if (e1000_tbi_compatibility_enabled_82543(hw)) {
+               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,
+                        * we do not need to enable TBI compatibility.
+                        */
+                       if (e1000_tbi_sbp_enabled_82543(hw)) {
+                               /*
+                                * If we previously were in the mode,
+                                * turn it off.
+                                */
+                               e1000_set_tbi_sbp_82543(hw, false);
+                               rctl = E1000_READ_REG(hw, E1000_RCTL);
+                               rctl &= ~E1000_RCTL_SBP;
+                               E1000_WRITE_REG(hw, E1000_RCTL, rctl);
+                       }
+               } else {
+                       /*
+                        * 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
+                        * will look like CRC errors to to the hardware.
+                        */
+                       if (!e1000_tbi_sbp_enabled_82543(hw)) {
+                               e1000_set_tbi_sbp_82543(hw, true);
+                               rctl = E1000_READ_REG(hw, E1000_RCTL);
+                               rctl |= E1000_RCTL_SBP;
+                               E1000_WRITE_REG(hw, E1000_RCTL, rctl);
+                       }
+               }
+       }
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_fiber_link_82543 - Check for link (Fiber)
+ *  @hw: pointer to the HW structure
+ *
+ *  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)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       u32 rxcw, ctrl, status;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_check_for_fiber_link_82543");
+
+       ctrl = 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
+        * 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
+        * need to give auto-negotiation time to complete, in case the cable
+        * was just plugged in. The autoneg_failed flag does this.
+        */
+       /* (ctrl & E1000_CTRL_SWDPIN1) == 0 == have signal */
+       if ((!(ctrl & E1000_CTRL_SWDPIN1)) &&
+           (!(status & E1000_STATUS_LU)) &&
+           (!(rxcw & E1000_RXCW_C))) {
+               if (!mac->autoneg_failed) {
+                       mac->autoneg_failed = true;
+                       ret_val = 0;
+                       goto out;
+               }
+               DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+
+               /* Disable auto-negotiation in the TXCW register */
+               E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
+
+               /* Force link-up and also force full-duplex. */
+               ctrl = E1000_READ_REG(hw, E1000_CTRL);
+               ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+               /* Configure Flow Control after forcing link up. */
+               ret_val = e1000_config_fc_after_link_up_generic(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error configuring flow control\n");
+                       goto out;
+               }
+       } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
+               /*
+                * 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.
+                */
+               DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+               E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
+               E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
+
+               mac->serdes_has_link = true;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_config_mac_to_phy_82543 - Configure MAC to PHY settings
+ *  @hw: pointer to the HW structure
+ *
+ *  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)
+{
+       u32 ctrl;
+       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
+        * registers depending on negotiated values.
+        */
+       ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+       if (ret_val)
+               goto out;
+
+       ctrl &= ~E1000_CTRL_FD;
+       if (phy_data & M88E1000_PSSR_DPLX)
+               ctrl |= E1000_CTRL_FD;
+
+       hw->mac.ops.config_collision_dist(hw);
+
+       /*
+        * Set up speed in the Device Control register depending on
+        * negotiated values.
+        */
+       if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+               ctrl |= E1000_CTRL_SPD_1000;
+       else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
+               ctrl |= E1000_CTRL_SPD_100;
+
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_write_vfta_82543 - Write value to VLAN filter table
+ *  @hw: pointer to the HW structure
+ *  @offset: the 32-bit offset in which to write the value to.
+ *  @value: the 32-bit value to write at location offset.
+ *
+ *  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)
+{
+       u32 temp;
+
+       DEBUGFUNC("e1000_write_vfta_82543");
+
+       if ((hw->mac.type == e1000_82544) && (offset & 1)) {
+               temp = E1000_READ_REG_ARRAY(hw, E1000_VFTA, offset - 1);
+               E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
+               E1000_WRITE_FLUSH(hw);
+               E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp);
+               E1000_WRITE_FLUSH(hw);
+       } else {
+               e1000_write_vfta_generic(hw, offset, value);
+       }
+}
+
+/**
+ *  e1000_led_on_82543 - Turn on SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED on.
+ **/
+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->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 {
+               /* Fiber 82544 and all 82543 use this method */
+               ctrl |= E1000_CTRL_SWDPIN0;
+               ctrl |= E1000_CTRL_SWDPIO0;
+       }
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_led_off_82543 - Turn off SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED off.
+ **/
+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->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 {
+               ctrl &= ~E1000_CTRL_SWDPIN0;
+               ctrl |= E1000_CTRL_SWDPIO0;
+       }
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_clear_hw_cntrs_82543 - 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_82543(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_clear_hw_cntrs_82543");
+
+       e1000_clear_hw_cntrs_base_generic(hw);
+
+       E1000_READ_REG(hw, E1000_PRC64);
+       E1000_READ_REG(hw, E1000_PRC127);
+       E1000_READ_REG(hw, E1000_PRC255);
+       E1000_READ_REG(hw, E1000_PRC511);
+       E1000_READ_REG(hw, E1000_PRC1023);
+       E1000_READ_REG(hw, E1000_PRC1522);
+       E1000_READ_REG(hw, E1000_PTC64);
+       E1000_READ_REG(hw, E1000_PTC127);
+       E1000_READ_REG(hw, E1000_PTC255);
+       E1000_READ_REG(hw, E1000_PTC511);
+       E1000_READ_REG(hw, E1000_PTC1023);
+       E1000_READ_REG(hw, E1000_PTC1522);
+
+       E1000_READ_REG(hw, E1000_ALGNERRC);
+       E1000_READ_REG(hw, E1000_RXERRC);
+       E1000_READ_REG(hw, E1000_TNCRS);
+       E1000_READ_REG(hw, E1000_CEXTERR);
+       E1000_READ_REG(hw, E1000_TSCTC);
+       E1000_READ_REG(hw, E1000_TSCTFC);
+}