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

📄 e1000_hw.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/*******************************************************************************    Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.    This program is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the Free   Software Foundation; either version 2 of the License, or (at your option)   any later version.    This program is distributed in the hope that it will be useful, but WITHOUT   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   more details.    You should have received a copy of the GNU General Public License along with  this program; if not, write to the Free Software Foundation, Inc., 59   Temple Place - Suite 330, Boston, MA  02111-1307, USA.    The full GNU General Public License is included in this distribution in the  file called LICENSE.    Contact Information:  Linux NICS <linux.nics@intel.com>  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************//* e1000_hw.c * Shared functions for accessing and configuring the MAC */#include "e1000_hw.h"static int32_t e1000_set_phy_type(struct e1000_hw *hw);static void e1000_phy_init_script(struct e1000_hw *hw);static int32_t e1000_setup_copper_link(struct e1000_hw *hw);static int32_t e1000_setup_fiber_serdes_link(struct e1000_hw *hw);static int32_t e1000_adjust_serdes_amplitude(struct e1000_hw *hw);static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw);static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw);static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data,                                     uint16_t count);static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw);static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw);static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset,                                      uint16_t words, uint16_t *data);static int32_t e1000_write_eeprom_microwire(struct e1000_hw *hw,                                            uint16_t offset, uint16_t words,                                            uint16_t *data);static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw);static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd);static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd);static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data,                                    uint16_t count);static int32_t e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,                                      uint16_t phy_data);static int32_t e1000_read_phy_reg_ex(struct e1000_hw *hw,uint32_t reg_addr,                                     uint16_t *phy_data);static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count);static int32_t e1000_acquire_eeprom(struct e1000_hw *hw);static void e1000_release_eeprom(struct e1000_hw *hw);static void e1000_standby_eeprom(struct e1000_hw *hw);static int32_t e1000_set_vco_speed(struct e1000_hw *hw);static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw);static int32_t e1000_set_phy_mode(struct e1000_hw *hw);static int32_t e1000_host_if_read_cookie(struct e1000_hw *hw, uint8_t *buffer);static uint8_t e1000_calculate_mng_checksum(char *buffer, uint32_t length);static uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);static int32_t e1000_check_downshift(struct e1000_hw *hw);static int32_t e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity);static void e1000_clear_hw_cntrs(struct e1000_hw *hw);static void e1000_clear_vfta(struct e1000_hw *hw);static int32_t e1000_commit_shadow_ram(struct e1000_hw *hw);static int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw,						  boolean_t link_up);static int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw);static int32_t e1000_detect_gig_phy(struct e1000_hw *hw);static int32_t e1000_get_auto_rd_done(struct e1000_hw *hw);static int32_t e1000_get_cable_length(struct e1000_hw *hw,				      uint16_t *min_length,				      uint16_t *max_length);static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);static int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw);static int32_t e1000_id_led_init(struct e1000_hw * hw);static void e1000_init_rx_addrs(struct e1000_hw *hw);static boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);static int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);static int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset,				      uint16_t words, uint16_t *data);static int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active);static int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);static int32_t e1000_wait_autoneg(struct e1000_hw *hw);static void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset,			       uint32_t value);#define E1000_WRITE_REG_IO(a, reg, val) \	    e1000_write_reg_io((a), E1000_##reg, val)/* IGP cable length table */static constuint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =    { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,      5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,      25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,      40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,      60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,      90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,      100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,      110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};static constuint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =    { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,      0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,      6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,      21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,      40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,      60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,      83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,      104, 109, 114, 118, 121, 124};/****************************************************************************** * Set the phy type member in the hw struct. * * hw - Struct containing variables accessed by shared code *****************************************************************************/int32_te1000_set_phy_type(struct e1000_hw *hw){    DEBUGFUNC("e1000_set_phy_type");    if(hw->mac_type == e1000_undefined)        return -E1000_ERR_PHY_TYPE;    switch(hw->phy_id) {    case M88E1000_E_PHY_ID:    case M88E1000_I_PHY_ID:    case M88E1011_I_PHY_ID:    case M88E1111_I_PHY_ID:        hw->phy_type = e1000_phy_m88;        break;    case IGP01E1000_I_PHY_ID:        if(hw->mac_type == e1000_82541 ||           hw->mac_type == e1000_82541_rev_2 ||           hw->mac_type == e1000_82547 ||           hw->mac_type == e1000_82547_rev_2) {            hw->phy_type = e1000_phy_igp;            break;        }        /* Fall Through */    default:        /* Should never have loaded on this device */        hw->phy_type = e1000_phy_undefined;        return -E1000_ERR_PHY_TYPE;    }    return E1000_SUCCESS;}/****************************************************************************** * IGP phy init script - initializes the GbE PHY * * hw - Struct containing variables accessed by shared code *****************************************************************************/static voide1000_phy_init_script(struct e1000_hw *hw){    uint32_t ret_val;    uint16_t phy_saved_data;    DEBUGFUNC("e1000_phy_init_script");    if(hw->phy_init_script) {        msec_delay(20);        /* Save off the current value of register 0x2F5B to be restored at         * the end of this routine. */        ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);        /* Disabled the PHY transmitter */        e1000_write_phy_reg(hw, 0x2F5B, 0x0003);        msec_delay(20);        e1000_write_phy_reg(hw,0x0000,0x0140);        msec_delay(5);        switch(hw->mac_type) {        case e1000_82541:        case e1000_82547:            e1000_write_phy_reg(hw, 0x1F95, 0x0001);            e1000_write_phy_reg(hw, 0x1F71, 0xBD21);            e1000_write_phy_reg(hw, 0x1F79, 0x0018);            e1000_write_phy_reg(hw, 0x1F30, 0x1600);            e1000_write_phy_reg(hw, 0x1F31, 0x0014);            e1000_write_phy_reg(hw, 0x1F32, 0x161C);            e1000_write_phy_reg(hw, 0x1F94, 0x0003);            e1000_write_phy_reg(hw, 0x1F96, 0x003F);            e1000_write_phy_reg(hw, 0x2010, 0x0008);            break;        case e1000_82541_rev_2:        case e1000_82547_rev_2:            e1000_write_phy_reg(hw, 0x1F73, 0x0099);            break;        default:            break;        }        e1000_write_phy_reg(hw, 0x0000, 0x3300);        msec_delay(20);        /* Now enable the transmitter */        e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);        if(hw->mac_type == e1000_82547) {            uint16_t fused, fine, coarse;            /* Move to analog registers page */            e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);            if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {                e1000_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused);                fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;                coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;                if(coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {                    coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;                    fine -= IGP01E1000_ANALOG_FUSE_FINE_1;                } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH)                    fine -= IGP01E1000_ANALOG_FUSE_FINE_10;                fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |                        (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |                        (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);                e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused);                e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS,                                    IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);            }        }    }}/****************************************************************************** * Set the mac type member in the hw struct. * * hw - Struct containing variables accessed by shared code *****************************************************************************/int32_te1000_set_mac_type(struct e1000_hw *hw){    DEBUGFUNC("e1000_set_mac_type");    switch (hw->device_id) {    case E1000_DEV_ID_82542:        switch (hw->revision_id) {        case E1000_82542_2_0_REV_ID:            hw->mac_type = e1000_82542_rev2_0;            break;        case E1000_82542_2_1_REV_ID:            hw->mac_type = e1000_82542_rev2_1;            break;        default:            /* Invalid 82542 revision ID */            return -E1000_ERR_MAC_TYPE;        }        break;    case E1000_DEV_ID_82543GC_FIBER:    case E1000_DEV_ID_82543GC_COPPER:        hw->mac_type = e1000_82543;        break;    case E1000_DEV_ID_82544EI_COPPER:    case E1000_DEV_ID_82544EI_FIBER:    case E1000_DEV_ID_82544GC_COPPER:    case E1000_DEV_ID_82544GC_LOM:        hw->mac_type = e1000_82544;        break;    case E1000_DEV_ID_82540EM:    case E1000_DEV_ID_82540EM_LOM:    case E1000_DEV_ID_82540EP:    case E1000_DEV_ID_82540EP_LOM:    case E1000_DEV_ID_82540EP_LP:        hw->mac_type = e1000_82540;        break;    case E1000_DEV_ID_82545EM_COPPER:    case E1000_DEV_ID_82545EM_FIBER:        hw->mac_type = e1000_82545;        break;    case E1000_DEV_ID_82545GM_COPPER:    case E1000_DEV_ID_82545GM_FIBER:    case E1000_DEV_ID_82545GM_SERDES:        hw->mac_type = e1000_82545_rev_3;        break;    case E1000_DEV_ID_82546EB_COPPER:    case E1000_DEV_ID_82546EB_FIBER:    case E1000_DEV_ID_82546EB_QUAD_COPPER:        hw->mac_type = e1000_82546;        break;    case E1000_DEV_ID_82546GB_COPPER:    case E1000_DEV_ID_82546GB_FIBER:    case E1000_DEV_ID_82546GB_SERDES:    case E1000_DEV_ID_82546GB_PCIE:        hw->mac_type = e1000_82546_rev_3;        break;    case E1000_DEV_ID_82541EI:    case E1000_DEV_ID_82541EI_MOBILE:        hw->mac_type = e1000_82541;        break;    case E1000_DEV_ID_82541ER:    case E1000_DEV_ID_82541GI:    case E1000_DEV_ID_82541GI_LF:    case E1000_DEV_ID_82541GI_MOBILE:        hw->mac_type = e1000_82541_rev_2;        break;    case E1000_DEV_ID_82547EI:        hw->mac_type = e1000_82547;        break;    case E1000_DEV_ID_82547GI:        hw->mac_type = e1000_82547_rev_2;        break;    case E1000_DEV_ID_82571EB_COPPER:    case E1000_DEV_ID_82571EB_FIBER:    case E1000_DEV_ID_82571EB_SERDES:            hw->mac_type = e1000_82571;        break;    case E1000_DEV_ID_82572EI_COPPER:    case E1000_DEV_ID_82572EI_FIBER:    case E1000_DEV_ID_82572EI_SERDES:        hw->mac_type = e1000_82572;        break;    case E1000_DEV_ID_82573E:    case E1000_DEV_ID_82573E_IAMT:    case E1000_DEV_ID_82573L:        hw->mac_type = e1000_82573;        break;    default:        /* Should never have loaded on this device */        return -E1000_ERR_MAC_TYPE;    }    switch(hw->mac_type) {    case e1000_82571:    case e1000_82572:    case e1000_82573:        hw->eeprom_semaphore_present = TRUE;        /* fall through */    case e1000_82541:    case e1000_82547:    case e1000_82541_rev_2:    case e1000_82547_rev_2:

⌨️ 快捷键说明

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