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

📄 e1000_hw.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
    if(hw->phy_type == e1000_phy_igp) {        ret_val = e1000_config_dsp_after_link_change(hw, TRUE);        if(ret_val) {            DEBUGOUT("Error Configuring DSP after link up\n");            return ret_val;        }    }                    return E1000_SUCCESS;}/******************************************************************************* Detects which PHY is present and setup the speed and duplex** hw - Struct containing variables accessed by shared code******************************************************************************/static int32_te1000_setup_copper_link(struct e1000_hw *hw){    int32_t ret_val;    uint16_t i;    uint16_t phy_data;    DEBUGFUNC("e1000_setup_copper_link");    /* Check if it is a valid PHY and set PHY mode if necessary. */    ret_val = e1000_copper_link_preconfig(hw);    if(ret_val)        return ret_val;    if (hw->phy_type == e1000_phy_igp ||        hw->phy_type == e1000_phy_igp_2) {        ret_val = e1000_copper_link_igp_setup(hw);        if(ret_val)            return ret_val;    } else if (hw->phy_type == e1000_phy_m88) {        ret_val = e1000_copper_link_mgp_setup(hw);        if(ret_val)            return ret_val;    }    if(hw->autoneg) {        /* Setup autoneg and flow control advertisement           * and perform autonegotiation */           ret_val = e1000_copper_link_autoneg(hw);        if(ret_val)            return ret_val;               } else {        /* PHY will be set to 10H, 10F, 100H,or 100F          * depending on value from forced_speed_duplex. */        DEBUGOUT("Forcing speed and duplex\n");        ret_val = e1000_phy_force_speed_duplex(hw);        if(ret_val) {            DEBUGOUT("Error Forcing Speed and Duplex\n");            return ret_val;        }    }    /* Check link status. Wait up to 100 microseconds for link to become     * valid.     */    for(i = 0; i < 10; i++) {        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);        if(ret_val)            return ret_val;        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);        if(ret_val)            return ret_val;        if(phy_data & MII_SR_LINK_STATUS) {            /* Config the MAC and PHY after link is up */            ret_val = e1000_copper_link_postconfig(hw);            if(ret_val)                return ret_val;                        DEBUGOUT("Valid link established!!!\n");            return E1000_SUCCESS;        }        udelay(10);    }    DEBUGOUT("Unable to establish link!!!\n");    return E1000_SUCCESS;}/******************************************************************************* Configures PHY autoneg and flow control advertisement settings** hw - Struct containing variables accessed by shared code******************************************************************************/int32_te1000_phy_setup_autoneg(struct e1000_hw *hw){    int32_t ret_val;    uint16_t mii_autoneg_adv_reg;    uint16_t mii_1000t_ctrl_reg;    DEBUGFUNC("e1000_phy_setup_autoneg");    /* Read the MII Auto-Neg Advertisement Register (Address 4). */    ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);    if(ret_val)        return ret_val;        /* Read the MII 1000Base-T Control Register (Address 9). */        ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);        if(ret_val)            return ret_val;    /* Need to parse both autoneg_advertised and fc and set up     * the appropriate PHY registers.  First we will parse for     * autoneg_advertised software override.  Since we can advertise     * a plethora of combinations, we need to check each bit     * individually.     */    /* First we clear all the 10/100 mb speed bits in the Auto-Neg     * Advertisement Register (Address 4) and the 1000 mb speed bits in     * the  1000Base-T Control Register (Address 9).     */    mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;    mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;    DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised);    /* Do we want to advertise 10 Mb Half Duplex? */    if(hw->autoneg_advertised & ADVERTISE_10_HALF) {        DEBUGOUT("Advertise 10mb Half duplex\n");        mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;    }    /* Do we want to advertise 10 Mb Full Duplex? */    if(hw->autoneg_advertised & ADVERTISE_10_FULL) {        DEBUGOUT("Advertise 10mb Full duplex\n");        mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;    }    /* Do we want to advertise 100 Mb Half Duplex? */    if(hw->autoneg_advertised & ADVERTISE_100_HALF) {        DEBUGOUT("Advertise 100mb Half duplex\n");        mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;    }    /* Do we want to advertise 100 Mb Full Duplex? */    if(hw->autoneg_advertised & ADVERTISE_100_FULL) {        DEBUGOUT("Advertise 100mb Full duplex\n");        mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;    }    /* We do not allow the Phy to advertise 1000 Mb Half Duplex */    if(hw->autoneg_advertised & ADVERTISE_1000_HALF) {        DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n");    }    /* Do we want to advertise 1000 Mb Full Duplex? */    if(hw->autoneg_advertised & ADVERTISE_1000_FULL) {        DEBUGOUT("Advertise 1000mb Full duplex\n");        mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;    }    /* Check for a software override of the flow control settings, and     * setup the PHY advertisement registers accordingly.  If     * auto-negotiation is enabled, then software will have to set the     * "PAUSE" bits to the correct value in the Auto-Negotiation     * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.     *     * 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.     *  other:  No software override.  The flow control configuration     *          in the EEPROM is used.     */    switch (hw->fc) {    case e1000_fc_none: /* 0 */        /* Flow control (RX & TX) is completely disabled by a         * software over-ride.         */        mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);        break;    case e1000_fc_rx_pause: /* 1 */        /* 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         * (in e1000_config_fc_after_link_up) we will disable the         *hw's ability to send PAUSE frames.         */        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);        break;    case e1000_fc_tx_pause: /* 2 */        /* TX Flow control is enabled, and RX Flow control is         * disabled, by a software over-ride.         */        mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;        mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;        break;    case e1000_fc_full: /* 3 */        /* Flow control (both RX and TX) is enabled by a software         * over-ride.         */        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);        break;    default:        DEBUGOUT("Flow control param set incorrectly\n");        return -E1000_ERR_CONFIG;    }    ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);    if(ret_val)        return ret_val;    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_stat

⌨️ 快捷键说明

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