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

📄 lib.c

📁 grub源码分析文档
💻 C
📖 第 1 页 / 共 5 页
字号:
/** *  e1000e_write_nvm_spi - Write to EEPROM using SPI *  @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 * *  Writes data to EEPROM at offset using SPI interface. * *  If e1000e_update_nvm_checksum is not called after this function , the *  EEPROM will most likely contain an invalid checksum. **/s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data){	struct e1000_nvm_info *nvm = &hw->nvm;	s32 ret_val;	u16 widx = 0;	/*	 * 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)) {		hw_dbg(hw, "nvm parameter(s) out of bounds\n");		return -E1000_ERR_NVM;	}	ret_val = nvm->ops.acquire_nvm(hw);	if (ret_val)		return ret_val;	msleep(10);	while (widx < words) {		u8 write_opcode = NVM_WRITE_OPCODE_SPI;		ret_val = e1000_ready_nvm_eeprom(hw);		if (ret_val) {			nvm->ops.release_nvm(hw);			return ret_val;		}		e1000_standby_nvm(hw);		/* Send the WRITE ENABLE command (8 bit opcode) */		e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,					 nvm->opcode_bits);		e1000_standby_nvm(hw);		/*		 * Some SPI eeproms use the 8th address bit embedded in the		 * opcode		 */		if ((nvm->address_bits == 8) && (offset >= 128))			write_opcode |= NVM_A8_OPCODE_SPI;		/* Send the Write command (8-bit opcode + addr) */		e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);		e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),					 nvm->address_bits);		/* Loop to allow for up to whole page write of eeprom */		while (widx < words) {			u16 word_out = data[widx];			word_out = (word_out >> 8) | (word_out << 8);			e1000_shift_out_eec_bits(hw, word_out, 16);			widx++;			if ((((offset + widx) * 2) % nvm->page_size) == 0) {				e1000_standby_nvm(hw);				break;			}		}	}	msleep(10);	return 0;}/** *  e1000e_read_mac_addr - Read device MAC address *  @hw: pointer to the HW structure * *  Reads the device MAC address from the EEPROM and stores the value. *  Since devices with two ports use the same EEPROM, we increment the *  last bit in the MAC address for the second port. **/s32 e1000e_read_mac_addr(struct e1000_hw *hw){	s32 ret_val;	u16 offset, nvm_data, i;	u16 mac_addr_offset = 0;	if (hw->mac.type == e1000_82571) {		/* Check for an alternate MAC address.  An alternate MAC		 * address can be setup by pre-boot software and must be		 * treated like a permanent address and must override the		 * actual permanent MAC address.*/		ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,		                         &mac_addr_offset);		if (ret_val) {			hw_dbg(hw, "NVM Read Error\n");			return ret_val;		}		if (mac_addr_offset == 0xFFFF)			mac_addr_offset = 0;		if (mac_addr_offset) {			if (hw->bus.func == E1000_FUNC_1)				mac_addr_offset += ETH_ALEN/sizeof(u16);			/* make sure we have a valid mac address here			* before using it */			ret_val = e1000_read_nvm(hw, mac_addr_offset, 1,			                         &nvm_data);			if (ret_val) {				hw_dbg(hw, "NVM Read Error\n");				return ret_val;			}			if (nvm_data & 0x0001)				mac_addr_offset = 0;		}		if (mac_addr_offset)		hw->dev_spec.e82571.alt_mac_addr_is_present = 1;	}	for (i = 0; i < ETH_ALEN; i += 2) {		offset = mac_addr_offset + (i >> 1);		ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);		if (ret_val) {			hw_dbg(hw, "NVM Read Error\n");			return ret_val;		}		hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);		hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);	}	/* Flip last bit of mac address if we're on second port */	if (!mac_addr_offset && hw->bus.func == E1000_FUNC_1)		hw->mac.perm_addr[5] ^= 1;	for (i = 0; i < ETH_ALEN; i++)		hw->mac.addr[i] = hw->mac.perm_addr[i];	return 0;}/** *  e1000e_validate_nvm_checksum_generic - 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. **/s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw){	s32 ret_val;	u16 checksum = 0;	u16 i, nvm_data;	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {		ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);		if (ret_val) {			hw_dbg(hw, "NVM Read Error\n");			return ret_val;		}		checksum += nvm_data;	}	if (checksum != (u16) NVM_SUM) {		hw_dbg(hw, "NVM Checksum Invalid\n");		return -E1000_ERR_NVM;	}	return 0;}/** *  e1000e_update_nvm_checksum_generic - 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. **/s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw){	s32 ret_val;	u16 checksum = 0;	u16 i, nvm_data;	for (i = 0; i < NVM_CHECKSUM_REG; i++) {		ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);		if (ret_val) {			hw_dbg(hw, "NVM Read Error while updating checksum.\n");			return ret_val;		}		checksum += nvm_data;	}	checksum = (u16) NVM_SUM - checksum;	ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum);	if (ret_val)		hw_dbg(hw, "NVM Write Error while updating checksum.\n");	return ret_val;}/** *  e1000e_reload_nvm - Reloads EEPROM *  @hw: pointer to the HW structure * *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the *  extended control register. **/void e1000e_reload_nvm(struct e1000_hw *hw){	u32 ctrl_ext;	udelay(10);	ctrl_ext = er32(CTRL_EXT);	ctrl_ext |= E1000_CTRL_EXT_EE_RST;	ew32(CTRL_EXT, ctrl_ext);	e1e_flush();}/** *  e1000_calculate_checksum - Calculate checksum for buffer *  @buffer: pointer to EEPROM *  @length: size of EEPROM to calculate a checksum for * *  Calculates the checksum for some buffer on a specified length.  The *  checksum calculated is returned. **/static u8 e1000_calculate_checksum(u8 *buffer, u32 length){	u32 i;	u8  sum = 0;	if (!buffer)		return 0;	for (i = 0; i < length; i++)		sum += buffer[i];	return (u8) (0 - sum);}/** *  e1000_mng_enable_host_if - Checks host interface is enabled *  @hw: pointer to the HW structure * *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND * *  This function checks whether the HOST IF is enabled for command operation *  and also checks whether the previous command is completed.  It busy waits *  in case of previous command is not completed. **/static s32 e1000_mng_enable_host_if(struct e1000_hw *hw){	u32 hicr;	u8 i;	/* Check that the host interface is enabled. */	hicr = er32(HICR);	if ((hicr & E1000_HICR_EN) == 0) {		hw_dbg(hw, "E1000_HOST_EN bit disabled.\n");		return -E1000_ERR_HOST_INTERFACE_COMMAND;	}	/* check the previous command is completed */	for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {		hicr = er32(HICR);		if (!(hicr & E1000_HICR_C))			break;		mdelay(1);	}	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {		hw_dbg(hw, "Previous command timeout failed .\n");		return -E1000_ERR_HOST_INTERFACE_COMMAND;	}	return 0;}/** *  e1000e_check_mng_mode - check management mode *  @hw: pointer to the HW structure * *  Reads the firmware semaphore register and returns true (>0) if *  manageability is enabled, else false (0). **/bool e1000e_check_mng_mode(struct e1000_hw *hw){	u32 fwsm = er32(FWSM);	return (fwsm & E1000_FWSM_MODE_MASK) == hw->mac.ops.mng_mode_enab;}/** *  e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx *  @hw: pointer to the HW structure * *  Enables packet filtering on transmit packets if manageability is enabled *  and host interface is enabled. **/bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw){	struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;	u32 *buffer = (u32 *)&hw->mng_cookie;	u32 offset;	s32 ret_val, hdr_csum, csum;	u8 i, len;	/* No manageability, no filtering */	if (!e1000e_check_mng_mode(hw)) {		hw->mac.tx_pkt_filtering = 0;		return 0;	}	/*	 * If we can't read from the host interface for whatever	 * reason, disable filtering.	 */	ret_val = e1000_mng_enable_host_if(hw);	if (ret_val != 0) {		hw->mac.tx_pkt_filtering = 0;		return ret_val;	}	/* Read in the header.  Length and offset are in dwords. */	len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;	offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;	for (i = 0; i < len; i++)		*(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset + i);	hdr_csum = hdr->checksum;	hdr->checksum = 0;	csum = e1000_calculate_checksum((u8 *)hdr,					E1000_MNG_DHCP_COOKIE_LENGTH);	/*	 * If either the checksums or signature don't match, then	 * the cookie area isn't considered valid, in which case we	 * take the safe route of assuming Tx filtering is enabled.	 */	if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {		hw->mac.tx_pkt_filtering = 1;		return 1;	}	/* Cookie area is valid, make the final check for filtering. */	if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {		hw->mac.tx_pkt_filtering = 0;		return 0;	}	hw->mac.tx_pkt_filtering = 1;	return 1;}/** *  e1000_mng_write_cmd_header - Writes manageability command header *  @hw: pointer to the HW structure *  @hdr: pointer to the host interface command header * *  Writes the command header after does the checksum calculation. **/static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,				  struct e1000_host_mng_command_header *hdr){	u16 i, length = sizeof(struct e1000_host_mng_command_header);	/* Write the whole command header structure with new checksum. */	hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);	length >>= 2;	/* Write the relevant command block into the ram area. */	for (i = 0; i < length; i++) {		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i,					    *((u32 *) hdr + i));		e1e_flush();	}	return 0;}/** *  e1000_mng_host_if_write - Writes to the manageability host interface *  @hw: pointer to the HW structure *  @buffer: pointer to the host interface buffer *  @length: size of the buffer *  @offset: location in the buffer to write to *  @sum: sum of the data (not checksum) * *  This function writes the buffer content at the offset given on the host if. *  It also does alignment considerations to do the writes in most efficient *  way.  Also fills up the sum of the buffer in *buffer parameter. **/static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,				   u16 length, u16 offset, u8 *sum){	u8 *tmp;	u8 *bufptr = buffer;	u32 data = 0;	u16 remaining, i, j, prev_bytes;	/* sum = only sum of the data and it is not checksum */	if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)		return -E1000_ERR_PARAM;	tmp = (u8 *)&data;	prev_bytes = offset & 0x3;	offset >>= 2;	if (prev_bytes) {		data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset);		for (j = prev_bytes; j < sizeof(u32); j++) {			*(tmp + j) = *bufptr++;			*sum += *(tmp + j);		}		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data);		length -= j - prev_bytes;		offset++;	}	remaining = length & 0x3;	length -= remaining;	/* Calculate length in DWORDs */	length >>= 2;	/*	 * The device driver writes the relevant command block into the	 * ram area.	 */	for (i = 0; i < length; i++) {		for (j = 0; j < sizeof(u32); j++) {			*(tmp + j) = *bufptr++;			*sum += *(tmp + j);		}		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);	}	if (remaining) {		for (j = 0; j < sizeof(u32); j++) {			if (j < remaining)				*(tmp + j) = *bufptr++;			else				*(tmp + j) = 0;			*sum += *(tmp + j);		}		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);	}	return 0;}/** *  e1000e_mng_write_dhcp_info - Writes DHCP info to host interface *  @hw: pointer to the HW structure *  @buffer: pointer to the host interface *  @length: size of the buffer * *  Writes the DHCP information to the host interface. **/s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length){	struct e1000_host_mng_command_header hdr;	s32 ret_val;	u32 hicr;	hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;	hdr.command_length = length;	hdr.reserved1 = 0;	hdr.reserved2 = 0;	hdr.checksum = 0;	/* Enabl

⌨️ 快捷键说明

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