aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/skge.c98
-rw-r--r--drivers/net/skge.h6
2 files changed, 102 insertions, 2 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index a439d4304458..953f8023f24c 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -59,6 +59,9 @@
59#define BLINK_MS 250 59#define BLINK_MS 250
60#define LINK_HZ HZ 60#define LINK_HZ HZ
61 61
62#define SKGE_EEPROM_MAGIC 0x9933aabb
63
64
62MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); 65MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
63MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>"); 66MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
64MODULE_LICENSE("GPL"); 67MODULE_LICENSE("GPL");
@@ -798,6 +801,98 @@ static int skge_phys_id(struct net_device *dev, u32 data)
798 return 0; 801 return 0;
799} 802}
800 803
804static int skge_get_eeprom_len(struct net_device *dev)
805{
806 struct skge_port *skge = netdev_priv(dev);
807 u32 reg2;
808
809 pci_read_config_dword(skge->hw->pdev, PCI_DEV_REG2, &reg2);
810 return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
811}
812
813static u32 skge_vpd_read(struct pci_dev *pdev, int cap, u16 offset)
814{
815 u32 val;
816
817 pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset);
818
819 do {
820 pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
821 } while (!(offset & PCI_VPD_ADDR_F));
822
823 pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val);
824 return val;
825}
826
827static void skge_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val)
828{
829 pci_write_config_dword(pdev, cap + PCI_VPD_DATA, val);
830 pci_write_config_word(pdev, cap + PCI_VPD_ADDR,
831 offset | PCI_VPD_ADDR_F);
832
833 do {
834 pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
835 } while (offset & PCI_VPD_ADDR_F);
836}
837
838static int skge_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
839 u8 *data)
840{
841 struct skge_port *skge = netdev_priv(dev);
842 struct pci_dev *pdev = skge->hw->pdev;
843 int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
844 int length = eeprom->len;
845 u16 offset = eeprom->offset;
846
847 if (!cap)
848 return -EINVAL;
849
850 eeprom->magic = SKGE_EEPROM_MAGIC;
851
852 while (length > 0) {
853 u32 val = skge_vpd_read(pdev, cap, offset);
854 int n = min_t(int, length, sizeof(val));
855
856 memcpy(data, &val, n);
857 length -= n;
858 data += n;
859 offset += n;
860 }
861 return 0;
862}
863
864static int skge_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
865 u8 *data)
866{
867 struct skge_port *skge = netdev_priv(dev);
868 struct pci_dev *pdev = skge->hw->pdev;
869 int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
870 int length = eeprom->len;
871 u16 offset = eeprom->offset;
872
873 if (!cap)
874 return -EINVAL;
875
876 if (eeprom->magic != SKGE_EEPROM_MAGIC)
877 return -EINVAL;
878
879 while (length > 0) {
880 u32 val;
881 int n = min_t(int, length, sizeof(val));
882
883 if (n < sizeof(val))
884 val = skge_vpd_read(pdev, cap, offset);
885 memcpy(&val, data, n);
886
887 skge_vpd_write(pdev, cap, offset, val);
888
889 length -= n;
890 data += n;
891 offset += n;
892 }
893 return 0;
894}
895
801static const struct ethtool_ops skge_ethtool_ops = { 896static const struct ethtool_ops skge_ethtool_ops = {
802 .get_settings = skge_get_settings, 897 .get_settings = skge_get_settings,
803 .set_settings = skge_set_settings, 898 .set_settings = skge_set_settings,
@@ -810,6 +905,9 @@ static const struct ethtool_ops skge_ethtool_ops = {
810 .set_msglevel = skge_set_msglevel, 905 .set_msglevel = skge_set_msglevel,
811 .nway_reset = skge_nway_reset, 906 .nway_reset = skge_nway_reset,
812 .get_link = ethtool_op_get_link, 907 .get_link = ethtool_op_get_link,
908 .get_eeprom_len = skge_get_eeprom_len,
909 .get_eeprom = skge_get_eeprom,
910 .set_eeprom = skge_set_eeprom,
813 .get_ringparam = skge_get_ring_param, 911 .get_ringparam = skge_get_ring_param,
814 .set_ringparam = skge_set_ring_param, 912 .set_ringparam = skge_set_ring_param,
815 .get_pauseparam = skge_get_pauseparam, 913 .get_pauseparam = skge_get_pauseparam,
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 800329d99b21..51754246d59d 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Definitions for the new Marvell Yukon / SysKonenct driver. 2 * Definitions for the new Marvell Yukon / SysKonnect driver.
3 */ 3 */
4#ifndef _SKGE_H 4#ifndef _SKGE_H
5#define _SKGE_H 5#define _SKGE_H
@@ -8,8 +8,10 @@
8#define PCI_DEV_REG1 0x40 8#define PCI_DEV_REG1 0x40
9#define PCI_PHY_COMA 0x8000000 9#define PCI_PHY_COMA 0x8000000
10#define PCI_VIO 0x2000000 10#define PCI_VIO 0x2000000
11
11#define PCI_DEV_REG2 0x44 12#define PCI_DEV_REG2 0x44
12#define PCI_REV_DESC 0x4 13#define PCI_VPD_ROM_SZ 7L<<14 /* VPD ROM size 0=256, 1=512, ... */
14#define PCI_REV_DESC 1<<2 /* Reverse Descriptor bytes */
13 15
14#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ 16#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
15 PCI_STATUS_SIG_SYSTEM_ERROR | \ 17 PCI_STATUS_SIG_SYSTEM_ERROR | \