lib.c
来自「linux 内核源代码」· C语言 代码 · 共 2,342 行 · 第 1/5 页
C
2,342 行
ctrl &= (~E1000_CTRL_TFCE); ctrl |= E1000_CTRL_RFCE; break; case e1000_fc_tx_pause: ctrl &= (~E1000_CTRL_RFCE); ctrl |= E1000_CTRL_TFCE; break; case e1000_fc_full: ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); break; default: hw_dbg(hw, "Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; } ew32(CTRL, ctrl); return 0;}/** * e1000e_config_fc_after_link_up - Configures flow control after link * @hw: pointer to the HW structure * * Checks the status of auto-negotiation after link up to ensure that the * speed and duplex were not forced. If the link needed to be forced, then * flow control needs to be forced also. If auto-negotiation is enabled * and did not fail, then we configure flow control based on our link * partner. **/s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; s32 ret_val = 0; u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; u16 speed, duplex; /* Check for the case where we have fiber media and auto-neg failed * so we had to force link. In this case, we need to force the * configuration of the MAC to match the "fc" parameter. */ if (mac->autoneg_failed) { if (hw->media_type == e1000_media_type_fiber || hw->media_type == e1000_media_type_internal_serdes) ret_val = e1000e_force_mac_fc(hw); } else { if (hw->media_type == e1000_media_type_copper) ret_val = e1000e_force_mac_fc(hw); } if (ret_val) { hw_dbg(hw, "Error forcing flow control settings\n"); return ret_val; } /* Check for the case where we have copper media and auto-neg is * enabled. In this case, we need to check and see if Auto-Neg * has completed, and if so, how the PHY and link partner has * flow control configured. */ if ((hw->media_type == e1000_media_type_copper) && mac->autoneg) { /* Read the MII Status Register and check to see if AutoNeg * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg); if (ret_val) return ret_val; ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg); if (ret_val) return ret_val; if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { hw_dbg(hw, "Copper PHY and Auto Neg " "has not completed.\n"); return ret_val; } /* The AutoNeg process has completed, so we now need to * read both the Auto Negotiation Advertisement * Register (Address 4) and the Auto_Negotiation Base * Page Ability Register (Address 5) to determine how * flow control was negotiated. */ ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg); if (ret_val) return ret_val; ret_val = e1e_rphy(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); if (ret_val) return ret_val; /* Two bits in the Auto Negotiation Advertisement Register * (Address 4) and two bits in the Auto Negotiation Base * Page Ability Register (Address 5) determine flow control * for both the PHY and the link partner. The following * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, * 1999, describes these PAUSE resolution bits and how flow * control is determined based upon these settings. * NOTE: DC = Don't Care * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution *-------|---------|-------|---------|-------------------- * 0 | 0 | DC | DC | e1000_fc_none * 0 | 1 | 0 | DC | e1000_fc_none * 0 | 1 | 1 | 0 | e1000_fc_none * 0 | 1 | 1 | 1 | e1000_fc_tx_pause * 1 | 0 | 0 | DC | e1000_fc_none * 1 | DC | 1 | DC | e1000_fc_full * 1 | 1 | 0 | 0 | e1000_fc_none * 1 | 1 | 0 | 1 | e1000_fc_rx_pause * */ /* Are both PAUSE bits set to 1? If so, this implies * Symmetric Flow Control is enabled at both ends. The * ASM_DIR bits are irrelevant per the spec. * * For Symmetric Flow Control: * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | DC | 1 | DC | E1000_fc_full * */ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { /* Now we need to check if the user selected RX ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise RX * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ if (mac->original_fc == e1000_fc_full) { mac->fc = e1000_fc_full; hw_dbg(hw, "Flow Control = FULL.\r\n"); } else { mac->fc = e1000_fc_rx_pause; hw_dbg(hw, "Flow Control = " "RX PAUSE frames only.\r\n"); } } /* For receiving PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 0 | 1 | 1 | 1 | e1000_fc_tx_pause * */ else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { mac->fc = e1000_fc_tx_pause; hw_dbg(hw, "Flow Control = TX PAUSE frames only.\r\n"); } /* For transmitting PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | 1 | 0 | 1 | e1000_fc_rx_pause * */ else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { mac->fc = e1000_fc_rx_pause; hw_dbg(hw, "Flow Control = RX PAUSE frames only.\r\n"); } /* Per the IEEE spec, at this point flow control should be * disabled. However, we want to consider that we could * be connected to a legacy switch that doesn't advertise * desired flow control, but can be forced on the link * partner. So if we advertised no flow control, that is * what we will resolve to. If we advertised some kind of * receive capability (Rx Pause Only or Full Flow Control) * and the link partner advertised none, we will configure * ourselves to enable Rx Flow Control only. We can do * this safely for two reasons: If the link partner really * didn't want flow control enabled, and we enable Rx, no * harm done since we won't be receiving any PAUSE frames * anyway. If the intent on the link partner was to have * flow control enabled, then by us enabling RX only, we * can at least receive pause frames and process them. * This is a good idea because in most cases, since we are * predominantly a server NIC, more times than not we will * be asked to delay transmission of packets than asking * our link partner to pause transmission of frames. */ else if ((mac->original_fc == e1000_fc_none) || (mac->original_fc == e1000_fc_tx_pause)) { mac->fc = e1000_fc_none; hw_dbg(hw, "Flow Control = NONE.\r\n"); } else { mac->fc = e1000_fc_rx_pause; hw_dbg(hw, "Flow Control = RX PAUSE frames only.\r\n"); } /* Now we need to do one last check... If we auto- * negotiated to HALF DUPLEX, flow control should not be * enabled per IEEE 802.3 spec. */ ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); if (ret_val) { hw_dbg(hw, "Error getting link speed and duplex\n"); return ret_val; } if (duplex == HALF_DUPLEX) mac->fc = e1000_fc_none; /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ ret_val = e1000e_force_mac_fc(hw); if (ret_val) { hw_dbg(hw, "Error forcing flow control settings\n"); return ret_val; } } return 0;}/** * e1000e_get_speed_and_duplex_copper - Retreive current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * Read the status register for the current speed/duplex and store the current * speed and duplex for copper connections. **/s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex){ u32 status; status = er32(STATUS); if (status & E1000_STATUS_SPEED_1000) { *speed = SPEED_1000; hw_dbg(hw, "1000 Mbs, "); } else if (status & E1000_STATUS_SPEED_100) { *speed = SPEED_100; hw_dbg(hw, "100 Mbs, "); } else { *speed = SPEED_10; hw_dbg(hw, "10 Mbs, "); } if (status & E1000_STATUS_FD) { *duplex = FULL_DUPLEX; hw_dbg(hw, "Full Duplex\n"); } else { *duplex = HALF_DUPLEX; hw_dbg(hw, "Half Duplex\n"); } return 0;}/** * e1000e_get_speed_and_duplex_fiber_serdes - Retreive current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * Sets the speed and duplex to gigabit full duplex (the only possible option) * for fiber/serdes links. **/s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex){ *speed = SPEED_1000; *duplex = FULL_DUPLEX; return 0;}/** * e1000e_get_hw_semaphore - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM **/s32 e1000e_get_hw_semaphore(struct e1000_hw *hw){ u32 swsm; s32 timeout = hw->nvm.word_size + 1; s32 i = 0; /* Get the SW semaphore */ while (i < timeout) { swsm = er32(SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; udelay(50); i++; } if (i == timeout) { hw_dbg(hw, "Driver can't access device - SMBI bit is set.\n"); return -E1000_ERR_NVM; } /* 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); hw_dbg(hw, "Driver can't access the NVM\n"); return -E1000_ERR_NVM; } return 0;}/** * e1000e_put_hw_semaphore - Release hardware semaphore * @hw: pointer to the HW structure * * Release hardware semaphore used to access the PHY or NVM **/void e1000e_put_hw_semaphore(struct e1000_hw *hw){ u32 swsm; swsm = er32(SWSM); swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); ew32(SWSM, swsm);}/** * e1000e_get_auto_rd_done - Check for auto read completion * @hw: pointer to the HW structure * * Check EEPROM for Auto Read done bit. **/s32 e1000e_get_auto_rd_done(struct e1000_hw *hw){ s32 i = 0; while (i < AUTO_READ_DONE_TIMEOUT) { if (er32(EECD) & E1000_EECD_AUTO_RD) break; msleep(1); i++; } if (i == AUTO_READ_DONE_TIMEOUT) { hw_dbg(hw, "Auto read by HW from NVM has not completed.\n"); return -E1000_ERR_RESET; } return 0;}/** * e1000e_valid_led_default - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) * * Read the EEPROM for the current default LED configuration. If the * LED configuration is not valid, set to a valid LED configuration. **/s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data){ s32 ret_val; ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { hw_dbg(hw, "NVM Read Error\n"); return ret_val; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) *data = ID_LED_DEFAULT; return 0;}/** * e1000e_id_led_init - * @hw: pointer to the HW structure * **/s32 e1000e_id_led_init(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; s32 ret_val; const u32 ledctl_mask = 0x000000FF; const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; u16 data, i, temp; const u16 led_mask = 0x0F; ret_val = hw->nvm.ops.valid_led_default(hw, &data); if (ret_val) return ret_val; mac->ledctl_default = er32(LEDCTL); mac->ledctl_mode1 = mac->ledctl_default; mac->ledctl_mode2 = mac->ledctl_default; for (i = 0; i < 4; i++) { temp = (data >> (i << 2)) & led_mask; switch (temp) { case ID_LED_ON1_DEF2: case ID_LED_ON1_ON2: case ID_LED_ON1_OFF2: mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode1 |= ledctl_on << (i << 3); break; case ID_LED_OFF1_DEF2: case ID_LED_OFF1_ON2: case ID_LED_OFF1_OFF2: mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode1 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break; } switch (temp) { case ID_LED_DEF1_ON2: case ID_LED_ON1_ON2: case ID_LED_OFF1_ON2: mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode2 |= ledctl_on << (i << 3); break; case ID_LED_DEF1_OFF2: case ID_LED_ON1_OFF2: case ID_LED_OFF1_OFF2: mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode2 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break; } } return 0;}/** * e1000e_cleanup_led_generic - Set LED config to default operation * @hw: pointer to the HW structure * * Remove the current LED configuration and set the LED configuration * to the default value, saved from the EEPROM. **/s32 e1000e_cleanup_led_generic(struct e1000_hw *hw){ ew32(LEDCTL, hw->mac.ledctl_default); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?