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

📄 e1000_hw.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);    ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);        if(ret_val)        return ret_val;    return E1000_SUCCESS;}/******************************************************************************* Force PHY speed and duplex settings to hw->forced_speed_duplex** hw - Struct containing variables accessed by shared code******************************************************************************/static int32_te1000_phy_force_speed_duplex(struct e1000_hw *hw){    uint32_t ctrl;    int32_t ret_val;    uint16_t mii_ctrl_reg;    uint16_t mii_status_reg;    uint16_t phy_data;    uint16_t i;    DEBUGFUNC("e1000_phy_force_speed_duplex");    /* Turn off Flow control if we are forcing speed and duplex. */    hw->fc = e1000_fc_none;    DEBUGOUT1("hw->fc = %d\n", hw->fc);    /* Read the Device Control Register. */    ctrl = E1000_READ_REG(hw, CTRL);    /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */    ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);    ctrl &= ~(DEVICE_SPEED_MASK);    /* Clear the Auto Speed Detect Enable bit. */    ctrl &= ~E1000_CTRL_ASDE;    /* Read the MII Control Register. */    ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg);    if(ret_val)        return ret_val;    /* We need to disable autoneg in order to force link and duplex. */    mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;    /* Are we forcing Full or Half Duplex? */    if(hw->forced_speed_duplex == e1000_100_full ||       hw->forced_speed_duplex == e1000_10_full) {        /* We want to force full duplex so we SET the full duplex bits in the         * Device and MII Control Registers.         */        ctrl |= E1000_CTRL_FD;        mii_ctrl_reg |= MII_CR_FULL_DUPLEX;        DEBUGOUT("Full Duplex\n");    } else {        /* We want to force half duplex so we CLEAR the full duplex bits in         * the Device and MII Control Registers.         */        ctrl &= ~E1000_CTRL_FD;        mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;        DEBUGOUT("Half Duplex\n");    }    /* Are we forcing 100Mbps??? */    if(hw->forced_speed_duplex == e1000_100_full ||       hw->forced_speed_duplex == e1000_100_half) {        /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */        ctrl |= E1000_CTRL_SPD_100;        mii_ctrl_reg |= MII_CR_SPEED_100;        mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);        DEBUGOUT("Forcing 100mb ");    } else {        /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */        ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);        mii_ctrl_reg |= MII_CR_SPEED_10;        mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);        DEBUGOUT("Forcing 10mb ");    }    e1000_config_collision_dist(hw);    /* Write the configured values back to the Device Control Reg. */    E1000_WRITE_REG(hw, CTRL, ctrl);    if (hw->phy_type == e1000_phy_m88) {        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);        if(ret_val)            return ret_val;        /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI         * forced whenever speed are duplex are forced.         */        phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;        ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);        if(ret_val)            return ret_val;        DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);        /* Need to reset the PHY or these changes will be ignored */        mii_ctrl_reg |= MII_CR_RESET;    } else {        /* Clear Auto-Crossover to force MDI manually.  IGP requires MDI         * forced whenever speed or duplex are forced.         */        ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);        if(ret_val)            return ret_val;        phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;        phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;        ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);        if(ret_val)            return ret_val;    }    /* Write back the modified PHY MII control register. */    ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);    if(ret_val)        return ret_val;    udelay(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.             */            ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);            if(ret_val)                return ret_val;            ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);            if(ret_val)                return ret_val;            if(mii_status_reg & MII_SR_LINK_STATUS) break;            msec_delay(100);        }        if((i == 0) && (hw->phy_type == e1000_phy_m88)) {            /* We didn't get link.  Reset the DSP and wait again for link. */            ret_val = e1000_phy_reset_dsp(hw);            if(ret_val) {                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.             */            ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);            if(ret_val)                return ret_val;            ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);            if(ret_val)                return ret_val;        }    }    if (hw->phy_type == e1000_phy_m88) {        /* 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.         */        ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);        if(ret_val)            return ret_val;        phy_data |= M88E1000_EPSCR_TX_CLK_25;        ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);        if(ret_val)            return ret_val;        /* 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.         */        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);        if(ret_val)            return ret_val;        phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;        ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);        if(ret_val)            return ret_val;        if((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&           (!hw->autoneg) &&           (hw->forced_speed_duplex == e1000_10_full ||            hw->forced_speed_duplex == e1000_10_half)) {            ret_val = e1000_polarity_reversal_workaround(hw);            if(ret_val)                return ret_val;        }    }    return E1000_SUCCESS;}/******************************************************************************* 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;    DEBUGFUNC("e1000_config_collision_dist");    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;    int32_t ret_val;    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 (hw->phy_type == e1000_phy_igp) {        ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,                                     &phy_data);        if(ret_val)            return ret_val;        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 {        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,                                     &phy_data);        if(ret_val)            return ret_val;        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 E1000_SUCCESS;}/****************************************************************************** * 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. *****************************************************************************/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 rec

⌨️ 快捷键说明

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