|
@@ -1308,6 +1308,117 @@ static int ks8851_nway_reset(struct net_device *dev)
|
|
|
return mii_nway_restart(&ks->mii);
|
|
|
}
|
|
|
|
|
|
+static int ks8851_get_eeprom_len(struct net_device *dev)
|
|
|
+{
|
|
|
+ struct ks8851_net *ks = netdev_priv(dev);
|
|
|
+ return ks->eeprom_size;
|
|
|
+}
|
|
|
+
|
|
|
+static int ks8851_get_eeprom(struct net_device *dev,
|
|
|
+ struct ethtool_eeprom *eeprom, u8 *bytes)
|
|
|
+{
|
|
|
+ struct ks8851_net *ks = netdev_priv(dev);
|
|
|
+ u16 *eeprom_buff;
|
|
|
+ int first_word;
|
|
|
+ int last_word;
|
|
|
+ int ret_val = 0;
|
|
|
+ u16 i;
|
|
|
+
|
|
|
+ if (eeprom->len == 0)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (eeprom->len > ks->eeprom_size)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ eeprom->magic = ks8851_rdreg16(ks, KS_CIDER);
|
|
|
+
|
|
|
+ first_word = eeprom->offset >> 1;
|
|
|
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
|
|
|
+
|
|
|
+ eeprom_buff = kmalloc(sizeof(u16) *
|
|
|
+ (last_word - first_word + 1), GFP_KERNEL);
|
|
|
+ if (!eeprom_buff)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ for (i = 0; i < last_word - first_word + 1; i++)
|
|
|
+ eeprom_buff[i] = ks8851_eeprom_read(dev, first_word + 1);
|
|
|
+
|
|
|
+ /* Device's eeprom is little-endian, word addressable */
|
|
|
+ for (i = 0; i < last_word - first_word + 1; i++)
|
|
|
+ le16_to_cpus(&eeprom_buff[i]);
|
|
|
+
|
|
|
+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
|
|
|
+ kfree(eeprom_buff);
|
|
|
+
|
|
|
+ return ret_val;
|
|
|
+}
|
|
|
+
|
|
|
+static int ks8851_set_eeprom(struct net_device *dev,
|
|
|
+ struct ethtool_eeprom *eeprom, u8 *bytes)
|
|
|
+{
|
|
|
+ struct ks8851_net *ks = netdev_priv(dev);
|
|
|
+ u16 *eeprom_buff;
|
|
|
+ void *ptr;
|
|
|
+ int max_len;
|
|
|
+ int first_word;
|
|
|
+ int last_word;
|
|
|
+ int ret_val = 0;
|
|
|
+ u16 i;
|
|
|
+
|
|
|
+ if (eeprom->len == 0)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ if (eeprom->len > ks->eeprom_size)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (eeprom->magic != ks8851_rdreg16(ks, KS_CIDER))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ first_word = eeprom->offset >> 1;
|
|
|
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
|
|
|
+ max_len = (last_word - first_word + 1) * 2;
|
|
|
+ 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] = ks8851_eeprom_read(dev, 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] =
|
|
|
+ ks8851_eeprom_read(dev, last_word);
|
|
|
+
|
|
|
+
|
|
|
+ /* Device's eeprom is little-endian, word addressable */
|
|
|
+ le16_to_cpus(&eeprom_buff[0]);
|
|
|
+ le16_to_cpus(&eeprom_buff[last_word - first_word]);
|
|
|
+
|
|
|
+ memcpy(ptr, bytes, eeprom->len);
|
|
|
+
|
|
|
+ for (i = 0; i < last_word - first_word + 1; i++)
|
|
|
+ eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
|
|
|
+
|
|
|
+ ks8851_eeprom_write(dev, EEPROM_OP_EWEN, 0, 0);
|
|
|
+
|
|
|
+ for (i = 0; i < last_word - first_word + 1; i++) {
|
|
|
+ ks8851_eeprom_write(dev, EEPROM_OP_WRITE, first_word + i,
|
|
|
+ eeprom_buff[i]);
|
|
|
+ mdelay(EEPROM_WRITE_TIME);
|
|
|
+ }
|
|
|
+
|
|
|
+ ks8851_eeprom_write(dev, EEPROM_OP_EWDS, 0, 0);
|
|
|
+
|
|
|
+ kfree(eeprom_buff);
|
|
|
+ return ret_val;
|
|
|
+}
|
|
|
+
|
|
|
static const struct ethtool_ops ks8851_ethtool_ops = {
|
|
|
.get_drvinfo = ks8851_get_drvinfo,
|
|
|
.get_msglevel = ks8851_get_msglevel,
|
|
@@ -1316,6 +1427,9 @@ static const struct ethtool_ops ks8851_ethtool_ops = {
|
|
|
.set_settings = ks8851_set_settings,
|
|
|
.get_link = ks8851_get_link,
|
|
|
.nway_reset = ks8851_nway_reset,
|
|
|
+ .get_eeprom_len = ks8851_get_eeprom_len,
|
|
|
+ .get_eeprom = ks8851_get_eeprom,
|
|
|
+ .set_eeprom = ks8851_set_eeprom,
|
|
|
};
|
|
|
|
|
|
/* MII interface controls */
|