⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 e1000_hw.c

📁 COPE the first practical network coding scheme which is developped on click
💻 C
📖 第 1 页 / 共 5 页
字号:
     * forced whenever speed are duplex are forced.     */    phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;    if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) {        DEBUGOUT("PHY Write Error\n");        return -E1000_ERR_PHY;    }    DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);        /* Need to reset the PHY or these changes will be ignored */    mii_ctrl_reg |= MII_CR_RESET;    if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) {        DEBUGOUT("PHY Write Error\n");        return -E1000_ERR_PHY;    }    usec_delay(1);    /* The wait_autoneg_complete flag may be a little misleading here.     * Since we are forcing speed and duplex, Auto-Neg is not enabled.     * But we do want to delay for a period while forcing only so we     * don't generate false No Link messages.  So we will wait here     * only if the user has set wait_autoneg_complete to 1, which is     * the default.     */    if(hw->wait_autoneg_complete) {        /* We will wait for autoneg to complete. */        DEBUGOUT("Waiting for forced speed/duplex link.\n");        mii_status_reg = 0;        /* We will wait for autoneg to complete or 4.5 seconds to expire. */        for(i = PHY_FORCE_TIME; i > 0; i--) {            /* Read the MII Status Register and wait for Auto-Neg Complete bit             * to be set.             */            if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {                DEBUGOUT("PHY Read Error\n");                return -E1000_ERR_PHY;            }            if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {                DEBUGOUT("PHY Read Error\n");                return -E1000_ERR_PHY;            }            if(mii_status_reg & MII_SR_LINK_STATUS) break;            msec_delay(100);        }        if(i == 0) { /* We didn't get link */            /* Reset the DSP and wait again for link. */                        ret_val = e1000_phy_reset_dsp(hw);            if(ret_val < 0) {                DEBUGOUT("Error Resetting PHY DSP\n");                return ret_val;            }        }        /* This loop will early-out if the link condition has been met.  */        for(i = PHY_FORCE_TIME; i > 0; i--) {            if(mii_status_reg & MII_SR_LINK_STATUS) break;            msec_delay(100);            /* Read the MII Status Register and wait for Auto-Neg Complete bit             * to be set.             */            if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {                DEBUGOUT("PHY Read Error\n");                return -E1000_ERR_PHY;            }            if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {                DEBUGOUT("PHY Read Error\n");                return -E1000_ERR_PHY;            }        }    }        /* Because we reset the PHY above, we need to re-force TX_CLK in the     * Extended PHY Specific Control Register to 25MHz clock.  This value     * defaults back to a 2.5MHz clock when the PHY is reset.     */    if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) {        DEBUGOUT("PHY Read Error\n");        return -E1000_ERR_PHY;    }    phy_data |= M88E1000_EPSCR_TX_CLK_25;    if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) {        DEBUGOUT("PHY Write Error\n");        return -E1000_ERR_PHY;    }    /* In addition, because of the s/w reset above, we need to enable CRS on     * TX.  This must be set for both full and 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(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) {        DEBUGOUT("PHY Write Error\n");        return -E1000_ERR_PHY;    }    return 0;}/******************************************************************************* Sets the collision distance in the Transmit Control register** hw - Struct containing variables accessed by shared code** Link should have been established previously. Reads the speed and duplex* information from the Device Status register.******************************************************************************/voide1000_config_collision_dist(struct e1000_hw *hw){    uint32_t tctl;    tctl = E1000_READ_REG(hw, TCTL);    tctl &= ~E1000_TCTL_COLD;    tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;    E1000_WRITE_REG(hw, TCTL, tctl);    E1000_WRITE_FLUSH(hw);}/******************************************************************************* Sets MAC speed and duplex settings to reflect the those in the PHY** hw - Struct containing variables accessed by shared code* mii_reg - data to write to the MII control register** The contents of the PHY register containing the needed information need to* be passed in.******************************************************************************/static int32_te1000_config_mac_to_phy(struct e1000_hw *hw){    uint32_t ctrl;    uint16_t phy_data;    DEBUGFUNC("e1000_config_mac_to_phy");    /* Read the Device Control Register and set the bits to Force Speed     * and Duplex.     */    ctrl = E1000_READ_REG(hw, 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.     */    if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) {        DEBUGOUT("PHY Read Error\n");        return -E1000_ERR_PHY;    }    if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD;    else ctrl &= ~E1000_CTRL_FD;    e1000_config_collision_dist(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;    /* Write the configured values back to the Device Control Reg. */    E1000_WRITE_REG(hw, CTRL, ctrl);    return 0;}/****************************************************************************** * Forces the MAC's flow control settings. *  * hw - Struct containing variables accessed by shared code * * Sets the TFCE and RFCE bits in the device control register to reflect * the adapter settings. TFCE and RFCE need to be explicitly set by * software when a Copper PHY is used because autonegotiation is managed * by the PHY rather than the MAC. Software must also configure these * bits when link is forced on a fiber connection. *****************************************************************************/static int32_te1000_force_mac_fc(struct e1000_hw *hw){    uint32_t ctrl;    DEBUGFUNC("e1000_force_mac_fc");    /* Get the current configuration of the Device Control Register */    ctrl = E1000_READ_REG(hw, CTRL);    /* Because we didn't get link via the internal auto-negotiation     * mechanism (we either forced link or we got link via PHY     * auto-neg), we have to manually enable/disable transmit an     * receive flow control.     *     * The "Case" statement below enables/disable flow control     * according to the "hw->fc" parameter.     *     * 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     *          frames but we do not receive pause frames).     *      3:  Both Rx and TX flow control (symmetric) is enabled.     *  other:  No other values should be possible at this point.     */    switch (hw->fc) {    case e1000_fc_none:        ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));        break;    case e1000_fc_rx_pause:        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:        DEBUGOUT("Flow control param set incorrectly\n");        return -E1000_ERR_CONFIG;    }    /* Disable TX Flow Control for 82542 (rev 2.0) */    if(hw->mac_type == e1000_82542_rev2_0)        ctrl &= (~E1000_CTRL_TFCE);    E1000_WRITE_REG(hw, CTRL, ctrl);    return 0;}/****************************************************************************** * Configures flow control settings after link is established *  * hw - Struct containing variables accessed by shared code * * Should be called immediately after a valid link has been established. * Forces MAC flow control settings if link was forced. When in MII/GMII mode * and autonegotiation is enabled, the MAC flow control settings will be set * based on the flow control negotiated by the PHY. In TBI mode, the TFCE * and RFCE bits will be automaticaly set to the negotiated flow control mode. *****************************************************************************/int32_te1000_config_fc_after_link_up(struct e1000_hw *hw){    int32_t ret_val;    uint16_t mii_status_reg;    uint16_t mii_nway_adv_reg;    uint16_t mii_nway_lp_ability_reg;    uint16_t speed;    uint16_t duplex;    DEBUGFUNC("e1000_config_fc_after_link_up");    /* 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(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) ||       ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) {        ret_val = e1000_force_mac_fc(hw);        if(ret_val < 0) {            DEBUGOUT("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) && hw->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.         */        if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {            DEBUGOUT("PHY Read Error \n");            return -E1000_ERR_PHY;        }        if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {            DEBUGOUT("PHY Read Error \n");            return -E1000_ERR_PHY;        }        if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {            /* 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.             */            if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg) < 0) {                DEBUGOUT("PHY Read Error\n");                return -E1000_ERR_PHY;            }            if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg) < 0) {                DEBUGOUT("PHY Read Error\n");                return -E1000_ERR_PHY;            }            /* 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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -