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

📄 ixgb_hw.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
 * address registers and the multicast table. Uses receive address registers * for the first 15 multicast addresses, and hashes the rest into the * multicast table. *****************************************************************************/voidixgb_mc_addr_list_update(struct ixgb_hw *hw,			  uint8_t *mc_addr_list,			  uint32_t mc_addr_count,			  uint32_t pad){	uint32_t hash_value;	uint32_t i;	uint32_t rar_used_count = 1;		/* RAR[0] is used for our MAC address */	DEBUGFUNC("ixgb_mc_addr_list_update");	/* Set the new number of MC addresses that we are being requested to use. */	hw->num_mc_addrs = mc_addr_count;	/* Clear RAR[1-15] */	DEBUGOUT(" Clearing RAR[1-15]\n");	for(i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) {		IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);		IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);	}	/* Clear the MTA */	DEBUGOUT(" Clearing MTA\n");	for(i = 0; i < IXGB_MC_TBL_SIZE; i++) {		IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);	}	/* Add the new addresses */	for(i = 0; i < mc_addr_count; i++) {		DEBUGOUT(" Adding the multicast addresses:\n");		DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)],			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +				       1],			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +				       2],			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +				       3],			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +				       4],			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +				       5]);		/* Place this multicast address in the RAR if there is room, *		 * else put it in the MTA		 */		if(rar_used_count < IXGB_RAR_ENTRIES) {			ixgb_rar_set(hw,				     mc_addr_list +				     (i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)),				     rar_used_count);			DEBUGOUT1("Added a multicast address to RAR[%d]\n", i);			rar_used_count++;		} else {			hash_value = ixgb_hash_mc_addr(hw,						       mc_addr_list +						       (i *							(IXGB_ETH_LENGTH_OF_ADDRESS							 + pad)));			DEBUGOUT1(" Hash value = 0x%03X\n", hash_value);			ixgb_mta_set(hw, hash_value);		}	}	DEBUGOUT("MC Update Complete\n");	return;}/****************************************************************************** * Hashes an address to determine its location in the multicast table * * hw - Struct containing variables accessed by shared code * mc_addr - the multicast address to hash * * Returns: *      The hash value *****************************************************************************/static uint32_tixgb_hash_mc_addr(struct ixgb_hw *hw,		   uint8_t *mc_addr){	uint32_t hash_value = 0;	DEBUGFUNC("ixgb_hash_mc_addr");	/* The portion of the address that is used for the hash table is	 * determined by the mc_filter_type setting.	 */	switch (hw->mc_filter_type) {		/* [0] [1] [2] [3] [4] [5]		 * 01  AA  00  12  34  56		 * LSB                 MSB - According to H/W docs */	case 0:		/* [47:36] i.e. 0x563 for above example address */		hash_value =		    ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));		break;	case 1:		/* [46:35] i.e. 0xAC6 for above example address */		hash_value =		    ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));		break;	case 2:		/* [45:34] i.e. 0x5D8 for above example address */		hash_value =		    ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));		break;	case 3:		/* [43:32] i.e. 0x634 for above example address */		hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));		break;	default:		/* Invalid mc_filter_type, what should we do? */		DEBUGOUT("MC filter type param set incorrectly\n");		ASSERT(0);		break;	}	hash_value &= 0xFFF;	return (hash_value);}/****************************************************************************** * Sets the bit in the multicast table corresponding to the hash value. * * hw - Struct containing variables accessed by shared code * hash_value - Multicast address hash value *****************************************************************************/static voidixgb_mta_set(struct ixgb_hw *hw,		  uint32_t hash_value){	uint32_t hash_bit, hash_reg;	uint32_t mta_reg;	/* The MTA is a register array of 128 32-bit registers.	 * It is treated like an array of 4096 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 register is determined by the	 * upper 7 bits of the hash value and the bit within that	 * register are determined by the lower 5 bits of the value.	 */	hash_reg = (hash_value >> 5) & 0x7F;	hash_bit = hash_value & 0x1F;	mta_reg = IXGB_READ_REG_ARRAY(hw, MTA, hash_reg);	mta_reg |= (1 << hash_bit);	IXGB_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta_reg);	return;}/****************************************************************************** * Puts an ethernet address into a receive address register. * * hw - Struct containing variables accessed by shared code * addr - Address to put into receive address register * index - Receive address register to write *****************************************************************************/voidixgb_rar_set(struct ixgb_hw *hw,		  uint8_t *addr,		  uint32_t index){	uint32_t rar_low, rar_high;	DEBUGFUNC("ixgb_rar_set");	/* HW expects these in little endian so we reverse the byte order	 * from network order (big endian) to little endian	 */	rar_low = ((uint32_t) addr[0] |		   ((uint32_t)addr[1] << 8) |		   ((uint32_t)addr[2] << 16) |		   ((uint32_t)addr[3] << 24));	rar_high = ((uint32_t) addr[4] |			((uint32_t)addr[5] << 8) |			IXGB_RAH_AV);	IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);	IXGB_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);	return;}/****************************************************************************** * Writes a value to the specified offset in the VLAN filter table. * * hw - Struct containing variables accessed by shared code * offset - Offset in VLAN filer table to write * value - Value to write into VLAN filter table *****************************************************************************/voidixgb_write_vfta(struct ixgb_hw *hw,		 uint32_t offset,		 uint32_t value){	IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value);	return;}/****************************************************************************** * Clears the VLAN filer table * * hw - Struct containing variables accessed by shared code *****************************************************************************/static voidixgb_clear_vfta(struct ixgb_hw *hw){	uint32_t offset;	for(offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)		IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0);	return;}/****************************************************************************** * Configures the flow control settings based on SW configuration. * * hw - Struct containing variables accessed by shared code *****************************************************************************/static boolean_tixgb_setup_fc(struct ixgb_hw *hw){	uint32_t ctrl_reg;	uint32_t pap_reg = 0;   /* by default, assume no pause time */	boolean_t status = TRUE;	DEBUGFUNC("ixgb_setup_fc");	/* Get the current control reg 0 settings */	ctrl_reg = IXGB_READ_REG(hw, CTRL0);	/* Clear the Receive Pause Enable and Transmit Pause Enable bits */	ctrl_reg &= ~(IXGB_CTRL0_RPE | IXGB_CTRL0_TPE);	/* The possible values of the "flow_control" parameter are:	 *      0:  Flow control is completely disabled	 *      1:  Rx flow control is enabled (we can receive pause frames	 *          but not send pause frames).	 *      2:  Tx flow control is enabled (we can send pause frames	 *          but we do not support receiving pause frames).	 *      3:  Both Rx and TX flow control (symmetric) are enabled.	 *  other:  Invalid.	 */	switch (hw->fc.type) {	case ixgb_fc_none:	/* 0 */		/* Set CMDC bit to disable Rx Flow control */		ctrl_reg |= (IXGB_CTRL0_CMDC);		break;	case ixgb_fc_rx_pause:	/* 1 */		/* RX Flow control is enabled, and TX Flow control is		 * disabled.		 */		ctrl_reg |= (IXGB_CTRL0_RPE);		break;	case ixgb_fc_tx_pause:	/* 2 */		/* TX Flow control is enabled, and RX Flow control is		 * disabled, by a software over-ride.		 */		ctrl_reg |= (IXGB_CTRL0_TPE);		pap_reg = hw->fc.pause_time;		break;	case ixgb_fc_full:	/* 3 */		/* Flow control (both RX and TX) is enabled by a software		 * over-ride.		 */		ctrl_reg |= (IXGB_CTRL0_RPE | IXGB_CTRL0_TPE);		pap_reg = hw->fc.pause_time;		break;	default:		/* We should never get here.  The value should be 0-3. */		DEBUGOUT("Flow control param set incorrectly\n");		ASSERT(0);		break;	}	/* Write the new settings */	IXGB_WRITE_REG(hw, CTRL0, ctrl_reg);	if (pap_reg != 0) {		IXGB_WRITE_REG(hw, PAP, pap_reg);	}	/* Set the flow control receive threshold registers.  Normally,	 * these registers will be set to a default threshold that may be	 * adjusted later by the driver's runtime code.  However, if the	 * ability to transmit pause frames in not enabled, then these	 * registers will be set to 0.	 */	if(!(hw->fc.type & ixgb_fc_tx_pause)) {		IXGB_WRITE_REG(hw, FCRTL, 0);		IXGB_WRITE_REG(hw, FCRTH, 0);	} else {	   /* We need to set up the Receive Threshold high and low water	    * marks as well as (optionally) enabling the transmission of XON	    * frames. */		if(hw->fc.send_xon) {			IXGB_WRITE_REG(hw, FCRTL,				(hw->fc.low_water | IXGB_FCRTL_XONE));		} else {			IXGB_WRITE_REG(hw, FCRTL, hw->fc.low_water);		}		IXGB_WRITE_REG(hw, FCRTH, hw->fc.high_water);	}	return (status);}/****************************************************************************** * Reads a word from a device over the Management Data Interface (MDI) bus. * This interface is used to manage Physical layer devices. * * hw          - Struct containing variables accessed by hw code * reg_address - Offset of device register being read. * phy_address - Address of device on MDI. * * Returns:  Data word (16 bits) from MDI device. * * The 82597EX has support for several MDI access methods.  This routine * uses the new protocol MDI Single Command and Address Operation. * This requires that first an address cycle command is sent, followed by a * read command. *****************************************************************************/static uint16_tixgb_read_phy_reg(struct ixgb_hw *hw,		uint32_t reg_address,		uint32_t phy_address,		uint32_t device_type){	uint32_t i;	uint32_t data;	uint32_t command = 0;	ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);	ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);	ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);	/* Setup and write the address cycle command */	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |		   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |		   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |		   (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));	IXGB_WRITE_REG(hw, MSCA, command);    /**************************************************************    ** Check every 10 usec to see if the address cycle completed    ** The COMMAND bit will clear when the operation is complete.    ** This may take as long as 64 usecs (we'll wait 100 usecs max)    ** from the CPU Write to the Ready bit assertion.    **************************************************************/	for(i = 0; i < 10; i++)	{		udelay(10);		command = IXGB_READ_REG(hw, MSCA);		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)			break;	}	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);	/* Address cycle complete, setup and write the read command */	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |		   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |		   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |		   (IXGB_MSCA_READ | IXGB_MSCA_MDI_COMMAND));	IXGB_WRITE_REG(hw, MSCA, command);    /**************************************************************    ** Check every 10 usec to see if the read command completed    ** The COMMAND bit will clear when the operation is complete.    ** The read may take as long as 64 usecs (we'll wait 100 usecs max)    ** from the CPU Write to the Ready bit assertion.    **************************************************************/	for(i = 0; i < 10; i++)	{		udelay(10);		command = IXGB_READ_REG(hw, MSCA);		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)			break;	}	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);	/* Operation is complete, get the data from the MDIO Read/Write Data	 * register and return.	 */	data = IXGB_READ_REG(hw, MSRWD);	data >>= IXGB_MSRWD_READ_DATA_SHIFT;	return((uint16_t) data);}

⌨️ 快捷键说明

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