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

📄 e1000_hw.c

📁 COPE the first practical network coding scheme which is developped on click
💻 C
📖 第 1 页 / 共 5 页
字号:
             *-------|---------|-------|---------|--------------------             *   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 + -