📄 lib.c
字号:
/** * 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 + -