📄 ixgbe_common.c
字号:
/******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2007 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: Linux NICS <linux.nics@intel.com> e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************/#include <linux/pci.h>#include <linux/delay.h>#include <linux/sched.h>#include "ixgbe_common.h"#include "ixgbe_phy.h"static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw);static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw);static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);static s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw);static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr);/** * ixgbe_start_hw - Prepare hardware for TX/RX * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, clears * all on chip counters, initializes receive address registers, multicast * table, VLAN filter table, calls routine to set up link and flow control * settings, and leaves transmit and receive units disabled and uninitialized **/s32 ixgbe_start_hw(struct ixgbe_hw *hw){ u32 ctrl_ext; /* Set the media type */ hw->phy.media_type = hw->mac.ops.get_media_type(hw); /* Identify the PHY */ ixgbe_identify_phy(hw); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table */ ixgbe_init_rx_addrs(hw); /* Clear the VLAN filter table */ ixgbe_clear_vfta(hw); /* Set up link */ hw->phy.ops.setup(hw); /* Clear statistics registers */ ixgbe_clear_hw_cntrs(hw); /* Set No Snoop Disable */ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); /* Clear adapter stopped flag */ hw->adapter_stopped = false; return 0;}/** * ixgbe_init_hw - Generic hardware initialization * @hw: pointer to hardware structure * * Initialize the hardware by reseting the hardware, filling the bus info * structure and media type, clears all on chip counters, initializes receive * address registers, multicast table, VLAN filter table, calls routine to set * up link and flow control settings, and leaves transmit and receive units * disabled and uninitialized **/s32 ixgbe_init_hw(struct ixgbe_hw *hw){ /* Reset the hardware */ hw->mac.ops.reset(hw); /* Start the HW */ ixgbe_start_hw(hw); return 0;}/** * ixgbe_clear_hw_cntrs - Generic clear hardware counters * @hw: pointer to hardware structure * * Clears all hardware statistics counters by reading them from the hardware * Statistics counters are clear on read. **/static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw){ u16 i = 0; IXGBE_READ_REG(hw, IXGBE_CRCERRS); IXGBE_READ_REG(hw, IXGBE_ILLERRC); IXGBE_READ_REG(hw, IXGBE_ERRBC); IXGBE_READ_REG(hw, IXGBE_MSPDC); for (i = 0; i < 8; i++) IXGBE_READ_REG(hw, IXGBE_MPC(i)); IXGBE_READ_REG(hw, IXGBE_MLFC); IXGBE_READ_REG(hw, IXGBE_MRFC); IXGBE_READ_REG(hw, IXGBE_RLEC); IXGBE_READ_REG(hw, IXGBE_LXONTXC); IXGBE_READ_REG(hw, IXGBE_LXONRXC); IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); for (i = 0; i < 8; i++) { IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); } IXGBE_READ_REG(hw, IXGBE_PRC64); IXGBE_READ_REG(hw, IXGBE_PRC127); IXGBE_READ_REG(hw, IXGBE_PRC255); IXGBE_READ_REG(hw, IXGBE_PRC511); IXGBE_READ_REG(hw, IXGBE_PRC1023); IXGBE_READ_REG(hw, IXGBE_PRC1522); IXGBE_READ_REG(hw, IXGBE_GPRC); IXGBE_READ_REG(hw, IXGBE_BPRC); IXGBE_READ_REG(hw, IXGBE_MPRC); IXGBE_READ_REG(hw, IXGBE_GPTC); IXGBE_READ_REG(hw, IXGBE_GORCL); IXGBE_READ_REG(hw, IXGBE_GORCH); IXGBE_READ_REG(hw, IXGBE_GOTCL); IXGBE_READ_REG(hw, IXGBE_GOTCH); for (i = 0; i < 8; i++) IXGBE_READ_REG(hw, IXGBE_RNBC(i)); IXGBE_READ_REG(hw, IXGBE_RUC); IXGBE_READ_REG(hw, IXGBE_RFC); IXGBE_READ_REG(hw, IXGBE_ROC); IXGBE_READ_REG(hw, IXGBE_RJC); IXGBE_READ_REG(hw, IXGBE_MNGPRC); IXGBE_READ_REG(hw, IXGBE_MNGPDC); IXGBE_READ_REG(hw, IXGBE_MNGPTC); IXGBE_READ_REG(hw, IXGBE_TORL); IXGBE_READ_REG(hw, IXGBE_TORH); IXGBE_READ_REG(hw, IXGBE_TPR); IXGBE_READ_REG(hw, IXGBE_TPT); IXGBE_READ_REG(hw, IXGBE_PTC64); IXGBE_READ_REG(hw, IXGBE_PTC127); IXGBE_READ_REG(hw, IXGBE_PTC255); IXGBE_READ_REG(hw, IXGBE_PTC511); IXGBE_READ_REG(hw, IXGBE_PTC1023); IXGBE_READ_REG(hw, IXGBE_PTC1522); IXGBE_READ_REG(hw, IXGBE_MPTC); IXGBE_READ_REG(hw, IXGBE_BPTC); for (i = 0; i < 16; i++) { IXGBE_READ_REG(hw, IXGBE_QPRC(i)); IXGBE_READ_REG(hw, IXGBE_QBRC(i)); IXGBE_READ_REG(hw, IXGBE_QPTC(i)); IXGBE_READ_REG(hw, IXGBE_QBTC(i)); } return 0;}/** * ixgbe_get_mac_addr - Generic get MAC address * @hw: pointer to hardware structure * @mac_addr: Adapter MAC address * * Reads the adapter's MAC address from first Receive Address Register (RAR0) * A reset of the adapter must be performed prior to calling this function * in order for the MAC address to have been loaded from the EEPROM into RAR0 **/s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr){ u32 rar_high; u32 rar_low; u16 i; rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); for (i = 0; i < 4; i++) mac_addr[i] = (u8)(rar_low >> (i*8)); for (i = 0; i < 2; i++) mac_addr[i+4] = (u8)(rar_high >> (i*8)); return 0;}s32 ixgbe_read_part_num(struct ixgbe_hw *hw, u32 *part_num){ s32 ret_val; u16 data; ret_val = ixgbe_read_eeprom(hw, IXGBE_PBANUM0_PTR, &data); if (ret_val) { hw_dbg(hw, "NVM Read Error\n"); return ret_val; } *part_num = (u32)(data << 16); ret_val = ixgbe_read_eeprom(hw, IXGBE_PBANUM1_PTR, &data); if (ret_val) { hw_dbg(hw, "NVM Read Error\n"); return ret_val; } *part_num |= data; return 0;}/** * ixgbe_stop_adapter - Generic stop TX/RX units * @hw: pointer to hardware structure * * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, * disables transmit and receive units. The adapter_stopped flag is used by * the shared code and drivers to determine if the adapter is in a stopped * state and should not touch the hardware. **/s32 ixgbe_stop_adapter(struct ixgbe_hw *hw){ u32 number_of_queues; u32 reg_val; u16 i; /* * Set the adapter_stopped flag so other driver functions stop touching * the hardware */ hw->adapter_stopped = true; /* Disable the receive unit */ reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL); reg_val &= ~(IXGBE_RXCTRL_RXEN); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val); msleep(2); /* Clear interrupt mask to stop from interrupts being generated */ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); /* Clear any pending interrupts */ IXGBE_READ_REG(hw, IXGBE_EICR); /* Disable the transmit unit. Each queue must be disabled. */ number_of_queues = hw->mac.num_tx_queues; for (i = 0; i < number_of_queues; i++) { reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); if (reg_val & IXGBE_TXDCTL_ENABLE) { reg_val &= ~IXGBE_TXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val); } } return 0;}/** * ixgbe_led_on - Turns on the software controllable LEDs. * @hw: pointer to hardware structure * @index: led number to turn on **/s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index){ u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); /* To turn on the LED, set mode to ON. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); return 0;}/** * ixgbe_led_off - Turns off the software controllable LEDs. * @hw: pointer to hardware structure * @index: led number to turn off **/s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index){ u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); /* To turn off the LED, set mode to OFF. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); return 0;}/** * ixgbe_init_eeprom - Initialize EEPROM params * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/s32 ixgbe_init_eeprom(struct ixgbe_hw *hw){ struct ixgbe_eeprom_info *eeprom = &hw->eeprom; u32 eec; u16 eeprom_size; if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->type = ixgbe_eeprom_none; /* * Check for EEPROM present first. * If not present leave as none */ eec = IXGBE_READ_REG(hw, IXGBE_EEC); if (eec & IXGBE_EEC_PRES) { eeprom->type = ixgbe_eeprom_spi; /* * SPI EEPROM is assumed here. This code would need to * change if a future EEPROM is not SPI. */ eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + IXGBE_EEPROM_WORD_SIZE_SHIFT); } if (eec & IXGBE_EEC_ADDR_SIZE) eeprom->address_bits = 16; else eeprom->address_bits = 8; hw_dbg(hw, "Eeprom params: type = %d, size = %d, address bits: " "%d\n", eeprom->type, eeprom->word_size, eeprom->address_bits); } return 0;}/** * ixgbe_read_eeprom - Read EEPROM word using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data){ u32 eerd; s32 status; eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) + IXGBE_EEPROM_READ_REG_START; IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); status = ixgbe_poll_eeprom_eerd_done(hw); if (status == 0) *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> IXGBE_EEPROM_READ_REG_DATA); else hw_dbg(hw, "Eeprom read timed out\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -