summaryrefslogtreecommitdiffstats
path: root/drivers/net/pcmcia/3c589_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/pcmcia/3c589_cs.c')
-rw-r--r--drivers/net/pcmcia/3c589_cs.c137
1 files changed, 61 insertions, 76 deletions
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 40e5a643f..e95b87104 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -4,7 +4,7 @@
Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
- 3c589_cs.c 1.137 1999/11/08 20:46:17
+ 3c589_cs.c 1.143 1999/12/30 21:28:10
The network driver code is based on Donald Becker's 3c589 code:
@@ -99,13 +99,15 @@ enum RxFilter {
#define TX_TIMEOUT ((400*HZ)/1000)
struct el3_private {
- dev_node_t node;
+ dev_link_t link;
+ struct net_device dev;
+ dev_node_t node;
struct net_device_stats stats;
/* For transceiver monitoring */
- struct timer_list media;
- u_short media_status;
- u_short fast_poll;
- u_long last_irq;
+ struct timer_list media;
+ u_short media_status;
+ u_short fast_poll;
+ u_long last_irq;
};
static char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
@@ -115,7 +117,7 @@ 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 =
-"3c589_cs.c 1.137 1999/11/08 20:46:17 (David Hinds)";
+"3c589_cs.c 1.143 1999/12/30 21:28:10 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -149,7 +151,7 @@ static int el3_config(struct net_device *dev, struct ifmap *map);
static int el3_open(struct net_device *dev);
static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void update_stats(ioaddr_t addr, struct net_device *dev);
+static void update_stats(struct net_device *dev);
static struct net_device_stats *el3_get_stats(struct net_device *dev);
static int el3_rx(struct net_device *dev);
static int el3_close(struct net_device *dev);
@@ -211,6 +213,7 @@ static int tc589_init(struct net_device *dev)
static dev_link_t *tc589_attach(void)
{
+ struct el3_private *lp;
client_reg_t client_reg;
dev_link_t *link;
struct net_device *dev;
@@ -220,8 +223,12 @@ static dev_link_t *tc589_attach(void)
flush_stale_links();
/* Create new ethernet device */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- memset(link, 0, sizeof(struct dev_link_t));
+ lp = kmalloc(sizeof(*lp), GFP_KERNEL);
+ if (!lp) return NULL;
+ memset(lp, 0, sizeof(*lp));
+ link = &lp->link; dev = &lp->dev;
+ link->priv = dev->priv = link->irq.Instance = lp;
+
link->release.function = &tc589_release;
link->release.data = (u_long)link;
link->io.NumPorts1 = 16;
@@ -240,25 +247,17 @@ static dev_link_t *tc589_attach(void)
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
- dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
- memset(dev, 0, sizeof(struct net_device));
-
- /* Make up a EL3-specific-data structure. */
- dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
- memset(dev->priv, 0, sizeof(struct el3_private));
-
/* The EL3-specific entries in the device structure. */
dev->hard_start_xmit = &el3_start_xmit;
dev->set_config = &el3_config;
dev->get_stats = &el3_get_stats;
dev->set_multicast_list = &set_multicast_list;
ether_setup(dev);
- dev->name = ((struct el3_private *)dev->priv)->node.dev_name;
+ dev->name = lp->node.dev_name;
dev->init = &tc589_init;
dev->open = &el3_open;
dev->stop = &el3_close;
dev->tbusy = 1;
- link->priv = link->irq.Instance = dev;
/* Register with Card Services */
link->next = dev_list;
@@ -293,6 +292,7 @@ static dev_link_t *tc589_attach(void)
static void tc589_detach(dev_link_t *link)
{
+ struct el3_private *lp = link->priv;
dev_link_t **linkp;
long flags;
@@ -325,15 +325,9 @@ static void tc589_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
- if (link->priv) {
- struct net_device *dev = link->priv;
- if (link->dev != NULL)
- unregister_netdev(dev);
- if (dev->priv)
- kfree(dev->priv);
- kfree(link->priv);
- }
- kfree(link);
+ if (link->dev)
+ unregister_netdev(&lp->dev);
+ kfree(lp);
} /* tc589_detach */
@@ -350,8 +344,9 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
static void tc589_config(dev_link_t *link)
{
- client_handle_t handle;
- struct net_device *dev;
+ client_handle_t handle = link->handle;
+ struct el3_private *lp = link->priv;
+ struct net_device *dev = &lp->dev;
tuple_t tuple;
cisparse_t parse;
u_short buf[32], *phys_addr;
@@ -359,12 +354,9 @@ static void tc589_config(dev_link_t *link)
ioaddr_t ioaddr;
char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
- handle = link->handle;
- dev = link->priv;
- phys_addr = (u_short *)dev->dev_addr;
-
DEBUG(0, "3c589_config(0x%p)\n", link);
+ phys_addr = (u_short *)dev->dev_addr;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, handle, &tuple);
@@ -434,7 +426,7 @@ static void tc589_config(dev_link_t *link)
}
}
- link->dev = &((struct el3_private *)dev->priv)->node;
+ link->dev = &lp->node;
/* The address and resource configuration register aren't loaded from
the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
@@ -507,7 +499,8 @@ static int tc589_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
+ struct el3_private *lp = link->priv;
+ struct net_device *dev = &lp->dev;
DEBUG(1, "3c589_event(0x%06x)\n", event);
@@ -683,10 +676,8 @@ static int el3_config(struct net_device *dev, struct ifmap *map)
static int el3_open(struct net_device *dev)
{
struct el3_private *lp = (struct el3_private *)dev->priv;
- dev_link_t *link;
+ dev_link_t *link = &lp->link;
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev) break;
if (!DEV_OK(link))
return -ENODEV;
@@ -696,14 +687,14 @@ static int el3_open(struct net_device *dev)
tc589_reset(dev);
lp->media.function = &media_check;
- lp->media.data = (u_long)dev;
+ lp->media.data = (u_long)lp;
lp->media.expires = jiffies + HZ;
add_timer(&lp->media);
DEBUG(1, "%s: opened, status %4.4x.\n",
dev->name, inw(dev->base_addr + EL3_STATUS));
- return 0; /* Always succeed */
+ return 0;
}
static void el3_tx_timeout(struct net_device *dev)
@@ -746,7 +737,6 @@ static void pop_tx_status(struct net_device *dev)
static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct el3_private *lp = (struct el3_private *)dev->priv;
ioaddr_t ioaddr = dev->base_addr;
/* Transmitter timeout, serious problems. */
@@ -765,6 +755,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_NOTICE "%s: transmitter access conflict.\n",
dev->name);
else {
+ struct el3_private *lp = (struct el3_private *)dev->priv;
lp->stats.tx_bytes += skb->len;
/* Put out the doubleword header... */
outw(skb->len, ioaddr + TX_FIFO);
@@ -789,14 +780,13 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* The EL3 interrupt handler. */
static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- struct net_device *dev = (struct net_device *)dev_id;
- struct el3_private *lp;
+ struct el3_private *lp = dev_id;
+ struct net_device *dev = &lp->dev;
ioaddr_t ioaddr, status;
int i = 0;
- if ((dev == NULL) || !dev->start)
+ if ((lp == NULL) || !dev->start)
return;
- lp = (struct el3_private *)dev->priv;
ioaddr = dev->base_addr;
#ifdef PCMCIA_DEBUG
@@ -834,7 +824,7 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & (AdapterFailure | RxEarly | StatsFull)) {
/* Handle all uncommon interrupts. */
if (status & StatsFull) /* Empty statistics. */
- update_stats(ioaddr, dev);
+ update_stats(dev);
if (status & RxEarly) { /* Rx early is unused. */
el3_rx(dev);
outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
@@ -883,14 +873,14 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void media_check(u_long arg)
{
- struct net_device *dev = (struct net_device *)(arg);
- struct el3_private *lp = (struct el3_private *)dev->priv;
+ struct el3_private *lp = (struct el3_private *)(arg);
+ struct net_device *dev = &lp->dev;
ioaddr_t ioaddr = dev->base_addr;
u_short media, errs;
u_long flags;
if (dev->start == 0) goto reschedule;
-
+
EL3WINDOW(1);
/* Check for pending interrupt with expired latency timer: with
this, we can limp along even if the interrupt is blocked */
@@ -898,7 +888,7 @@ static void media_check(u_long arg)
(inb(ioaddr + EL3_TIMER) == 0xff)) {
if (!lp->fast_poll)
printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
- el3_interrupt(dev->irq, dev, NULL);
+ el3_interrupt(dev->irq, lp, NULL);
lp->fast_poll = HZ;
}
if (lp->fast_poll) {
@@ -965,14 +955,12 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
{
struct el3_private *lp = (struct el3_private *)dev->priv;
unsigned long flags;
- dev_link_t *link;
+ dev_link_t *link = &lp->link;
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev) break;
if (DEV_OK(link)) {
save_flags(flags);
cli();
- update_stats(dev->base_addr, dev);
+ update_stats(dev);
restore_flags(flags);
}
return &lp->stats;
@@ -984,10 +972,11 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
operation, and it's simpler for the rest of the driver to assume that
window 1 is always valid rather than use a special window-state variable.
*/
-static void update_stats(ioaddr_t ioaddr, struct net_device *dev)
+static void update_stats(struct net_device *dev)
{
struct el3_private *lp = (struct el3_private *)dev->priv;
-
+ ioaddr_t ioaddr = dev->base_addr;
+
DEBUG(2, "%s: updating the statistics.\n", dev->name);
/* Turn off statistics updates while reading. */
outw(StatsDisable, ioaddr + EL3_CMD);
@@ -1002,8 +991,8 @@ static void update_stats(ioaddr_t ioaddr, struct net_device *dev)
lp->stats.tx_packets += inb(ioaddr + 6);
/* Rx packets */ inb(ioaddr + 7);
/* Tx deferrals */ inb(ioaddr + 8);
- inw(ioaddr + 10); /* Total Rx and Tx octets. */
- inw(ioaddr + 12);
+ /* Rx octets */ inw(ioaddr + 10);
+ /* Tx octets */ inw(ioaddr + 12);
/* Back to window 1, and turn statistics back on. */
EL3WINDOW(1);
@@ -1025,12 +1014,12 @@ static int el3_rx(struct net_device *dev)
short error = rx_status & 0x3800;
lp->stats.rx_errors++;
switch (error) {
- case 0x0000: lp->stats.rx_over_errors++; break;
- case 0x0800: lp->stats.rx_length_errors++; break;
- case 0x1000: lp->stats.rx_frame_errors++; break;
- case 0x1800: lp->stats.rx_length_errors++; break;
- case 0x2000: lp->stats.rx_frame_errors++; break;
- case 0x2800: lp->stats.rx_crc_errors++; break;
+ case 0x0000: lp->stats.rx_over_errors++; break;
+ case 0x0800: lp->stats.rx_length_errors++; break;
+ case 0x1000: lp->stats.rx_frame_errors++; break;
+ case 0x1800: lp->stats.rx_length_errors++; break;
+ case 0x2000: lp->stats.rx_frame_errors++; break;
+ case 0x2800: lp->stats.rx_crc_errors++; break;
}
} else {
short pkt_len = rx_status & 0x7ff;
@@ -1073,10 +1062,10 @@ static int el3_rx(struct net_device *dev)
*/
static void set_multicast_list(struct net_device *dev)
{
+ struct el3_private *lp = dev->priv;
+ dev_link_t *link = &lp->link;
ioaddr_t ioaddr = dev->base_addr;
- dev_link_t *link;
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev) break;
+
if (!(DEV_OK(link))) return;
#ifdef PCMCIA_DEBUG
if (pc_debug > 2) {
@@ -1099,13 +1088,9 @@ static void set_multicast_list(struct net_device *dev)
static int el3_close(struct net_device *dev)
{
+ struct el3_private *lp = dev->priv;
+ dev_link_t *link = &lp->link;
ioaddr_t ioaddr = dev->base_addr;
- dev_link_t *link;
-
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev) break;
- if (link == NULL)
- return -ENODEV;
DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
@@ -1133,12 +1118,12 @@ static int el3_close(struct net_device *dev)
/* Check if the card still exists */
if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000)
- update_stats(ioaddr, dev);
+ update_stats(dev);
}
link->open--;
dev->start = 0;
- del_timer(&((struct el3_private *)dev->priv)->media);
+ del_timer(&lp->media);
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ/20;
link->state |= DEV_RELEASE_PENDING;