static int
e1000_set_eeprom(struct net_device *netdev,
                      struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
	struct e1000_adapter *adapter = netdev->priv;
	struct e1000_hw *hw = &adapter->hw;
	uint16_t *eeprom_buff;
	void *ptr;
	int max_len, first_word, last_word, ret_val = 0;
	uint16_t i;

	if(eeprom->len == 0)
		return -EOPNOTSUPP;

	if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
		return -EFAULT;

	max_len = hw->eeprom.word_size * 2;

	first_word = eeprom->offset >> 1;
	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
	if(!eeprom_buff)
		return -ENOMEM;

	ptr = (void *)eeprom_buff;

	if(eeprom->offset & 1) {
		/* need read/modify/write of first changed EEPROM word */
		/* only the second byte of the word is being modified */
		ret_val = e1000_read_eeprom(hw, first_word, 1,
					    &eeprom_buff[0]);
		ptr++;
	}
	if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
		/* need read/modify/write of last changed EEPROM word */
		/* only the first byte of the word is being modified */
		ret_val = e1000_read_eeprom(hw, last_word, 1,
		                  &eeprom_buff[last_word - first_word]);
	}

	/* Device's eeprom is always little-endian, word addressable */
	for (i = 0; i < last_word - first_word + 1; i++)
		le16_to_cpus(&eeprom_buff[i]);

	memcpy(ptr, bytes, eeprom->len);

	for (i = 0; i < last_word - first_word + 1; i++)
		eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);

	ret_val = e1000_write_eeprom(hw, first_word,
				     last_word - first_word + 1, eeprom_buff);

	/* Update the checksum over the first part of the EEPROM if needed */
	if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
		e1000_update_eeprom_checksum(hw);

	kfree(eeprom_buff);
	return ret_val;
}
static int
e1000_ethtool_seeprom(struct e1000_adapter *adapter,
                      struct ethtool_eeprom *eeprom, void *user_data)
{
	struct e1000_hw *hw = &adapter->hw;
	uint16_t *eeprom_buff;
	void *ptr;
	int max_len, first_word, last_word, ret_val = 0;

	if(eeprom->len == 0)
		return -EOPNOTSUPP;

	if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
		return -EFAULT;

	max_len = hw->eeprom.word_size * 2;

	if((eeprom->offset + eeprom->len) > max_len)
		eeprom->len = (max_len - eeprom->offset);

	first_word = eeprom->offset >> 1;
	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
	if(!eeprom_buff)
		return -ENOMEM;

	ptr = (void *)eeprom_buff;

	if(eeprom->offset & 1) {
		/* need read/modify/write of first changed EEPROM word */
		/* only the second byte of the word is being modified */
		ret_val = e1000_read_eeprom(hw, first_word, 1,
					    &eeprom_buff[0]);
		ptr++;
	}
	if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
		/* need read/modify/write of last changed EEPROM word */
		/* only the first byte of the word is being modified */
		ret_val = e1000_read_eeprom(hw, last_word, 1,
		                  &eeprom_buff[last_word - first_word]);
	}
	if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) {
		ret_val = -EFAULT;
		goto seeprom_error;
	}

	ret_val = e1000_write_eeprom(hw, first_word,
				     last_word - first_word + 1, eeprom_buff);

	/* Update the checksum over the first part of the EEPROM if needed */
	if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
		e1000_update_eeprom_checksum(hw);

seeprom_error:
	kfree(eeprom_buff);
	return ret_val;
}
static int
e1000_get_eeprom(struct net_device *netdev,
                      struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
	struct e1000_adapter *adapter = netdev->priv;
	struct e1000_hw *hw = &adapter->hw;
	uint16_t *eeprom_buff;
	int first_word, last_word;
	int ret_val = 0;
	uint16_t i;

	if(eeprom->len == 0)
		return -EINVAL;

	eeprom->magic = hw->vendor_id | (hw->device_id << 16);

	first_word = eeprom->offset >> 1;
	last_word = (eeprom->offset + eeprom->len - 1) >> 1;

	eeprom_buff = kmalloc(sizeof(uint16_t) *
			(last_word - first_word + 1), GFP_KERNEL);
	if(!eeprom_buff)
		return -ENOMEM;

	if(hw->eeprom.type == e1000_eeprom_spi)
		ret_val = e1000_read_eeprom(hw, first_word,
					    last_word - first_word + 1,
					    eeprom_buff);
	else {
		for (i = 0; i < last_word - first_word + 1; i++)
			if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
							&eeprom_buff[i])))
				break;
	}

	/* Device's eeprom is always little-endian, word addressable */
	for (i = 0; i < last_word - first_word + 1; i++)
		le16_to_cpus(&eeprom_buff[i]);

	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
			eeprom->len);
	kfree(eeprom_buff);

	return ret_val;
}
static int
e1000_ethtool_geeprom(struct e1000_adapter *adapter,
                      struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
{
	struct e1000_hw *hw = &adapter->hw;
	int first_word, last_word;
	int ret_val = 0;

	if(eeprom->len == 0) {
		ret_val = -EINVAL;
		goto geeprom_error;
	}

	eeprom->magic = hw->vendor_id | (hw->device_id << 16);

	if(eeprom->offset > eeprom->offset + eeprom->len) {
		ret_val = -EINVAL;
		goto geeprom_error;
	}

	if((eeprom->offset + eeprom->len) > (hw->eeprom.word_size * 2))
		eeprom->len = ((hw->eeprom.word_size * 2) - eeprom->offset);

	first_word = eeprom->offset >> 1;
	last_word = (eeprom->offset + eeprom->len - 1) >> 1;

	if(hw->eeprom.type == e1000_eeprom_spi)
		ret_val = e1000_read_eeprom(hw, first_word,
					    last_word - first_word + 1,
					    eeprom_buff);
	else {
		uint16_t i;
		for (i = 0; i < last_word - first_word + 1; i++)
			if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
							&eeprom_buff[i])))
				break;
	}
geeprom_error:
	return ret_val;
}
u32
bd_ans_drv_hw_flags(BOARD_PRIVATE_STRUCT *bps)
{
	u16 data;
	if(bps->hw.mac_type < e1000_82544)
		return IANS_BD_FLAG4;

	if(e1000_read_eeprom(&bps->hw, 3, &data) != 0)
		return 0;

	if((data & 0x0600) == 0x0400)
		return IANS_BD_FLAG4;
	else
		return 0;
}
static int
e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
{
	uint16_t temp;
	uint16_t checksum = 0;
	uint16_t i;

	*data = 0;
	/* Read and add up the contents of the EEPROM */
	for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
		if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
			*data = 1;
			break;
		}
		checksum += temp;
	}

	/* If Checksum is not Correct return error else test passed */
	if((checksum != (uint16_t) EEPROM_SUM) && !(*data))
		*data = 2;

	return *data;
}