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->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; 
e1000_setup_copper_link(struct e1000_hw *hw){    uint32_t ctrl;    uint32_t 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) {        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;    if(!hw->phy_reset_disable) {        if (hw->phy_type == e1000_phy_igp) {            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;            }            /* 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;            }        } else {            /* 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;            }        }        /* 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) {                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;        } else {            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;            }        }    } /* !hw->phy_reset_disable */    /* 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) {            /* 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) {                    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;            }            DEBUGOUT("Valid link established!!!\n");            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;                }            }            DEBUGOUT("Valid link established!!!\n");            return E1000_SUCCESS;        }        udelay(10);    }    DEBUGOUT("Unable to establish link!!!\n");    return E1000_SUCCESS;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/2d7edb923a823660b081bd4c660300ee19adca8d/e1000_hw.c/clean/drivers/net/e1000/e1000_hw.c