📄 e1000_82543.c
字号:
* @hw: pointer to the HW structure * * Checks the phy for link, if link exists, do the following: * - check for downshift * - do polarity workaround (if necessary) * - configure collision distance * - configure flow control after link up * - configure tbi compatibility **/static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; u32 icr, rctl; s32 ret_val; u16 speed, duplex; bool link; DEBUGFUNC("e1000_check_for_copper_link_82543"); if (!mac->get_link_status) { ret_val = E1000_SUCCESS; goto out; } ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) goto out; if (!link) goto out; /* No link detected */ mac->get_link_status = FALSE; e1000_check_downshift_generic(hw); /* * If we are forcing speed/duplex, then we can return since * we have already determined whether we have link or not. */ if (!mac->autoneg) { /* * If speed and duplex are forced to 10H or 10F, then we will * implement the polarity reversal workaround. We disable * interrupts first, and upon returning, place the devices * interrupt state to its previous value except for the link * status change interrupt which will happened due to the * execution of this workaround. */ if (mac->forced_speed_duplex & E1000_ALL_10_SPEED) { E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); ret_val = e1000_polarity_reversal_workaround_82543(hw); icr = E1000_READ_REG(hw, E1000_ICR); E1000_WRITE_REG(hw, E1000_ICS, (icr & ~E1000_ICS_LSC)); E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK); } ret_val = -E1000_ERR_CONFIG; goto out; } /* * We have a M88E1000 PHY and Auto-Neg is enabled. If we * have Si on board that is 82544 or newer, Auto * Speed Detection takes care of MAC speed/duplex * configuration. So we only need to configure Collision * Distance in the MAC. Otherwise, we need to force * speed/duplex on the MAC to the current PHY speed/duplex * settings. */ if (mac->type == e1000_82544) 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; } } /* * Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) { DEBUGOUT("Error configuring flow control\n"); } /* * At this point we know that we are on copper and we have * auto-negotiated link. These are conditions for checking the link * partner capability register. We use the link speed to determine if * TBI compatibility needs to be turned on or off. If the link is not * at gigabit speed, then TBI compatibility is not needed. If we are * at gigabit speed, we turn on TBI compatibility. */ if (e1000_tbi_compatibility_enabled_82543(hw)) { ret_val = 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) { /* * If link speed is not set to gigabit speed, * we do not need to enable TBI compatibility. */ if (e1000_tbi_sbp_enabled_82543(hw)) { /* * If we previously were in the mode, * turn it off. */ e1000_set_tbi_sbp_82543(hw, FALSE); rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= ~E1000_RCTL_SBP; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } } else { /* * If TBI compatibility is was previously off, * turn it on. For compatibility with a TBI link * partner, we will store bad packets. Some * frames have an additional byte on the end and * will look like CRC errors to to the hardware. */ if (!e1000_tbi_sbp_enabled_82543(hw)) { e1000_set_tbi_sbp_82543(hw, TRUE); rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= E1000_RCTL_SBP; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } } }out: return ret_val;}/** * e1000_check_for_fiber_link_82543 - Check for link (Fiber) * @hw: pointer to the HW structure * * Checks for link up on the hardware. If link is not up and we have * a signal, then we need to force link up. **/static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; u32 rxcw, ctrl, status; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_check_for_fiber_link_82543"); ctrl = E1000_READ_REG(hw, E1000_CTRL); status = E1000_READ_REG(hw, E1000_STATUS); rxcw = E1000_READ_REG(hw, E1000_RXCW); /* * If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), the cable is plugged in (we have signal), * and our link partner is not trying to auto-negotiate with us (we * are receiving idles or data), we need to force link up. We also * need to give auto-negotiation time to complete, in case the cable * was just plugged in. The autoneg_failed flag does this. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 0 == have signal */ if ((!(ctrl & E1000_CTRL_SWDPIN1)) && (!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { if (mac->autoneg_failed == 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)) { /* * If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. */ DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); mac->serdes_has_link = TRUE; }out: return ret_val;}/** * e1000_config_mac_to_phy_82543 - Configure MAC to PHY settings * @hw: pointer to the HW structure * * For the 82543 silicon, we need to set the MAC to match the settings * of the PHY, even if the PHY is auto-negotiating. **/static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw){ u32 ctrl; s32 ret_val; 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); /* * Set up duplex in the Device Control and Transmit Control * 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); /* * Set up speed in the Device Control register depending on * negotiated values. */ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) ctrl |= E1000_CTRL_SPD_1000; else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) ctrl |= E1000_CTRL_SPD_100; E1000_WRITE_REG(hw, E1000_CTRL, ctrl);out: return ret_val;}/** * e1000_write_vfta_82543 - Write value to VLAN filter table * @hw: pointer to the HW structure * @offset: the 32-bit offset in which to write the value to. * @value: the 32-bit value to write at location offset. * * This writes a 32-bit value to a 32-bit offset in the VLAN filter * table. **/static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value){ u32 temp; DEBUGFUNC("e1000_write_vfta_82543"); if ((hw->mac.type == e1000_82544) && (offset & 1)) { temp = E1000_READ_REG_ARRAY(hw, E1000_VFTA, offset - 1); E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp); E1000_WRITE_FLUSH(hw); } else { e1000_write_vfta_generic(hw, offset, value); }}/** * e1000_mta_set_82543 - Set multicast filter table address * @hw: pointer to the HW structure * @hash_value: determines the MTA register and bit to set * * 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. **/static void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value){ u32 hash_bit, hash_reg, mta, temp; DEBUGFUNC("e1000_mta_set_82543"); hash_reg = (hash_value >> 5); /* * If we are on an 82544 and we are trying to write an odd offset * 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); } else { e1000_mta_set_generic(hw, hash_value); }}/** * e1000_led_on_82543 - Turn on SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED on. This is a function pointer entry point * called by the api module. **/static s32 e1000_led_on_82543(struct e1000_hw *hw){ u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGFUNC("e1000_led_on_82543"); if (hw->mac.type == e1000_82544 && hw->phy.media_type == e1000_media_type_copper) { /* Clear SW-defineable Pin 0 to turn on the LED */ ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; } else { /* Fiber 82544 and all 82543 use this method */ ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; } E1000_WRITE_REG(hw, E1000_CTRL, ctrl); return E1000_SUCCESS;}/** * e1000_led_off_82543 - Turn off SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED off. This is a function pointer entry point * called by the api module. **/static s32 e1000_led_off_82543(struct e1000_hw *hw){ u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGFUNC("e1000_led_off_82543"); if (hw->mac.type == e1000_82544 && hw->phy.media_type == e1000_media_type_copper) { /* Set SW-defineable Pin 0 to turn off the LED */ ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; } else { ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; } E1000_WRITE_REG(hw, E1000_CTRL, ctrl); return E1000_SUCCESS;}/** * e1000_clear_hw_cntrs_82543 - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw){ 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -