static int ixgb_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { struct ixgb_adapter *adapter = netdev_priv(netdev); struct ixgb_hw *hw = &adapter->hw; u16 *eeprom_buff; void *ptr; int max_len, first_word, last_word; u16 i; if (eeprom->len == 0) return -EINVAL; if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EFAULT; max_len = ixgb_get_eeprom_len(netdev); if (eeprom->offset > eeprom->offset + eeprom->len) return -EINVAL; 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 */ eeprom_buff[0] = ixgb_read_eeprom(hw, first_word); ptr++; } if ((eeprom->offset + eeprom->len) & 1) { /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ eeprom_buff[last_word - first_word] = ixgb_read_eeprom(hw, last_word); } memcpy(ptr, bytes, eeprom->len); for (i = 0; i <= (last_word - first_word); i++) ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]); /* Update the checksum over the first part of the EEPROM if needed */ if (first_word <= EEPROM_CHECKSUM_REG) ixgb_update_eeprom_checksum(hw); kfree(eeprom_buff); return 0; }
/****************************************************************************** * Calculates the EEPROM checksum and writes it to the EEPROM * * hw - Struct containing variables accessed by shared code * * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. * Writes the difference to word offset 63 of the EEPROM. *****************************************************************************/ void ixgb_update_eeprom_checksum(struct ixgb_hw *hw) { u16 checksum = 0; u16 i; for (i = 0; i < EEPROM_CHECKSUM_REG; i++) checksum += ixgb_read_eeprom(hw, i); checksum = (u16) EEPROM_SUM - checksum; ixgb_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum); }
/****************************************************************************** * Calculates the EEPROM checksum and writes it to the EEPROM * * hw - Struct containing variables accessed by shared code * * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. * Writes the difference to word offset 63 of the EEPROM. *****************************************************************************/ void ixgb_update_eeprom_checksum(struct ixgb_hw *hw) { uint16_t checksum = 0; uint16_t i; for(i = 0; i < EEPROM_CHECKSUM_REG; i++) checksum += ixgb_read_eeprom(hw, i); checksum = (uint16_t)EEPROM_SUM - checksum; ixgb_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum); return; }
static int ixgb_ethtool_seeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; /* We are under rtnl, so static is OK */ static uint16_t eeprom_buff[IXGB_EEPROM_SIZE]; int i, first_word, last_word; char *ptr; if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EFAULT; first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; ptr = (char *)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 */ eeprom_buff[0] = ixgb_read_eeprom(hw, first_word); ptr++; } if ((eeprom->offset + eeprom->len) & 1) { /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ eeprom_buff[last_word - first_word] = ixgb_read_eeprom(hw, last_word); } memcpy(ptr, data, eeprom->len); for (i = 0; i <= (last_word - first_word); i++) ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]); /* Update the checksum over the first part of the EEPROM if needed */ if (first_word <= EEPROM_CHECKSUM_REG) ixgb_update_eeprom_checksum(hw); return 0; }