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

📄 e1000_hw.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
    } else {        ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);        E1000_WRITE_REG(hw, CTRL, ctrl);        ret_val = e1000_phy_hw_reset(hw);        if(ret_val)            return ret_val;    }    /* Make sure we have a valid PHY */    ret_val = e1000_detect_gig_phy(hw);    if(ret_val) {        DEBUGOUT("Error, did not detect valid phy.\n");        return ret_val;    }    DEBUGOUT1("Phy ID = %x \n", hw->phy_id);    /* Set PHY to class A mode (if necessary) */    ret_val = e1000_set_phy_mode(hw);    if(ret_val)        return ret_val;    if((hw->mac_type == e1000_82545_rev_3) ||       (hw->mac_type == e1000_82546_rev_3)) {        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);        phy_data |= 0x00000008;        ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);    }    if(hw->mac_type <= e1000_82543 ||       hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||       hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)        hw->phy_reset_disable = FALSE;   return E1000_SUCCESS;}/********************************************************************* Copper link setup for e1000_phy_igp series.** hw - Struct containing variables accessed by shared code*********************************************************************/static int32_te1000_copper_link_igp_setup(struct e1000_hw *hw){    uint32_t led_ctrl;    int32_t ret_val;    uint16_t phy_data;    DEBUGFUNC("e1000_copper_link_igp_setup");    if (hw->phy_reset_disable)        return E1000_SUCCESS;        ret_val = e1000_phy_reset(hw);    if (ret_val) {        DEBUGOUT("Error Resetting the PHY\n");        return ret_val;    }    /* Wait 10ms for MAC to configure PHY from eeprom settings */    msec_delay(15);    /* Configure activity LED after PHY reset */    led_ctrl = E1000_READ_REG(hw, LEDCTL);    led_ctrl &= IGP_ACTIVITY_LED_MASK;    led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);    E1000_WRITE_REG(hw, LEDCTL, led_ctrl);    /* disable lplu d3 during driver init */    ret_val = e1000_set_d3_lplu_state(hw, FALSE);    if (ret_val) {        DEBUGOUT("Error Disabling LPLU D3\n");        return ret_val;    }    /* disable lplu d0 during driver init */    ret_val = e1000_set_d0_lplu_state(hw, FALSE);    if (ret_val) {        DEBUGOUT("Error Disabling LPLU D0\n");        return ret_val;    }    /* Configure mdi-mdix settings */    ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);    if (ret_val)        return ret_val;    if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {        hw->dsp_config_state = e1000_dsp_config_disabled;        /* Force MDI for earlier revs of the IGP PHY */        phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | IGP01E1000_PSCR_FORCE_MDI_MDIX);        hw->mdix = 1;    } else {        hw->dsp_config_state = e1000_dsp_config_enabled;        phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;        switch (hw->mdix) {        case 1:            phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;            break;        case 2:            phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;            break;        case 0:        default:            phy_data |= IGP01E1000_PSCR_AUTO_MDIX;            break;        }    }    ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);    if(ret_val)        return ret_val;    /* set auto-master slave resolution settings */    if(hw->autoneg) {        e1000_ms_type phy_ms_setting = hw->master_slave;        if(hw->ffe_config_state == e1000_ffe_config_active)            hw->ffe_config_state = e1000_ffe_config_enabled;        if(hw->dsp_config_state == e1000_dsp_config_activated)            hw->dsp_config_state = e1000_dsp_config_enabled;        /* when autonegotiation advertisment is only 1000Mbps then we          * should disable SmartSpeed and enable Auto MasterSlave          * resolution as hardware default. */        if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {            /* Disable SmartSpeed */            ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);            if(ret_val)                return ret_val;            phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;            ret_val = e1000_write_phy_reg(hw,                                                  IGP01E1000_PHY_PORT_CONFIG,                                                  phy_data);            if(ret_val)                return ret_val;            /* Set auto Master/Slave resolution process */            ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);            if(ret_val)                return ret_val;            phy_data &= ~CR_1000T_MS_ENABLE;            ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);            if(ret_val)                return ret_val;        }        ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);        if(ret_val)            return ret_val;        /* load defaults for future use */        hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?                                        ((phy_data & CR_1000T_MS_VALUE) ?                                         e1000_ms_force_master :                                         e1000_ms_force_slave) :                                         e1000_ms_auto;        switch (phy_ms_setting) {        case e1000_ms_force_master:            phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);            break;        case e1000_ms_force_slave:            phy_data |= CR_1000T_MS_ENABLE;            phy_data &= ~(CR_1000T_MS_VALUE);            break;        case e1000_ms_auto:            phy_data &= ~CR_1000T_MS_ENABLE;            default:            break;        }        ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);        if(ret_val)            return ret_val;    }    return E1000_SUCCESS;}/********************************************************************* Copper link setup for e1000_phy_m88 series.** hw - Struct containing variables accessed by shared code*********************************************************************/static int32_te1000_copper_link_mgp_setup(struct e1000_hw *hw){    int32_t ret_val;    uint16_t phy_data;    DEBUGFUNC("e1000_copper_link_mgp_setup");    if(hw->phy_reset_disable)        return E1000_SUCCESS;        /* Enable CRS on TX. This must be set for 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;    /* Options:     *   MDI/MDI-X = 0 (default)     *   0 - Auto for all speeds     *   1 - MDI mode     *   2 - MDI-X mode     *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)     */    phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;    switch (hw->mdix) {    case 1:        phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;        break;    case 2:        phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;        break;    case 3:        phy_data |= M88E1000_PSCR_AUTO_X_1000T;        break;    case 0:    default:        phy_data |= M88E1000_PSCR_AUTO_X_MODE;        break;    }    /* Options:     *   disable_polarity_correction = 0 (default)     *       Automatic Correction for Reversed Cable Polarity     *   0 - Disabled     *   1 - Enabled     */    phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;    if(hw->disable_polarity_correction == 1)        phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;        ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);        if(ret_val)            return ret_val;    /* Force TX_CLK in the Extended PHY Specific Control Register     * to 25MHz clock.     */    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;    if (hw->phy_revision < M88E1011_I_REV_4) {        /* Configure Master and Slave downshift values */        phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |                              M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);        phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |                             M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);        ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);        if(ret_val)            return ret_val;    }    /* SW Reset the PHY so all changes take effect */    ret_val = e1000_phy_reset(hw);    if(ret_val) {        DEBUGOUT("Error Resetting the PHY\n");        return ret_val;    }   return E1000_SUCCESS;}/********************************************************************* Setup auto-negotiation and flow control advertisements,* and then perform auto-negotiation.** hw - Struct containing variables accessed by shared code*********************************************************************/static int32_te1000_copper_link_autoneg(struct e1000_hw *hw){    int32_t ret_val;    uint16_t phy_data;    DEBUGFUNC("e1000_copper_link_autoneg");    /* Perform some bounds checking on the hw->autoneg_advertised     * parameter.  If this variable is zero, then set it to the default.     */    hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;    /* If autoneg_advertised is zero, we assume it was not defaulted     * by the calling code so we set to advertise full capability.     */    if(hw->autoneg_advertised == 0)        hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;    DEBUGOUT("Reconfiguring auto-neg advertisement params\n");    ret_val = e1000_phy_setup_autoneg(hw);    if(ret_val) {        DEBUGOUT("Error Setting up Auto-Negotiation\n");        return ret_val;    }    DEBUGOUT("Restarting Auto-Neg\n");    /* Restart auto-negotiation by setting the Auto Neg Enable bit and     * the Auto Neg Restart bit in the PHY control register.     */    ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);    if(ret_val)        return ret_val;    phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);    ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);    if(ret_val)        return ret_val;    /* Does the user want to wait for Auto-Neg to complete here, or     * check at a later time (for example, callback routine).     */    if(hw->wait_autoneg_complete) {        ret_val = e1000_wait_autoneg(hw);        if(ret_val) {            DEBUGOUT("Error while waiting for autoneg to complete\n");            return ret_val;        }    }    hw->get_link_status = TRUE;    return E1000_SUCCESS;}/******************************************************************************* Config the MAC and the PHY after link is up.*   1) Set up the MAC to the current PHY speed/duplex*      if we are on 82543.  If we*      are on newer silicon, we only need to configure*      collision distance in the Transmit Control Register.*   2) Set up flow control on the MAC to that established with*      the link partner.*   3) Config DSP to improve Gigabit link quality for some PHY revisions.    ** hw - Struct containing variables accessed by shared code******************************************************************************/static int32_te1000_copper_link_postconfig(struct e1000_hw *hw){    int32_t ret_val;    DEBUGFUNC("e1000_copper_link_postconfig");        if(hw->mac_type >= e1000_82544) {        e1000_config_collision_dist(hw);    } else {        ret_val = e1000_config_mac_to_phy(hw);        if(ret_val) {            DEBUGOUT("Error configuring MAC to PHY settings\n");            return ret_val;        }    }    ret_val = e1000_config_fc_after_link_up(hw);    if(ret_val) {        DEBUGOUT("Error Configuring Flow Control\n");        return ret_val;    }    /* Config DSP to improve Giga link quality */

⌨️ 快捷键说明

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