]> git.hungrycats.org Git - linux/commitdiff
[PATCH] pcnet32 add led blink capability
authorDon Fry <brazilnut@us.ibm.com>
Tue, 6 Apr 2004 03:57:37 +0000 (23:57 -0400)
committerJeff Garzik <jgarzik@redhat.com>
Tue, 6 Apr 2004 03:57:37 +0000 (23:57 -0400)
Please apply this patch to 2.6.5 to include the capability of blinking
the LED's for device identification.  Ethtool -p support.

drivers/net/pcnet32.c

index 8ddc30dcf7141f4b269cbfc747c8302b8442db16..0ded6a0dce0d37d28a7ffae5cdf98dd0026cdddc 100644 (file)
@@ -102,6 +102,7 @@ static int rx_copybreak = 200;
 #define PCNET32_DMA_MASK 0xffffffff
 
 #define PCNET32_WATCHDOG_TIMEOUT (jiffies + (2 * HZ))
+#define PCNET32_BLINK_TIMEOUT  (jiffies + (HZ/4))
 
 /*
  * table to translate option values from tulip
@@ -232,6 +233,8 @@ static int full_duplex[MAX_UNITS];
  *        length errors, and transmit hangs.  Cleans up after errors in open.
  *        Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test.
  *        Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections.
+ * v1.29   6 Apr 2004 Jim Lewis <jklewis@us.ibm.com> added physical
+ *        identification code (blink led's).
  */
 
 
@@ -342,6 +345,7 @@ struct pcnet32_private {
     struct net_device  *next;
     struct mii_if_info mii_if;
     struct timer_list  watchdog_timer;
+    struct timer_list  blink_timer;
     u32                        msg_enable;     /* debug message level */
 };
 
@@ -365,6 +369,8 @@ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits);
 static void pcnet32_ethtool_test(struct net_device *dev,
        struct ethtool_test *eth_test, u64 *data);
 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);
 
 enum pci_flags_bit {
     PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -746,6 +752,63 @@ clean_up:
     return(rc);
 } /* end pcnet32_loopback_test  */
 
+static void pcnet32_led_blink_callback(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+    struct pcnet32_access *a = &lp->a;
+    ulong ioaddr = dev->base_addr;
+    unsigned long flags;
+    int i;
+
+    spin_lock_irqsave(&lp->lock, flags);
+    for (i=4; i<8; i++) {
+       a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000);
+    }
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT);
+}
+
+static int pcnet32_phys_id(struct net_device *dev, u32 data)
+{
+    struct pcnet32_private *lp = dev->priv;
+    struct pcnet32_access *a = &lp->a;
+    ulong ioaddr = dev->base_addr;
+    unsigned long flags;
+    int i, regs[4];
+
+    if (!lp->blink_timer.function) {
+       init_timer(&lp->blink_timer);
+       lp->blink_timer.function = (void *) pcnet32_led_blink_callback;
+       lp->blink_timer.data = (unsigned long) dev;
+    }
+
+    /* Save the current value of the bcrs */
+    spin_lock_irqsave(&lp->lock, flags);
+    for (i=4; i<8; i++) {
+       regs[i-4] = a->read_bcr(ioaddr, i);
+    }
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    mod_timer(&lp->blink_timer, jiffies);
+    set_current_state(TASK_INTERRUPTIBLE);
+
+    if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)))
+    data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+
+    schedule_timeout(data * HZ);
+    del_timer_sync(&lp->blink_timer);
+
+    /* Restore the original value of the bcrs */
+    spin_lock_irqsave(&lp->lock, flags);
+    for (i=4; i<8; i++) {
+       a->write_bcr(ioaddr, i, regs[i-4]);
+    }
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    return 0;
+}
+
 static struct ethtool_ops pcnet32_ethtool_ops = {
     .get_settings      = pcnet32_get_settings,
     .set_settings      = pcnet32_set_settings,
@@ -761,6 +824,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
     .get_strings       = pcnet32_get_strings,
     .self_test_count   = pcnet32_self_test_count,
     .self_test         = pcnet32_ethtool_test,
+    .phys_id           = pcnet32_phys_id,
 };
 
 /* only probes for non-PCI devices, the rest are handled by
@@ -1157,6 +1221,9 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
     if (pcnet32_debug & NETIF_MSG_PROBE)
        printk(KERN_INFO "%s: registered as %s\n", dev->name, lp->name);
     cards_found++;
+
+    a->write_bcr(ioaddr, 2, 0x1002);   /* enable LED writes */
+
     return 0;
 
 err_free_consistent: