📄 e1000_ich8lan.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*******************************************************************************//* e1000_ich8lan * e1000_ich9lan */#include "e1000_api.h"#include "e1000_ich8lan.h"static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw);static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw);static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw);static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw);static void e1000_release_swflag_ich8lan(struct e1000_hw *hw);static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw);static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw);static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw);static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw);static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw);static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active);static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active);static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw);static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw);static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data);static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw);static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw);static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw);static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw);static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, u16 *duplex);static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw);static s32 e1000_led_on_ich8lan(struct e1000_hw *hw);static s32 e1000_led_off_ich8lan(struct e1000_hw *hw);static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank);static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout);static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw);static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw);static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, u8 size, u16* data);static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data);static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 byte);static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 data);static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, u8 size, u16 data);static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown *//* Offset 04h HSFSTS */union ich8_hws_flash_status { struct ich8_hsfsts { u16 flcdone :1; /* bit 0 Flash Cycle Done */ u16 flcerr :1; /* bit 1 Flash Cycle Error */ u16 dael :1; /* bit 2 Direct Access error Log */ u16 berasesz :2; /* bit 4:3 Sector Erase Size */ u16 flcinprog :1; /* bit 5 flash cycle in Progress */ u16 reserved1 :2; /* bit 13:6 Reserved */ u16 reserved2 :6; /* bit 13:6 Reserved */ u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */ u16 flockdn :1; /* bit 15 Flash Config Lock-Down */ } hsf_status; u16 regval;};/* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown *//* Offset 06h FLCTL */union ich8_hws_flash_ctrl { struct ich8_hsflctl { u16 flcgo :1; /* 0 Flash Cycle Go */ u16 flcycle :2; /* 2:1 Flash Cycle */ u16 reserved :5; /* 7:3 Reserved */ u16 fldbcount :2; /* 9:8 Flash Data Byte Count */ u16 flockdn :6; /* 15:10 Reserved */ } hsf_ctrl; u16 regval;};/* ICH Flash Region Access Permissions */union ich8_hws_flash_regacc { struct ich8_flracc { u32 grra :8; /* 0:7 GbE region Read Access */ u32 grwa :8; /* 8:15 GbE region Write Access */ u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */ u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */ } hsf_flregacc; u16 regval;};struct e1000_shadow_ram { u16 value; bool modified;};struct e1000_dev_spec_ich8lan { bool kmrn_lock_loss_workaround_enabled; struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS];};/** * e1000_init_phy_params_ich8lan - Initialize PHY function pointers * @hw: pointer to the HW structure * * Initialize family-specific PHY parameters and function pointers. **/static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw){ struct e1000_phy_info *phy = &hw->phy; struct e1000_functions *func = &hw->func; s32 ret_val = E1000_SUCCESS; u16 i = 0; DEBUGFUNC("e1000_init_phy_params_ich8lan"); phy->addr = 1; phy->reset_delay_us = 100; func->acquire_phy = e1000_acquire_swflag_ich8lan; func->check_polarity = e1000_check_polarity_ife_ich8lan; func->check_reset_block = e1000_check_reset_block_ich8lan; func->force_speed_duplex = e1000_phy_force_speed_duplex_ich8lan; func->get_cable_length = e1000_get_cable_length_igp_2; func->get_cfg_done = e1000_get_cfg_done_ich8lan; func->get_phy_info = e1000_get_phy_info_ich8lan; func->read_phy_reg = e1000_read_phy_reg_igp; func->release_phy = e1000_release_swflag_ich8lan; func->reset_phy = e1000_phy_hw_reset_ich8lan; func->set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan; func->set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan; func->write_phy_reg = e1000_write_phy_reg_igp; func->power_up_phy = e1000_power_up_phy_copper; func->power_down_phy = e1000_power_down_phy_copper_ich8lan; phy->id = 0; while ((e1000_phy_unknown == e1000_get_phy_type_from_id(phy->id)) && (i++ < 100)) { msec_delay(1); ret_val = e1000_get_phy_id(hw); if (ret_val) goto out; } /* Verify phy id */ switch (phy->id) { case IGP03E1000_E_PHY_ID: phy->type = e1000_phy_igp_3; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; break; case IFE_E_PHY_ID: case IFE_PLUS_E_PHY_ID: case IFE_C_E_PHY_ID: phy->type = e1000_phy_ife; phy->autoneg_mask = E1000_ALL_NOT_GIG; break; default: ret_val = -E1000_ERR_PHY; goto out; }out: return ret_val;}/** * e1000_init_nvm_params_ich8lan - Initialize NVM function pointers * @hw: pointer to the HW structure * * Initialize family-specific NVM parameters and function * pointers. **/static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw){ struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_functions *func = &hw->func; struct e1000_dev_spec_ich8lan *dev_spec; u32 gfpreg, sector_base_addr, sector_end_addr; s32 ret_val = E1000_SUCCESS; u16 i; DEBUGFUNC("e1000_init_nvm_params_ich8lan"); /* Can't read flash registers if the register set isn't mapped. */ if (!hw->flash_address) { DEBUGOUT("ERROR: Flash registers not mapped\n"); ret_val = -E1000_ERR_CONFIG; goto out; } nvm->type = e1000_nvm_flash_sw; gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); /* * sector_X_addr is a "sector"-aligned address (4096 bytes) * Add 1 to sector_end_addr since this sector is included in * the overall size. */ sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; /* flash_base_addr is byte-aligned */ nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; /* * find total size of the NVM, then cut in half since the total * size represents two separate NVM banks. */ nvm->flash_bank_size = (sector_end_addr - sector_base_addr) << FLASH_SECTOR_ADDR_SHIFT; nvm->flash_bank_size /= 2; /* Adjust to word count */ nvm->flash_bank_size /= sizeof(u16); nvm->word_size = E1000_SHADOW_RAM_WORDS; dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; if (!dev_spec) { DEBUGOUT("dev_spec pointer is set to NULL.\n"); ret_val = -E1000_ERR_CONFIG; goto out; } /* Clear shadow ram */ for (i = 0; i < nvm->word_size; i++) { dev_spec->shadow_ram[i].modified = FALSE; dev_spec->shadow_ram[i].value = 0xFFFF; } /* Function Pointers */ func->acquire_nvm = e1000_acquire_swflag_ich8lan; func->read_nvm = e1000_read_nvm_ich8lan; func->release_nvm = e1000_release_swflag_ich8lan; func->update_nvm = e1000_update_nvm_checksum_ich8lan; func->valid_led_default = e1000_valid_led_default_ich8lan; func->validate_nvm = e1000_validate_nvm_checksum_ich8lan; func->write_nvm = e1000_write_nvm_ich8lan;out: return ret_val;}/** * e1000_init_mac_params_ich8lan - Initialize MAC function pointers * @hw: pointer to the HW structure * * Initialize family-specific MAC parameters and function * pointers. **/static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; struct e1000_functions *func = &hw->func; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_mac_params_ich8lan"); /* Set media type function pointer */ hw->phy.media_type = e1000_media_type_copper; /* Set mta register count */ mac->mta_reg_count = 32; /* Set rar entry count */ mac->rar_entry_count = E1000_ICH_RAR_ENTRIES; if (mac->type == e1000_ich8lan) mac->rar_entry_count--; /* Set if part includes ASF firmware */ mac->asf_firmware_present = TRUE; /* Set if manageability features are enabled. */ mac->arc_subsystem_valid = TRUE; /* Function pointers */ /* bus type/speed/width */ func->get_bus_info = e1000_get_bus_info_ich8lan; /* reset */ func->reset_hw = e1000_reset_hw_ich8lan; /* hw initialization */ func->init_hw = e1000_init_hw_ich8lan; /* link setup */ func->setup_link = e1000_setup_link_ich8lan; /* physical interface setup */ func->setup_physical_interface = e1000_setup_copper_link_ich8lan; /* check for link */ func->check_for_link = e1000_check_for_copper_link_generic; /* check management mode */ func->check_mng_mode = e1000_check_mng_mode_ich8lan; /* link info */ func->get_link_up_info = e1000_get_link_up_info_ich8lan; /* multicast address update */ func->update_mc_addr_list = e1000_update_mc_addr_list_generic; /* setting MTA */ func->mta_set = e1000_mta_set_generic; /* blink LED */ func->blink_led = e1000_blink_led_generic; /* setup LED */ func->setup_led = e1000_setup_led_generic; /* cleanup LED */ func->cleanup_led = e1000_cleanup_led_ich8lan; /* turn on/off LED */ func->led_on = e1000_led_on_ich8lan; func->led_off = e1000_led_off_ich8lan; /* remove device */ func->remove_device = e1000_remove_device_generic; /* clear hardware counters */ func->clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan; hw->dev_spec_size = sizeof(struct e1000_dev_spec_ich8lan); /* Device-specific structure allocation */ ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); if (ret_val) goto out; /* Enable PCS Lock-loss workaround for ICH8 */ if (mac->type == e1000_ich8lan) e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, TRUE);out: return ret_val;}/** * e1000_init_function_pointers_ich8lan - Initialize ICH8 function pointers * @hw: pointer to the HW structure * * Initialize family-specific function pointers for PHY, MAC, and NVM. **/void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw){ DEBUGFUNC("e1000_init_function_pointers_ich8lan"); hw->func.init_mac_params = e1000_init_mac_params_ich8lan; hw->func.init_nvm_params = e1000_init_nvm_params_ich8lan; hw->func.init_phy_params = e1000_init_phy_params_ich8lan;}/** * e1000_acquire_swflag_ich8lan - Acquire software control flag * @hw: pointer to the HW structure * * Acquires the software control flag for performing NVM and PHY * operations. This is a function pointer entry point only called by * read/write routines for the PHY and NVM parts. **/static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw){ u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_acquire_swflag_ich8lan"); while (timeout) { extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) break; msec_delay_irq(1); timeout--; } if (!timeout) { DEBUGOUT("FW or HW has locked the resource for too long.\n"); extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); ret_val = -E1000_ERR_CONFIG; goto out; }out: return ret_val;}/** * e1000_release_swflag_ich8lan - Release software control flag * @hw: pointer to the HW structure * * Releases the software control flag for performing NVM and PHY operations. * This is a function pointer entry point only called by read/write * routines for the PHY and NVM parts. **/static void e1000_release_swflag_ich8lan(struct e1000_hw *hw){ u32 extcnf_ctrl; DEBUGFUNC("e1000_release_swflag_ich8lan"); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); return;}/** * e1000_check_mng_mode_ich8lan - Checks management mode * @hw: pointer to the HW structure * * This checks if the adapter has manageability enabled. * This is a function pointer entry point only called by read/write * routines for the PHY and NVM parts. **/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -