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

📄 e1000_mac.c

📁 e1000 8.0.1 version.最新的e1000 linux下的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	E1000_WRITE_REG(hw, E1000_RAH(index), rar_high);}/** *  e1000_mta_set_generic - 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. **/void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value){	u32 hash_bit, hash_reg, mta;	DEBUGFUNC("e1000_mta_set_generic");	/*	 * 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);	E1000_WRITE_FLUSH(hw);}/** *  e1000_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 e1000_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;	DEBUGFUNC("e1000_update_mc_addr_list_generic");	/*	 * 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) {			hw->mac.ops.rar_set(hw, mc_addr_list, i);			mc_addr_count--;			mc_addr_list += ETH_ADDR_LEN;		} else {			E1000_WRITE_REG_ARRAY(hw, E1000_RA, i << 1, 0);			E1000_WRITE_FLUSH(hw);			E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1) + 1, 0);			E1000_WRITE_FLUSH(hw);		}	}	/* Clear the old settings from the MTA */	DEBUGOUT("Clearing MTA\n");	for (i = 0; i < hw->mac.mta_reg_count; i++) {		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);		E1000_WRITE_FLUSH(hw);	}	/* 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);		DEBUGOUT1("Hash value = 0x%03X\n", hash_value);		hw->mac.ops.mta_set(hw, hash_value);		mc_addr_list += ETH_ADDR_LEN;	}}/** *  e1000_hash_mc_addr_generic - 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() **/u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr){	u32 hash_value, hash_mask;	u8 bit_shift = 0;	DEBUGFUNC("e1000_hash_mc_addr_generic");	/* 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;}/** *  e1000_pcix_mmrbc_workaround_generic - Fix incorrect MMRBC value *  @hw: pointer to the HW structure * *  In certain situations, a system BIOS may report that the PCIx maximum *  memory read byte count (MMRBC) value is higher than than the actual *  value. We check the PCIx command register with the current PCIx status *  register. **/void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw){	u16 cmd_mmrbc;	u16 pcix_cmd;	u16 pcix_stat_hi_word;	u16 stat_mmrbc;	DEBUGFUNC("e1000_pcix_mmrbc_workaround_generic");	/* Workaround for PCI-X issue when BIOS sets MMRBC incorrectly */	if (hw->bus.type != e1000_bus_type_pcix)		return;	e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd);	e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word);	cmd_mmrbc = (pcix_cmd & PCIX_COMMAND_MMRBC_MASK) >>	             PCIX_COMMAND_MMRBC_SHIFT;	stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>	              PCIX_STATUS_HI_MMRBC_SHIFT;	if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)		stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;	if (cmd_mmrbc > stat_mmrbc) {		pcix_cmd &= ~PCIX_COMMAND_MMRBC_MASK;		pcix_cmd |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;		e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd);	}}/** *  e1000_clear_hw_cntrs_base_generic - Clear base hardware counters *  @hw: pointer to the HW structure * *  Clears the base hardware counters by reading the counter registers. **/void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw){	volatile u32 temp;	DEBUGFUNC("e1000_clear_hw_cntrs_base_generic");	temp = E1000_READ_REG(hw, E1000_CRCERRS);	temp = E1000_READ_REG(hw, E1000_SYMERRS);	temp = E1000_READ_REG(hw, E1000_MPC);	temp = E1000_READ_REG(hw, E1000_SCC);	temp = E1000_READ_REG(hw, E1000_ECOL);	temp = E1000_READ_REG(hw, E1000_MCC);	temp = E1000_READ_REG(hw, E1000_LATECOL);	temp = E1000_READ_REG(hw, E1000_COLC);	temp = E1000_READ_REG(hw, E1000_DC);	temp = E1000_READ_REG(hw, E1000_SEC);	temp = E1000_READ_REG(hw, E1000_RLEC);	temp = E1000_READ_REG(hw, E1000_XONRXC);	temp = E1000_READ_REG(hw, E1000_XONTXC);	temp = E1000_READ_REG(hw, E1000_XOFFRXC);	temp = E1000_READ_REG(hw, E1000_XOFFTXC);	temp = E1000_READ_REG(hw, E1000_FCRUC);	temp = E1000_READ_REG(hw, E1000_GPRC);	temp = E1000_READ_REG(hw, E1000_BPRC);	temp = E1000_READ_REG(hw, E1000_MPRC);	temp = E1000_READ_REG(hw, E1000_GPTC);	temp = E1000_READ_REG(hw, E1000_GORCL);	temp = E1000_READ_REG(hw, E1000_GORCH);	temp = E1000_READ_REG(hw, E1000_GOTCL);	temp = E1000_READ_REG(hw, E1000_GOTCH);	temp = E1000_READ_REG(hw, E1000_RNBC);	temp = E1000_READ_REG(hw, E1000_RUC);	temp = E1000_READ_REG(hw, E1000_RFC);	temp = E1000_READ_REG(hw, E1000_ROC);	temp = E1000_READ_REG(hw, E1000_RJC);	temp = E1000_READ_REG(hw, E1000_TORL);	temp = E1000_READ_REG(hw, E1000_TORH);	temp = E1000_READ_REG(hw, E1000_TOTL);	temp = E1000_READ_REG(hw, E1000_TOTH);	temp = E1000_READ_REG(hw, E1000_TPR);	temp = E1000_READ_REG(hw, E1000_TPT);	temp = E1000_READ_REG(hw, E1000_MPTC);	temp = E1000_READ_REG(hw, E1000_BPTC);}/** *  e1000_check_for_copper_link_generic - 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 e1000_check_for_copper_link_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	s32 ret_val;	bool link;	DEBUGFUNC("e1000_check_for_copper_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) {		ret_val = E1000_SUCCESS;		goto out;	}	/*	 * 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 = e1000_phy_has_link_generic(hw, 1, 0, &link);	if (ret_val)		goto out;	if (!link)		goto out; /* No link detected */	mac->get_link_status = FALSE;	/*	 * Check if there was DownShift, must be checked	 * immediately after link-up	 */	e1000_check_downshift_generic(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;		goto out;	}	/*	 * 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.	 */	e1000_config_collision_dist_generic(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 = e1000_config_fc_after_link_up_generic(hw);	if (ret_val) {		DEBUGOUT("Error configuring flow control\n");	}out:	return ret_val;}/** *  e1000_check_for_fiber_link_generic - 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 e1000_check_for_fiber_link_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 rxcw;	u32 ctrl;	u32 status;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_check_for_fiber_link_generic");	ctrl = E1000_READ_REG(hw, E1000_CTRL);	status = E1000_READ_REG(hw, E1000_STATUS);	rxcw = E1000_READ_REG(hw, E1000_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;			goto out;		}		DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");		/* Disable auto-negotiation in the TXCW register */		E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));		/* Force link-up and also force full-duplex. */		ctrl = E1000_READ_REG(hw, E1000_CTRL);		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);		/* Configure Flow Control after forcing link up. */		ret_val = e1000_config_fc_after_link_up_generic(hw);		if (ret_val) {			DEBUGOUT("Error configuring flow control\n");			goto out;		}	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {		/*		 * If we are forcing link and we are receiving /C/ ordered		 * sets, re-enable auto-negotiation in the TXCW register		 * and disable forced link in the Device Control register		 * in an attempt to auto-negotiate with our link partner.		 */		DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");		E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);		E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));		mac->serdes_has_link = TRUE;	}out:	return ret_val;}/** *  e1000_check_for_serdes_link_generic - Check for link (Serdes) *  @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 e1000_check_for_serdes_link_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 rxcw;	u32 ctrl;	u32 status;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_check_for_serdes_link_generic");	ctrl = E1000_READ_REG(hw, E1000_CTRL);	status = E1000_READ_REG(hw, E1000_STATUS);	rxcw = E1000_READ_REG(hw, E1000_RXCW);	/*	 * If we don't have link (auto-negotiation failed or link partner	 * cannot auto-negotiate), 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.	 */	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */	if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {

⌨️ 快捷键说明

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