📄 e1000_82571.c
字号:
/******************************************************************************* Intel PRO/1000 Linux driver Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: Linux NICS <linux.nics@intel.com> e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************//* * 82571EB Gigabit Ethernet Controller * 82571EB Gigabit Ethernet Controller (Copper) * 82571EB Gigabit Ethernet Controller (Fiber) * 82571EB Dual Port Gigabit Mezzanine Adapter * 82571EB Quad Port Gigabit Mezzanine Adapter * 82571PT Gigabit PT Quad Port Server ExpressModule * 82572EI Gigabit Ethernet Controller (Copper) * 82572EI Gigabit Ethernet Controller (Fiber) * 82572EI Gigabit Ethernet Controller * 82573V Gigabit Ethernet Controller (Copper) * 82573E Gigabit Ethernet Controller (Copper) * 82573L Gigabit Ethernet Controller * 82574L Gigabit Network Connection */#include "e1000.h"static s32 e1000_init_phy_params_82571(struct e1000_hw *hw);static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw);static s32 e1000_init_mac_params_82571(struct e1000_hw *hw);static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw);static void e1000_release_nvm_82571(struct e1000_hw *hw);static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw);static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw);static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw);static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active);static s32 e1000_reset_hw_82571(struct e1000_hw *hw);static s32 e1000_init_hw_82571(struct e1000_hw *hw);static void e1000_clear_vfta_82571(struct e1000_hw *hw);static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);static s32 e1000_led_on_82574(struct e1000_hw *hw);static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, u32 rar_used_count, u32 rar_count);static s32 e1000_setup_link_82571(struct e1000_hw *hw);static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw);static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data);static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw);static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw);static s32 e1000_get_phy_id_82571(struct e1000_hw *hw);static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw);static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw);static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw);/** * e1000_init_phy_params_82571 - Init PHY func ptrs. * @hw: pointer to the HW structure **/static s32 e1000_init_phy_params_82571(struct e1000_hw *hw){ struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; goto out; } phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 100; phy->ops.acquire = e1000_get_hw_semaphore_82571; phy->ops.check_polarity = e1000_check_polarity_igp; phy->ops.check_reset_block = e1000e_check_reset_block_generic; phy->ops.release = e1000_put_hw_semaphore_82571; phy->ops.reset = e1000e_phy_hw_reset_generic; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82571; phy->ops.set_d3_lplu_state = e1000e_set_d3_lplu_state; phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_82571; switch (hw->mac.type) { case e1000_82571: case e1000_82572: phy->type = e1000_phy_igp_2; phy->ops.get_cfg_done = e1000_get_cfg_done_82571; phy->ops.get_info = e1000e_get_phy_info_igp; phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_igp; phy->ops.get_cable_length = e1000e_get_cable_length_igp_2; phy->ops.read_reg = e1000e_read_phy_reg_igp; phy->ops.write_reg = e1000e_write_phy_reg_igp; /* This uses above function pointers */ ret_val = e1000_get_phy_id_82571(hw); /* Verify PHY ID */ if (phy->id != IGP01E1000_I_PHY_ID) { ret_val = -E1000_ERR_PHY; goto out; } break; case e1000_82573: phy->type = e1000_phy_m88; phy->ops.get_cfg_done = e1000e_get_cfg_done; phy->ops.get_info = e1000e_get_phy_info_m88; phy->ops.commit = e1000e_phy_sw_reset; phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; phy->ops.get_cable_length = e1000e_get_cable_length_m88; phy->ops.read_reg = e1000e_read_phy_reg_m88; phy->ops.write_reg = e1000e_write_phy_reg_m88; /* This uses above function pointers */ ret_val = e1000_get_phy_id_82571(hw); /* Verify PHY ID */ if (phy->id != M88E1111_I_PHY_ID) { ret_val = -E1000_ERR_PHY; e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id); goto out; } break; case e1000_82574: phy->type = e1000_phy_bm; phy->ops.get_cfg_done = e1000e_get_cfg_done; phy->ops.get_info = e1000e_get_phy_info_m88; phy->ops.commit = e1000e_phy_sw_reset; phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; phy->ops.get_cable_length = e1000e_get_cable_length_m88; phy->ops.read_reg = e1000e_read_phy_reg_bm2; phy->ops.write_reg = e1000e_write_phy_reg_bm2; /* This uses above function pointers */ ret_val = e1000_get_phy_id_82571(hw); /* Verify PHY ID */ if (phy->id != BME1000_E_PHY_ID_R2) { ret_val = -E1000_ERR_PHY; e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id); goto out; } break; default: ret_val = -E1000_ERR_PHY; goto out; break; }out: return ret_val;}/** * e1000_init_nvm_params_82571 - Init NVM func ptrs. * @hw: pointer to the HW structure **/static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw){ struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = er32(EECD); u16 size; nvm->opcode_bits = 8; nvm->delay_usec = 1; switch (nvm->override) { case e1000_nvm_override_spi_large: nvm->page_size = 32; nvm->address_bits = 16; break; case e1000_nvm_override_spi_small: nvm->page_size = 8; nvm->address_bits = 8; break; default: nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; break; } switch (hw->mac.type) { case e1000_82573: case e1000_82574: if (((eecd >> 15) & 0x3) == 0x3) { nvm->type = e1000_nvm_flash_hw; nvm->word_size = 2048; /* * Autonomous Flash update bit must be cleared due * to Flash update issue. */ eecd &= ~E1000_EECD_AUPDEN; ew32(EECD, eecd); break; } /* Fall Through */ default: nvm->type = e1000_nvm_eeprom_spi; size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); /* * Added to a constant, "size" becomes the left-shift value * for setting word_size. */ size += NVM_WORD_SIZE_BASE_SHIFT; /* EEPROM access above 16k is unsupported */ if (size > 14) size = 14; nvm->word_size = 1 << size; break; } /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_82571; nvm->ops.read = e1000e_read_nvm_eerd; nvm->ops.release = e1000_release_nvm_82571; nvm->ops.update = e1000_update_nvm_checksum_82571; nvm->ops.validate = e1000_validate_nvm_checksum_82571; nvm->ops.valid_led_default = e1000_valid_led_default_82571; nvm->ops.write = e1000_write_nvm_82571; return E1000_SUCCESS;}/** * e1000_init_mac_params_82571 - Init MAC func ptrs. * @hw: pointer to the HW structure **/static s32 e1000_init_mac_params_82571(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; /* Set media type */ switch (hw->device_id) { case E1000_DEV_ID_82571EB_FIBER: case E1000_DEV_ID_82572EI_FIBER: case E1000_DEV_ID_82571EB_QUAD_FIBER: hw->phy.media_type = e1000_media_type_fiber; break; case E1000_DEV_ID_82571EB_SERDES: case E1000_DEV_ID_82571EB_SERDES_DUAL: case E1000_DEV_ID_82571EB_SERDES_QUAD: case E1000_DEV_ID_82572EI_SERDES: hw->phy.media_type = e1000_media_type_internal_serdes; 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; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; /* Set if manageability features are enabled. */ mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK) ? true : false; /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000e_get_bus_info_pcie; /* function id */ switch (hw->mac.type) { case e1000_82573: case e1000_82574: mac->ops.set_lan_id = e1000_set_lan_id_single_port; break; default: break; } /* reset */ mac->ops.reset_hw = e1000_reset_hw_82571; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_82571; /* link setup */ mac->ops.setup_link = e1000_setup_link_82571; /* physical interface link setup */ mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) ? e1000_setup_copper_link_82571 : e1000_setup_fiber_serdes_link_82571; /* check for link */ switch (hw->phy.media_type) { case e1000_media_type_copper: mac->ops.check_for_link = e1000e_check_for_copper_link; break; case e1000_media_type_fiber: mac->ops.check_for_link = e1000e_check_for_fiber_link; break; case e1000_media_type_internal_serdes: mac->ops.check_for_link = e1000e_check_for_serdes_link; break; default: ret_val = -E1000_ERR_CONFIG; goto out; break; } /* check management mode */ switch (hw->mac.type) { case e1000_82574: mac->ops.check_mng_mode = e1000_check_mng_mode_82574; break; default: mac->ops.check_mng_mode = e1000_check_mng_mode_generic; break; } /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82571; /* writing VFTA */ mac->ops.write_vfta = e1000e_write_vfta_generic; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_82571; /* setting MTA */ mac->ops.mta_set = e1000_mta_set_generic; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_82571; /* ID LED init */ mac->ops.id_led_init = e1000e_id_led_init; /* blink LED */ mac->ops.blink_led = e1000e_blink_led; /* setup LED */ mac->ops.setup_led = e1000_setup_led_generic; /* cleanup LED */ mac->ops.cleanup_led = e1000e_cleanup_led_generic; /* turn on/off LED */ switch (hw->mac.type) { case e1000_82574: mac->ops.led_on = e1000_led_on_82574; break; default: mac->ops.led_on = e1000e_led_on_generic; break; } mac->ops.led_off = e1000e_led_off_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82571; /* link info */ mac->ops.get_link_up_info = (hw->phy.media_type == e1000_media_type_copper) ? e1000e_get_speed_and_duplex_copper : e1000e_get_speed_and_duplex_fiber_serdes;out: return ret_val;}/** * e1000_init_function_pointers_82571 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/void e1000_init_function_pointers_82571(struct e1000_hw *hw){ e1000_init_mac_ops_generic(hw); e1000_init_nvm_ops_generic(hw); hw->mac.ops.init_params = e1000_init_mac_params_82571; hw->nvm.ops.init_params = e1000_init_nvm_params_82571; hw->phy.ops.init_params = e1000_init_phy_params_82571;}/** * e1000_get_phy_id_82571 - Retrieve the PHY ID and revision * @hw: pointer to the HW structure * * Reads the PHY registers and stores the PHY ID and possibly the PHY * revision in the hardware structure. **/static s32 e1000_get_phy_id_82571(struct e1000_hw *hw){ struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_id = 0; switch (hw->mac.type) { case e1000_82571: case e1000_82572: /* * The 82571 firmware may still be configuring the PHY. * In this case, we cannot access the PHY until the * configuration is done. So we explicitly set the * PHY ID. */ phy->id = IGP01E1000_I_PHY_ID; break; case e1000_82573: ret_val = e1000e_get_phy_id(hw); break; case e1000_82574: ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); if (ret_val) goto out; phy->id = (u32)(phy_id << 16); udelay(20); ret_val = e1e_rphy(hw, PHY_ID2, &phy_id); if (ret_val) goto out; phy->id |= (u32)(phy_id); phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); break; default: ret_val = -E1000_ERR_PHY; break; }out: return ret_val;}/** * e1000_get_hw_semaphore_82571 - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM **/static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw){ u32 swsm; s32 ret_val = E1000_SUCCESS; s32 timeout = hw->nvm.word_size + 1; s32 i = 0; /* Get the FW semaphore. */ for (i = 0; i < timeout; i++) { swsm = er32(SWSM); ew32(SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (er32(SWSM) & E1000_SWSM_SWESMBI) break; udelay(50); } if (i == timeout) { /* Release semaphores */ e1000e_put_hw_semaphore(hw); e_dbg("Driver can't access the NVM\n"); ret_val = -E1000_ERR_NVM; goto out; }out: return ret_val;}/** * e1000_put_hw_semaphore_82571 - Release hardware semaphore * @hw: pointer to the HW structure * * Release hardware semaphore used to access the PHY or NVM **/static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw){ u32 swsm; swsm = er32(SWSM); swsm &= ~E1000_SWSM_SWESMBI; ew32(SWSM, swsm);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -