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

📄 e1000_hw.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
    uint32_t ctrl, led_ctrl;    int32_t ret_val;    uint16_t i;    uint16_t phy_data;    DEBUGFUNC("e1000_setup_copper_link");    ctrl = E1000_READ_REG(hw, CTRL);    /* With 82543, we need to force speed and duplex on the MAC equal to what     * the PHY speed and duplex configuration is. In addition, we need to     * perform a hardware reset on the PHY to take it out of reset.     */    if(hw->mac_type > e1000_82543) {        ctrl |= E1000_CTRL_SLU;        ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);        E1000_WRITE_REG(hw, CTRL, ctrl);    } else {        ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);        E1000_WRITE_REG(hw, CTRL, ctrl);        e1000_phy_hw_reset(hw);    }    /* Make sure we have a valid PHY */    ret_val = e1000_detect_gig_phy(hw);    if(ret_val < 0) {        DEBUGOUT("Error, did not detect valid phy.\n");        return ret_val;    }    DEBUGOUT1("Phy ID = %x \n", hw->phy_id);    if (hw->phy_type == e1000_phy_igp) {        ret_val = e1000_phy_reset(hw);        if(ret_val < 0) {            DEBUGOUT("Error Resetting the PHY\n");            return ret_val;        }        /* Wait 10ms for MAC to configure PHY from eeprom settings */        msec_delay(15);        if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) {            DEBUGOUT("PHY Write Error\n");            return -E1000_ERR_PHY;        }        /* 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;        if(hw->mac_type == e1000_82547)            led_ctrl |= IGP_LED3_MODE;        E1000_WRITE_REG(hw, LEDCTL, led_ctrl);        if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {            /* Disable SmartSpeed */            if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,                                  &phy_data) < 0) {                DEBUGOUT("PHY Read Error\n");                return -E1000_ERR_PHY;            }            phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;            if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,                                   phy_data) < 0) {                DEBUGOUT("PHY Write Error\n");                return -E1000_ERR_PHY;            }            /* Set auto Master/Slave resolution process */            if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) {                DEBUGOUT("PHY Read Error\n");                return -E1000_ERR_PHY;            }            phy_data &= ~CR_1000T_MS_ENABLE;            if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) {                DEBUGOUT("PHY Write Error\n");                return -E1000_ERR_PHY;            }        }        if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) {            DEBUGOUT("PHY Read Error\n");            return -E1000_ERR_PHY;        }        /* Force MDI for IGP PHY */        phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX |                      IGP01E1000_PSCR_FORCE_MDI_MDIX);        hw->mdix = 1;        if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) {            DEBUGOUT("PHY Write Error\n");            return -E1000_ERR_PHY;        }    } else {        /* Enable CRS on TX. This must be set for half-duplex operation. */        if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) {            DEBUGOUT("PHY Read Error\n");            return -E1000_ERR_PHY;        }        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;        if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) {            DEBUGOUT("PHY Write Error\n");            return -E1000_ERR_PHY;        }        /* Force TX_CLK in the Extended PHY Specific Control Register         * to 25MHz clock.         */        if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) {            DEBUGOUT("PHY Read Error\n");            return -E1000_ERR_PHY;        }        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);            if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,                                   phy_data) < 0) {                DEBUGOUT("PHY Write Error\n");                return -E1000_ERR_PHY;            }        }        /* SW Reset the PHY so all changes take effect */        ret_val = e1000_phy_reset(hw);        if(ret_val < 0) {            DEBUGOUT("Error Resetting the PHY\n");            return ret_val;        }    }    /* Options:     *   autoneg = 1 (default)     *      PHY will advertise value(s) parsed from     *      autoneg_advertised and fc     *   autoneg = 0     *      PHY will be set to 10H, 10F, 100H, or 100F     *      depending on value parsed from forced_speed_duplex.     */    /* Is autoneg enabled?  This is enabled by default or by software override.     * If so, call e1000_phy_setup_autoneg routine to parse the     * autoneg_advertised and fc options. If autoneg is NOT enabled, then the     * user should have provided a speed/duplex override.  If so, then call     * e1000_phy_force_speed_duplex to parse and set this up.     */    if(hw->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 < 0) {            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.         */        if(e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) {            DEBUGOUT("PHY Read Error\n");            return -E1000_ERR_PHY;        }        phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);        if(e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) {            DEBUGOUT("PHY Write Error\n");            return -E1000_ERR_PHY;        }        /* 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 < 0) {                DEBUGOUT("Error while waiting for autoneg to complete\n");                return ret_val;            }        }        hw->get_link_status = TRUE;    } else {        DEBUGOUT("Forcing speed and duplex\n");        ret_val = e1000_phy_force_speed_duplex(hw);        if(ret_val < 0) {            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++) {        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) {            /* We have link, so we need to finish the config process:             *   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.             */            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;                  }            }            ret_val = e1000_config_fc_after_link_up(hw);            if(ret_val < 0) {                DEBUGOUT("Error Configuring Flow Control\n");                return ret_val;            }            DEBUGOUT("Valid link established!!!\n");            return 0;        }        udelay(10);    }    DEBUGOUT("Unable to establish link!!!\n");    return 0;}/******************************************************************************* 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){    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). */    if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg) < 0) {        DEBUGOUT("PHY Read Error\n");        return -E1000_ERR_PHY;    }    /* Read the MII 1000Base-T Control Register (Address 9). */    if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg) < 0) {        DEBUGOUT("PHY Read Error\n");        return -E1000_ERR_PHY;    }    /* 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? */

⌨️ 快捷键说明

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