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; }