patch-2.4.17 linux/drivers/net/pcmcia/axnet_cs.c
Next file: linux/drivers/net/pcmcia/fmvj18x_cs.c
Previous file: linux/drivers/net/pcmcia/ax8390.h
Back to the patch index
Back to the overall index
- Lines: 551
- Date:
Fri Dec 21 16:40:32 2001
- Orig file:
linux-2.4.16/drivers/net/pcmcia/axnet_cs.c
- Orig date:
Mon Nov 12 17:35:43 2001
diff -Naur -X /home/marcelo/lib/dontdiff linux-2.4.16/drivers/net/pcmcia/axnet_cs.c linux/drivers/net/pcmcia/axnet_cs.c
@@ -11,7 +11,7 @@
Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net
- axnet_cs.c 1.11 2001/06/12 12:42:40
+ axnet_cs.c 1.24 2001/11/18 02:46:51
The network driver code is based on Donald Becker's NE2000 code:
@@ -20,7 +20,7 @@
Director, National Security Agency. This software may be used and
distributed according to the terms of the GNU General Public License,
incorporated herein by reference.
- Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
+ Donald Becker may be reached at becker@scyld.com
======================================================================*/
@@ -33,12 +33,13 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/delay.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/byteorder.h>
#include <linux/netdevice.h>
-#include "ax8390.h"
+#include "../8390.h"
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
@@ -51,7 +52,6 @@
#define AXNET_CMD 0x00
#define AXNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */
#define AXNET_RESET 0x1f /* Issue a read to reset, a write to clear. */
-#define AXNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */
#define AXNET_MII_EEP 0x14 /* Offset of MII access port */
#define AXNET_START_PG 0x40 /* First page of TX buffer */
@@ -59,26 +59,13 @@
#define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */
-#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 =
-"axnet_cs.c 1.11 2001/06/12 12:42:40 (David Hinds)";
-#else
-#define DEBUG(n, args...)
-#endif
-
-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb);
-#define skb_tx_check(dev, skb)
-#define add_rx_bytes(stats, n) (stats)->rx_bytes += n;
-#define add_tx_bytes(stats, n) (stats)->tx_bytes += n;
-#define netif_mark_up(dev) do { } while (0)
-#define netif_mark_down(dev) do { } while (0)
-
/*====================================================================*/
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
@@ -87,9 +74,14 @@
static int irq_list[4] = { -1 };
MODULE_PARM(irq_list, "1-4i");
-/* Ugh! Let the user hardwire the hardware address for queer cards */
-static int hw_addr[6] = { 0, /* ... */ };
-MODULE_PARM(hw_addr, "6i");
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"axnet_cs.c 1.24 2001/11/18 02:46:51 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
/*====================================================================*/
@@ -120,6 +112,11 @@
static dev_info_t dev_info = "axnet_cs";
static dev_link_t *dev_list;
+static int axdev_init(struct net_device *dev);
+static void AX88190_init(struct net_device *dev, int startp);
+static int ax_open(struct net_device *dev);
+static void ax_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
/*====================================================================*/
typedef struct axnet_dev_t {
@@ -210,7 +207,7 @@
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
- ethdev_init(dev);
+ axdev_init(dev);
dev->init = &axnet_init;
dev->open = &axnet_open;
dev->stop = &axnet_close;
@@ -302,7 +299,7 @@
{0x00, EN0_RCNTHI},
{0x00, EN0_IMR}, /* Mask completion irq. */
{0xFF, EN0_ISR},
- {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
+ {E8390_RXOFF|0x40, EN0_RXCR}, /* 0x60 Set to monitor */
{E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
{0x10, EN0_RCNTLO},
{0x00, EN0_RCNTHI},
@@ -331,30 +328,6 @@
/*======================================================================
- This should be totally unnecessary... but when we can't figure
- out the hardware address any other way, we'll let the user hard
- wire it when the module is initialized.
-
-======================================================================*/
-
-static int get_hwired(dev_link_t *link)
-{
- struct net_device *dev = link->priv;
- int i;
-
- for (i = 0; i < 6; i++)
- if (hw_addr[i] != 0) break;
- if (i == 6)
- return 0;
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = hw_addr[i];
-
- return 1;
-} /* get_hwired */
-
-/*======================================================================
-
axnet_config() is scheduled to run after a CARD_INSERTION event
is received, to configure the PCMCIA socket, and to make the
ethernet device available to the system.
@@ -419,7 +392,8 @@
CS_CHECK(GetTupleData, handle, &tuple);
CS_CHECK(ParseTuple, handle, &tuple, &parse);
link->conf.ConfigBase = parse.config.base;
- link->conf.Present = parse.config.rmask[0];
+ /* don't trust the CIS on this; Linksys got it wrong */
+ link->conf.Present = 0x63;
/* Configure card */
link->state |= DEV_CONFIG;
@@ -440,7 +414,7 @@
if ((cfg->index == 0) || (cfg->io.nwin == 0))
goto next_entry;
- link->conf.ConfigIndex = cfg->index;
+ link->conf.ConfigIndex = 0x05;
/* For multifunction cards, by convention, we configure the
network function with window 0, and serial with window 1 */
if (io->nwin > 1) {
@@ -480,9 +454,9 @@
goto failed;
}
- if (!get_prom(link) && !get_hwired(link)) {
- printk(KERN_NOTICE "axnet_cs: unable to read hardware net"
- " address for io base %#3lx\n", dev->base_addr);
+ if (!get_prom(link)) {
+ printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n");
+ printk(KERN_NOTICE "axnet_cs: use pcnet_cs instead.\n");
unregister_netdev(dev);
goto failed;
}
@@ -542,7 +516,7 @@
if (link->open) {
DEBUG(1, "axnet_cs: release postponed, '%s' still open\n",
- info->node.dev_name);
+ ((axnet_dev_t *)(link->priv))->node.dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
@@ -602,7 +576,7 @@
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
axnet_reset_8390(&info->dev);
- NS8390_init(&info->dev, 1);
+ AX88190_init(&info->dev, 1);
netif_device_attach(&info->dev);
}
}
@@ -692,7 +666,7 @@
info->watchdog.expires = jiffies + HZ;
add_timer(&info->watchdog);
- return ei_open(dev);
+ return ax_open(dev);
} /* axnet_open */
/*====================================================================*/
@@ -708,7 +682,6 @@
link->open--;
netif_stop_queue(dev);
- netif_mark_down(dev);
del_timer(&info->watchdog);
if (link->state & DEV_STALE_CONFIG)
mod_timer(&link->release, jiffies + HZ/20);
@@ -755,7 +728,7 @@
{
axnet_dev_t *info = dev_id;
info->stale = 0;
- ei_interrupt(irq, dev_id, regs);
+ ax_interrupt(irq, dev_id, regs);
}
static void ei_watchdog(u_long arg)
@@ -807,7 +780,7 @@
else
printk(KERN_INFO "%s: link partner did not autonegotiate\n",
dev->name);
- NS8390_init(dev, 1);
+ AX88190_init(dev, 1);
}
info->link_status = link;
}
@@ -944,10 +917,11 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
- Center of Excellence in Space Data and Information Sciences
- Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-
+ The author may be reached as becker@scyld.com, or C/O
+ Scyld Computing Corporation
+ 410 Severn Ave., Suite 210
+ Annapolis MD 21403
+
This is the chip-specific code for many 8390-based ethernet adaptors.
This is not a complete driver, it must be combined with board-specific
code such as ne.c, wd.c, 3c503.c, etc.
@@ -957,7 +931,6 @@
a simple innocent change. Please contact me or Donald if you think
you have found something that needs changing. -- PG
-
Changelog:
Paul Gortmaker : remove set_bit lock, other cleanups.
@@ -981,8 +954,8 @@
*/
-static const char *version =
- "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+static const char *version_8390 =
+ "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n";
#include <asm/uaccess.h>
#include <asm/bitops.h>
@@ -1062,25 +1035,23 @@
* them.
*/
-
-
/**
- * ei_open - Open/initialize the board.
+ * ax_open - Open/initialize the board.
* @dev: network device to initialize
*
* This routine goes all-out, setting everything
* up anew at each open, even though many of these registers should only
* need to be set once at boot.
*/
-static int ei_open(struct net_device *dev)
+static int ax_open(struct net_device *dev)
{
unsigned long flags;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
- /* This can't happen unless somebody forgot to call ethdev_init(). */
+ /* This can't happen unless somebody forgot to call axdev_init(). */
if (ei_local == NULL)
{
- printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
+ printk(KERN_EMERG "%s: ax_open passed a non-existent device!\n", dev->name);
return -ENXIO;
}
@@ -1099,10 +1070,9 @@
*/
spin_lock_irqsave(&ei_local->page_lock, flags);
- NS8390_init(dev, 1);
+ AX88190_init(dev, 1);
/* Set the flag before we drop the lock, That way the IRQ arrives
after its set and we get no silly warnings */
- netif_mark_up(dev);
netif_start_queue(dev);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
ei_local->irqlock = 0;
@@ -1110,27 +1080,6 @@
}
/**
- * ei_close - shut down network device
- * @dev: network device to close
- *
- * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
- */
-static int ei_close(struct net_device *dev)
-{
- unsigned long flags;
-
- /*
- * Hold the page lock during close
- */
-
- spin_lock_irqsave(&((struct ei_device *)dev->priv)->page_lock, flags);
- NS8390_init(dev, 0);
- spin_unlock_irqrestore(&((struct ei_device *)dev->priv)->page_lock, flags);
- netif_stop_queue(dev);
- return 0;
-}
-
-/**
* ei_tx_timeout - handle transmit time out condition
* @dev: network device which has apparently fallen asleep
*
@@ -1169,7 +1118,7 @@
/* Try to restart the card. Perhaps the user has fixed something. */
ei_reset_8390(dev);
- NS8390_init(dev, 1);
+ AX88190_init(dev, 1);
spin_unlock(&ei_local->page_lock);
enable_irq(dev->irq);
@@ -1192,7 +1141,6 @@
unsigned long flags;
netif_stop_queue(dev);
- skb_tx_check(dev, skb);
length = skb->len;
@@ -1205,7 +1153,6 @@
outb_p(0x00, e8390_base + EN0_IMR);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
/*
* Slow phase with lock held.
*/
@@ -1218,8 +1165,6 @@
send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
-#ifdef EI_PINGPONG
-
/*
* We have two Tx slots available for use. Find the first free
* slot, and then perform some sanity checks. With two Tx bufs,
@@ -1288,22 +1233,6 @@
else
netif_start_queue(dev);
-#else /* EI_PINGPONG */
-
- /*
- * Only one Tx buffer in use. You need two Tx bufs to come close to
- * back-to-back transmits. Expect a 20 -> 25% performance hit on
- * reasonable hardware if you only use one Tx buffer.
- */
-
- ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
- ei_local->txing = 1;
- NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
- dev->trans_start = jiffies;
- netif_stop_queue(dev);
-
-#endif /* EI_PINGPONG */
-
/* Turn 8390 interrupts back on. */
ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -1311,14 +1240,14 @@
spin_unlock(&ei_local->page_lock);
enable_irq(dev->irq);
- DEV_KFREE_SKB (skb);
- add_tx_bytes(&ei_local->stat, send_length);
+ dev_kfree_skb (skb);
+ ei_local->stat.tx_bytes += send_length;
return 0;
}
/**
- * ei_interrupt - handle the interrupts from an 8390
+ * ax_interrupt - handle the interrupts from an 8390
* @irq: interrupt number
* @dev_id: a pointer to the net_device
* @regs: unused
@@ -1330,7 +1259,7 @@
* needed.
*/
-static void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void ax_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = dev_id;
long e8390_base;
@@ -1497,8 +1426,6 @@
struct ei_device *ei_local = (struct ei_device *) dev->priv;
int status = inb(e8390_base + EN0_TSR);
-#ifdef EI_PINGPONG
-
/*
* There are two Tx buffers, see which one finished, and trigger
* the send of another one if it exists.
@@ -1541,13 +1468,6 @@
// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
// dev->name, ei_local->lasttx);
-#else /* EI_PINGPONG */
- /*
- * Single Tx buffer: mark it free so another packet can be loaded.
- */
- ei_local->txing = 0;
-#endif
-
/* Minimize Tx latency: update the statistics after we restart TXing. */
if (status & ENTSR_COL)
ei_local->stat.collisions++;
@@ -1655,7 +1575,7 @@
netif_rx(skb);
dev->last_rx = jiffies;
ei_local->stat.rx_packets++;
- add_rx_bytes(&ei_local->stat, pkt_len);
+ ei_local->stat.rx_bytes += pkt_len;
if (pkt_stat & ENRSR_PHY)
ei_local->stat.multicast++;
}
@@ -1801,11 +1721,11 @@
long e8390_base = dev->base_addr;
if(dev->flags&IFF_PROMISC)
- outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+ outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
else if(dev->flags&IFF_ALLMULTI || dev->mc_list)
- outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+ outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR);
else
- outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+ outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR);
}
/*
@@ -1813,28 +1733,30 @@
* be parallel to just about everything else. Its also fairly quick and
* not called too often. Must protect against both bh and irq users
*/
-
+
+#define dev_lock(dev) (((struct ei_device *)(dev)->priv)->page_lock)
+
static void set_multicast_list(struct net_device *dev)
{
unsigned long flags;
- spin_lock_irqsave(&((struct ei_device *)dev->priv)->page_lock, flags);
+ spin_lock_irqsave(&dev_lock(dev), flags);
do_set_multicast_list(dev);
- spin_unlock_irqrestore(&((struct ei_device *)dev->priv)->page_lock, flags);
+ spin_unlock_irqrestore(&dev_lock(dev), flags);
}
/**
- * ethdev_init - init rest of 8390 device struct
+ * axdev_init - init rest of 8390 device struct
* @dev: network device structure to init
*
* Initialize the rest of the 8390 device structure. Do NOT __init
* this, as it is used by 8390 based modular drivers too.
*/
-static int ethdev_init(struct net_device *dev)
+static int axdev_init(struct net_device *dev)
{
if (ei_debug > 1)
- printk(version);
+ printk(version_8390);
if (dev->priv == NULL)
{
@@ -1857,20 +1779,18 @@
return 0;
}
-
-
/* This page of functions should be 8390 generic */
/* Follow National Semi's recommendations for initializing the "NIC". */
/**
- * NS8390_init - initialize 8390 hardware
+ * AX88190_init - initialize 8390 hardware
* @dev: network device to initialize
* @startp: boolean. non-zero value to initiate chip processing
*
* Must be called with lock held.
*/
-static void NS8390_init(struct net_device *dev, int startp)
+static void AX88190_init(struct net_device *dev, int startp)
{
axnet_dev_t *info = (axnet_dev_t *)dev;
long e8390_base = dev->base_addr;
@@ -1887,7 +1807,7 @@
outb_p(0x00, e8390_base + EN0_RCNTLO);
outb_p(0x00, e8390_base + EN0_RCNTHI);
/* Set to monitor and loopback mode -- this is vital!. */
- outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
+ outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */
outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
/* Set the transmit page and receive ring. */
outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
@@ -1931,7 +1851,7 @@
outb_p(E8390_TXCONFIG | info->duplex_flag,
e8390_base + EN0_TXCR); /* xmit on. */
/* 3c503 TechMan says rxconfig only after the NIC is started. */
- outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */
+ outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */
do_set_multicast_list(dev); /* (re)load the mcast table */
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)