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

📄 e1000_hw.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
        if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) {            DEBUGOUT("PHY Read Error\n");            return -E1000_ERR_PHY;        }        if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) 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 & IGP01E1000_PSSR_SPEED_MASK) ==           IGP01E1000_PSSR_SPEED_1000MBPS)            ctrl |= E1000_CTRL_SPD_1000;        else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==                IGP01E1000_PSSR_SPEED_100MBPS)            ctrl |= E1000_CTRL_SPD_100;    } else {        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             *-------|---------|-------|---------|--------------------             *   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);

⌨️ 快捷键说明

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