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

📄 e1000_ich8lan.c

📁 DELL755 Intel 网卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
		hsflctl.hsf_ctrl.fldbcount = size - 1;		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;		E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);		ret_val = e1000_flash_cycle_ich8lan(hw,		                                ICH_FLASH_READ_COMMAND_TIMEOUT);		/*		 * Check if FCERR is set to 1, if set to 1, clear it		 * and try the whole sequence a few more times, else		 * read in (shift in) the Flash Data0, the order is		 * least significant byte first msb to lsb		 */		if (ret_val == E1000_SUCCESS) {			flash_data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0);			if (size == 1) {				*data = (u8)(flash_data & 0x000000FF);			} else if (size == 2) {				*data = (u16)(flash_data & 0x0000FFFF);			}			break;		} else {			/*			 * If we've gotten here, then things are probably			 * 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_nvm_ich8lan - Write word(s) to the NVM *  @hw: pointer to the HW structure *  @offset: The offset (in bytes) of the word(s) to write. *  @words: Size of data to write in words *  @data: Pointer to the word(s) to write at offset. * *  Writes a byte or word to the NVM using the flash access registers. **/static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,                                   u16 *data){	struct e1000_nvm_info *nvm = &hw->nvm;	struct e1000_dev_spec_ich8lan *dev_spec;	s32 ret_val = E1000_SUCCESS;	u16 i;	DEBUGFUNC("e1000_write_nvm_ich8lan");	dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec;	if (!dev_spec) {		DEBUGOUT("dev_spec pointer is set to NULL.\n");		ret_val = -E1000_ERR_CONFIG;		goto out;	}	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;	}	ret_val = nvm->ops.acquire(hw);	if (ret_val)		goto out;	for (i = 0; i < words; i++) {		dev_spec->shadow_ram[offset+i].modified = true;		dev_spec->shadow_ram[offset+i].value = data[i];	}	nvm->ops.release(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 successful 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 = nvm->ops.acquire(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");		nvm->ops.release(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) {		nvm->ops.release(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) {		nvm->ops.release(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;	}	nvm->ops.release(hw);	/*	 * Reload the EEPROM, or else modifications will not appear	 * until after the next adapter reset.	 */	nvm->ops.reload(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 = hw->nvm.ops.read(hw, 0x19, 1, &data);	if (ret_val)		goto out;	if ((data & 0x40) == 0) {		data |= 0x40;		ret_val = hw->nvm.ops.write(hw, 0x19, 1, &data);		if (ret_val)			goto out;		ret_val = hw->nvm.ops.update(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;

⌨️ 快捷键说明

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