📄 e1000_82540.c
字号:
DEBUGOUT("Initializing the IEEE VLAN\n"); if (mac->type < e1000_82545_rev_3) 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); /* * Avoid back to back register writes by adding the register * read (flush). This is to protect against some strange * bridge configurations that may issue Memory Write Block * (MWB) to our register space. The *_rev_3 hardware at * least doesn't respond correctly to every other dword in an * MWB to our register space. */ E1000_WRITE_FLUSH(hw); } if (mac->type < e1000_82545_rev_3) e1000_pcix_mmrbc_workaround_generic(hw); /* Setup link and flow control */ ret_val = e1000_setup_link(hw); txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_82540(hw); if ((hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER) || (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3)) { ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); /* * Relaxed ordering must be disabled to avoid a parity * error crash in a PCI slot. */ ctrl_ext |= E1000_CTRL_EXT_RO_DIS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); } return ret_val;}/** * e1000_setup_copper_link_82540 - Configure copper link settings * @hw: pointer to the HW structure * * Calls the appropriate function to configure the link for auto-neg or forced * speed and duplex. Then we check for link, once link is established calls * to configure collision distance and flow control are called. If link is * not established, we return -E1000_ERR_PHY (-2). This is a function * pointer entry point called by the api module. **/static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw){ u32 ctrl; s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_setup_copper_link_82540"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ret_val = e1000_set_phy_mode_82540(hw); if (ret_val) goto out; if (hw->mac.type == e1000_82545_rev_3 || hw->mac.type == e1000_82546_rev_3) { ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &data); if (ret_val) goto out; data |= 0x00000008; ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, data); if (ret_val) goto out; } ret_val = e1000_copper_link_setup_m88(hw); if (ret_val) goto out; ret_val = e1000_setup_copper_link_generic(hw);out: return ret_val;}/** * e1000_setup_fiber_serdes_link_82540 - Setup link for fiber/serdes * @hw: pointer to the HW structure * * Set the output amplitude to the value in the EEPROM and adjust the VCO * speed to improve Bit Error Rate (BER) performance. Configures collision * distance and flow control for fiber and serdes links. Upon successful * setup, poll for link. This is a function pointer entry point called by * the api module. **/static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_setup_fiber_serdes_link_82540"); switch (mac->type) { case e1000_82545_rev_3: case e1000_82546_rev_3: if (hw->phy.media_type == e1000_media_type_internal_serdes) { /* * If we're on serdes media, adjust the output * amplitude to value set in the EEPROM. */ ret_val = e1000_adjust_serdes_amplitude_82540(hw); if (ret_val) goto out; } /* Adjust VCO speed to improve BER performance */ ret_val = e1000_set_vco_speed_82540(hw); if (ret_val) goto out; default: break; } ret_val = e1000_setup_fiber_serdes_link_generic(hw);out: return ret_val;}/** * e1000_adjust_serdes_amplitude_82540 - Adjust amplitude based on EEPROM * @hw: pointer to the HW structure * * Adjust the SERDES ouput amplitude based on the EEPROM settings. **/static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw){ s32 ret_val = E1000_SUCCESS; u16 nvm_data; DEBUGFUNC("e1000_adjust_serdes_amplitude_82540"); ret_val = e1000_read_nvm(hw, NVM_SERDES_AMPLITUDE, 1, &nvm_data); if (ret_val) goto out; if (nvm_data != NVM_RESERVED_WORD) { /* Adjust serdes output amplitude only. */ nvm_data &= NVM_SERDES_AMPLITUDE_MASK; ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, nvm_data); if (ret_val) goto out; }out: return ret_val;}/** * e1000_set_vco_speed_82540 - Set VCO speed for better performance * @hw: pointer to the HW structure * * Set the VCO speed to improve Bit Error Rate (BER) performance. **/static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw){ s32 ret_val = E1000_SUCCESS; u16 default_page = 0; u16 phy_data; DEBUGFUNC("e1000_set_vco_speed_82540"); /* Set PHY register 30, page 5, bit 8 to 0 */ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page); if (ret_val) goto out; ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005); if (ret_val) goto out; ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); if (ret_val) goto out; phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); if (ret_val) goto out; /* Set PHY register 30, page 4, bit 11 to 1 */ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004); if (ret_val) goto out; ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); if (ret_val) goto out; phy_data |= M88E1000_PHY_VCO_REG_BIT11; ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); if (ret_val) goto out; ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page);out: return ret_val;}/** * e1000_set_phy_mode_82540 - Set PHY to class A mode * @hw: pointer to the HW structure * * Sets the PHY to class A mode and assumes the following operations will * follow to enable the new class mode: * 1. Do a PHY soft reset. * 2. Restart auto-negotiation or force link. **/static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw){ struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 nvm_data; DEBUGFUNC("e1000_set_phy_mode_82540"); if (hw->mac.type != e1000_82545_rev_3) goto out; ret_val = e1000_read_nvm(hw, NVM_PHY_CLASS_WORD, 1, &nvm_data); if (ret_val) { ret_val = -E1000_ERR_PHY; goto out; } if ((nvm_data != NVM_RESERVED_WORD) && (nvm_data & NVM_PHY_CLASS_A)) { ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x000B); if (ret_val) { ret_val = -E1000_ERR_PHY; goto out; } ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x8104); if (ret_val) { ret_val = -E1000_ERR_PHY; goto out; } phy->reset_disable = FALSE; }out: return ret_val;}/** * e1000_power_down_phy_copper_82540 - Remove link in case of PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw){ /* If the management interface is not enabled, then power down */ if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN)) e1000_power_down_phy_copper(hw); return;}/** * e1000_clear_hw_cntrs_82540 - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw){ volatile u32 temp; DEBUGFUNC("e1000_clear_hw_cntrs_82540"); e1000_clear_hw_cntrs_base_generic(hw); temp = E1000_READ_REG(hw, E1000_PRC64); temp = E1000_READ_REG(hw, E1000_PRC127); temp = E1000_READ_REG(hw, E1000_PRC255); temp = E1000_READ_REG(hw, E1000_PRC511); temp = E1000_READ_REG(hw, E1000_PRC1023); temp = E1000_READ_REG(hw, E1000_PRC1522); temp = E1000_READ_REG(hw, E1000_PTC64); temp = E1000_READ_REG(hw, E1000_PTC127); temp = E1000_READ_REG(hw, E1000_PTC255); temp = E1000_READ_REG(hw, E1000_PTC511); temp = E1000_READ_REG(hw, E1000_PTC1023); temp = E1000_READ_REG(hw, E1000_PTC1522); 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); temp = E1000_READ_REG(hw, E1000_MGTPRC); temp = E1000_READ_REG(hw, E1000_MGTPDC); temp = E1000_READ_REG(hw, E1000_MGTPTC);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -