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

📄 e1000_82571.c

📁 linux下的网卡驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw){	s32 ret_val;	DEBUGFUNC("e1000_acquire_nvm_82571");	ret_val = e1000_get_hw_semaphore_82571(hw);	if (ret_val)		goto out;	if (hw->mac.type != e1000_82573)		ret_val = e1000_acquire_nvm_generic(hw);	if (ret_val)		e1000_put_hw_semaphore_82571(hw);out:	return ret_val;}/** *  e1000_release_nvm_82571 - Release exclusive access to EEPROM *  @hw: pointer to the HW structure * *  Stop any current commands to the EEPROM and clear the EEPROM request bit. **/static void e1000_release_nvm_82571(struct e1000_hw *hw){	DEBUGFUNC("e1000_release_nvm_82571");	e1000_release_nvm_generic(hw);	e1000_put_hw_semaphore_82571(hw);}/** *  e1000_write_nvm_82571 - Write to EEPROM using appropriate interface *  @hw: pointer to the HW structure *  @offset: offset within the EEPROM to be written to *  @words: number of words to write *  @data: 16 bit word(s) to be written to the EEPROM * *  For non-82573 silicon, write data to EEPROM at offset using SPI interface. * *  If e1000_update_nvm_checksum is not called after this function, the *  EEPROM will most likley contain an invalid checksum. **/static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words,                                 u16 *data){	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_write_nvm_82571");	switch (hw->mac.type) {	case e1000_82573:		ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data);		break;	case e1000_82571:	case e1000_82572:		ret_val = e1000_write_nvm_spi(hw, offset, words, data);		break;	default:		ret_val = -E1000_ERR_NVM;		break;	}	return ret_val;}/** *  e1000_update_nvm_checksum_82571 - Update EEPROM checksum *  @hw: pointer to the HW structure * *  Updates the EEPROM checksum by reading/adding each word of the EEPROM *  up to the checksum.  Then calculates the EEPROM checksum and writes the *  value to the EEPROM. **/static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw){	u32 eecd;	s32 ret_val;	u16 i;	DEBUGFUNC("e1000_update_nvm_checksum_82571");	ret_val = e1000_update_nvm_checksum_generic(hw);	if (ret_val)		goto out;	/* If our nvm is an EEPROM, then we're done	 * otherwise, commit the checksum to the flash NVM. */	if (hw->nvm.type != e1000_nvm_flash_hw)		goto out;	/* Check for pending operations. */	for (i = 0; i < E1000_FLASH_UPDATES; i++) {		msec_delay(1);		if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0)			break;	}	if (i == E1000_FLASH_UPDATES) {		ret_val = -E1000_ERR_NVM;		goto out;	}	/* Reset the firmware if using STM opcode. */	if ((E1000_READ_REG(hw, E1000_FLOP) & 0xFF00) == E1000_STM_OPCODE) {		/* The enabling of and the actual reset must be done		 * in two write cycles.		 */		E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET_ENABLE);		E1000_WRITE_FLUSH(hw);		E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET);	}	/* Commit the write to flash */	eecd = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD;	E1000_WRITE_REG(hw, E1000_EECD, eecd);	for (i = 0; i < E1000_FLASH_UPDATES; i++) {		msec_delay(1);		if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0)			break;	}	if (i == E1000_FLASH_UPDATES) {		ret_val = -E1000_ERR_NVM;		goto out;	}out:	return ret_val;}/** *  e1000_validate_nvm_checksum_82571 - Validate EEPROM checksum *  @hw: pointer to the HW structure * *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM *  and then verifies that the sum of the EEPROM is equal to 0xBABA. **/static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw){	DEBUGFUNC("e1000_validate_nvm_checksum_82571");	if (hw->nvm.type == e1000_nvm_flash_hw)		e1000_fix_nvm_checksum_82571(hw);	return e1000_validate_nvm_checksum_generic(hw);}/** *  e1000_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon *  @hw: pointer to the HW structure *  @offset: offset within the EEPROM to be written to *  @words: number of words to write *  @data: 16 bit word(s) to be written to the EEPROM * *  After checking for invalid values, poll the EEPROM to ensure the previous *  command has completed before trying to write the next word.  After write *  poll for completion. * *  If e1000_update_nvm_checksum is not called after this function, the *  EEPROM will most likley contain an invalid checksum. **/static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,                                      u16 words, u16 *data){	struct e1000_nvm_info *nvm = &hw->nvm;	u32 i, eewr = 0;	s32 ret_val = 0;	DEBUGFUNC("e1000_write_nvm_eewr_82571");	/* A check for invalid values:  offset too large, too many words,	 * and not enough words. */	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||	    (words == 0)) {		DEBUGOUT("nvm parameter(s) out of bounds\n");		ret_val = -E1000_ERR_NVM;		goto out;	}	for (i = 0; i < words; i++) {		eewr = (data[i] << E1000_NVM_RW_REG_DATA) |		       ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |		       E1000_NVM_RW_REG_START;		ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);		if (ret_val)			break;		E1000_WRITE_REG(hw, E1000_EEWR, eewr);		ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);		if (ret_val)			break;	}out:	return ret_val;}/** *  e1000_get_cfg_done_82571 - Poll for configuration done *  @hw: pointer to the HW structure * *  Reads the management control register for the config done bit to be set. **/static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw){	s32 timeout = PHY_CFG_TIMEOUT;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_get_cfg_done_82571");	while (timeout) {		if (E1000_READ_REG(hw, E1000_EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0)			break;		msec_delay(1);		timeout--;	}	if (!timeout) {		DEBUGOUT("MNG configuration cycle has not completed.\n");		ret_val = -E1000_ERR_RESET;		goto out;	}out:	return ret_val;}/** *  e1000_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state *  @hw: pointer to the HW structure *  @active: TRUE to enable LPLU, FALSE to disable * *  Sets the LPLU D0 state according to the active flag.  When activating LPLU *  this function also disables smart speed and vice versa.  LPLU will not be *  activated unless the device autonegotiation advertisement meets standards *  of either 10 or 10/100 or 10/100/1000 at all duplexes.  This is a function *  pointer entry point only called by PHY setup routines. **/static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, boolean_t active){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val;	u16 data;	DEBUGFUNC("e1000_set_d0_lplu_state_82571");	ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);	if (ret_val)		goto out;	if (active) {		data |= IGP02E1000_PM_D0_LPLU;		ret_val = e1000_write_phy_reg(hw,		                              IGP02E1000_PHY_POWER_MGMT,		                              data);		if (ret_val)			goto out;		/* When LPLU is enabled, we should disable SmartSpeed */		ret_val = e1000_read_phy_reg(hw,		                             IGP01E1000_PHY_PORT_CONFIG,		                             &data);		data &= ~IGP01E1000_PSCFR_SMART_SPEED;		ret_val = e1000_write_phy_reg(hw,		                              IGP01E1000_PHY_PORT_CONFIG,		                              data);		if (ret_val)			goto out;	} else {		data &= ~IGP02E1000_PM_D0_LPLU;		ret_val = e1000_write_phy_reg(hw,		                              IGP02E1000_PHY_POWER_MGMT,		                              data);		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used		 * during Dx states where the power conservation is most		 * important.  During driver activity we should enable		 * SmartSpeed, so performance is maintained. */		if (phy->smart_speed == e1000_smart_speed_on) {			ret_val = e1000_read_phy_reg(hw,			                             IGP01E1000_PHY_PORT_CONFIG,			                             &data);			if (ret_val)				goto out;			data |= IGP01E1000_PSCFR_SMART_SPEED;			ret_val = e1000_write_phy_reg(hw,			                             IGP01E1000_PHY_PORT_CONFIG,			                             data);			if (ret_val)				goto out;		} else if (phy->smart_speed == e1000_smart_speed_off) {			ret_val = e1000_read_phy_reg(hw,			                             IGP01E1000_PHY_PORT_CONFIG,			                             &data);			if (ret_val)				goto out;			data &= ~IGP01E1000_PSCFR_SMART_SPEED;			ret_val = e1000_write_phy_reg(hw,			                             IGP01E1000_PHY_PORT_CONFIG,			                             data);			if (ret_val)				goto out;		}	}out:	return ret_val;}/** *  e1000_reset_hw_82571 - Reset hardware *  @hw: pointer to the HW structure * *  This resets the hardware into a known state.  This is a *  function pointer entry point called by the api module. **/static s32 e1000_reset_hw_82571(struct e1000_hw *hw){	u32 ctrl, extcnf_ctrl, ctrl_ext, icr;	s32 ret_val;	u16 i = 0;	DEBUGFUNC("e1000_reset_hw_82571");	/* Prevent the PCI-E bus from sticking if there is no TLP connection	 * on the last TLP read/write transaction when MAC is reset.	 */	ret_val = e1000_disable_pcie_master_generic(hw);	if (ret_val) {		DEBUGOUT("PCI-E Master disable polling has failed.\n");	}	DEBUGOUT("Masking off all interrupts\n");	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);	E1000_WRITE_REG(hw, E1000_RCTL, 0);	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);	E1000_WRITE_FLUSH(hw);	msec_delay(10);	/* Must acquire the MDIO ownership before MAC reset.	 * Ownership defaults to firmware after a reset. */	if (hw->mac.type == e1000_82573) {		extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);		extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;		do {			E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);			extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);			if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)				break;			extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;			msec_delay(2);			i++;		} while (i < MDIO_OWNERSHIP_TIMEOUT);	}	ctrl = E1000_READ_REG(hw, E1000_CTRL);	DEBUGOUT("Issuing a global reset to MAC\n");	E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);	if (hw->nvm.type == e1000_nvm_flash_hw) {		usec_delay(10);		ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);		ctrl_ext |= E1000_CTRL_EXT_EE_RST;		E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);		E1000_WRITE_FLUSH(hw);	}	ret_val = e1000_get_auto_rd_done_generic(hw);	if (ret_val)		/* We don't want to continue accessing MAC registers. */		goto out;	/* Phy configuration from NVM just starts after EECD_AUTO_RD is set.	 * Need to wait for Phy configuration completion before accessing	 * NVM and Phy.	 */	if (hw->mac.type == e1000_82573)		msec_delay(25);	/* Clear any pending interrupt events. */	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);	icr = E1000_READ_REG(hw, E1000_ICR);out:	return ret_val;}/** *  e1000_init_hw_82571 - Initialize hardware *  @hw: pointer to the HW structure * *  This inits the hardware readying it for operation. **/static s32 e1000_init_hw_82571(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 reg_data;	s32 ret_val;	u16 i, rar_count = mac->rar_entry_count;	DEBUGFUNC("e1000_init_hw_82571");	e1000_initialize_hw_bits_82571(hw);	/* Initialize identification LED */	ret_val = e1000_id_led_init_generic(hw);	if (ret_val) {		DEBUGOUT("Error initializing identification LED\n");		goto out;	}	/* Disabling VLAN filtering */	DEBUGOUT("Initializing the IEEE VLAN\n");	e1000_clear_vfta(hw);	/* Setup the receive address. */	/* If, however, a locally administered address was assigned to the	 * 82571, we must reserve a RAR for it to work around an issue where	 * resetting one port will reload the MAC on the other port.	 */	if (e1000_get_laa_state_82571(hw) == TRUE)		rar_count--;	e1000_init_rx_addrs_generic(hw, rar_count);	/* Zero out the Multicast HASH table */	DEBUGOUT("Zeroing the MTA\n");	for (i = 0; i < mac->mta_reg_count; i++)		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);	/* Setup link and flow control */	ret_val = e1000_setup_link(hw);	/* Set the transmit descriptor write-back policy */	reg_data = E1000_READ_REG(hw, E1000_TXDCTL);	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |	           E1000_TXDCTL_FULL_TX_DESC_WB |	           E1000_TXDCTL_COUNT_DESC;	E1000_WRITE_REG(hw, E1000_TXDCTL, reg_data);	/* ...for both queues. */	if (mac->type != e1000_82573) {		reg_data = E1000_READ_REG(hw, E1000_TXDCTL1);		reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |

⌨️ 快捷键说明

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