netdev
[Top] [All Lists]

[PATCH 1/2 2.6.6-rc1-bk5] pcnet32 add register dump capability

To: tsbogend@xxxxxxxxxxxxxxxx, jgarzik@xxxxxxxxx, netdev@xxxxxxxxxxx
Subject: [PATCH 1/2 2.6.6-rc1-bk5] pcnet32 add register dump capability
From: Don Fry <brazilnut@xxxxxxxxxx>
Date: Tue, 20 Apr 2004 15:54:56 -0700 (PDT)
Sender: netdev-bounce@xxxxxxxxxxx
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.

--- linux-2.6.6-rc1-bk5/drivers/net/good.pcnet32.c      Tue Apr 20 15:46:32 2004
+++ linux-2.6.6-rc1-bk5/drivers/net/pcnet32.c   Tue Apr 20 15:43:34 2004
@@ -132,6 +132,8 @@
 };
 #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 */
 static int options[MAX_UNITS];
 static int full_duplex[MAX_UNITS];
@@ -234,7 +236,7 @@
  *        Jim Lewis <jklewis@xxxxxxxxxx> added ethernet loopback test.
  *        Thomas Munck Steenholdt <tmus@xxxxxxx> non-mii ioctl corrections.
  * v1.29   6 Apr 2004 Jim Lewis <jklewis@xxxxxxxxxx> added physical
- *        identification code (blink led's).
+ *        identification code (blink led's) and register dump.
  */
 
 
@@ -372,6 +374,9 @@
 static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1);
 static int pcnet32_phys_id(struct net_device *dev, u32 data);
 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 {
     PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -681,7 +686,7 @@
            for (i=0; i<6; i++)
                *packet++ = dev->dev_addr[i];
            for (i=0; i<6; i++)
-               *packet++ = dev->dev_addr[i]; 
+               *packet++ = dev->dev_addr[i];
            /* type */
            *packet++ = 0x08;
            *packet++ = 0x06;
@@ -837,6 +842,72 @@
     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 = {
     .get_settings      = pcnet32_get_settings,
     .set_settings      = pcnet32_set_settings,
@@ -853,6 +924,8 @@
     .self_test_count   = pcnet32_self_test_count,
     .self_test         = pcnet32_ethtool_test,
     .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
@@ -1371,7 +1444,7 @@
 
     /* Re-initialize the PCNET32, and start it when done. */
     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 +
                offsetof(struct pcnet32_private, init_block)) >> 16);
 

-- 
Don Fry
brazilnut@xxxxxxxxxx

<Prev in Thread] Current Thread [Next in Thread>