diff options
author | Mark Brown <broonie@sirena.org.uk> | 2006-03-28 17:08:55 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-03-29 17:34:02 -0500 |
commit | a8b4cf42cf57e44e3c4a585e0f0a71e3a7efbf29 (patch) | |
tree | ba3bcaea18d88f12297d3302dd1c9a1b9cec4709 /drivers | |
parent | 8dfc914a3f2ae4e303e2bff89f28fc14cee8a9a6 (diff) |
[PATCH] natsemi: Support oversized EEPROMs
The natsemi chip can have a larger EEPROM attached than it itself uses for
configuration. This patch adds support for user space access to such an
EEPROM.
Signed-off-by: Mark Brown <broonie@sirena.org.uk>
Cc: Tim Hockin <thockin@hockin.org>
Cc: Jeff Garzik <jgarzik@pobox.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/natsemi.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 8d4999837b65..7826afbb9db9 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c | |||
@@ -226,7 +226,7 @@ static int full_duplex[MAX_UNITS]; | |||
226 | NATSEMI_PG1_NREGS) | 226 | NATSEMI_PG1_NREGS) |
227 | #define NATSEMI_REGS_VER 1 /* v1 added RFDR registers */ | 227 | #define NATSEMI_REGS_VER 1 /* v1 added RFDR registers */ |
228 | #define NATSEMI_REGS_SIZE (NATSEMI_NREGS * sizeof(u32)) | 228 | #define NATSEMI_REGS_SIZE (NATSEMI_NREGS * sizeof(u32)) |
229 | #define NATSEMI_EEPROM_SIZE 24 /* 12 16-bit values */ | 229 | #define NATSEMI_DEF_EEPROM_SIZE 24 /* 12 16-bit values */ |
230 | 230 | ||
231 | /* Buffer sizes: | 231 | /* Buffer sizes: |
232 | * The nic writes 32-bit values, even if the upper bytes of | 232 | * The nic writes 32-bit values, even if the upper bytes of |
@@ -714,6 +714,8 @@ struct netdev_private { | |||
714 | unsigned int iosize; | 714 | unsigned int iosize; |
715 | spinlock_t lock; | 715 | spinlock_t lock; |
716 | u32 msg_enable; | 716 | u32 msg_enable; |
717 | /* EEPROM data */ | ||
718 | int eeprom_size; | ||
717 | }; | 719 | }; |
718 | 720 | ||
719 | static void move_int_phy(struct net_device *dev, int addr); | 721 | static void move_int_phy(struct net_device *dev, int addr); |
@@ -890,6 +892,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, | |||
890 | np->msg_enable = (debug >= 0) ? (1<<debug)-1 : NATSEMI_DEF_MSG; | 892 | np->msg_enable = (debug >= 0) ? (1<<debug)-1 : NATSEMI_DEF_MSG; |
891 | np->hands_off = 0; | 893 | np->hands_off = 0; |
892 | np->intr_status = 0; | 894 | np->intr_status = 0; |
895 | np->eeprom_size = NATSEMI_DEF_EEPROM_SIZE; | ||
893 | 896 | ||
894 | /* Initial port: | 897 | /* Initial port: |
895 | * - If the nic was configured to use an external phy and if find_mii | 898 | * - If the nic was configured to use an external phy and if find_mii |
@@ -2582,7 +2585,8 @@ static int get_regs_len(struct net_device *dev) | |||
2582 | 2585 | ||
2583 | static int get_eeprom_len(struct net_device *dev) | 2586 | static int get_eeprom_len(struct net_device *dev) |
2584 | { | 2587 | { |
2585 | return NATSEMI_EEPROM_SIZE; | 2588 | struct netdev_private *np = netdev_priv(dev); |
2589 | return np->eeprom_size; | ||
2586 | } | 2590 | } |
2587 | 2591 | ||
2588 | static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | 2592 | static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) |
@@ -2669,15 +2673,20 @@ static u32 get_link(struct net_device *dev) | |||
2669 | static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) | 2673 | static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) |
2670 | { | 2674 | { |
2671 | struct netdev_private *np = netdev_priv(dev); | 2675 | struct netdev_private *np = netdev_priv(dev); |
2672 | u8 eebuf[NATSEMI_EEPROM_SIZE]; | 2676 | u8 *eebuf; |
2673 | int res; | 2677 | int res; |
2674 | 2678 | ||
2679 | eebuf = kmalloc(np->eeprom_size, GFP_KERNEL); | ||
2680 | if (!eebuf) | ||
2681 | return -ENOMEM; | ||
2682 | |||
2675 | eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16); | 2683 | eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16); |
2676 | spin_lock_irq(&np->lock); | 2684 | spin_lock_irq(&np->lock); |
2677 | res = netdev_get_eeprom(dev, eebuf); | 2685 | res = netdev_get_eeprom(dev, eebuf); |
2678 | spin_unlock_irq(&np->lock); | 2686 | spin_unlock_irq(&np->lock); |
2679 | if (!res) | 2687 | if (!res) |
2680 | memcpy(data, eebuf+eeprom->offset, eeprom->len); | 2688 | memcpy(data, eebuf+eeprom->offset, eeprom->len); |
2689 | kfree(eebuf); | ||
2681 | return res; | 2690 | return res; |
2682 | } | 2691 | } |
2683 | 2692 | ||
@@ -3033,9 +3042,10 @@ static int netdev_get_eeprom(struct net_device *dev, u8 *buf) | |||
3033 | int i; | 3042 | int i; |
3034 | u16 *ebuf = (u16 *)buf; | 3043 | u16 *ebuf = (u16 *)buf; |
3035 | void __iomem * ioaddr = ns_ioaddr(dev); | 3044 | void __iomem * ioaddr = ns_ioaddr(dev); |
3045 | struct netdev_private *np = netdev_priv(dev); | ||
3036 | 3046 | ||
3037 | /* eeprom_read reads 16 bits, and indexes by 16 bits */ | 3047 | /* eeprom_read reads 16 bits, and indexes by 16 bits */ |
3038 | for (i = 0; i < NATSEMI_EEPROM_SIZE/2; i++) { | 3048 | for (i = 0; i < np->eeprom_size/2; i++) { |
3039 | ebuf[i] = eeprom_read(ioaddr, i); | 3049 | ebuf[i] = eeprom_read(ioaddr, i); |
3040 | /* The EEPROM itself stores data bit-swapped, but eeprom_read | 3050 | /* The EEPROM itself stores data bit-swapped, but eeprom_read |
3041 | * reads it back "sanely". So we swap it back here in order to | 3051 | * reads it back "sanely". So we swap it back here in order to |