📄 e1000.c
字号:
#endif if (hw->mac_type >= e1000_82543) { status = E1000_READ_REG(hw, STATUS); bus_type = (status & E1000_STATUS_PCIX_MODE) ? e1000_bus_type_pcix : e1000_bus_type_pci; } /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ if (bus_type == e1000_bus_type_pcix) { pci_read_config_word(hw->pdev, PCIX_COMMAND_REGISTER, &pcix_cmd_word); pci_read_config_word(hw->pdev, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> PCIX_COMMAND_MMRBC_SHIFT; stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> PCIX_STATUS_HI_MMRBC_SHIFT; if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; if (cmd_mmrbc > stat_mmrbc) { pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; pci_write_config_word(hw->pdev, PCIX_COMMAND_REGISTER, pcix_cmd_word); } } /* Call a subroutine to configure the link and setup flow control. */ ret_val = e1000_setup_link(nic); /* Set the transmit descriptor write-back policy */ if (hw->mac_type > e1000_82544) { ctrl = E1000_READ_REG(hw, TXDCTL); ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; E1000_WRITE_REG(hw, TXDCTL, ctrl); }#if 0 /* 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(hw);#endif return ret_val;}/****************************************************************************** * Configures flow control and link settings. * * hw - Struct containing variables accessed by shared code * * 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 eth_device *nic){ struct e1000_hw *hw = nic->priv; uint32_t ctrl_ext; int32_t ret_val; uint16_t eeprom_data; DEBUGFUNC(); /* 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, &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 ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1)) hw->fc &= (~e1000_fc_rx_pause); hw->original_fc = hw->fc; DEBUGOUT("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_fiber) ? e1000_setup_fiber_link(nic) : e1000_setup_copper_link(nic); 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); E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time); /* 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 (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); } } return ret_val;}/****************************************************************************** * Sets up link for a fiber 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_link(struct eth_device *nic){ struct e1000_hw *hw = nic->priv; uint32_t ctrl; uint32_t status; uint32_t txcw = 0; uint32_t i; uint32_t signal; int32_t ret_val; DEBUGFUNC(); /* 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 */ ctrl = E1000_READ_REG(hw, CTRL); if ((hw->mac_type > e1000_82544) && !(ctrl & E1000_CTRL_ILOS)) signal = E1000_CTRL_SWDPIN1; else signal = 0; printf("signal for %s is %x (ctrl %08x)!!!!\n", nic->name, signal, ctrl); /* Take the link out of reset */ ctrl &= ~(E1000_CTRL_LRST); 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 (%#x)\n", txcw); 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). */ if ((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)) { /* 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. */ DEBUGOUT("Never got a valid link from auto-neg!!!\n"); hw->autoneg_failed = 1; ret_val = e1000_check_for_link(nic); if (ret_val < 0) { 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_ERR_NOLINK; } return 0;}/******************************************************************************* Detects which PHY is present and the speed and duplex** hw - Struct containing variables accessed by shared code******************************************************************************/static inte1000_setup_copper_link(struct eth_device *nic){ struct e1000_hw *hw = nic->priv; uint32_t ctrl; int32_t ret_val; uint16_t i; uint16_t phy_data; DEBUGFUNC(); 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 */ ret_val = e1000_detect_gig_phy(hw); if (ret_val < 0) { DEBUGOUT("Error, did not detect valid phy.\n"); return ret_val; } DEBUGOUT("Phy ID = %x \n", hw->phy_id); /* Enable CRS on TX. This must be set for half-duplex operation. */ if (e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;#if 0 /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode * 2 - MDI-X mode * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) */ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; switch (hw->mdix) { case 1: phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; break; case 2: phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; break; case 3: phy_data |= M88E1000_PSCR_AUTO_X_1000T; break; case 0: default: phy_data |= M88E1000_PSCR_AUTO_X_MODE; break; }#else phy_data |= M88E1000_PSCR_AUTO_X_MODE;#endif#if 0 /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled * 1 - Enabled */ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; if (hw->disable_polarity_correction == 1) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;#else phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;#endif if (e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { DEBUGOUT("PHY Write Error\n"); return -E1000_ERR_PHY; } /* Force TX_CLK in the Extended PHY Specific Control Register * to 25MHz clock. */ if (e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -