patch-2.3.19 linux/drivers/net/pcmcia/pcnet_cs.c
Next file: linux/drivers/net/pcmcia/ray_cs.c
Previous file: linux/drivers/net/pcmcia/Makefile
Back to the patch index
Back to the overall index
- Lines: 204
- Date:
Sat Oct 2 07:38:27 1999
- Orig file:
v2.3.18/linux/drivers/net/pcmcia/pcnet_cs.c
- Orig date:
Fri Sep 10 23:57:30 1999
diff -u --recursive --new-file v2.3.18/linux/drivers/net/pcmcia/pcnet_cs.c linux/drivers/net/pcmcia/pcnet_cs.c
@@ -9,9 +9,9 @@
Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory
mode. It will also handle the Socket EA card in either mode.
- Copyright (C) 1998 David A. Hinds -- dhinds@hyper.stanford.edu
+ Copyright (C) 1999 David A. Hinds -- dhinds@hyper.stanford.edu
- pcnet_cs.c 1.94 1999/07/29 06:04:49
+ pcnet_cs.c 1.99 1999/09/15 15:33:09
The network driver code is based on Donald Becker's NE2000 code:
@@ -29,6 +29,7 @@
======================================================================*/
#include <linux/module.h>
+#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
@@ -40,7 +41,7 @@
#include <asm/system.h>
#include <linux/netdevice.h>
-#include "../../drivers/net/8390.h"
+#include <../drivers/net/8390.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
@@ -66,13 +67,12 @@
static char *if_names[] = { "auto", "10baseT", "10base2"};
-#define PCMCIA_DEBUG 6
#ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"pcnet_cs.c 1.94 1999/07/29 06:04:49 (David Hinds)";
+"pcnet_cs.c 1.99 1999/09/15 15:33:09 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -125,6 +125,8 @@
static int pcnet_open(struct net_device *dev);
static int pcnet_close(struct net_device *dev);
+static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
+static void ei_watchdog(u_long arg);
static void pcnet_reset_8390(struct net_device *dev);
@@ -226,6 +228,9 @@
dev_node_t node;
u_long flags;
caddr_t base;
+ struct timer_list watchdog;
+ int stale;
+ u_short fast_poll;
} pcnet_dev_t;
/*======================================================================
@@ -890,7 +895,13 @@
}
set_misc_reg(dev);
- request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev_info, dev);
+ request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev);
+
+ info->watchdog.function = &ei_watchdog;
+ info->watchdog.data = (u_long)info;
+ info->watchdog.expires = jiffies + HZ;
+ add_timer(&info->watchdog);
+
return ei_open(dev);
} /* pcnet_open */
@@ -909,8 +920,9 @@
free_irq(dev->irq, dev);
link->open--; dev->start = 0;
+ del_timer(&((pcnet_dev_t *)dev)->watchdog);
if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies+HZ/20;
+ link->release.expires = jiffies + HZ/20;
link->state |= DEV_RELEASE_PENDING;
add_timer(&link->release);
}
@@ -973,6 +985,44 @@
/* ======================================================================= */
+static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs)
+{
+ pcnet_dev_t *info = dev_id;
+ info->stale = 0;
+ ei_interrupt(irq, dev_id, regs);
+}
+
+static void ei_watchdog(u_long arg)
+{
+ pcnet_dev_t *info = (pcnet_dev_t *)(arg);
+ struct net_device *dev = &info->dev;
+ int nic_base = dev->base_addr;
+
+ if (dev->start == 0) goto reschedule;
+
+ /* Check for pending interrupt with expired latency timer: with
+ this, we can limp along even if the interrupt is blocked */
+ outb_p(E8390_NODMA+E8390_PAGE0, nic_base + E8390_CMD);
+ if (info->stale++ && inb_p(nic_base + EN0_ISR)) {
+ if (!info->fast_poll)
+ printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+ ei_irq_wrapper(dev->irq, dev, NULL);
+ info->fast_poll = HZ;
+ }
+ if (info->fast_poll) {
+ info->fast_poll--;
+ info->watchdog.expires = jiffies + 1;
+ add_timer(&info->watchdog);
+ return;
+ }
+
+reschedule:
+ info->watchdog.expires = jiffies + HZ;
+ add_timer(&info->watchdog);
+}
+
+/* ======================================================================= */
+
static void dma_get_8390_hdr(struct net_device *dev,
struct e8390_pkt_hdr *hdr,
int ring_page)
@@ -1180,7 +1230,7 @@
odd = (c & 01); c >>= 1;
if (c) {
- do { *d++ = readw(s++); } while (--c);
+ do { *d++ = __raw_readw(s++); } while (--c);
}
/* get last byte by fetching a word and masking */
if (odd)
@@ -1198,7 +1248,7 @@
odd = (c & 01); c >>= 1;
if (c) {
- do { writew(*s++, d++); } while (--c);
+ do { __raw_writew(*s++, d++); } while (--c);
}
/* copy last byte doing a read-modify-write */
if (odd)
@@ -1291,10 +1341,10 @@
/* Try scribbling on the buffer */
info->base = ioremap(req.Base, window_size);
for (i = 0; i < (TX_PAGES<<8); i += 2)
- writew((i>>1), info->base+offset+i);
+ __raw_writew((i>>1), info->base+offset+i);
udelay(100);
for (i = 0; i < (TX_PAGES<<8); i += 2)
- if (readw(info->base+offset+i) != (i>>1)) break;
+ if (__raw_readw(info->base+offset+i) != (i>>1)) break;
pcnet_reset_8390(dev);
if (i != (TX_PAGES<<8)) {
iounmap(info->base);
@@ -1327,11 +1377,7 @@
/*====================================================================*/
-#ifdef MODULE
-int init_module(void)
-#else
-int init_pcnet_cs(void)
-#endif
+static int __init init_pcnet_cs(void)
{
servinfo_t serv;
DEBUG(0, "%s\n", version);
@@ -1341,19 +1387,17 @@
"does not match!\n");
return -1;
}
- register_pcmcia_driver(&dev_info, &pcnet_attach, &pcnet_detach);
- DEBUG(0, "pcnet driver registered\n" );
+ register_pccard_driver(&dev_info, &pcnet_attach, &pcnet_detach);
return 0;
}
-//__initcall(init_pcnet_cs);
-
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit exit_pcnet_cs(void)
{
DEBUG(0, "pcnet_cs: unloading\n");
- unregister_pcmcia_driver(&dev_info);
+ unregister_pccard_driver(&dev_info);
while (dev_list != NULL)
pcnet_detach(dev_list);
}
-#endif
+
+module_init(init_pcnet_cs);
+module_exit(exit_pcnet_cs);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)