📄 e1000_80003es2lan.c
字号:
reg_data &= ~0x00100000; E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data); /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_80003es2lan(hw); return ret_val;}/** * e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2 * @hw: pointer to the HW structure * * Initializes required hardware-dependent bits needed for normal operation. **/static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw){ u32 reg; DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan"); if (hw->mac.disable_hw_init_bits) goto out; /* Transmit Descriptor Control 0 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); /* Transmit Descriptor Control 1 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); /* Transmit Arbitration Control 0 */ reg = E1000_READ_REG(hw, E1000_TARC(0)); reg &= ~(0xF << 27); /* 30:27 */ if (hw->phy.media_type != e1000_media_type_copper) reg &= ~(1 << 20); E1000_WRITE_REG(hw, E1000_TARC(0), reg); /* Transmit Arbitration Control 1 */ reg = E1000_READ_REG(hw, E1000_TARC(1)); if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) reg &= ~(1 << 28); else reg |= (1 << 28); E1000_WRITE_REG(hw, E1000_TARC(1), reg);out: return;}/** * e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link * @hw: pointer to the HW structure * * Setup some GG82563 PHY registers for obtaining link **/static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw){ struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u32 ctrl_ext; u16 data; DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan"); if (!phy->reset_disable) { ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &data); if (ret_val) goto out; data |= GG82563_MSCR_ASSERT_CRS_ON_TX; /* Use 25MHz for both link down and 1000Base-T for Tx clock. */ data |= GG82563_MSCR_TX_CLK_1000MBPS_25; ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, data); if (ret_val) goto out; /* * 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) */ ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &data); if (ret_val) goto out; data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; switch (phy->mdix) { case 1: data |= GG82563_PSCR_CROSSOVER_MODE_MDI; break; case 2: data |= GG82563_PSCR_CROSSOVER_MODE_MDIX; break; case 0: default: data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; break; } /* * Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled * 1 - Enabled */ data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; if (phy->disable_polarity_correction) data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, data); if (ret_val) goto out; /* SW Reset the PHY so all changes take effect */ ret_val = e1000_phy_commit(hw); if (ret_val) { DEBUGOUT("Error Resetting the PHY\n"); goto out; } } /* Bypass Rx and Tx FIFO's */ ret_val = e1000_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL, E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); if (ret_val) goto out; ret_val = e1000_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, &data); if (ret_val) goto out; data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; ret_val = e1000_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, data); if (ret_val) goto out; ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data); if (ret_val) goto out; data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, data); if (ret_val) goto out; ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data); if (ret_val) goto out; /* * Do not init these registers when the HW is in IAMT mode, since the * firmware will have already initialized them. We only initialize * them if the HW is not in IAMT mode. */ if (!(e1000_check_mng_mode(hw))) { /* Enable Electrical Idle on the PHY */ data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; ret_val = e1000_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, data); if (ret_val) goto out; ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &data); if (ret_val) goto out; data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, data); if (ret_val) goto out; } /* * Workaround: Disable padding in Kumeran interface in the MAC * and in the PHY to avoid CRC errors. */ ret_val = e1000_read_phy_reg(hw, GG82563_PHY_INBAND_CTRL, &data); if (ret_val) goto out; data |= GG82563_ICR_DIS_PADDING; ret_val = e1000_write_phy_reg(hw, GG82563_PHY_INBAND_CTRL, data); if (ret_val) goto out;out: return ret_val;}/** * e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2 * @hw: pointer to the HW structure * * Essentially a wrapper for setting up all things "copper" related. * This is a function pointer entry point called by the mac module. **/static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw){ u32 ctrl; s32 ret_val; u16 reg_data; DEBUGFUNC("e1000_setup_copper_link_80003es2lan"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* * Set the mac to wait the maximum time between each * iteration and increase the max iterations when * polling the phy; this fixes erroneous timeouts at 10Mbps. */ ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF); if (ret_val) goto out; ret_val = e1000_read_kmrn_reg(hw, GG82563_REG(0x34, 9), ®_data); if (ret_val) goto out; reg_data |= 0x3F; ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data); if (ret_val) goto out; ret_val = e1000_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, ®_data); if (ret_val) goto out; reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; ret_val = e1000_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, reg_data); if (ret_val) goto out; ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw); if (ret_val) goto out; ret_val = e1000_setup_copper_link_generic(hw);out: return ret_val;}/** * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation * @hw: pointer to the HW structure * @duplex: current duplex setting * * Configure the KMRN interface by applying last minute quirks for * 10/100 operation. **/static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex){ s32 ret_val = E1000_SUCCESS; u32 tipg; u32 i = 0; u16 reg_data, reg_data2; DEBUGFUNC("e1000_configure_kmrn_for_10_100"); reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; ret_val = e1000_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, reg_data); if (ret_val) goto out; /* Configure Transmit Inter-Packet Gap */ tipg = E1000_READ_REG(hw, E1000_TIPG); tipg &= ~E1000_TIPG_IPGT_MASK; tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN; E1000_WRITE_REG(hw, E1000_TIPG, tipg); do { ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); if (ret_val) goto out; ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); if (ret_val) goto out; i++; } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); if (duplex == HALF_DUPLEX) reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; else reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);out: return ret_val;}/** * e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation * @hw: pointer to the HW structure * * Configure the KMRN interface by applying last minute quirks for * gigabit operation. **/static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw){ s32 ret_val = E1000_SUCCESS; u16 reg_data, reg_data2; u32 tipg; u32 i = 0; DEBUGFUNC("e1000_configure_kmrn_for_1000"); reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; ret_val = e1000_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, reg_data); if (ret_val) goto out; /* Configure Transmit Inter-Packet Gap */ tipg = E1000_READ_REG(hw, E1000_TIPG); tipg &= ~E1000_TIPG_IPGT_MASK; tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; E1000_WRITE_REG(hw, E1000_TIPG, tipg); do { ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); if (ret_val) goto out; ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); if (ret_val) goto out; i++; } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);out: return ret_val;}/** * e1000_read_mac_addr_80003es2lan - Read device MAC address * @hw: pointer to the HW structure **/static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw){ s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_mac_addr_80003es2lan"); if (e1000_check_alt_mac_addr_generic(hw)) ret_val = e1000_read_mac_addr_generic(hw); return ret_val;}/** * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw){ /* If the management interface is not enabled, then power down */ if (!(e1000_check_mng_mode(hw) || e1000_check_reset_block(hw))) e1000_power_down_phy_copper(hw); return;}/** * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw){ volatile u32 temp; DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan"); e1000_clear_hw_cntrs_base_generic(hw); temp = E1000_READ_REG(hw, E1000_PRC64); temp = E1000_READ_REG(hw, E1000_PRC127); temp = E1000_READ_REG(hw, E1000_PRC255); temp = E1000_READ_REG(hw, E1000_PRC511); temp = E1000_READ_REG(hw, E1000_PRC1023); temp = E1000_READ_REG(hw, E1000_PRC1522); temp = E1000_READ_REG(hw, E1000_PTC64); temp = E1000_READ_REG(hw, E1000_PTC127); temp = E1000_READ_REG(hw, E1000_PTC255); temp = E1000_READ_REG(hw, E1000_PTC511); temp = E1000_READ_REG(hw, E1000_PTC1023); temp = E1000_READ_REG(hw, E1000_PTC1522); temp = E1000_READ_REG(hw, E1000_ALGNERRC); temp = E1000_READ_REG(hw, E1000_RXERRC); temp = E1000_READ_REG(hw, E1000_TNCRS); temp = E1000_READ_REG(hw, E1000_CEXTERR); temp = E1000_READ_REG(hw, E1000_TSCTC); temp = E1000_READ_REG(hw, E1000_TSCTFC); temp = E1000_READ_REG(hw, E1000_MGTPRC); temp = E1000_READ_REG(hw, E1000_MGTPDC); temp = E1000_READ_REG(hw, E1000_MGTPTC); temp = E1000_READ_REG(hw, E1000_IAC); temp = E1000_READ_REG(hw, E1000_ICRXOC); temp = E1000_READ_REG(hw, E1000_ICRXPTC); temp = E1000_READ_REG(hw, E1000_ICRXATC); temp = E1000_READ_REG(hw, E1000_ICTXPTC); temp = E1000_READ_REG(hw, E1000_ICTXATC); temp = E1000_READ_REG(hw, E1000_ICTXQEC); temp = E1000_READ_REG(hw, E1000_ICTXQMTC); temp = E1000_READ_REG(hw, E1000_ICRXDMTC);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -