Commit 991eb379 authored by Don Fry's avatar Don Fry Committed by Jeff Garzik

[PATCH] pcnet32 add register dump capability

At the next opportunity to add new code to 2.6.6, please apply the following
patch to include the capability to dump chip registers.  Ethtool -d support.
parent a8588521
...@@ -132,6 +132,8 @@ static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = { ...@@ -132,6 +132,8 @@ static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = {
}; };
#define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
#define PCNET32_NUM_REGS 146
#define MAX_UNITS 8 /* More are supported, limit only on options */ #define MAX_UNITS 8 /* More are supported, limit only on options */
static int options[MAX_UNITS]; static int options[MAX_UNITS];
static int full_duplex[MAX_UNITS]; static int full_duplex[MAX_UNITS];
...@@ -234,7 +236,7 @@ static int full_duplex[MAX_UNITS]; ...@@ -234,7 +236,7 @@ static int full_duplex[MAX_UNITS];
* Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test. * Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test.
* Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections. * Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections.
* v1.29 6 Apr 2004 Jim Lewis <jklewis@us.ibm.com> added physical * v1.29 6 Apr 2004 Jim Lewis <jklewis@us.ibm.com> added physical
* identification code (blink led's). * identification code (blink led's) and register dump.
*/ */
...@@ -372,6 +374,9 @@ static void pcnet32_ethtool_test(struct net_device *dev, ...@@ -372,6 +374,9 @@ static void pcnet32_ethtool_test(struct net_device *dev,
static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1); static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1);
static int pcnet32_phys_id(struct net_device *dev, u32 data); static int pcnet32_phys_id(struct net_device *dev, u32 data);
static void pcnet32_led_blink_callback(struct net_device *dev); static void pcnet32_led_blink_callback(struct net_device *dev);
static int pcnet32_get_regs_len(struct net_device *dev);
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr);
enum pci_flags_bit { enum pci_flags_bit {
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
...@@ -681,7 +686,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) ...@@ -681,7 +686,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
for (i=0; i<6; i++) for (i=0; i<6; i++)
*packet++ = dev->dev_addr[i]; *packet++ = dev->dev_addr[i];
for (i=0; i<6; i++) for (i=0; i<6; i++)
*packet++ = dev->dev_addr[i]; *packet++ = dev->dev_addr[i];
/* type */ /* type */
*packet++ = 0x08; *packet++ = 0x08;
*packet++ = 0x06; *packet++ = 0x06;
...@@ -837,6 +842,72 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) ...@@ -837,6 +842,72 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data)
return 0; return 0;
} }
int pcnet32_get_regs_len(struct net_device *dev)
{
return(PCNET32_NUM_REGS * sizeof(u16));
}
void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr)
{
int i, csr0;
u16 *buff = ptr;
struct pcnet32_private *lp = dev->priv;
struct pcnet32_access *a = &lp->a;
ulong ioaddr = dev->base_addr;
int ticks;
unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
csr0 = a->read_csr(ioaddr, 0);
if (!(csr0 & 0x0004)) { /* If not stopped */
/* set SUSPEND (SPND) - CSR5 bit 0 */
a->write_csr(ioaddr, 5, 0x0001);
/* poll waiting for bit to be set */
ticks = 0;
while (!(a->read_csr(ioaddr, 5) & 0x0001)) {
spin_unlock_irqrestore(&lp->lock, flags);
mdelay(1);
spin_lock_irqsave(&lp->lock, flags);
ticks++;
if (ticks > 200) {
if (netif_msg_hw(lp))
printk(KERN_DEBUG "%s: Error getting into suspend!\n",
dev->name);
break;
}
}
}
/* read address PROM */
for (i=0; i<16; i += 2)
*buff++ = inw(ioaddr + i);
for (i = 0; i <= 89; i++) {
*buff++ = a->read_csr(ioaddr, i);
}
*buff++ = a->read_csr(ioaddr, 112);
*buff++ = a->read_csr(ioaddr, 114);
for (i = 0; i <= 35; i++) {
*buff++ = a->read_bcr(ioaddr, i);
}
if (!(csr0 & 0x0004)) { /* If not stopped */
/* clear SUSPEND (SPND) - CSR5 bit 0 */
a->write_csr(ioaddr, 5, 0x0000);
}
i = buff - (u16 *)ptr;
for (; i < PCNET32_NUM_REGS; i++)
*buff++ = 0;
spin_unlock_irqrestore(&lp->lock, flags);
}
static struct ethtool_ops pcnet32_ethtool_ops = { static struct ethtool_ops pcnet32_ethtool_ops = {
.get_settings = pcnet32_get_settings, .get_settings = pcnet32_get_settings,
.set_settings = pcnet32_set_settings, .set_settings = pcnet32_set_settings,
...@@ -853,6 +924,8 @@ static struct ethtool_ops pcnet32_ethtool_ops = { ...@@ -853,6 +924,8 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.self_test_count = pcnet32_self_test_count, .self_test_count = pcnet32_self_test_count,
.self_test = pcnet32_ethtool_test, .self_test = pcnet32_ethtool_test,
.phys_id = pcnet32_phys_id, .phys_id = pcnet32_phys_id,
.get_regs_len = pcnet32_get_regs_len,
.get_regs = pcnet32_get_regs,
}; };
/* only probes for non-PCI devices, the rest are handled by /* only probes for non-PCI devices, the rest are handled by
...@@ -1371,7 +1444,7 @@ pcnet32_open(struct net_device *dev) ...@@ -1371,7 +1444,7 @@ pcnet32_open(struct net_device *dev)
/* Re-initialize the PCNET32, and start it when done. */ /* Re-initialize the PCNET32, and start it when done. */
lp->a.write_csr (ioaddr, 1, (lp->dma_addr + lp->a.write_csr (ioaddr, 1, (lp->dma_addr +
offsetof(struct pcnet32_private, init_block)) & 0xffff); offsetof(struct pcnet32_private, init_block)) & 0xffff);
lp->a.write_csr (ioaddr, 2, (lp->dma_addr + lp->a.write_csr (ioaddr, 2, (lp->dma_addr +
offsetof(struct pcnet32_private, init_block)) >> 16); offsetof(struct pcnet32_private, init_block)) >> 16);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment