📄 e1000_hw.c
字号:
*-------|---------|-------|---------|-------------------- * 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(hw->original_fc == e1000_fc_full) { hw->fc = e1000_fc_full; DEBUGOUT("Flow Control = FULL.\r\n"); } else { hw->fc = e1000_fc_rx_pause; DEBUGOUT("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)) { hw->fc = e1000_fc_tx_pause; DEBUGOUT("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)) { hw->fc = e1000_fc_rx_pause; DEBUGOUT("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(hw->original_fc == e1000_fc_none || hw->original_fc == e1000_fc_tx_pause) { hw->fc = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\r\n"); } else { hw->fc = e1000_fc_rx_pause; DEBUGOUT("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. */ e1000_get_speed_and_duplex(hw, &speed, &duplex); if(duplex == HALF_DUPLEX) hw->fc = e1000_fc_none; /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ ret_val = e1000_force_mac_fc(hw); if(ret_val < 0) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } } else { DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n"); } } return 0;}/****************************************************************************** * Checks to see if the link status of the hardware has changed. * * hw - Struct containing variables accessed by shared code * * Called by any function that needs to check the link status of the adapter. *****************************************************************************/int32_te1000_check_for_link(struct e1000_hw *hw){ uint32_t rxcw; uint32_t ctrl; uint32_t status; uint32_t rctl; uint32_t signal; int32_t ret_val; uint16_t phy_data; uint16_t lp_capability; DEBUGFUNC("e1000_check_for_link"); /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be * set when the optics detect a signal. On older adapters, it will be * cleared when there is a signal */ if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1; else signal = 0; ctrl = E1000_READ_REG(hw, CTRL); status = E1000_READ_REG(hw, STATUS); rxcw = E1000_READ_REG(hw, RXCW); /* If we have a copper PHY then we only want to go out to the PHY * registers to see if Auto-Neg has completed and/or if our link * status has changed. The get_link_status flag will be set if we * receive a Link Status Change interrupt or we have Rx Sequence * Errors. */ if((hw->media_type == e1000_media_type_copper) && hw->get_link_status) { /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. * Read the register twice since the link bit is sticky. */ if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } if(phy_data & MII_SR_LINK_STATUS) { hw->get_link_status = FALSE; } else { /* No link detected */ return 0; } /* If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ if(!hw->autoneg) return -E1000_ERR_CONFIG; /* 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(hw->mac_type >= e1000_82544) e1000_config_collision_dist(hw); else { ret_val = e1000_config_mac_to_phy(hw); if(ret_val < 0) { DEBUGOUT("Error configuring MAC to PHY settings\n"); return ret_val; } } /* 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(hw); if(ret_val < 0) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } /* At this point we know that we are on copper and we have * auto-negotiated link. These are conditions for checking the link * parter capability register. We use the link partner capability to * determine if TBI Compatibility needs to be turned on or off. If * the link partner advertises any speed in addition to Gigabit, then * we assume that they are GMII-based, and TBI compatibility is not * needed. If no other speeds are advertised, we assume the link * partner is TBI-based, and we turn on TBI Compatibility. */ if(hw->tbi_compatibility_en) { if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &lp_capability) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } if(lp_capability & (NWAY_LPAR_10T_HD_CAPS | NWAY_LPAR_10T_FD_CAPS | NWAY_LPAR_100TX_HD_CAPS | NWAY_LPAR_100TX_FD_CAPS | NWAY_LPAR_100T4_CAPS)) { /* If our link partner advertises anything in addition to * gigabit, we do not need to enable TBI compatibility. */ if(hw->tbi_compatibility_on) { /* If we previously were in the mode, turn it off. */ rctl = E1000_READ_REG(hw, RCTL); rctl &= ~E1000_RCTL_SBP; E1000_WRITE_REG(hw, RCTL, rctl); hw->tbi_compatibility_on = FALSE; } } 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(!hw->tbi_compatibility_on) { hw->tbi_compatibility_on = TRUE; rctl = E1000_READ_REG(hw, RCTL); rctl |= E1000_RCTL_SBP; E1000_WRITE_REG(hw, RCTL, rctl); } } } } /* 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. */ else if((hw->media_type == e1000_media_type_fiber) && (!(status & E1000_STATUS_LU)) && ((ctrl & E1000_CTRL_SWDPIN1) == signal) && (!(rxcw & E1000_RXCW_C))) { if(hw->autoneg_failed == 0) { hw->autoneg_failed = 1; return 0; } DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); /* Disable auto-negotiation in the TXCW register */ E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE)); /* Force link-up and also force full-duplex. */ ctrl = E1000_READ_REG(hw, CTRL); ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); E1000_WRITE_REG(hw, CTRL, ctrl); /* Configure Flow Control after forcing link up. */ ret_val = e1000_config_fc_after_link_up(hw); if(ret_val < 0) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } } /* 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. */ else if((hw->media_type == e1000_media_type_fiber) && (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n"); E1000_WRITE_REG(hw, TXCW, hw->txcw); E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); } return 0;}/****************************************************************************** * Detects the current speed and duplex settings of the hardware. * * hw - Struct containing variables accessed by shared code * speed - Speed of the connection * duplex - Duplex setting of the connection *****************************************************************************/voide1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed, uint16_t *duplex){ uint32_t status; DEBUGFUNC("e1000_get_speed_and_duplex"); if(hw->mac_type >= e1000_82543) { status = E1000_READ_REG(hw, STATUS); if(status & E1000_STATUS_SPEED_1000) { *speed = SPEED_1000; DEBUGOUT("1000 Mbs, "); } else if(status & E1000_STATUS_SPEED_100) { *speed = SPEED_100; DEBUGOUT("100 Mbs, "); } else { *speed = SPEED_10; DEBUGOUT("10 Mbs, "); } if(status & E1000_STATUS_FD) { *duplex = FULL_DUPLEX; DEBUGOUT("Full Duplex\r\n"); } else { *duplex = HALF_DUPLEX; DEBUGOUT(" Half Duplex\r\n"); } } else { DEBUGOUT("1000 Mbs, Full Duplex\r\n"); *speed = SPEED_1000; *duplex = FULL_DUPLEX; }}/******************************************************************************* Blocks until autoneg completes or times out (~4.5 seconds)** hw - Struct containing variables accessed by shared code******************************************************************************/int32_te1000_wait_autoneg(struct e
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -