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

📄 e1000_ich8lan.c

📁 linux系统的网卡驱动包
💻 C
📖 第 1 页 / 共 5 页
字号:
	e1000_release_nvm(hw);out:	return ret_val;}/** *  e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM *  @hw: pointer to the HW structure * *  The NVM checksum is updated by calling the generic update_nvm_checksum, *  which writes the checksum to the shadow ram.  The changes in the shadow *  ram are then committed to the EEPROM by processing each bank at a time *  checking for the modified bit and writing only the pending changes. *  After a succesful commit, the shadow ram is cleared and is ready for *  future writes. **/static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw){	struct e1000_nvm_info *nvm = &hw->nvm;	struct e1000_dev_spec_ich8lan *dev_spec;	u32 i, act_offset, new_bank_offset, old_bank_offset, bank;	s32 ret_val;	u16 data;	DEBUGFUNC("e1000_update_nvm_checksum_ich8lan");	dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec;	ret_val = e1000_update_nvm_checksum_generic(hw);	if (ret_val)		goto out;	if (nvm->type != e1000_nvm_flash_sw)		goto out;	ret_val = e1000_acquire_nvm(hw);	if (ret_val)		goto out;	/*	 * We're writing to the opposite bank so if we're on bank 1,	 * write to bank 0 etc.  We also need to erase the segment that	 * is going to be written	 */	ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);	if (ret_val != E1000_SUCCESS)		goto out;	if (bank == 0) {		new_bank_offset = nvm->flash_bank_size;		old_bank_offset = 0;		e1000_erase_flash_bank_ich8lan(hw, 1);	} else {		old_bank_offset = nvm->flash_bank_size;		new_bank_offset = 0;		e1000_erase_flash_bank_ich8lan(hw, 0);	}	for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {		/*		 * Determine whether to write the value stored		 * in the other NVM bank or a modified value stored		 * in the shadow RAM		 */		if (dev_spec->shadow_ram[i].modified) {			data = dev_spec->shadow_ram[i].value;		} else {			e1000_read_flash_word_ich8lan(hw,			                              i + old_bank_offset,			                              &data);		}		/*		 * If the word is 0x13, then make sure the signature bits		 * (15:14) are 11b until the commit has completed.		 * This will allow us to write 10b which indicates the		 * signature is valid.  We want to do this after the write		 * has completed so that we don't mark the segment valid		 * while the write is still in progress		 */		if (i == E1000_ICH_NVM_SIG_WORD)			data |= E1000_ICH_NVM_SIG_MASK;		/* Convert offset to bytes. */		act_offset = (i + new_bank_offset) << 1;		usec_delay(100);		/* Write the bytes to the new bank. */		ret_val = e1000_retry_write_flash_byte_ich8lan(hw,		                                               act_offset,		                                               (u8)data);		if (ret_val)			break;		usec_delay(100);		ret_val = e1000_retry_write_flash_byte_ich8lan(hw,		                                          act_offset + 1,		                                          (u8)(data >> 8));		if (ret_val)			break;	}	/*	 * Don't bother writing the segment valid bits if sector	 * programming failed.	 */	if (ret_val) {		DEBUGOUT("Flash commit failed.\n");		e1000_release_nvm(hw);		goto out;	}	/*	 * Finally validate the new segment by setting bit 15:14	 * to 10b in word 0x13 , this can be done without an	 * erase as well since these bits are 11 to start with	 * and we need to change bit 14 to 0b	 */	act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;	e1000_read_flash_word_ich8lan(hw, act_offset, &data);	data &= 0xBFFF;	ret_val = e1000_retry_write_flash_byte_ich8lan(hw,	                                               act_offset * 2 + 1,	                                               (u8)(data >> 8));	if (ret_val) {		e1000_release_nvm(hw);		goto out;	}	/*	 * And invalidate the previously valid segment by setting	 * its signature word (0x13) high_byte to 0b. This can be	 * done without an erase because flash erase sets all bits	 * to 1's. We can write 1's to 0's without an erase	 */	act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;	ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);	if (ret_val) {		e1000_release_nvm(hw);		goto out;	}	/* Great!  Everything worked, we can now clear the cached entries. */	for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {		dev_spec->shadow_ram[i].modified = FALSE;		dev_spec->shadow_ram[i].value = 0xFFFF;	}	e1000_release_nvm(hw);	/*	 * Reload the EEPROM, or else modifications will not appear	 * until after the next adapter reset.	 */	e1000_reload_nvm(hw);	msec_delay(10);out:	return ret_val;}/** *  e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum *  @hw: pointer to the HW structure * *  Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. *  If the bit is 0, that the EEPROM had been modified, but the checksum was *  not calculated, in which case we need to calculate the checksum and set *  bit 6. **/static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw){	s32 ret_val = E1000_SUCCESS;	u16 data;	DEBUGFUNC("e1000_validate_nvm_checksum_ich8lan");	/*	 * Read 0x19 and check bit 6.  If this bit is 0, the checksum	 * needs to be fixed.  This bit is an indication that the NVM	 * was prepared by OEM software and did not calculate the	 * checksum...a likely scenario.	 */	ret_val = e1000_read_nvm(hw, 0x19, 1, &data);	if (ret_val)		goto out;	if ((data & 0x40) == 0) {		data |= 0x40;		ret_val = e1000_write_nvm(hw, 0x19, 1, &data);		if (ret_val)			goto out;		ret_val = e1000_update_nvm_checksum(hw);		if (ret_val)			goto out;	}	ret_val = e1000_validate_nvm_checksum_generic(hw);out:	return ret_val;}/** *  e1000_write_flash_data_ich8lan - Writes bytes to the NVM *  @hw: pointer to the HW structure *  @offset: The offset (in bytes) of the byte/word to read. *  @size: Size of data to read, 1=byte 2=word *  @data: The byte(s) to write to the NVM. * *  Writes one/two bytes to the NVM using the flash access registers. **/static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,                                          u8 size, u16 data){	union ich8_hws_flash_status hsfsts;	union ich8_hws_flash_ctrl hsflctl;	u32 flash_linear_addr;	u32 flash_data = 0;	s32 ret_val = -E1000_ERR_NVM;	u8 count = 0;	DEBUGFUNC("e1000_write_ich8_data");	if (size < 1 || size > 2 || data > size * 0xff ||	    offset > ICH_FLASH_LINEAR_ADDR_MASK)		goto out;	flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +	                    hw->nvm.flash_base_addr;	do {		usec_delay(1);		/* Steps */		ret_val = e1000_flash_cycle_init_ich8lan(hw);		if (ret_val != E1000_SUCCESS)			break;		hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */		hsflctl.hsf_ctrl.fldbcount = size -1;		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;		E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);		if (size == 1)			flash_data = (u32)data & 0x00FF;		else			flash_data = (u32)data;		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);		/*		 * check if FCERR is set to 1 , if set to 1, clear it		 * and try the whole sequence a few more times else done		 */		ret_val = e1000_flash_cycle_ich8lan(hw,		                               ICH_FLASH_WRITE_COMMAND_TIMEOUT);		if (ret_val == E1000_SUCCESS) {			break;		} else {			/*			 * If we're here, then things are most likely			 * completely hosed, but if the error condition			 * is detected, it won't hurt to give it another			 * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.			 */			hsfsts.regval = E1000_READ_FLASH_REG16(hw,			                                      ICH_FLASH_HSFSTS);			if (hsfsts.hsf_status.flcerr == 1) {				/* Repeat for some time before giving up. */				continue;			} else if (hsfsts.hsf_status.flcdone == 0) {				DEBUGOUT("Timeout error - flash cycle "				         "did not complete.");				break;			}		}	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);out:	return ret_val;}/** *  e1000_write_flash_byte_ich8lan - Write a single byte to NVM *  @hw: pointer to the HW structure *  @offset: The index of the byte to read. *  @data: The byte to write to the NVM. * *  Writes a single byte to the NVM using the flash access registers. **/static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,                                          u8 data){	u16 word = (u16)data;	DEBUGFUNC("e1000_write_flash_byte_ich8lan");	return e1000_write_flash_data_ich8lan(hw, offset, 1, word);}/** *  e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM *  @hw: pointer to the HW structure *  @offset: The offset of the byte to write. *  @byte: The byte to write to the NVM. * *  Writes a single byte to the NVM using the flash access registers. *  Goes through a retry algorithm before giving up. **/static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,                                                u32 offset, u8 byte){	s32 ret_val;	u16 program_retries;	DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan");	ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);	if (ret_val == E1000_SUCCESS)		goto out;	for (program_retries = 0; program_retries < 100; program_retries++) {		DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset);		usec_delay(100);		ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);		if (ret_val == E1000_SUCCESS)			break;	}	if (program_retries == 100) {		ret_val = -E1000_ERR_NVM;		goto out;	}out:	return ret_val;}/** *  e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM *  @hw: pointer to the HW structure *  @bank: 0 for first bank, 1 for second bank, etc. * *  Erases the bank specified. Each bank is a 4k block. Banks are 0 based. *  bank N is 4096 * N + flash_reg_addr. **/static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank){	struct e1000_nvm_info *nvm = &hw->nvm;	union ich8_hws_flash_status hsfsts;	union ich8_hws_flash_ctrl hsflctl;	u32 flash_linear_addr;	/* bank size is in 16bit words - adjust to bytes */	u32 flash_bank_size = nvm->flash_bank_size * 2;	s32  ret_val = E1000_SUCCESS;	s32  count = 0;	s32  j, iteration, sector_size;	DEBUGFUNC("e1000_erase_flash_bank_ich8lan");	hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);	/*	 * Determine HW Sector size: Read BERASE bits of hw flash status	 * register	 * 00: The Hw sector is 256 bytes, hence we need to erase 16	 *     consecutive sectors.  The start index for the nth Hw sector	 *     can be calculated as = bank * 4096 + n * 256	 * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.	 *     The start index for the nth Hw sector can be calculated	 *     as = bank * 4096	 * 10: The Hw sector is 8K bytes, nth sector = bank * 8192	 *     (ich9 only, otherwise error condition)	 * 11: The Hw sector is 64K bytes, nth sector = bank * 65536	 */	switch (hsfsts.hsf_status.berasesz) {	case 0:		/* Hw sector size 256 */		sector_size = ICH_FLASH_SEG_SIZE_256;		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256;		break;	case 1:		sector_size = ICH_FLASH_SEG_SIZE_4K;		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K;		break;	case 2:		if (hw->mac.type == e1000_ich9lan) {			sector_size = ICH_FLASH_SEG_SIZE_8K;			iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K;		} else {			ret_val = -E1000_ERR_NVM;			goto out;		}		break;	case 3:		sector_size = ICH_FLASH_SEG_SIZE_64K;		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K;		break;	default:		ret_val = -E1000_ERR_NVM;		goto out;	}	/* Start with the base address, then add the sector offset. */	flash_linear_addr = hw->nvm.flash_base_addr;	flash_linear_addr += (bank) ? (sector_size * iteration) : 0;	for (j = 0; j < iteration ; j++) {		do {			/* Steps */			ret_val = e1000_flash_cycle_init_ich8lan(hw);			if (ret_val)				goto out;			/*			 * Write a value 11 (block Erase) in Flash			 * Cycle field in hw flash control			 */			hsflctl.regval = E1000_READ_FLASH_REG16(hw,			                                      ICH_FLASH_HSFCTL);			hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;			E1000_WRITE_FLASH_REG16(hw,			                        ICH_FLASH_HSFCTL,			                        hsflctl.regval);			/*			 * Write the last 24 bits of an index within the			 * block into Flash Linear address field in Flash			 * Address.			 */			flash_linear_addr += (j * sector_size);			E1000_WRITE_FLASH_REG(hw,			                      ICH_FLASH_FADDR,			                      flash_linear_addr);			ret_val = e1000_flash_cycle_ich8lan(hw,			                       ICH_FLASH_ERASE_COMMAND_TIMEOUT);			if (ret_val == E1000_SUCCESS) {				break;			} else {				/*				 * Check if FCERR is set to 1.  If 1,				 * clear it and try the whole sequence

⌨️ 快捷键说明

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