2007-05-04 00:00:12 +00:00
|
|
|
/*******************************************************************************
|
|
|
|
|
2008-02-29 21:50:11 +00:00
|
|
|
Copyright (c) 2001-2008, Intel Corporation
|
2007-05-04 00:00:12 +00:00
|
|
|
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.
|
|
|
|
|
|
|
|
*******************************************************************************/
|
2007-11-20 21:41:22 +00:00
|
|
|
/* $FreeBSD$ */
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* e1000_82543
|
|
|
|
* e1000_82544
|
|
|
|
*/
|
|
|
|
|
2007-05-16 00:14:23 +00:00
|
|
|
#include "e1000_api.h"
|
2007-05-04 00:00:12 +00:00
|
|
|
#include "e1000_82543.h"
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
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);
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
struct e1000_dev_spec_82543 {
|
|
|
|
u32 tbi_compatibility;
|
2007-11-20 21:41:22 +00:00
|
|
|
bool dma_fairness;
|
|
|
|
bool init_phy_disabled;
|
2007-05-04 00:00:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_init_phy_params_82543 - Init PHY func ptrs.
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* This is a function pointer entry point called by the api module.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_init_phy_params_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_phy_info *phy = &hw->phy;
|
|
|
|
struct e1000_functions *func = &hw->func;
|
|
|
|
s32 ret_val = E1000_SUCCESS;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_init_phy_params_82543");
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
if (hw->phy.media_type != e1000_media_type_copper) {
|
2007-05-04 00:00:12 +00:00
|
|
|
phy->type = e1000_phy_none;
|
|
|
|
goto out;
|
2007-11-20 21:41:22 +00:00
|
|
|
} else {
|
|
|
|
func->power_up_phy = e1000_power_up_phy_copper;
|
|
|
|
func->power_down_phy = e1000_power_down_phy_copper;
|
2007-05-04 00:00:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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_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)
|
|
|
|
? e1000_read_phy_reg_82543
|
|
|
|
: e1000_read_phy_reg_m88;
|
|
|
|
func->reset_phy = (hw->mac.type == e1000_82543)
|
|
|
|
? e1000_phy_hw_reset_82543
|
|
|
|
: e1000_phy_hw_reset_generic;
|
|
|
|
func->write_phy_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;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* The external PHY of the 82543 can be in a funky state.
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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);
|
|
|
|
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.
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* This is a function pointer entry point called by the api module.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_init_nvm_params_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_nvm_info *nvm = &hw->nvm;
|
|
|
|
struct e1000_functions *func = &hw->func;
|
|
|
|
|
|
|
|
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 */
|
|
|
|
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;
|
|
|
|
|
|
|
|
return E1000_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_init_mac_params_82543 - Init MAC func ptrs.
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* This is a function pointer entry point called by the api module.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_init_mac_params_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_mac_info *mac = &hw->mac;
|
|
|
|
struct e1000_functions *func = &hw->func;
|
|
|
|
s32 ret_val;
|
|
|
|
|
|
|
|
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:
|
2007-11-20 21:41:22 +00:00
|
|
|
hw->phy.media_type = e1000_media_type_fiber;
|
2007-05-04 00:00:12 +00:00
|
|
|
break;
|
|
|
|
default:
|
2007-11-20 21:41:22 +00:00
|
|
|
hw->phy.media_type = e1000_media_type_copper;
|
2007-05-04 00:00:12 +00:00
|
|
|
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 */
|
|
|
|
func->get_bus_info = e1000_get_bus_info_pci_generic;
|
|
|
|
/* reset */
|
|
|
|
func->reset_hw = e1000_reset_hw_82543;
|
|
|
|
/* hw initialization */
|
|
|
|
func->init_hw = e1000_init_hw_82543;
|
|
|
|
/* link setup */
|
|
|
|
func->setup_link = e1000_setup_link_82543;
|
|
|
|
/* physical interface setup */
|
|
|
|
func->setup_physical_interface =
|
2007-11-20 21:41:22 +00:00
|
|
|
(hw->phy.media_type == e1000_media_type_copper)
|
2007-05-04 00:00:12 +00:00
|
|
|
? e1000_setup_copper_link_82543
|
|
|
|
: e1000_setup_fiber_link_82543;
|
|
|
|
/* check for link */
|
|
|
|
func->check_for_link =
|
2007-11-20 21:41:22 +00:00
|
|
|
(hw->phy.media_type == e1000_media_type_copper)
|
2007-05-04 00:00:12 +00:00
|
|
|
? e1000_check_for_copper_link_82543
|
|
|
|
: e1000_check_for_fiber_link_82543;
|
|
|
|
/* link info */
|
|
|
|
func->get_link_up_info =
|
2007-11-20 21:41:22 +00:00
|
|
|
(hw->phy.media_type == e1000_media_type_copper)
|
2007-05-04 00:00:12 +00:00
|
|
|
? e1000_get_speed_and_duplex_copper_generic
|
|
|
|
: e1000_get_speed_and_duplex_fiber_serdes_generic;
|
|
|
|
/* multicast address update */
|
2007-11-20 21:41:22 +00:00
|
|
|
func->update_mc_addr_list = e1000_update_mc_addr_list_generic;
|
2007-05-04 00:00:12 +00:00
|
|
|
/* writing VFTA */
|
|
|
|
func->write_vfta = e1000_write_vfta_82543;
|
|
|
|
/* clearing VFTA */
|
|
|
|
func->clear_vfta = e1000_clear_vfta_generic;
|
|
|
|
/* setting MTA */
|
|
|
|
func->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;
|
|
|
|
/* clear hardware counters */
|
|
|
|
func->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) ||
|
2007-11-20 21:41:22 +00:00
|
|
|
(hw->phy.media_type == e1000_media_type_fiber))
|
2007-05-04 00:00:12 +00:00
|
|
|
e1000_set_tbi_compatibility_82543(hw, FALSE);
|
|
|
|
|
|
|
|
out:
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_init_function_pointers_82543 - Init func ptrs.
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* The only function explicitly called by the api module to initialize
|
|
|
|
* all function pointers and parameters.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
void e1000_init_function_pointers_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_tbi_compatibility_enabled_82543 - Returns TBI compat status
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
2008-02-29 21:50:11 +00:00
|
|
|
* Returns the current status of 10-bit Interface (TBI) compatibility
|
2007-05-04 00:00:12 +00:00
|
|
|
* (enabled/disabled).
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_dev_spec_82543 *dev_spec;
|
2007-11-20 21:41:22 +00:00
|
|
|
bool state = FALSE;
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
DEBUGFUNC("e1000_tbi_compatibility_enabled_82543");
|
|
|
|
|
|
|
|
if (hw->mac.type != e1000_82543) {
|
|
|
|
DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
if (!dev_spec) {
|
2007-05-04 00:00:12 +00:00
|
|
|
DEBUGOUT("dev_spec pointer is set to NULL.\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = (dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED)
|
|
|
|
? TRUE : FALSE;
|
|
|
|
|
|
|
|
out:
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_set_tbi_compatibility_82543 - Set TBI compatibility
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @state: enable/disable TBI compatibility
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Enables or disabled 10-bit Interface (TBI) compatibility.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_dev_spec_82543 *dev_spec;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_set_tbi_compatibility_82543");
|
|
|
|
|
|
|
|
if (hw->mac.type != e1000_82543) {
|
|
|
|
DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
if (!dev_spec) {
|
2007-05-04 00:00:12 +00:00
|
|
|
DEBUGOUT("dev_spec pointer is set to NULL.\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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
2008-02-29 21:50:11 +00:00
|
|
|
* Returns the current status of 10-bit Interface (TBI) store bad packet (SBP)
|
2007-05-04 00:00:12 +00:00
|
|
|
* (enabled/disabled).
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_dev_spec_82543 *dev_spec;
|
2007-11-20 21:41:22 +00:00
|
|
|
bool state = FALSE;
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
DEBUGFUNC("e1000_tbi_sbp_enabled_82543");
|
|
|
|
|
|
|
|
if (hw->mac.type != e1000_82543) {
|
|
|
|
DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
if (!dev_spec) {
|
2007-05-04 00:00:12 +00:00
|
|
|
DEBUGOUT("dev_spec pointer is set to NULL.\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = (dev_spec->tbi_compatibility & TBI_SBP_ENABLED)
|
|
|
|
? TRUE : FALSE;
|
|
|
|
|
|
|
|
out:
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_set_tbi_sbp_82543 - Set TBI SBP
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @state: enable/disable TBI store bad packet
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Enables or disabled 10-bit Interface (TBI) store bad packet (SBP).
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_dev_spec_82543 *dev_spec;
|
|
|
|
|
|
|
|
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
|
|
|
|
dev_spec->tbi_compatibility &= ~TBI_SBP_ENABLED;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_init_phy_disabled_82543 - Returns init PHY status
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Returns the current status of whether PHY initialization is disabled.
|
|
|
|
* True if PHY initialization is disabled else false.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_dev_spec_82543 *dev_spec;
|
2007-11-20 21:41:22 +00:00
|
|
|
bool ret_val;
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
DEBUGFUNC("e1000_init_phy_disabled_82543");
|
|
|
|
|
|
|
|
if (hw->mac.type != e1000_82543) {
|
|
|
|
ret_val = FALSE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
if (!dev_spec) {
|
2007-05-04 00:00:12 +00:00
|
|
|
DEBUGOUT("dev_spec pointer is set to NULL.\n");
|
|
|
|
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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @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
|
2007-11-20 21:41:22 +00:00
|
|
|
* @max_frame_size: The maximum frame size
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
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)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
2007-11-20 21:41:22 +00:00
|
|
|
if (!(e1000_tbi_sbp_enabled_82543(hw)))
|
2007-05-04 00:00:12 +00:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* First adjust the frame length. */
|
|
|
|
frame_len--;
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* We need to adjust the statistics counters, since the hardware
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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 */
|
2007-11-20 21:41:22 +00:00
|
|
|
stats->gorc += frame_len;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Is this a broadcast or multicast? Check broadcast first,
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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++;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* In this case, the hardware has overcounted the number of
|
2007-05-04 00:00:12 +00:00
|
|
|
* oversize frames.
|
|
|
|
*/
|
2007-11-20 21:41:22 +00:00
|
|
|
if ((frame_len == max_frame_size) && (stats->roc > 0))
|
2007-05-04 00:00:12 +00:00
|
|
|
stats->roc--;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Adjust the bin counters when the extra byte put the frame in the
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @offset: register offset to be read
|
|
|
|
* @data: pointer to the read data
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Reads the PHY at offset and stores the information read to data.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* We must first send a preamble through the MDIO pin to signal the
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Now combine the next few fields that are required for a read
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Now that we've shifted out the read command to the MII, we need to
|
2007-05-04 00:00:12 +00:00
|
|
|
* "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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @offset: register offset to be written
|
|
|
|
* @data: pointer to the data to be written at offset
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Writes data to the PHY at offset.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* We'll need to use the SW defined pins to shift the write command
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Now combine the remaining required fields that will indicate a
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @ctrl: pointer to the control register
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Raise the management data input clock by setting the MDC bit in the control
|
|
|
|
* register.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Raise the clock input to the Management Data Clock (by setting the
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @ctrl: pointer to the control register
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
2008-02-29 21:50:11 +00:00
|
|
|
* Lower the management data input clock by clearing the MDC bit in the
|
|
|
|
* control register.
|
2007-05-04 00:00:12 +00:00
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Lower the clock input to the Management Data Clock (by clearing the
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @data: data to send to the PHY
|
|
|
|
* @count: number of bits to shift out
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
|
|
|
|
u16 count)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 ctrl, mask;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* We need to shift "count" number of bits out to the PHY. So, the
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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) {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* A "1" is shifted out to the PHY by setting the MDIO bit to
|
2007-05-04 00:00:12 +00:00
|
|
|
* "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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
static u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 ctrl;
|
|
|
|
u16 data = 0;
|
|
|
|
u8 i;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* In order to read a register from the PHY, we need to shift in a
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
|
2007-05-04 00:00:12 +00:00
|
|
|
* input.
|
|
|
|
*/
|
|
|
|
ctrl &= ~E1000_CTRL_MDIO_DIR;
|
|
|
|
ctrl &= ~E1000_CTRL_MDIO;
|
|
|
|
|
|
|
|
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
|
|
|
|
E1000_WRITE_FLUSH(hw);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Raise and lower the clock before reading in the data. This accounts
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity
|
2008-02-29 21:50:11 +00:00
|
|
|
* inadvertently. To workaround the issue, we disable the transmitter on
|
2007-05-04 00:00:12 +00:00
|
|
|
* the PHY until we have established the link partner's link parameters.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
s32 ret_val;
|
|
|
|
u16 mii_status_reg;
|
|
|
|
u16 i;
|
2007-11-20 21:41:22 +00:00
|
|
|
bool link;
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* This loop will early-out if the NO link condition has been met.
|
2007-05-04 00:00:12 +00:00
|
|
|
* In other words, DO NOT use e1000_phy_has_link_generic() here.
|
|
|
|
*/
|
|
|
|
for (i = PHY_FORCE_TIME; i > 0; i--) {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Read the MII Status Register and wait for Link Status bit
|
2007-05-04 00:00:12 +00:00
|
|
|
* to be clear.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0)
|
|
|
|
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 = e1000_write_phy_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);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
msec_delay_irq(50);
|
|
|
|
ret_val = e1000_write_phy_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);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Read the MII Status Register and wait for Link Status bit
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_functions *func = &hw->func;
|
|
|
|
u32 ctrl_ext;
|
|
|
|
s32 ret_val;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_phy_hw_reset_82543");
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Read the Extended Device Control Register, assert the PHY_RESET_DIR
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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);
|
|
|
|
|
|
|
|
ret_val = func->get_cfg_done(hw);
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_reset_hw_82543 - Reset hardware
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* This resets the hardware into a known state. This is a
|
|
|
|
* function pointer entry point called by the api module.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_reset_hw_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 ctrl, icr;
|
|
|
|
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);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Delay to allow any outstanding PCI transactions to complete before
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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 {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* The 82544 can't ACK the 64-bit write when issuing the
|
2007-05-04 00:00:12 +00:00
|
|
|
* reset, so use IO-mapping as a workaround.
|
|
|
|
*/
|
|
|
|
E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
|
|
|
|
}
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* After MAC reset, force reload of NVM to restore power-on
|
2007-05-04 00:00:12 +00:00
|
|
|
* settings to device.
|
|
|
|
*/
|
|
|
|
e1000_reload_nvm(hw);
|
|
|
|
msec_delay(2);
|
|
|
|
|
|
|
|
/* Masking off and clearing any pending interrupts */
|
|
|
|
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
|
|
|
|
icr = E1000_READ_REG(hw, E1000_ICR);
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_init_hw_82543 - Initialize hardware
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* This inits the hardware readying it for operation.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_init_hw_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_mac_info *mac = &hw->mac;
|
|
|
|
struct e1000_dev_spec_82543 *dev_spec;
|
|
|
|
u32 ctrl;
|
|
|
|
s32 ret_val;
|
|
|
|
u16 i;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_init_hw_82543");
|
|
|
|
|
|
|
|
dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
if (!dev_spec) {
|
2007-05-04 00:00:12 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Set the PCI priority bit correctly in the CTRL register. This
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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 = e1000_setup_link(hw);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Clear all of the statistics registers (clear on read). It is
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_setup_link_82543 - Setup flow control and link settings
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_setup_link_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 ctrl_ext;
|
|
|
|
s32 ret_val;
|
|
|
|
u16 data;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_setup_link_82543");
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Take the 4 bits from NVM word 0xF that determine the initial
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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);
|
|
|
|
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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_setup_copper_link_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 ctrl;
|
|
|
|
s32 ret_val;
|
2007-11-20 21:41:22 +00:00
|
|
|
bool link;
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
DEBUGFUNC("e1000_setup_copper_link_82543");
|
|
|
|
|
|
|
|
ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU;
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* With 82543, we need to force speed and duplex on the MAC
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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 = e1000_phy_hw_reset(hw);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
hw->phy.reset_disable = FALSE;
|
|
|
|
} 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) {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Setup autoneg and flow control advertisement and perform
|
|
|
|
* autonegotiation.
|
|
|
|
*/
|
2007-05-04 00:00:12 +00:00
|
|
|
ret_val = e1000_copper_link_autoneg(hw);
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
} else {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* PHY will be set to 10H, 10F, 100H or 100F
|
|
|
|
* depending on user settings.
|
|
|
|
*/
|
2007-05-04 00:00:12 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Check link status. Wait up to 100 microseconds for link to become
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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 */
|
2007-11-20 21:41:22 +00:00
|
|
|
if (hw->mac.type == e1000_82544) {
|
2007-05-04 00:00:12 +00:00
|
|
|
e1000_config_collision_dist_generic(hw);
|
2007-11-20 21:41:22 +00:00
|
|
|
} else {
|
2007-05-04 00:00:12 +00:00
|
|
|
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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Configures collision distance and flow control for fiber links. Upon
|
|
|
|
* successful setup, poll for link.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
|
|
|
e1000_config_collision_dist_generic(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);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
2008-02-29 21:50:11 +00:00
|
|
|
* For these adapters, the SW definable pin 1 is cleared when the
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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)
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_mac_info *mac = &hw->mac;
|
|
|
|
u32 icr, rctl;
|
|
|
|
s32 ret_val;
|
|
|
|
u16 speed, duplex;
|
2007-11-20 21:41:22 +00:00
|
|
|
bool link;
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If we are forcing speed/duplex, then we can return since
|
2007-05-04 00:00:12 +00:00
|
|
|
* we have already determined whether we have link or not.
|
|
|
|
*/
|
|
|
|
if (!mac->autoneg) {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If speed and duplex are forced to 10H or 10F, then we will
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* We have a M88E1000 PHY and Auto-Neg is enabled. If we
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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)
|
|
|
|
e1000_config_collision_dist_generic(hw);
|
|
|
|
else {
|
|
|
|
ret_val = e1000_config_mac_to_phy_82543(hw);
|
|
|
|
if (ret_val) {
|
|
|
|
DEBUGOUT("Error configuring MAC to PHY settings\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Configure Flow Control now that Auto-Neg has completed.
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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");
|
|
|
|
}
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* At this point we know that we are on copper and we have
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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 = e1000_get_speed_and_duplex(hw, &speed, &duplex);
|
|
|
|
if (ret_val) {
|
|
|
|
DEBUGOUT("Error getting link speed and duplex\n");
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
if (speed != SPEED_1000) {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If link speed is not set to gigabit speed,
|
2007-05-04 00:00:12 +00:00
|
|
|
* we do not need to enable TBI compatibility.
|
|
|
|
*/
|
|
|
|
if (e1000_tbi_sbp_enabled_82543(hw)) {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If we previously were in the mode,
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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 {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If TBI compatibility is was previously off,
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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)
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Checks for link up on the hardware. If link is not up and we have
|
|
|
|
* a signal, then we need to force link up.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
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);
|
2007-11-20 21:41:22 +00:00
|
|
|
status = E1000_READ_REG(hw, E1000_STATUS);
|
|
|
|
rxcw = E1000_READ_REG(hw, E1000_RXCW);
|
2007-05-04 00:00:12 +00:00
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If we don't have link (auto-negotiation failed or link partner
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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 == 0) {
|
|
|
|
mac->autoneg_failed = 1;
|
|
|
|
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)) {
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If we are forcing link and we are receiving /C/ ordered
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* For the 82543 silicon, we need to set the MAC to match the settings
|
|
|
|
* of the PHY, even if the PHY is auto-negotiating.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 ctrl;
|
|
|
|
s32 ret_val;
|
|
|
|
u16 phy_data;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_config_mac_to_phy_82543");
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Set up duplex in the Device Control and Transmit Control
|
2007-05-04 00:00:12 +00:00
|
|
|
* registers depending on negotiated values.
|
|
|
|
*/
|
|
|
|
ret_val = e1000_read_phy_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;
|
|
|
|
|
|
|
|
e1000_config_collision_dist_generic(hw);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* Set up speed in the Device Control register depending on
|
2007-05-04 00:00:12 +00:00
|
|
|
* 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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @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.
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* This writes a 32-bit value to a 32-bit offset in the VLAN filter
|
|
|
|
* table.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
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);
|
2007-11-20 21:41:22 +00:00
|
|
|
} else {
|
2007-05-04 00:00:12 +00:00
|
|
|
e1000_write_vfta_generic(hw, offset, value);
|
2007-11-20 21:41:22 +00:00
|
|
|
}
|
2007-05-04 00:00:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_mta_set_82543 - Set multicast filter table address
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @hash_value: determines the MTA register and bit to set
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* The multicast table address is a register array of 32-bit registers.
|
|
|
|
* The hash_value is used to determine what register the bit is in, the
|
|
|
|
* current value is read, the new bit is OR'd in and the new value is
|
|
|
|
* written back into the register.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 hash_bit, hash_reg, mta, temp;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_mta_set_82543");
|
|
|
|
|
|
|
|
hash_reg = (hash_value >> 5);
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If we are on an 82544 and we are trying to write an odd offset
|
2007-05-04 00:00:12 +00:00
|
|
|
* in the MTA, save off the previous entry before writing and
|
|
|
|
* restore the old value after writing.
|
|
|
|
*/
|
|
|
|
if ((hw->mac.type == e1000_82544) && (hash_reg & 1)) {
|
|
|
|
hash_reg &= (hw->mac.mta_reg_count - 1);
|
|
|
|
hash_bit = hash_value & 0x1F;
|
|
|
|
mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg);
|
|
|
|
mta |= (1 << hash_bit);
|
|
|
|
temp = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg - 1);
|
|
|
|
|
|
|
|
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta);
|
|
|
|
E1000_WRITE_FLUSH(hw);
|
|
|
|
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg - 1, temp);
|
|
|
|
E1000_WRITE_FLUSH(hw);
|
2007-11-20 21:41:22 +00:00
|
|
|
} else {
|
2007-05-04 00:00:12 +00:00
|
|
|
e1000_mta_set_generic(hw, hash_value);
|
2007-11-20 21:41:22 +00:00
|
|
|
}
|
2007-05-04 00:00:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_led_on_82543 - Turn on SW controllable LED
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Turns the SW defined LED on. This is a function pointer entry point
|
|
|
|
* called by the api module.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_led_on_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_led_on_82543");
|
|
|
|
|
|
|
|
if (hw->mac.type == e1000_82544 &&
|
2007-11-20 21:41:22 +00:00
|
|
|
hw->phy.media_type == e1000_media_type_copper) {
|
2008-02-29 21:50:11 +00:00
|
|
|
/* Clear SW-definable Pin 0 to turn on the LED */
|
2007-05-04 00:00:12 +00:00
|
|
|
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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Turns the SW defined LED off. This is a function pointer entry point
|
|
|
|
* called by the api module.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC s32 e1000_led_off_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_led_off_82543");
|
|
|
|
|
|
|
|
if (hw->mac.type == e1000_82544 &&
|
2007-11-20 21:41:22 +00:00
|
|
|
hw->phy.media_type == e1000_media_type_copper) {
|
2008-02-29 21:50:11 +00:00
|
|
|
/* Set SW-definable Pin 0 to turn off the LED */
|
2007-05-04 00:00:12 +00:00
|
|
|
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
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Clears the hardware counters by reading the counter registers.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
STATIC void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|