📄 e1000.c
字号:
* * Determines which flow control settings to use. Calls the apropriate media- * specific link configuration function. Configures the flow control settings. * Assuming the adapter has a valid link partner, a valid link should be * established. Assumes the hardware has previously been reset and the * transmitter and receiver are not enabled. *****************************************************************************/static inte1000_setup_link(struct e1000_hw *hw){ uint32_t ctrl_ext; int32_t ret_val; uint16_t eeprom_data; DEBUGFUNC("e1000_setup_link"); /* Read and store word 0x0F of the EEPROM. This word contains bits * that determine the hardware's default PAUSE (flow control) mode, * a bit that determines whether the HW defaults to enabling or * disabling auto-negotiation, and the direction of the * SW defined pins. If there is no SW over-ride of the flow * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } if(hw->fc == e1000_fc_default) { if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) hw->fc = e1000_fc_none; else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == EEPROM_WORD0F_ASM_DIR) hw->fc = e1000_fc_tx_pause; else hw->fc = e1000_fc_full; } /* We want to save off the original Flow Control configuration just * in case we get disconnected and then reconnected into a different * hub or switch with different Flow Control capabilities. */ if(hw->mac_type == e1000_82542_rev2_0) hw->fc &= (~e1000_fc_tx_pause);#if 0 /* See e1000_sw_init() of the Linux driver */ if((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))#else if((hw->mac_type < e1000_82543) && (hw->mac_type >= e1000_82543))#endif hw->fc &= (~e1000_fc_rx_pause); #if 0 hw->original_fc = hw->fc;#endif DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc); /* Take the 4 bits from EEPROM word 0x0F that determine the initial * polarity value for the SW controlled pins, and setup the * Extended Device Control reg with that info. * This is needed because one of the SW controlled pins is used for * signal detection. So this should be done before e1000_setup_pcs_link() * or e1000_phy_setup() is called. */ if(hw->mac_type == e1000_82543) { ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << SWDPIO__EXT_SHIFT); E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); } /* Call the necessary subroutine to configure the link. */ ret_val = (hw->media_type == e1000_media_type_copper) ? e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw); if (ret_val < 0) { return ret_val; } /* Initialize the flow control address, type, and PAUSE timer * registers to their default values. This is done even if flow * control is disabled, because it does not hurt anything to * initialize these registers. */ DEBUGOUT("Initializing the Flow Control address, type and timer regs\n"); E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH); E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);#if 0 E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);#else E1000_WRITE_REG(hw, FCTTV, FC_DEFAULT_TX_TIMER);#endif /* Set the flow control receive threshold registers. Normally, * these registers will be set to a default threshold that may be * adjusted later by the driver's runtime code. However, if the * ability to transmit pause frames in not enabled, then these * registers will be set to 0. */ if(!(hw->fc & e1000_fc_tx_pause)) { E1000_WRITE_REG(hw, FCRTL, 0); E1000_WRITE_REG(hw, FCRTH, 0); } else { /* We need to set up the Receive Threshold high and low water marks * as well as (optionally) enabling the transmission of XON frames. */#if 0 if(hw->fc_send_xon) { E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE)); E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); } else { E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water); E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); }#else E1000_WRITE_REG(hw, FCRTL, (FC_DEFAULT_LO_THRESH | E1000_FCRTL_XONE)); E1000_WRITE_REG(hw, FCRTH, FC_DEFAULT_HI_THRESH);#endif } return ret_val;}/****************************************************************************** * Sets up link for a fiber based or serdes based adapter * * hw - Struct containing variables accessed by shared code * * Manipulates Physical Coding Sublayer functions in order to configure * link. Assumes the hardware has been previously reset and the transmitter * and receiver are not enabled. *****************************************************************************/static inte1000_setup_fiber_serdes_link(struct e1000_hw *hw){ uint32_t ctrl; uint32_t status; uint32_t txcw = 0; uint32_t i; uint32_t signal = 0; int32_t ret_val; DEBUGFUNC("e1000_setup_fiber_serdes_link"); /* On adapters with a MAC newer than 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. This applies to fiber media only. * If we're on serdes media, adjust the output amplitude to value set in * the EEPROM. */ ctrl = E1000_READ_REG(hw, CTRL); if(hw->media_type == e1000_media_type_fiber) signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; if((ret_val = e1000_adjust_serdes_amplitude(hw))) return ret_val; /* Take the link out of reset */ ctrl &= ~(E1000_CTRL_LRST);#if 0 /* Adjust VCO speed to improve BER performance */ if((ret_val = e1000_set_vco_speed(hw))) return ret_val;#endif e1000_config_collision_dist(hw); /* Check for a software override of the flow control settings, and setup * the device accordingly. If auto-negotiation is enabled, then software * will have to set the "PAUSE" bits to the correct value in the Tranmsit * Config Word Register (TXCW) and re-start auto-negotiation. However, if * auto-negotiation is disabled, then software will have to manually * configure the two flow control enable bits in the CTRL register. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, but * not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but we do * not support receiving pause frames). * 3: Both Rx and TX flow control (symmetric) are enabled. */ switch (hw->fc) { case e1000_fc_none: /* Flow control is completely disabled by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); break; case e1000_fc_rx_pause: /* RX Flow control is enabled and TX Flow control is disabled by a * software over-ride. Since there really isn't a way to advertise * that we are capable of RX Pause ONLY, we will advertise that we * support both symmetric and asymmetric RX PAUSE. Later, we will * disable the adapter's ability to send PAUSE frames. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; case e1000_fc_tx_pause: /* TX Flow control is enabled, and RX Flow control is disabled, by a * software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); break; case e1000_fc_full: /* Flow control (both RX and TX) is enabled by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; default: DEBUGOUT("Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; break; } /* Since auto-negotiation is enabled, take the link out of reset (the link * will be in reset, because we previously reset the chip). This will * restart auto-negotiation. If auto-neogtiation is successful then the * link-up status bit will be set and the flow control enable bits (RFCE * and TFCE) will be set according to their negotiated value. */ DEBUGOUT("Auto-negotiation enabled\n"); E1000_WRITE_REG(hw, TXCW, txcw); E1000_WRITE_REG(hw, CTRL, ctrl); E1000_WRITE_FLUSH(hw); hw->txcw = txcw; mdelay(1); /* If we have a signal (the cable is plugged in) then poll for a "Link-Up" * indication in the Device Status Register. Time-out if a link isn't * seen in 500 milliseconds seconds (Auto-negotiation should complete in * less than 500 milliseconds even if the other end is doing it in SW). * For internal serdes, we just assume a signal is present, then poll. */ if(hw->media_type == e1000_media_type_internal_serdes || (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { DEBUGOUT("Looking for Link\n"); for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { mdelay(10); status = E1000_READ_REG(hw, STATUS); if(status & E1000_STATUS_LU) break; } if(i == (LINK_UP_TIMEOUT / 10)) { DEBUGOUT("Never got a valid link from auto-neg!!!\n"); hw->autoneg_failed = 1; /* AutoNeg failed to achieve a link, so we'll call * e1000_check_for_link. This routine will force the link up if * we detect a signal. This will allow us to communicate with * non-autonegotiating link partners. */ if((ret_val = e1000_check_for_link(hw))) { DEBUGOUT("Error while checking for link\n"); return ret_val; } hw->autoneg_failed = 0; } else { hw->autoneg_failed = 0; DEBUGOUT("Valid Link Found\n"); } } else { DEBUGOUT("No Signal Detected\n"); } return E1000_SUCCESS;}/******************************************************************************* Detects which PHY is present and the speed and duplex** hw - Struct containing variables accessed by shared code******************************************************************************/static inte1000_setup_copper_link(struct e1000_hw *hw){ uint32_t ctrl; int32_t ret_val; uint16_t i; uint16_t phy_data; DEBUGFUNC("e1000_setup_copper_link"); ctrl = E1000_READ_REG(hw, CTRL); /* With 82543, we need to force speed and duplex on the MAC equal to what * the PHY speed and duplex configuration is. In addition, we need to * perform a hardware reset on the PHY to take it out of reset. */ if(hw->mac_type > e1000_82543) { ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, CTRL, ctrl); } else { ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); E1000_WRITE_REG(hw, CTRL, ctrl); e1000_phy_hw_reset(hw); } /* Make sure we have a valid PHY */ if((ret_val = e1000_detect_gig_phy(hw))) { DEBUGOUT("Error, did not detect valid phy.\n"); return ret_val; } DEBUGOUT1("Phy ID = %x \n", hw->phy_id); if(hw->mac_type <= e1000_82543 || hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||#if 0 hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) hw->phy_reset_disable = FALSE; if(!hw->phy_reset_disable) {#else hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {#endif if (hw->phy_type == e1000_phy_igp) { if((ret_val = e1000_phy_reset(hw))) { DEBUGOUT("Error Resetting the PHY\n"); return ret_val; } /* Wait 10ms for MAC to configure PHY from eeprom settings */ mdelay(15);#if 0 /* disable lplu d3 during driver init */ if((ret_val = e1000_set_d3_lplu_state(hw, FALSE))) { DEBUGOUT("Error Disabling LPLU D3\n"); return ret_val; } /* Configure mdi-mdix settings */ if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data))) return ret_val; if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { hw->dsp_config_state = e1000_dsp_config_disabled; /* Force MDI for IGP B-0 PHY */ phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | IGP01E1000_PSCR_FORCE_MDI_MDIX); hw->mdix = 1; } else { hw->dsp_config_state = e1000_dsp_config_enabled; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; switch (hw->mdix) { case 1: phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; break; case 2: phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; break; case 0: default: phy_data |= IGP01E1000_PSCR_AUTO_MDIX; break; } } if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data))) return ret_val; /* set auto-master slave resolution settings */ e1000_ms_type phy_ms_setting = hw->master_slave; if(hw->ffe_config_state == e1000_ffe_config_active) hw->ffe_config_state = e1000_ffe_config_enabled; if(hw->dsp_config_state == e1000_dsp_config_activated) hw->dsp_config_state = e1000_dsp_config_enabled;#endif /* when autonegotiation advertisment is only 1000Mbps then we * should disable SmartSpeed and enable Auto MasterSlave * resolution as hardware default. */ if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { /* Disable SmartSpeed */ if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data))) return ret_val; phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data))) return ret_val; /* Set auto Master/Slave resolution process */ if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data))) return ret_val; phy_data &= ~CR_1000T_MS_ENABLE; if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data))) return ret_val; } if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data))) return ret_val;#if 0 /* load defaults for future use */ hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? ((phy_data & CR_1000T_MS_VALUE) ? e1000_ms_force_master : e1000_ms_force_slave) : e1000_ms_auto; switch (phy_ms_setting) { case e1000_ms_force_master: phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); break; case e1000_ms_force_slave: phy_data |= CR_1000T_MS_ENABLE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -