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

📄 lib.c

📁 grub源码分析文档
💻 C
📖 第 1 页 / 共 5 页
字号:
/*******************************************************************************  Intel PRO/1000 Linux driver  Copyright(c) 1999 - 2008 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/netdevice.h>#include <linux/ethtool.h>#include <linux/delay.h>#include <linux/pci.h>#include "e1000.h"enum e1000_mng_mode {	e1000_mng_mode_none = 0,	e1000_mng_mode_asf,	e1000_mng_mode_pt,	e1000_mng_mode_ipmi,	e1000_mng_mode_host_if_only};#define E1000_FACTPS_MNGCG		0x20000000/* Intel(R) Active Management Technology signature */#define E1000_IAMT_SIGNATURE		0x544D4149/** *  e1000e_get_bus_info_pcie - Get PCIe bus information *  @hw: pointer to the HW structure * *  Determines and stores the system bus information for a particular *  network interface.  The following bus information is determined and stored: *  bus speed, bus width, type (PCIe), and PCIe function. **/s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw){	struct e1000_bus_info *bus = &hw->bus;	struct e1000_adapter *adapter = hw->adapter;	u32 status;	u16 pcie_link_status, pci_header_type, cap_offset;	cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);	if (!cap_offset) {		bus->width = e1000_bus_width_unknown;	} else {		pci_read_config_word(adapter->pdev,				     cap_offset + PCIE_LINK_STATUS,				     &pcie_link_status);		bus->width = (enum e1000_bus_width)((pcie_link_status &						     PCIE_LINK_WIDTH_MASK) >>						    PCIE_LINK_WIDTH_SHIFT);	}	pci_read_config_word(adapter->pdev, PCI_HEADER_TYPE_REGISTER,			     &pci_header_type);	if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) {		status = er32(STATUS);		bus->func = (status & E1000_STATUS_FUNC_MASK)			    >> E1000_STATUS_FUNC_SHIFT;	} else {		bus->func = 0;	}	return 0;}/** *  e1000e_write_vfta - Write value to VLAN filter table *  @hw: pointer to the HW structure *  @offset: register offset in VLAN filter table *  @value: register value written to VLAN filter table * *  Writes value at the given offset in the register array which stores *  the VLAN filter table. **/void e1000e_write_vfta(struct e1000_hw *hw, u32 offset, u32 value){	E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);	e1e_flush();}/** *  e1000e_init_rx_addrs - Initialize receive address's *  @hw: pointer to the HW structure *  @rar_count: receive address registers * *  Setups the receive address registers by setting the base receive address *  register to the devices MAC address and clearing all the other receive *  address registers to 0. **/void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count){	u32 i;	/* Setup the receive address */	hw_dbg(hw, "Programming MAC Address into RAR[0]\n");	e1000e_rar_set(hw, hw->mac.addr, 0);	/* Zero out the other (rar_entry_count - 1) receive addresses */	hw_dbg(hw, "Clearing RAR[1-%u]\n", rar_count-1);	for (i = 1; i < rar_count; i++) {		E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1), 0);		e1e_flush();		E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((i << 1) + 1), 0);		e1e_flush();	}}/** *  e1000e_rar_set - Set receive address register *  @hw: pointer to the HW structure *  @addr: pointer to the receive address *  @index: receive address array register * *  Sets the receive address array register at index to the address passed *  in by addr. **/void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index){	u32 rar_low, rar_high;	/*	 * HW expects these in little endian so we reverse the byte order	 * from network order (big endian) to little endian	 */	rar_low = ((u32) addr[0] |		   ((u32) addr[1] << 8) |		    ((u32) addr[2] << 16) | ((u32) addr[3] << 24));	rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));	rar_high |= E1000_RAH_AV;	E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);	E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);}/** *  e1000_mta_set - Set multicast filter table address *  @hw: pointer to the HW structure *  @hash_value: determines the MTA register and bit to set * *  The multicast table address is a register array of 32-bit registers. *  The hash_value is used to determine what register the bit is in, the *  current value is read, the new bit is OR'd in and the new value is *  written back into the register. **/static void e1000_mta_set(struct e1000_hw *hw, u32 hash_value){	u32 hash_bit, hash_reg, mta;	/*	 * The MTA is a register array of 32-bit registers. It is	 * treated like an array of (32*mta_reg_count) bits.  We want to	 * set bit BitArray[hash_value]. So we figure out what register	 * the bit is in, read it, OR in the new bit, then write	 * back the new value.  The (hw->mac.mta_reg_count - 1) serves as a	 * mask to bits 31:5 of the hash value which gives us the	 * register we're modifying.  The hash bit within that register	 * is determined by the lower 5 bits of the hash value.	 */	hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);	hash_bit = hash_value & 0x1F;	mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg);	mta |= (1 << hash_bit);	E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta);	e1e_flush();}/** *  e1000_hash_mc_addr - Generate a multicast hash value *  @hw: pointer to the HW structure *  @mc_addr: pointer to a multicast address * *  Generates a multicast address hash value which is used to determine *  the multicast filter table array address and new table value.  See *  e1000_mta_set_generic() **/static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr){	u32 hash_value, hash_mask;	u8 bit_shift = 0;	/* Register count multiplied by bits per register */	hash_mask = (hw->mac.mta_reg_count * 32) - 1;	/*	 * For a mc_filter_type of 0, bit_shift is the number of left-shifts	 * where 0xFF would still fall within the hash mask.	 */	while (hash_mask >> bit_shift != 0xFF)		bit_shift++;	/*	 * The portion of the address that is used for the hash table	 * is determined by the mc_filter_type setting.	 * The algorithm is such that there is a total of 8 bits of shifting.	 * The bit_shift for a mc_filter_type of 0 represents the number of	 * left-shifts where the MSB of mc_addr[5] would still fall within	 * the hash_mask.  Case 0 does this exactly.  Since there are a total	 * of 8 bits of shifting, then mc_addr[4] will shift right the	 * remaining number of bits. Thus 8 - bit_shift.  The rest of the	 * cases are a variation of this algorithm...essentially raising the	 * number of bits to shift mc_addr[5] left, while still keeping the	 * 8-bit shifting total.	 *	 * For example, given the following Destination MAC Address and an	 * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask),	 * we can see that the bit_shift for case 0 is 4.  These are the hash	 * values resulting from each mc_filter_type...	 * [0] [1] [2] [3] [4] [5]	 * 01  AA  00  12  34  56	 * LSB		 MSB	 *	 * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563	 * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6	 * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163	 * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634	 */	switch (hw->mac.mc_filter_type) {	default:	case 0:		break;	case 1:		bit_shift += 1;		break;	case 2:		bit_shift += 2;		break;	case 3:		bit_shift += 4;		break;	}	hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |				  (((u16) mc_addr[5]) << bit_shift)));	return hash_value;}/** *  e1000e_update_mc_addr_list_generic - Update Multicast addresses *  @hw: pointer to the HW structure *  @mc_addr_list: array of multicast addresses to program *  @mc_addr_count: number of multicast addresses to program *  @rar_used_count: the first RAR register free to program *  @rar_count: total number of supported Receive Address Registers * *  Updates the Receive Address Registers and Multicast Table Array. *  The caller must have a packed mc_addr_list of multicast addresses. *  The parameter rar_count will usually be hw->mac.rar_entry_count *  unless there are workarounds that change this. **/void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,					u8 *mc_addr_list, u32 mc_addr_count,					u32 rar_used_count, u32 rar_count){	u32 hash_value;	u32 i;	/*	 * Load the first set of multicast addresses into the exact	 * filters (RAR).  If there are not enough to fill the RAR	 * array, clear the filters.	 */	for (i = rar_used_count; i < rar_count; i++) {		if (mc_addr_count) {			e1000e_rar_set(hw, mc_addr_list, i);			mc_addr_count--;			mc_addr_list += ETH_ALEN;		} else {			E1000_WRITE_REG_ARRAY(hw, E1000_RA, i << 1, 0);			e1e_flush();			E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1) + 1, 0);			e1e_flush();		}	}	/* Clear the old settings from the MTA */	hw_dbg(hw, "Clearing MTA\n");	for (i = 0; i < hw->mac.mta_reg_count; i++) {		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);		e1e_flush();	}	/* Load any remaining multicast addresses into the hash table. */	for (; mc_addr_count > 0; mc_addr_count--) {		hash_value = e1000_hash_mc_addr(hw, mc_addr_list);		hw_dbg(hw, "Hash value = 0x%03X\n", hash_value);		e1000_mta_set(hw, hash_value);		mc_addr_list += ETH_ALEN;	}}/** *  e1000e_clear_hw_cntrs_base - Clear base hardware counters *  @hw: pointer to the HW structure * *  Clears the base hardware counters by reading the counter registers. **/void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw){	u32 temp;	temp = er32(CRCERRS);	temp = er32(SYMERRS);	temp = er32(MPC);	temp = er32(SCC);	temp = er32(ECOL);	temp = er32(MCC);	temp = er32(LATECOL);	temp = er32(COLC);	temp = er32(DC);	temp = er32(SEC);	temp = er32(RLEC);	temp = er32(XONRXC);	temp = er32(XONTXC);	temp = er32(XOFFRXC);	temp = er32(XOFFTXC);	temp = er32(FCRUC);	temp = er32(GPRC);	temp = er32(BPRC);	temp = er32(MPRC);	temp = er32(GPTC);	temp = er32(GORCL);	temp = er32(GORCH);	temp = er32(GOTCL);	temp = er32(GOTCH);	temp = er32(RNBC);	temp = er32(RUC);	temp = er32(RFC);	temp = er32(ROC);	temp = er32(RJC);	temp = er32(TORL);	temp = er32(TORH);	temp = er32(TOTL);	temp = er32(TOTH);	temp = er32(TPR);	temp = er32(TPT);	temp = er32(MPTC);	temp = er32(BPTC);}/** *  e1000e_check_for_copper_link - Check for link (Copper) *  @hw: pointer to the HW structure * *  Checks to see of the link status of the hardware has changed.  If a *  change in link status has been detected, then we read the PHY registers *  to get the current speed/duplex if link exists. **/s32 e1000e_check_for_copper_link(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	s32 ret_val;	bool link;	/*	 * We only want to go out to the PHY registers to see if Auto-Neg	 * has completed and/or if our link status has changed.  The	 * get_link_status flag is set upon receiving a Link Status	 * Change or Rx Sequence Error interrupt.	 */	if (!mac->get_link_status)		return 0;	/*	 * First we want to see if the MII Status Register reports	 * link.  If so, then we want to get the current speed/duplex	 * of the PHY.	 */	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);	if (ret_val)		return ret_val;	if (!link)		return ret_val; /* No link detected */	mac->get_link_status = 0;	/*	 * Check if there was DownShift, must be checked	 * immediately after link-up	 */	e1000e_check_downshift(hw);	/*	 * If we are forcing speed/duplex, then we simply return since	 * we have already determined whether we have link or not.	 */	if (!mac->autoneg) {		ret_val = -E1000_ERR_CONFIG;		return ret_val;	}	/*	 * Auto-Neg is enabled.  Auto Speed Detection takes care	 * of MAC speed/duplex configuration.  So we only need to	 * configure Collision Distance in the MAC.	 */	e1000e_config_collision_dist(hw);	/*	 * Configure Flow Control now that Auto-Neg has completed.	 * First, we need to restore the desired flow control	 * settings because we may have had to re-autoneg with a	 * different link partner.	 */	ret_val = e1000e_config_fc_after_link_up(hw);	if (ret_val) {		hw_dbg(hw, "Error configuring flow control\n");	}	return ret_val;}/** *  e1000e_check_for_fiber_link - Check for link (Fiber) *  @hw: pointer to the HW structure * *  Checks for link up on the hardware.  If link is not up and we have *  a signal, then we need to force link up. **/s32 e1000e_check_for_fiber_link(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 rxcw;	u32 ctrl;	u32 status;	s32 ret_val;	ctrl = er32(CTRL);	status = er32(STATUS);	rxcw = er32(RXCW);	/*	 * If we don't have link (auto-negotiation failed or link partner	 * cannot auto-negotiate), the cable is plugged in (we have signal),	 * and our link partner is not trying to auto-negotiate with us (we	 * are receiving idles or data), we need to force link up. We also	 * need to give auto-negotiation time to complete, in case the cable	 * was just plugged in. The autoneg_failed flag does this.	 */	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */	if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&	    (!(rxcw & E1000_RXCW_C))) {		if (mac->autoneg_failed == 0) {			mac->autoneg_failed = 1;			return 0;		}		hw_dbg(hw, "NOT RXing /C/, disable AutoNeg and force link.\n");		/* Disable auto-negotiation in the TXCW register */		ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));		/* Force link-up and also force full-duplex. */		ctrl = er32(CTRL);		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);

⌨️ 快捷键说明

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