|
@@ -59,6 +59,9 @@
|
|
#define BLINK_MS 250
|
|
#define BLINK_MS 250
|
|
#define LINK_HZ HZ
|
|
#define LINK_HZ HZ
|
|
|
|
|
|
|
|
+#define SKGE_EEPROM_MAGIC 0x9933aabb
|
|
|
|
+
|
|
|
|
+
|
|
MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
|
|
MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
|
|
MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
|
|
MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_LICENSE("GPL");
|
|
@@ -798,6 +801,98 @@ static int skge_phys_id(struct net_device *dev, u32 data)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int skge_get_eeprom_len(struct net_device *dev)
|
|
|
|
+{
|
|
|
|
+ struct skge_port *skge = netdev_priv(dev);
|
|
|
|
+ u32 reg2;
|
|
|
|
+
|
|
|
|
+ pci_read_config_dword(skge->hw->pdev, PCI_DEV_REG2, ®2);
|
|
|
|
+ return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static u32 skge_vpd_read(struct pci_dev *pdev, int cap, u16 offset)
|
|
|
|
+{
|
|
|
|
+ u32 val;
|
|
|
|
+
|
|
|
|
+ pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset);
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
|
|
|
|
+ } while (!(offset & PCI_VPD_ADDR_F));
|
|
|
|
+
|
|
|
|
+ pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val);
|
|
|
|
+ return val;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void skge_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val)
|
|
|
|
+{
|
|
|
|
+ pci_write_config_dword(pdev, cap + PCI_VPD_DATA, val);
|
|
|
|
+ pci_write_config_word(pdev, cap + PCI_VPD_ADDR,
|
|
|
|
+ offset | PCI_VPD_ADDR_F);
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
|
|
|
|
+ } while (offset & PCI_VPD_ADDR_F);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int skge_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
|
|
|
|
+ u8 *data)
|
|
|
|
+{
|
|
|
|
+ struct skge_port *skge = netdev_priv(dev);
|
|
|
|
+ struct pci_dev *pdev = skge->hw->pdev;
|
|
|
|
+ int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
|
|
|
|
+ int length = eeprom->len;
|
|
|
|
+ u16 offset = eeprom->offset;
|
|
|
|
+
|
|
|
|
+ if (!cap)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ eeprom->magic = SKGE_EEPROM_MAGIC;
|
|
|
|
+
|
|
|
|
+ while (length > 0) {
|
|
|
|
+ u32 val = skge_vpd_read(pdev, cap, offset);
|
|
|
|
+ int n = min_t(int, length, sizeof(val));
|
|
|
|
+
|
|
|
|
+ memcpy(data, &val, n);
|
|
|
|
+ length -= n;
|
|
|
|
+ data += n;
|
|
|
|
+ offset += n;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int skge_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
|
|
|
|
+ u8 *data)
|
|
|
|
+{
|
|
|
|
+ struct skge_port *skge = netdev_priv(dev);
|
|
|
|
+ struct pci_dev *pdev = skge->hw->pdev;
|
|
|
|
+ int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
|
|
|
|
+ int length = eeprom->len;
|
|
|
|
+ u16 offset = eeprom->offset;
|
|
|
|
+
|
|
|
|
+ if (!cap)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ if (eeprom->magic != SKGE_EEPROM_MAGIC)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ while (length > 0) {
|
|
|
|
+ u32 val;
|
|
|
|
+ int n = min_t(int, length, sizeof(val));
|
|
|
|
+
|
|
|
|
+ if (n < sizeof(val))
|
|
|
|
+ val = skge_vpd_read(pdev, cap, offset);
|
|
|
|
+ memcpy(&val, data, n);
|
|
|
|
+
|
|
|
|
+ skge_vpd_write(pdev, cap, offset, val);
|
|
|
|
+
|
|
|
|
+ length -= n;
|
|
|
|
+ data += n;
|
|
|
|
+ offset += n;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct ethtool_ops skge_ethtool_ops = {
|
|
static const struct ethtool_ops skge_ethtool_ops = {
|
|
.get_settings = skge_get_settings,
|
|
.get_settings = skge_get_settings,
|
|
.set_settings = skge_set_settings,
|
|
.set_settings = skge_set_settings,
|
|
@@ -810,6 +905,9 @@ static const struct ethtool_ops skge_ethtool_ops = {
|
|
.set_msglevel = skge_set_msglevel,
|
|
.set_msglevel = skge_set_msglevel,
|
|
.nway_reset = skge_nway_reset,
|
|
.nway_reset = skge_nway_reset,
|
|
.get_link = ethtool_op_get_link,
|
|
.get_link = ethtool_op_get_link,
|
|
|
|
+ .get_eeprom_len = skge_get_eeprom_len,
|
|
|
|
+ .get_eeprom = skge_get_eeprom,
|
|
|
|
+ .set_eeprom = skge_set_eeprom,
|
|
.get_ringparam = skge_get_ring_param,
|
|
.get_ringparam = skge_get_ring_param,
|
|
.set_ringparam = skge_set_ring_param,
|
|
.set_ringparam = skge_set_ring_param,
|
|
.get_pauseparam = skge_get_pauseparam,
|
|
.get_pauseparam = skge_get_pauseparam,
|