summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-02-05 01:02:11 +0100
committerJeff Garzik <jeff@garzik.org>2008-02-11 17:06:29 +0100
commit29d52e545f6f077d8c29fa35d1c52d95e4a2185a (patch)
tree6616b6142343855a0b9bcd6a934a32bddd252df4
parentDM9000: Add mutex to protect access (diff)
downloadlinux-29d52e545f6f077d8c29fa35d1c52d95e4a2185a.tar.xz
linux-29d52e545f6f077d8c29fa35d1c52d95e4a2185a.zip
DM9000: Add ethtool support for reading and writing EEPROM
Add ethtool support to access the configuration EEPROM connected to the DM9000. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/dm9000.c66
1 files changed, 60 insertions, 6 deletions
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index a769c89a3690..082372515432 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -186,7 +186,8 @@ static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg)
static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
int value);
-static void dm9000_read_eeprom(board_info_t *, int addr, unsigned char *to);
+static void dm9000_read_eeprom(board_info_t *, int addr, u8 *to);
+static void dm9000_write_eeprom(board_info_t *, int addr, u8 *dp);
static void dm9000_rx(struct net_device *);
static void dm9000_hash_table(struct net_device *);
@@ -409,12 +410,65 @@ static u32 dm9000_get_link(struct net_device *dev)
return mii_link_ok(&dm->mii);
}
+#define DM_EEPROM_MAGIC (0x444D394B)
+
+static int dm9000_get_eeprom_len(struct net_device *dev)
+{
+ return 128;
+}
+
+static int dm9000_get_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ board_info_t *dm = to_dm9000_board(dev);
+ int offset = ee->offset;
+ int len = ee->len;
+ int i;
+
+ /* EEPROM access is aligned to two bytes */
+
+ if ((len & 1) != 0 || (offset & 1) != 0)
+ return -EINVAL;
+
+ ee->magic = DM_EEPROM_MAGIC;
+
+ for (i = 0; i < len; i += 2)
+ dm9000_read_eeprom(dm, (offset + i) / 2, data + i);
+
+ return 0;
+}
+
+static int dm9000_set_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ board_info_t *dm = to_dm9000_board(dev);
+ int offset = ee->offset;
+ int len = ee->len;
+ int i;
+
+ /* EEPROM access is aligned to two bytes */
+
+ if ((len & 1) != 0 || (offset & 1) != 0)
+ return -EINVAL;
+
+ if (ee->magic != DM_EEPROM_MAGIC)
+ return -EINVAL;
+
+ for (i = 0; i < len; i += 2)
+ dm9000_write_eeprom(dm, (offset + i) / 2, data + i);
+
+ return 0;
+}
+
static const struct ethtool_ops dm9000_ethtool_ops = {
.get_drvinfo = dm9000_get_drvinfo,
.get_settings = dm9000_get_settings,
.set_settings = dm9000_set_settings,
.nway_reset = dm9000_nway_reset,
.get_link = dm9000_get_link,
+ .get_eeprom_len = dm9000_get_eeprom_len,
+ .get_eeprom = dm9000_get_eeprom,
+ .set_eeprom = dm9000_set_eeprom,
};
@@ -1008,7 +1062,7 @@ dm9000_rx(struct net_device *dev)
* Read a word data from EEPROM
*/
static void
-dm9000_read_eeprom(board_info_t *db, int offset, unsigned char *to)
+dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
{
mutex_lock(&db->addr_lock);
@@ -1024,18 +1078,17 @@ dm9000_read_eeprom(board_info_t *db, int offset, unsigned char *to)
mutex_unlock(&db->addr_lock);
}
-#ifdef DM9000_PROGRAM_EEPROM
/*
* Write a word data to SROM
*/
static void
-write_srom_word(board_info_t * db, int offset, u16 val)
+dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
{
mutex_lock(&db->addr_lock);
iow(db, DM9000_EPAR, offset);
- iow(db, DM9000_EPDRH, ((val >> 8) & 0xff));
- iow(db, DM9000_EPDRL, (val & 0xff));
+ iow(db, DM9000_EPDRH, data[1]);
+ iow(db, DM9000_EPDRL, data[0]);
iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
mdelay(8); /* same shit */
iow(db, DM9000_EPCR, 0);
@@ -1043,6 +1096,7 @@ write_srom_word(board_info_t * db, int offset, u16 val)
mutex_unlock(&db->addr_lock);
}
+#ifdef DM9000_PROGRAM_EEPROM
/*
* Only for development:
* Here we write static data to the eeprom in case