lkml.org 
[lkml]   [2008]   [Feb]   [11]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateMon, 11 Feb 2008 12:05:16 -0500
FromJeff Garzik <>
Subject[git patches] net driver updates
Mostly fixes, a few cleanups (generally assisting fixes), and an
exception for PS3 wireless because it had been posted, reviewed and
acked for a while, just not committed.

Please pull from 'upstream-davem' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git upstream-davem

to receive the following updates:

 drivers/net/8139too.c            |    2 +-
 drivers/net/Kconfig              |   18 +
 drivers/net/Makefile             |    3 +-
 drivers/net/cxgb3/l2t.c          |    2 +-
 drivers/net/cxgb3/sge.c          |   35 +-
 drivers/net/dm9000.c             |  654 ++++++----
 drivers/net/e1000/e1000_main.c   |   18 +-
 drivers/net/forcedeth.c          |  132 ++-
 drivers/net/ni52.c               | 1142 ++++++++--------
 drivers/net/ni52.h               |  158 ++--
 drivers/net/pcnet32.c            |   48 +-
 drivers/net/phy/fixed.c          |    4 +-
 drivers/net/ps3_gelic_net.c      | 1215 ++++++++++-------
 drivers/net/ps3_gelic_net.h      |  415 ++++--
 drivers/net/ps3_gelic_wireless.c | 2753 ++++++++++++++++++++++++++++++++++++++
 drivers/net/ps3_gelic_wireless.h |  329 +++++
 drivers/net/r6040.c              |  233 ++--
 drivers/net/sis190.c             |    3 +-
 drivers/s390/net/claw.h          |   19 +-
 drivers/s390/net/lcs.c           |    2 +-
 drivers/s390/net/lcs.h           |   16 +-
 drivers/s390/net/netiucv.c       |   29 +-
 include/linux/dm9000.h           |    2 +
 23 files changed, 5440 insertions(+), 1792 deletions(-)
 create mode 100644 drivers/net/ps3_gelic_wireless.c
 create mode 100644 drivers/net/ps3_gelic_wireless.h
Adrian Bunk (1):
      net/phy/fixed.c: fix a use-after-free

Adrian McMenamin (1):
      8139too fix for Dreamcast

Alan Cox (1):
      ni52: Remove 278 scripts/checkpatch errors

Ayaz Abdulla (2):
      forcedeth: tx collision fix
      forcedeth: tx pause watermarks

Ben Dooks (24):
      DM9000: Fix endian-ness of data accesses.
      DM9000: Add platform data to specify external phy
      DM9000 use dev_xxx() instead of printk for output.
      DM9000 update debugging macros to use debug level
      DM9000: Pass IRQ flags via platform resources
      DM9000: Remove old timer based poll routines
      DM9000: Add initial ethtool support
      DM9000: Do not sleep with spinlock and IRQs held
      DM9000: Use msleep() instead of udelay()
      DM9000: Remove barely used SROM array read.
      DM9000: Add mutex to protect access
      DM9000: Add ethtool support for reading and writing EEPROM
      DM9000: Add ethtool control of msg_enable value
      DM9000: Remove EEPROM initialisation code.
      DM9000: Ensure spinlock held whilst accessing EEPROM registers
      DM9000: Remove unnecessary changelog in header comment
      DM9000: Use netif_msg to enable debugging options
      DM9000: Fix delays used by EEPROM read and write
      DM9000: Remove cal_CRC() and use ether_crc_le instead
      DM9000: Remove redudant use of "& 0xff"
      DM9000: Add platform flag for no attached EEPROM
      DM9000: Add support for MII ioctl() calls
      DM9000: Update retry count whilst identifying chip
      DM9000: Show the MAC address source after printing MAC

Benjamin Herrenschmidt (1):
      e1000: Fix for 32 bits platforms with 64 bits resources

Cornelia Huck (1):
      netiucv: Remember to set driver->owner.

Don Fry (2):
      pcnet32: use NET_IP_ALIGN instead of 2
      pcnet32: Use print_mac

Florian Fainelli (4):
      r6040: do not use a private stats structure to store statistics
      r6040: add helpers to allocate and free the Tx/Rx buffers
      r6040: recover from transmit timeout
      r6040: cleanups

Krishna Kumar (1):
      Optimize cxgb3 xmit path (a bit)

Masakazu Mokuno (7):
      PS3: gelic: Fix the wrong dev_id passed
      PS3: gelic: Add endianness macros
      PS3: gelic: code cleanup
      PS3: gelic: remove duplicated ethtool handlers
      PS3: gelic: add support for port link status
      PS3: gelic: Add support for dual network interface
      PS3: gelic: Add wireless support for PS3

Peter Tiedemann (2):
      lcs: avoid/reduce unused s390dbf debug areas.
      claw/lcs/netiucv: check s390dbf level before sprints

Sergio Luis (1):
      drivers/net/sis190: fix section mismatch warning in sis190_get_mac_addr

Steve Wise (1):
      cxgb3: Handle ARP completions that mark neighbors stale.

Ursula Braun (2):
      claw: removal of volatile variables
      netiucv: change name of nop function

diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index eef6fec..be6e918 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -168,7 +168,7 @@ static int debug = -1;
  * Warning: 64K ring has hardware issues and may lock up.
  */
 #if defined(CONFIG_SH_DREAMCAST)
-#define RX_BUF_IDX	1	/* 16K ring */
+#define RX_BUF_IDX 0	/* 8K ring */
 #else
 #define RX_BUF_IDX	2	/* 32K ring */
 #endif
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 50c2b60..f337800 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -931,6 +931,14 @@ config ENC28J60_WRITEVERIFY
 	  Enable the verify after the buffer write useful for debugging purpose.
 	  If unsure, say N.
 
+config DM9000_DEBUGLEVEL
+	int "DM9000 maximum debug level"
+	depends on DM9000
+	default 4
+	help
+	  The maximum level of debugging code compiled into the DM9000
+	  driver.
+
 config SMC911X
 	tristate "SMSC LAN911[5678] support"
 	select CRC32
@@ -2352,6 +2360,16 @@ config GELIC_NET
 	  To compile this driver as a module, choose M here: the
 	  module will be called ps3_gelic.
 
+config GELIC_WIRELESS
+       bool "PS3 Wireless support"
+       depends on GELIC_NET
+       help
+        This option adds the support for the wireless feature of PS3.
+        If you have the wireless-less model of PS3 or have no plan to
+        use wireless feature, disabling this option saves memory.  As
+        the driver automatically distinguishes the models, you can
+        safely enable this option even if you have a wireless-less model.
+
 config GIANFAR
 	tristate "Gianfar Ethernet"
 	depends on FSL_SOC
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 9fc7794..3b1ea32 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -70,7 +70,8 @@ obj-$(CONFIG_BNX2X) += bnx2x.o
 spidernet-y += spider_net.o spider_net_ethtool.o
 obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o
 obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
-ps3_gelic-objs += ps3_gelic_net.o
+gelic_wireless-$(CONFIG_GELIC_WIRELESS) += ps3_gelic_wireless.o
+ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y)
 obj-$(CONFIG_TC35815) += tc35815.o
 obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c
index 17ed4c3..865faee 100644
--- a/drivers/net/cxgb3/l2t.c
+++ b/drivers/net/cxgb3/l2t.c
@@ -404,7 +404,7 @@ found:
 			if (neigh->nud_state & NUD_FAILED) {
 				arpq = e->arpq_head;
 				e->arpq_head = e->arpq_tail = NULL;
-			} else if (neigh_is_connected(neigh))
+			} else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE))
 				setup_l2e_send_pending(dev, NULL, e);
 		} else {
 			e->state = neigh_is_connected(neigh) ?
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 9ca8c66..979f3fc 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -1059,6 +1059,14 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
 			 htonl(V_WR_TID(q->token)));
 }
 
+static inline void t3_stop_queue(struct net_device *dev, struct sge_qset *qs,
+				 struct sge_txq *q)
+{
+	netif_stop_queue(dev);
+	set_bit(TXQ_ETH, &qs->txq_stopped);
+	q->stops++;
+}
+
 /**
  *	eth_xmit - add a packet to the Ethernet Tx queue
  *	@skb: the packet
@@ -1090,31 +1098,18 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 	ndesc = calc_tx_descs(skb);
 
 	if (unlikely(credits < ndesc)) {
-		if (!netif_queue_stopped(dev)) {
-			netif_stop_queue(dev);
-			set_bit(TXQ_ETH, &qs->txq_stopped);
-			q->stops++;
-			dev_err(&adap->pdev->dev,
-				"%s: Tx ring %u full while queue awake!\n",
-				dev->name, q->cntxt_id & 7);
-		}
+		t3_stop_queue(dev, qs, q);
+		dev_err(&adap->pdev->dev,
+			"%s: Tx ring %u full while queue awake!\n",
+			dev->name, q->cntxt_id & 7);
 		spin_unlock(&q->lock);
 		return NETDEV_TX_BUSY;
 	}
 
 	q->in_use += ndesc;
-	if (unlikely(credits - ndesc < q->stop_thres)) {
-		q->stops++;
-		netif_stop_queue(dev);
-		set_bit(TXQ_ETH, &qs->txq_stopped);
-#if !USE_GTS
-		if (should_restart_tx(q) &&
-		    test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) {
-			q->restarts++;
-			netif_wake_queue(dev);
-		}
-#endif
-	}
+	if (unlikely(credits - ndesc < q->stop_thres))
+		if (USE_GTS || !should_restart_tx(q))
+			t3_stop_queue(dev, qs, q);
 
 	gen = q->gen;
 	q->unacked += ndesc;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 6a20a54..1fe305c 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -1,7 +1,5 @@
 /*
- *   dm9000.c: Version 1.2 03/18/2003
- *
- *         A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
+ *      Davicom DM9000 Fast Ethernet driver for Linux.
  * 	Copyright (C) 1997  Sten Wang
  *
  * 	This program is free software; you can redistribute it and/or
@@ -14,44 +12,11 @@
  * 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * 	GNU General Public License for more details.
  *
- *   (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
- *
- * V0.11	06/20/2001	REG_0A bit3=1, default enable BP with DA match
- * 	06/22/2001 	Support DM9801 progrmming
- * 	 	 	E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
- * 		 	E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
- * 		     		R17 = (R17 & 0xfff0) | NF + 3
- * 		 	E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
- * 		     		R17 = (R17 & 0xfff0) | NF
- *
- * v1.00               	modify by simon 2001.9.5
- *                         change for kernel 2.4.x
- *
- * v1.1   11/09/2001      	fix force mode bug
- *
- * v1.2   03/18/2003       Weilun Huang <weilun_huang@davicom.com.tw>:
- * 			Fixed phy reset.
- * 			Added tx/rx 32 bit mode.
- * 			Cleaned up for kernel merge.
- *
- *        03/03/2004    Sascha Hauer <s.hauer@pengutronix.de>
- *                      Port to 2.6 kernel
- *
- *	  24-Sep-2004   Ben Dooks <ben@simtec.co.uk>
- *			Cleanup of code to remove ifdefs
- *			Allowed platform device data to influence access width
- *			Reformatting areas of code
- *
- *        17-Mar-2005   Sascha Hauer <s.hauer@pengutronix.de>
- *                      * removed 2.4 style module parameters
- *                      * removed removed unused stat counter and fixed
- *                        net_device_stats
- *                      * introduced tx_timeout function
- *                      * reworked locking
+ * (C) Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
  *
- *	  01-Jul-2005   Ben Dooks <ben@simtec.co.uk>
- *			* fixed spinlock call without pointer
- *			* ensure spinlock is initialised
+ * Additional updates, Copyright:
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	Sascha Hauer <s.hauer@pengutronix.de>
  */
 
 #include <linux/module.h>
@@ -63,6 +28,7 @@
 #include <linux/spinlock.h>
 #include <linux/crc32.h>
 #include <linux/mii.h>
+#include <linux/ethtool.h>
 #include <linux/dm9000.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
@@ -80,30 +46,7 @@
 
 #define CARDNAME "dm9000"
 #define PFX CARDNAME ": "
-
-#define DM9000_TIMER_WUT  jiffies+(HZ*2)	/* timer wakeup time : 2 second */
-
-#define DM9000_DEBUG 0
-
-#if DM9000_DEBUG > 2
-#define PRINTK3(args...)  printk(CARDNAME ": " args)
-#else
-#define PRINTK3(args...)  do { } while(0)
-#endif
-
-#if DM9000_DEBUG > 1
-#define PRINTK2(args...)  printk(CARDNAME ": " args)
-#else
-#define PRINTK2(args...)  do { } while(0)
-#endif
-
-#if DM9000_DEBUG > 0
-#define PRINTK1(args...)  printk(CARDNAME ": " args)
-#define PRINTK(args...)   printk(CARDNAME ": " args)
-#else
-#define PRINTK1(args...)  do { } while(0)
-#define PRINTK(args...)   printk(KERN_DEBUG args)
-#endif
+#define DRV_VERSION	"1.30"
 
 #ifdef CONFIG_BLACKFIN
 #define readsb	insb
@@ -112,9 +55,9 @@
 #define writesb	outsb
 #define writesw	outsw
 #define writesl	outsl
-#define DM9000_IRQ_FLAGS	(IRQF_SHARED | IRQF_TRIGGER_HIGH)
+#define DEFAULT_TRIGGER IRQF_TRIGGER_HIGH
 #else
-#define DM9000_IRQ_FLAGS	(IRQF_SHARED | IRQT_RISING)
+#define DEFAULT_TRIGGER (0)
 #endif
 
 /*
@@ -124,6 +67,24 @@ static int watchdog = 5000;
 module_param(watchdog, int, 0400);
 MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
 
+/* DM9000 register address locking.
+ *
+ * The DM9000 uses an address register to control where data written
+ * to the data register goes. This means that the address register
+ * must be preserved over interrupts or similar calls.
+ *
+ * During interrupt and other critical calls, a spinlock is used to
+ * protect the system, but the calls themselves save the address
+ * in the address register in case they are interrupting another
+ * access to the device.
+ *
+ * For general accesses a lock is provided so that calls which are
+ * allowed to sleep are serialised so that the address register does
+ * not need to be saved. This lock also serves to serialise access
+ * to the EEPROM and PHY access registers which are shared between
+ * these two devices.
+ */
+
 /* Structure/enum declaration ------------------------------- */
 typedef struct board_info {
 
@@ -137,33 +98,52 @@ typedef struct board_info {
 	u16 dbug_cnt;
 	u8 io_mode;		/* 0:word, 2:byte */
 	u8 phy_addr;
+	unsigned int flags;
+	unsigned int in_suspend :1;
+
+	int debug_level;
 
 	void (*inblk)(void __iomem *port, void *data, int length);
 	void (*outblk)(void __iomem *port, void *data, int length);
 	void (*dumpblk)(void __iomem *port, int length);
 
+	struct device	*dev;	     /* parent device */
+
 	struct resource	*addr_res;   /* resources found */
 	struct resource *data_res;
 	struct resource	*addr_req;   /* resources requested */
 	struct resource *data_req;
 	struct resource *irq_res;
 
-	struct timer_list timer;
-	unsigned char srom[128];
+	struct mutex	 addr_lock;	/* phy and eeprom access lock */
+
 	spinlock_t lock;
 
 	struct mii_if_info mii;
 	u32 msg_enable;
 } board_info_t;
 
+/* debug code */
+
+#define dm9000_dbg(db, lev, msg...) do {		\
+	if ((lev) < CONFIG_DM9000_DEBUGLEVEL &&		\
+	    (lev) < db->debug_level) {			\
+		dev_dbg(db->dev, msg);			\
+	}						\
+} while (0)
+
+static inline board_info_t *to_dm9000_board(struct net_device *dev)
+{
+	return dev->priv;
+}
+
 /* function declaration ------------------------------------- */
 static int dm9000_probe(struct platform_device *);
 static int dm9000_open(struct net_device *);
 static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
 static int dm9000_stop(struct net_device *);
+static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
 
-
-static void dm9000_timer(unsigned long);
 static void dm9000_init_dm9000(struct net_device *);
 
 static irqreturn_t dm9000_interrupt(int, void *);
@@ -171,20 +151,19 @@ static irqreturn_t dm9000_interrupt(int, void *);
 static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);
 static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
 			   int value);
-static u16 read_srom_word(board_info_t *, int);
+
+static void dm9000_read_eeprom(board_info_t *, int addr, u8 *to);
+static void dm9000_write_eeprom(board_info_t *, int addr, u8 *dp);
 static void dm9000_rx(struct net_device *);
 static void dm9000_hash_table(struct net_device *);
 
-//#define DM9000_PROGRAM_EEPROM
-#ifdef DM9000_PROGRAM_EEPROM
-static void program_eeprom(board_info_t * db);
-#endif
 /* DM9000 network board routine ---------------------------- */
 
 static void
 dm9000_reset(board_info_t * db)
 {
-	PRINTK1("dm9000x: resetting\n");
+	dev_dbg(db->dev, "resetting device\n");
+
 	/* RESET device */
 	writeb(DM9000_NCR, db->io_addr);
 	udelay(200);
@@ -300,14 +279,10 @@ static void dm9000_set_io(struct board_info *db, int byte_width)
 		db->inblk   = dm9000_inblk_8bit;
 		break;
 
-	case 2:
-		db->dumpblk = dm9000_dumpblk_16bit;
-		db->outblk  = dm9000_outblk_16bit;
-		db->inblk   = dm9000_inblk_16bit;
-		break;
 
 	case 3:
-		printk(KERN_ERR PFX ": 3 byte IO, falling back to 16bit\n");
+		dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n");
+	case 2:
 		db->dumpblk = dm9000_dumpblk_16bit;
 		db->outblk  = dm9000_outblk_16bit;
 		db->inblk   = dm9000_inblk_16bit;
@@ -358,6 +333,139 @@ static void dm9000_poll_controller(struct net_device *dev)
 }
 #endif
 
+static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
+}
+
+/* ethtool ops */
+
+static void dm9000_get_drvinfo(struct net_device *dev,
+			       struct ethtool_drvinfo *info)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+
+	strcpy(info->driver, CARDNAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, to_platform_device(dm->dev)->name);
+}
+
+static u32 dm9000_get_msglevel(struct net_device *dev)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+
+	return dm->msg_enable;
+}
+
+static void dm9000_set_msglevel(struct net_device *dev, u32 value)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+
+	dm->msg_enable = value;
+}
+
+static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+
+	mii_ethtool_gset(&dm->mii, cmd);
+	return 0;
+}
+
+static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+
+	return mii_ethtool_sset(&dm->mii, cmd);
+}
+
+static int dm9000_nway_reset(struct net_device *dev)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+	return mii_nway_restart(&dm->mii);
+}
+
+static u32 dm9000_get_link(struct net_device *dev)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+	return mii_link_ok(&dm->mii);
+}
+
+#define DM_EEPROM_MAGIC		(0x444D394B)
+
+static int dm9000_get_eeprom_len(struct net_device *dev)
+{
+	return 128;
+}
+
+static int dm9000_get_eeprom(struct net_device *dev,
+			     struct ethtool_eeprom *ee, u8 *data)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+	int offset = ee->offset;
+	int len = ee->len;
+	int i;
+
+	/* EEPROM access is aligned to two bytes */
+
+	if ((len & 1) != 0 || (offset & 1) != 0)
+		return -EINVAL;
+
+	if (dm->flags & DM9000_PLATF_NO_EEPROM)
+		return -ENOENT;
+
+	ee->magic = DM_EEPROM_MAGIC;
+
+	for (i = 0; i < len; i += 2)
+		dm9000_read_eeprom(dm, (offset + i) / 2, data + i);
+
+	return 0;
+}
+
+static int dm9000_set_eeprom(struct net_device *dev,
+			     struct ethtool_eeprom *ee, u8 *data)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+	int offset = ee->offset;
+	int len = ee->len;
+	int i;
+
+	/* EEPROM access is aligned to two bytes */
+
+	if ((len & 1) != 0 || (offset & 1) != 0)
+		return -EINVAL;
+
+	if (dm->flags & DM9000_PLATF_NO_EEPROM)
+		return -ENOENT;
+
+	if (ee->magic != DM_EEPROM_MAGIC)
+		return -EINVAL;
+
+	for (i = 0; i < len; i += 2)
+		dm9000_write_eeprom(dm, (offset + i) / 2, data + i);
+
+	return 0;
+}
+
+static const struct ethtool_ops dm9000_ethtool_ops = {
+	.get_drvinfo		= dm9000_get_drvinfo,
+	.get_settings		= dm9000_get_settings,
+	.set_settings		= dm9000_set_settings,
+	.get_msglevel		= dm9000_get_msglevel,
+	.set_msglevel		= dm9000_set_msglevel,
+	.nway_reset		= dm9000_nway_reset,
+	.get_link		= dm9000_get_link,
+ 	.get_eeprom_len		= dm9000_get_eeprom_len,
+ 	.get_eeprom		= dm9000_get_eeprom,
+ 	.set_eeprom		= dm9000_set_eeprom,
+};
+
+
 /* dm9000_release_board
  *
  * release a board, and any mapped resources
@@ -401,6 +509,7 @@ dm9000_probe(struct platform_device *pdev)
 	struct dm9000_plat_data *pdata = pdev->dev.platform_data;
 	struct board_info *db;	/* Point a board information structure */
 	struct net_device *ndev;
+	const unsigned char *mac_src;
 	unsigned long base;
 	int ret = 0;
 	int iosize;
@@ -410,19 +519,22 @@ dm9000_probe(struct platform_device *pdev)
 	/* Init network device */
 	ndev = alloc_etherdev(sizeof (struct board_info));
 	if (!ndev) {
-		printk("%s: could not allocate device.\n", CARDNAME);
+		dev_err(&pdev->dev, "could not allocate device.\n");
 		return -ENOMEM;
 	}
 
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
-	PRINTK2("dm9000_probe()");
+	dev_dbg(&pdev->dev, "dm9000_probe()");
 
 	/* setup board info structure */
 	db = (struct board_info *) ndev->priv;
 	memset(db, 0, sizeof (*db));
 
+	db->dev = &pdev->dev;
+
 	spin_lock_init(&db->lock);
+	mutex_init(&db->addr_lock);
 
 	if (pdev->num_resources < 2) {
 		ret = -ENODEV;
@@ -450,7 +562,7 @@ dm9000_probe(struct platform_device *pdev)
 
 		if (db->addr_res == NULL || db->data_res == NULL ||
 		    db->irq_res == NULL) {
-			printk(KERN_ERR PFX "insufficient resources\n");
+			dev_err(db->dev, "insufficient resources\n");
 			ret = -ENOENT;
 			goto out;
 		}
@@ -460,7 +572,7 @@ dm9000_probe(struct platform_device *pdev)
 						  pdev->name);
 
 		if (db->addr_req == NULL) {
-			printk(KERN_ERR PFX "cannot claim address reg area\n");
+			dev_err(db->dev, "cannot claim address reg area\n");
 			ret = -EIO;
 			goto out;
 		}
@@ -468,7 +580,7 @@ dm9000_probe(struct platform_device *pdev)
 		db->io_addr = ioremap(db->addr_res->start, i);
 
 		if (db->io_addr == NULL) {
-			printk(KERN_ERR "failed to ioremap address reg\n");
+			dev_err(db->dev, "failed to ioremap address reg\n");
 			ret = -EINVAL;
 			goto out;
 		}
@@ -478,7 +590,7 @@ dm9000_probe(struct platform_device *pdev)
 						  pdev->name);
 
 		if (db->data_req == NULL) {
-			printk(KERN_ERR PFX "cannot claim data reg area\n");
+			dev_err(db->dev, "cannot claim data reg area\n");
 			ret = -EIO;
 			goto out;
 		}
@@ -486,7 +598,7 @@ dm9000_probe(struct platform_device *pdev)
 		db->io_data = ioremap(db->data_res->start, iosize);
 
 		if (db->io_data == NULL) {
-			printk(KERN_ERR "failed to ioremap data reg\n");
+			dev_err(db->dev,"failed to ioremap data reg\n");
 			ret = -EINVAL;
 			goto out;
 		}
@@ -525,12 +637,14 @@ dm9000_probe(struct platform_device *pdev)
 
 		if (pdata->dumpblk != NULL)
 			db->dumpblk = pdata->dumpblk;
+
+		db->flags = pdata->flags;
 	}
 
 	dm9000_reset(db);
 
 	/* try two times, DM9000 sometimes gets the first read wrong */
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < 8; i++) {
 		id_val  = ior(db, DM9000_VIDL);
 		id_val |= (u32)ior(db, DM9000_VIDH) << 8;
 		id_val |= (u32)ior(db, DM9000_PIDL) << 16;
@@ -538,11 +652,11 @@ dm9000_probe(struct platform_device *pdev)
 
 		if (id_val == DM9000_ID)
 			break;
-		printk("%s: read wrong id 0x%08x\n", CARDNAME, id_val);
+		dev_err(db->dev, "read wrong id 0x%08x\n", id_val);
 	}
 
 	if (id_val != DM9000_ID) {
-		printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val);
+		dev_err(db->dev, "wrong id: 0x%08x\n", id_val);
 		ret = -ENODEV;
 		goto out;
 	}
@@ -558,13 +672,13 @@ dm9000_probe(struct platform_device *pdev)
 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
 	ndev->stop		 = &dm9000_stop;
 	ndev->set_multicast_list = &dm9000_hash_table;
+	ndev->ethtool_ops	 = &dm9000_ethtool_ops;
+	ndev->do_ioctl		 = &dm9000_ioctl;
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	ndev->poll_controller	 = &dm9000_poll_controller;
 #endif
 
-#ifdef DM9000_PROGRAM_EEPROM
-	program_eeprom(db);
-#endif
 	db->msg_enable       = NETIF_MSG_LINK;
 	db->mii.phy_id_mask  = 0x1f;
 	db->mii.reg_num_mask = 0x1f;
@@ -574,38 +688,37 @@ dm9000_probe(struct platform_device *pdev)
 	db->mii.mdio_read    = dm9000_phy_read;
 	db->mii.mdio_write   = dm9000_phy_write;
 
-	/* Read SROM content */
-	for (i = 0; i < 64; i++)
-		((u16 *) db->srom)[i] = read_srom_word(db, i);
+	mac_src = "eeprom";
 
-	/* Set Node Address */
-	for (i = 0; i < 6; i++)
-		ndev->dev_addr[i] = db->srom[i];
+	/* try reading the node address from the attached EEPROM */
+	for (i = 0; i < 6; i += 2)
+		dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);
 
 	if (!is_valid_ether_addr(ndev->dev_addr)) {
 		/* try reading from mac */
-
+		
+		mac_src = "chip";
 		for (i = 0; i < 6; i++)
 			ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
 	}
 
 	if (!is_valid_ether_addr(ndev->dev_addr))
-		printk("%s: Invalid ethernet MAC address.  Please "
-		       "set using ifconfig\n", ndev->name);
+		dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "
+			 "set using ifconfig\n", ndev->name);
 
 	platform_set_drvdata(pdev, ndev);
 	ret = register_netdev(ndev);
 
 	if (ret == 0) {
 		DECLARE_MAC_BUF(mac);
-		printk("%s: dm9000 at %p,%p IRQ %d MAC: %s\n",
+		printk("%s: dm9000 at %p,%p IRQ %d MAC: %s (%s)\n",
 		       ndev->name,  db->io_addr, db->io_data, ndev->irq,
-		       print_mac(mac, ndev->dev_addr));
+		       print_mac(mac, ndev->dev_addr), mac_src);
 	}
 	return 0;
 
 out:
-	printk("%s: not found (%d).\n", CARDNAME, ret);
+	dev_err(db->dev, "not found (%d).\n", ret);
 
 	dm9000_release_board(pdev, db);
 	free_netdev(ndev);
@@ -621,10 +734,22 @@ static int
 dm9000_open(struct net_device *dev)
 {
 	board_info_t *db = (board_info_t *) dev->priv;
+	unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
 
-	PRINTK2("entering dm9000_open\n");
+	if (netif_msg_ifup(db))
+		dev_dbg(db->dev, "enabling %s\n", dev->name);
 
-	if (request_irq(dev->irq, &dm9000_interrupt, DM9000_IRQ_FLAGS, dev->name, dev))
+	/* If there is no IRQ type specified, default to something that
+	 * may work, and tell the user that this is a problem */
+
+	if (irqflags == IRQF_TRIGGER_NONE) {
+		dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
+		irqflags = DEFAULT_TRIGGER;
+	}
+	
+	irqflags |= IRQF_SHARED;
+
+	if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev))
 		return -EAGAIN;
 
 	/* Initialize DM9000 board */
@@ -634,13 +759,6 @@ dm9000_open(struct net_device *dev)
 	/* Init driver variable */
 	db->dbug_cnt = 0;
 
-	/* set and active a timer process */
-	init_timer(&db->timer);
-	db->timer.expires  = DM9000_TIMER_WUT;
-	db->timer.data     = (unsigned long) dev;
-	db->timer.function = &dm9000_timer;
-	add_timer(&db->timer);
-
 	mii_check_media(&db->mii, netif_msg_link(db), 1);
 	netif_start_queue(dev);
 
@@ -655,7 +773,7 @@ dm9000_init_dm9000(struct net_device *dev)
 {
 	board_info_t *db = (board_info_t *) dev->priv;
 
-	PRINTK1("entering %s\n",__FUNCTION__);
+	dm9000_dbg(db, 1, "entering %s\n", __func__);
 
 	/* I/O mode */
 	db->io_mode = ior(db, DM9000_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */
@@ -665,6 +783,9 @@ dm9000_init_dm9000(struct net_device *dev)
 	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */
 	iow(db, DM9000_GPR, 0);	/* Enable PHY */
 
+	if (db->flags & DM9000_PLATF_EXT_PHY)
+		iow(db, DM9000_NCR, NCR_EXT_PHY);
+
 	/* Program operating register */
 	iow(db, DM9000_TCR, 0);	        /* TX Polling clear */
 	iow(db, DM9000_BPTR, 0x3f);	/* Less 3Kb, 200us */
@@ -698,7 +819,7 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	unsigned long flags;
 	board_info_t *db = (board_info_t *) dev->priv;
 
-	PRINTK3("dm9000_start_xmit\n");
+	dm9000_dbg(db, 3, "%s:\n", __func__);
 
 	if (db->tx_pkt_cnt > 1)
 		return 1;
@@ -715,8 +836,8 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* TX control: First packet immediately send, second packet queue */
 	if (db->tx_pkt_cnt == 1) {
 		/* Set TX length to DM9000 */
-		iow(db, DM9000_TXPLL, skb->len & 0xff);
-		iow(db, DM9000_TXPLH, (skb->len >> 8) & 0xff);
+		iow(db, DM9000_TXPLL, skb->len);
+		iow(db, DM9000_TXPLH, skb->len >> 8);
 
 		/* Issue TX polling command */
 		iow(db, DM9000_TCR, TCR_TXREQ);	/* Cleared after TX complete */
@@ -757,10 +878,8 @@ dm9000_stop(struct net_device *ndev)
 {
 	board_info_t *db = (board_info_t *) ndev->priv;
 
-	PRINTK1("entering %s\n",__FUNCTION__);
-
-	/* deleted timer */
-	del_timer(&db->timer);
+	if (netif_msg_ifdown(db))
+		dev_dbg(db->dev, "shutting down %s\n", ndev->name);
 
 	netif_stop_queue(ndev);
 	netif_carrier_off(ndev);
@@ -788,10 +907,13 @@ dm9000_tx_done(struct net_device *dev, board_info_t * db)
 		db->tx_pkt_cnt--;
 		dev->stats.tx_packets++;
 
+		if (netif_msg_tx_done(db))
+			dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
+
 		/* Queue packet check & send */
 		if (db->tx_pkt_cnt > 0) {
-			iow(db, DM9000_TXPLL, db->queue_pkt_len & 0xff);
-			iow(db, DM9000_TXPLH, (db->queue_pkt_len >> 8) & 0xff);
+			iow(db, DM9000_TXPLL, db->queue_pkt_len);
+			iow(db, DM9000_TXPLH, db->queue_pkt_len >> 8);
 			iow(db, DM9000_TCR, TCR_TXREQ);
 			dev->trans_start = jiffies;
 		}
@@ -803,19 +925,14 @@ static irqreturn_t
 dm9000_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
-	board_info_t *db;
+	board_info_t *db = (board_info_t *) dev->priv;
 	int int_status;
 	u8 reg_save;
 
-	PRINTK3("entering %s\n",__FUNCTION__);
-
-	if (!dev) {
-		PRINTK1("dm9000_interrupt() without DEVICE arg\n");
-		return IRQ_HANDLED;
-	}
+	dm9000_dbg(db, 3, "entering %s\n", __func__);
 
 	/* A real interrupt coming */
-	db = (board_info_t *) dev->priv;
+
 	spin_lock(&db->lock);
 
 	/* Save previous register address */
@@ -828,6 +945,9 @@ dm9000_interrupt(int irq, void *dev_id)
 	int_status = ior(db, DM9000_ISR);	/* Got ISR */
 	iow(db, DM9000_ISR, int_status);	/* Clear ISR status */
 
+	if (netif_msg_intr(db))
+		dev_dbg(db->dev, "interrupt status %02x\n", int_status);
+
 	/* Received the coming packet */
 	if (int_status & ISR_PRS)
 		dm9000_rx(dev);
@@ -847,27 +967,9 @@ dm9000_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-/*
- *  A periodic timer routine
- *  Dynamic media sense, allocated Rx buffer...
- */
-static void
-dm9000_timer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *) data;
-	board_info_t *db = (board_info_t *) dev->priv;
-
-	PRINTK3("dm9000_timer()\n");
-
-	mii_check_media(&db->mii, netif_msg_link(db), 0);
-
-	/* Set timer again */
-	db->timer.expires = DM9000_TIMER_WUT;
-	add_timer(&db->timer);
-}
-
 struct dm9000_rxhdr {
-	u16	RxStatus;
+	u8	RxPktReady;
+	u8	RxStatus;
 	u16	RxLen;
 } __attribute__((__packed__));
 
@@ -893,7 +995,7 @@ dm9000_rx(struct net_device *dev)
 
 		/* Status check: this byte must be 0 or 1 */
 		if (rxbyte > DM9000_PKT_RDY) {
-			printk("status check failed: %d\n", rxbyte);
+			dev_warn(db->dev, "status check fail: %d\n", rxbyte);
 			iow(db, DM9000_RCR, 0x00);	/* Stop Device */
 			iow(db, DM9000_ISR, IMR_PAR);	/* Stop INT request */
 			return;
@@ -908,30 +1010,38 @@ dm9000_rx(struct net_device *dev)
 
 		(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));
 
-		RxLen = rxhdr.RxLen;
+		RxLen = le16_to_cpu(rxhdr.RxLen);
+
+		if (netif_msg_rx_status(db))
+			dev_dbg(db->dev, "RX: status %02x, length %04x\n",
+				rxhdr.RxStatus, RxLen);
 
 		/* Packet Status check */
 		if (RxLen < 0x40) {
 			GoodPacket = false;
-			PRINTK1("Bad Packet received (runt)\n");
+			if (netif_msg_rx_err(db))
+				dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
 		}
 
 		if (RxLen > DM9000_PKT_MAX) {
-			PRINTK1("RST: RX Len:%x\n", RxLen);
+			dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
 		}
 
-		if (rxhdr.RxStatus & 0xbf00) {
+		if (rxhdr.RxStatus & 0xbf) {
 			GoodPacket = false;
-			if (rxhdr.RxStatus & 0x100) {
-				PRINTK1("fifo error\n");
+			if (rxhdr.RxStatus & 0x01) {
+				if (netif_msg_rx_err(db))
+					dev_dbg(db->dev, "fifo error\n");
 				dev->stats.rx_fifo_errors++;
 			}
-			if (rxhdr.RxStatus & 0x200) {
-				PRINTK1("crc error\n");
+			if (rxhdr.RxStatus & 0x02) {
+				if (netif_msg_rx_err(db))
+					dev_dbg(db->dev, "crc error\n");
 				dev->stats.rx_crc_errors++;
 			}
-			if (rxhdr.RxStatus & 0x8000) {
-				PRINTK1("length error\n");
+			if (rxhdr.RxStatus & 0x80) {
+				if (netif_msg_rx_err(db))
+					dev_dbg(db->dev, "length error\n");
 				dev->stats.rx_length_errors++;
 			}
 		}
@@ -960,72 +1070,119 @@ dm9000_rx(struct net_device *dev)
 	} while (rxbyte == DM9000_PKT_RDY);
 }
 
-/*
- *  Read a word data from SROM
- */
-static u16
-read_srom_word(board_info_t * db, int offset)
+static unsigned int
+dm9000_read_locked(board_info_t *db, int reg)
 {
-	iow(db, DM9000_EPAR, offset);
-	iow(db, DM9000_EPCR, EPCR_ERPRR);
-	mdelay(8);		/* according to the datasheet 200us should be enough,
-				   but it doesn't work */
-	iow(db, DM9000_EPCR, 0x0);
-	return (ior(db, DM9000_EPDRL) + (ior(db, DM9000_EPDRH) << 8));
+	unsigned long flags;
+	unsigned int ret;
+
+	spin_lock_irqsave(&db->lock, flags);
+	ret = ior(db, reg);
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	return ret;
+}
+
+static int dm9000_wait_eeprom(board_info_t *db)
+{
+	unsigned int status;
+	int timeout = 8;	/* wait max 8msec */
+
+	/* The DM9000 data sheets say we should be able to
+	 * poll the ERRE bit in EPCR to wait for the EEPROM
+	 * operation. From testing several chips, this bit
+	 * does not seem to work. 
+	 *
+	 * We attempt to use the bit, but fall back to the
+	 * timeout (which is why we do not return an error
+	 * on expiry) to say that the EEPROM operation has
+	 * completed.
+	 */
+
+	while (1) {
+		status = dm9000_read_locked(db, DM9000_EPCR);
+
+		if ((status & EPCR_ERRE) == 0)
+			break;
+
+		if (timeout-- < 0) {
+			dev_dbg(db->dev, "timeout waiting EEPROM\n");
+			break;
+		}
+	}
+
+	return 0;
 }
 
-#ifdef DM9000_PROGRAM_EEPROM
 /*
- * Write a word data to SROM
+ *  Read a word data from EEPROM
  */
 static void
-write_srom_word(board_info_t * db, int offset, u16 val)
+dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
 {
+	unsigned long flags;
+
+	if (db->flags & DM9000_PLATF_NO_EEPROM) {
+		to[0] = 0xff;
+		to[1] = 0xff;
+		return;
+	}
+
+	mutex_lock(&db->addr_lock);
+
+	spin_lock_irqsave(&db->lock, flags);
+
 	iow(db, DM9000_EPAR, offset);
-	iow(db, DM9000_EPDRH, ((val >> 8) & 0xff));
-	iow(db, DM9000_EPDRL, (val & 0xff));
-	iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
-	mdelay(8);		/* same shit */
-	iow(db, DM9000_EPCR, 0);
+	iow(db, DM9000_EPCR, EPCR_ERPRR);
+
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	dm9000_wait_eeprom(db);
+
+	/* delay for at-least 150uS */
+	msleep(1);
+
+	spin_lock_irqsave(&db->lock, flags);
+
+	iow(db, DM9000_EPCR, 0x0);
+
+	to[0] = ior(db, DM9000_EPDRL);
+	to[1] = ior(db, DM9000_EPDRH);
+
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	mutex_unlock(&db->addr_lock);
 }
 
 /*
- * Only for development:
- * Here we write static data to the eeprom in case
- * we don't have valid content on a new board
+ * Write a word data to SROM
  */
 static void
-program_eeprom(board_info_t * db)
+dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
 {
-	u16 eeprom[] = { 0x0c00, 0x007f, 0x1300,	/* MAC Address */
-		0x0000,		/* Autoload: accept nothing */
-		0x0a46, 0x9000,	/* Vendor / Product ID */
-		0x0000,		/* pin control */
-		0x0000,
-	};			/* Wake-up mode control */
-	int i;
-	for (i = 0; i < 8; i++)
-		write_srom_word(db, i, eeprom[i]);
-}
-#endif
+	unsigned long flags;
 
+	if (db->flags & DM9000_PLATF_NO_EEPROM)
+		return;
 
-/*
- *  Calculate the CRC valude of the Rx packet
- *  flag = 1 : return the reverse CRC (for the received packet CRC)
- *         0 : return the normal CRC (for Hash Table index)
- */
+	mutex_lock(&db->addr_lock);
 
-static unsigned long
-cal_CRC(unsigned char *Data, unsigned int Len, u8 flag)
-{
+	spin_lock_irqsave(&db->lock, flags);
+	iow(db, DM9000_EPAR, offset);
+	iow(db, DM9000_EPDRH, data[1]);
+	iow(db, DM9000_EPDRL, data[0]);
+	iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	dm9000_wait_eeprom(db);
 
-       u32 crc = ether_crc_le(Len, Data);
+	mdelay(1);	/* wait at least 150uS to clear */
 
-       if (flag)
-               return ~crc;
+	spin_lock_irqsave(&db->lock, flags);
+	iow(db, DM9000_EPCR, 0);
+	spin_unlock_irqrestore(&db->lock, flags);
 
-       return crc;
+	mutex_unlock(&db->addr_lock);
 }
 
 /*
@@ -1037,15 +1194,16 @@ dm9000_hash_table(struct net_device *dev)
 	board_info_t *db = (board_info_t *) dev->priv;
 	struct dev_mc_list *mcptr = dev->mc_list;
 	int mc_cnt = dev->mc_count;
+	int i, oft;
 	u32 hash_val;
-	u16 i, oft, hash_table[4];
+	u16 hash_table[4];
 	unsigned long flags;
 
-	PRINTK2("dm9000_hash_table()\n");
+	dm9000_dbg(db, 1, "entering %s\n", __func__);
 
-	spin_lock_irqsave(&db->lock,flags);
+	spin_lock_irqsave(&db->lock, flags);
 
-	for (i = 0, oft = 0x10; i < 6; i++, oft++)
+	for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
 		iow(db, oft, dev->dev_addr[i]);
 
 	/* Clear Hash Table */
@@ -1057,21 +1215,33 @@ dm9000_hash_table(struct net_device *dev)
 
 	/* the multicast address in Hash Table : 64 bits */
 	for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
-		hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
+		hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f;
 		hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
 	}
 
 	/* Write the hash table to MAC MD table */
-	for (i = 0, oft = 0x16; i < 4; i++) {
-		iow(db, oft++, hash_table[i] & 0xff);
-		iow(db, oft++, (hash_table[i] >> 8) & 0xff);
+	for (i = 0, oft = DM9000_MAR; i < 4; i++) {
+		iow(db, oft++, hash_table[i]);
+		iow(db, oft++, hash_table[i] >> 8);
 	}
 
-	spin_unlock_irqrestore(&db->lock,flags);
+	spin_unlock_irqrestore(&db->lock, flags);
 }
 
 
 /*
+ * Sleep, either by using msleep() or if we are suspending, then
+ * use mdelay() to sleep.
+ */
+static void dm9000_msleep(board_info_t *db, unsigned int ms)
+{
+	if (db->in_suspend)
+		mdelay(ms);
+	else
+		msleep(ms);
+}
+
+/*
  *   Read a word from phyxcer
  */
 static int
@@ -1082,6 +1252,8 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
 	unsigned int reg_save;
 	int ret;
 
+	mutex_lock(&db->addr_lock);
+
 	spin_lock_irqsave(&db->lock,flags);
 
 	/* Save previous register address */
@@ -1091,7 +1263,15 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
 	iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
 	iow(db, DM9000_EPCR, 0xc);	/* Issue phyxcer read command */
-	udelay(100);		/* Wait read complete */
+
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(&db->lock,flags);
+
+	dm9000_msleep(db, 1);		/* Wait read complete */
+
+	spin_lock_irqsave(&db->lock,flags);
+	reg_save = readb(db->io_addr);
+
 	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
 
 	/* The read data keeps on REG_0D & REG_0E */
@@ -1099,9 +1279,9 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
 
 	/* restore the previous address */
 	writeb(reg_save, db->io_addr);
-
 	spin_unlock_irqrestore(&db->lock,flags);
 
+	mutex_unlock(&db->addr_lock);
 	return ret;
 }
 
@@ -1115,6 +1295,8 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
 	unsigned long flags;
 	unsigned long reg_save;
 
+	mutex_lock(&db->addr_lock);
+
 	spin_lock_irqsave(&db->lock,flags);
 
 	/* Save previous register address */
@@ -1124,25 +1306,38 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
 	iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
 	/* Fill the written data into REG_0D & REG_0E */
-	iow(db, DM9000_EPDRL, (value & 0xff));
-	iow(db, DM9000_EPDRH, ((value >> 8) & 0xff));
+	iow(db, DM9000_EPDRL, value);
+	iow(db, DM9000_EPDRH, value >> 8);
 
 	iow(db, DM9000_EPCR, 0xa);	/* Issue phyxcer write command */
-	udelay(500);		/* Wait write complete */
+
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	dm9000_msleep(db, 1);		/* Wait write complete */
+
+	spin_lock_irqsave(&db->lock,flags);
+	reg_save = readb(db->io_addr);
+
 	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
 
 	/* restore the previous address */
 	writeb(reg_save, db->io_addr);
 
-	spin_unlock_irqrestore(&db->lock,flags);
+	spin_unlock_irqrestore(&db->lock, flags);
+	mutex_unlock(&db->addr_lock);
 }
 
 static int
 dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct net_device *ndev = platform_get_drvdata(dev);
+	board_info_t *db;
 
 	if (ndev) {
+		db = (board_info_t *) ndev->priv;
+		db->in_suspend = 1;
+
 		if (netif_running(ndev)) {
 			netif_device_detach(ndev);
 			dm9000_shutdown(ndev);
@@ -1165,6 +1360,8 @@ dm9000_drv_resume(struct platform_device *dev)
 
 			netif_device_attach(ndev);
 		}
+
+		db->in_suspend = 0;
 	}
 	return 0;
 }
@@ -1180,8 +1377,7 @@ dm9000_drv_remove(struct platform_device *pdev)
 	dm9000_release_board(pdev, (board_info_t *) ndev->priv);
 	free_netdev(ndev);		/* free device structure */
 
-	PRINTK1("clean_module() exit\n");
-
+	dev_dbg(&pdev->dev, "released and freed device\n");
 	return 0;
 }
 
@@ -1199,7 +1395,7 @@ static struct platform_driver dm9000_driver = {
 static int __init
 dm9000_init(void)
 {
-	printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
+	printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION);
 
 	return platform_driver_register(&dm9000_driver);	/* search board and register */
 }
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 7c5b05a..d4ee8ec 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -926,8 +926,6 @@ e1000_probe(struct pci_dev *pdev,
 {
 	struct net_device *netdev;
 	struct e1000_adapter *adapter;
-	unsigned long mmio_start, mmio_len;
-	unsigned long flash_start, flash_len;
 
 	static int cards_found = 0;
 	static int global_quad_port_a = 0; /* global ksp3 port a indication */
@@ -970,11 +968,9 @@ e1000_probe(struct pci_dev *pdev,
 	adapter->hw.back = adapter;
 	adapter->msg_enable = (1 << debug) - 1;
 
-	mmio_start = pci_resource_start(pdev, BAR_0);
-	mmio_len = pci_resource_len(pdev, BAR_0);
-
 	err = -EIO;
-	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
+	adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
+				      pci_resource_len(pdev, BAR_0));
 	if (!adapter->hw.hw_addr)
 		goto err_ioremap;
 
@@ -1009,10 +1005,6 @@ e1000_probe(struct pci_dev *pdev,
 #endif
 	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
 
-	netdev->mem_start = mmio_start;
-	netdev->mem_end = mmio_start + mmio_len;
-	netdev->base_addr = adapter->hw.io_base;
-
 	adapter->bd_number = cards_found;
 
 	/* setup the private structure */
@@ -1025,9 +1017,9 @@ e1000_probe(struct pci_dev *pdev,
 	 * because it depends on mac_type */
 	if ((adapter->hw.mac_type == e1000_ich8lan) &&
 	   (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
-		flash_start = pci_resource_start(pdev, 1);
-		flash_len = pci_resource_len(pdev, 1);
-		adapter->hw.flash_address = ioremap(flash_start, flash_len);
+		adapter->hw.flash_address =
+			ioremap(pci_resource_start(pdev, 1),
+				pci_resource_len(pdev, 1));
 		if (!adapter->hw.flash_address)
 			goto err_flashmap;
 	}
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index d4843d0..801b4d9 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -166,21 +166,24 @@
  * Hardware access:
  */
 
-#define DEV_NEED_TIMERIRQ	0x0001  /* set the timer irq flag in the irq mask */
-#define DEV_NEED_LINKTIMER	0x0002	/* poll link settings. Relies on the timer irq */
-#define DEV_HAS_LARGEDESC	0x0004	/* device supports jumbo frames and needs packet format 2 */
-#define DEV_HAS_HIGH_DMA        0x0008  /* device supports 64bit dma */
-#define DEV_HAS_CHECKSUM        0x0010  /* device supports tx and rx checksum offloads */
-#define DEV_HAS_VLAN            0x0020  /* device supports vlan tagging and striping */
-#define DEV_HAS_MSI             0x0040  /* device supports MSI */
-#define DEV_HAS_MSI_X           0x0080  /* device supports MSI-X */
-#define DEV_HAS_POWER_CNTRL     0x0100  /* device supports power savings */
-#define DEV_HAS_PAUSEFRAME_TX   0x0200  /* device supports tx pause frames */
-#define DEV_HAS_STATISTICS_V1   0x0400  /* device supports hw statistics version 1 */
-#define DEV_HAS_STATISTICS_V2   0x0800  /* device supports hw statistics version 2 */
-#define DEV_HAS_TEST_EXTENDED   0x1000  /* device supports extended diagnostic test */
-#define DEV_HAS_MGMT_UNIT       0x2000  /* device supports management unit */
-#define DEV_HAS_CORRECT_MACADDR 0x4000  /* device supports correct mac address order */
+#define DEV_NEED_TIMERIRQ          0x00001  /* set the timer irq flag in the irq mask */
+#define DEV_NEED_LINKTIMER         0x00002  /* poll link settings. Relies on the timer irq */
+#define DEV_HAS_LARGEDESC          0x00004  /* device supports jumbo frames and needs packet format 2 */
+#define DEV_HAS_HIGH_DMA           0x00008  /* device supports 64bit dma */
+#define DEV_HAS_CHECKSUM           0x00010  /* device supports tx and rx checksum offloads */
+#define DEV_HAS_VLAN               0x00020  /* device supports vlan tagging and striping */
+#define DEV_HAS_MSI                0x00040  /* device supports MSI */
+#define DEV_HAS_MSI_X              0x00080  /* device supports MSI-X */
+#define DEV_HAS_POWER_CNTRL        0x00100  /* device supports power savings */
+#define DEV_HAS_STATISTICS_V1      0x00200  /* device supports hw statistics version 1 */
+#define DEV_HAS_STATISTICS_V2      0x00400  /* device supports hw statistics version 2 */
+#define DEV_HAS_TEST_EXTENDED      0x00800  /* device supports extended diagnostic test */
+#define DEV_HAS_MGMT_UNIT          0x01000  /* device supports management unit */
+#define DEV_HAS_CORRECT_MACADDR    0x02000  /* device supports correct mac address order */
+#define DEV_HAS_COLLISION_FIX      0x04000  /* device supports tx collision fix */
+#define DEV_HAS_PAUSEFRAME_TX_V1   0x08000  /* device supports tx pause frames version 1 */
+#define DEV_HAS_PAUSEFRAME_TX_V2   0x10000  /* device supports tx pause frames version 2 */
+#define DEV_HAS_PAUSEFRAME_TX_V3   0x20000  /* device supports tx pause frames version 3 */
 
 enum {
 	NvRegIrqStatus = 0x000,
@@ -266,9 +269,12 @@ enum {
 #define NVREG_RNDSEED_FORCE3	0x7400
 
 	NvRegTxDeferral = 0xA0,
-#define NVREG_TX_DEFERRAL_DEFAULT	0x15050f
-#define NVREG_TX_DEFERRAL_RGMII_10_100	0x16070f
-#define NVREG_TX_DEFERRAL_RGMII_1000	0x14050f
+#define NVREG_TX_DEFERRAL_DEFAULT		0x15050f
+#define NVREG_TX_DEFERRAL_RGMII_10_100		0x16070f
+#define NVREG_TX_DEFERRAL_RGMII_1000		0x14050f
+#define NVREG_TX_DEFERRAL_RGMII_STRETCH_10	0x16190f
+#define NVREG_TX_DEFERRAL_RGMII_STRETCH_100	0x16300f
+#define NVREG_TX_DEFERRAL_MII_STRETCH		0x152000
 	NvRegRxDeferral = 0xA4,
 #define NVREG_RX_DEFERRAL_DEFAULT	0x16
 	NvRegMacAddrA = 0xA8,
@@ -318,8 +324,10 @@ enum {
 	NvRegTxRingPhysAddrHigh = 0x148,
 	NvRegRxRingPhysAddrHigh = 0x14C,
 	NvRegTxPauseFrame = 0x170,
-#define NVREG_TX_PAUSEFRAME_DISABLE	0x01ff0080
-#define NVREG_TX_PAUSEFRAME_ENABLE	0x01800010
+#define NVREG_TX_PAUSEFRAME_DISABLE	0x0fff0080
+#define NVREG_TX_PAUSEFRAME_ENABLE_V1	0x01800010
+#define NVREG_TX_PAUSEFRAME_ENABLE_V2	0x056003f0
+#define NVREG_TX_PAUSEFRAME_ENABLE_V3	0x09f00880
 	NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR		0x0001
 #define NVREG_MIISTAT_LINKCHANGE	0x0008
@@ -2751,7 +2759,12 @@ static void nv_update_pause(struct net_device *dev, u32 pause_flags)
 	if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE) {
 		u32 regmisc = readl(base + NvRegMisc1) & ~NVREG_MISC1_PAUSE_TX;
 		if (pause_flags & NV_PAUSEFRAME_TX_ENABLE) {
-			writel(NVREG_TX_PAUSEFRAME_ENABLE,  base + NvRegTxPauseFrame);
+			u32 pause_enable = NVREG_TX_PAUSEFRAME_ENABLE_V1;
+			if (np->driver_data & DEV_HAS_PAUSEFRAME_TX_V2)
+				pause_enable = NVREG_TX_PAUSEFRAME_ENABLE_V2;
+			if (np->driver_data & DEV_HAS_PAUSEFRAME_TX_V3)
+				pause_enable = NVREG_TX_PAUSEFRAME_ENABLE_V3;
+			writel(pause_enable,  base + NvRegTxPauseFrame);
 			writel(regmisc|NVREG_MISC1_PAUSE_TX, base + NvRegMisc1);
 			np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
 		} else {
@@ -2785,6 +2798,7 @@ static int nv_update_linkspeed(struct net_device *dev)
 	int retval = 0;
 	u32 control_1000, status_1000, phyreg, pause_flags, txreg;
 	u32 txrxFlags = 0;
+	u32 phy_exp;
 
 	/* BMSR_LSTATUS is latched, read it twice:
 	 * we want the current value.
@@ -2912,13 +2926,25 @@ set_speed:
 		phyreg |= PHY_1000;
 	writel(phyreg, base + NvRegPhyInterface);
 
+	phy_exp = mii_rw(dev, np->phyaddr, MII_EXPANSION, MII_READ) & EXPANSION_NWAY; /* autoneg capable */
 	if (phyreg & PHY_RGMII) {
-		if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_1000)
+		if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_1000) {
 			txreg = NVREG_TX_DEFERRAL_RGMII_1000;
-		else
-			txreg = NVREG_TX_DEFERRAL_RGMII_10_100;
+		} else {
+			if (!phy_exp && !np->duplex && (np->driver_data & DEV_HAS_COLLISION_FIX)) {
+				if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_10)
+					txreg = NVREG_TX_DEFERRAL_RGMII_STRETCH_10;
+				else
+					txreg = NVREG_TX_DEFERRAL_RGMII_STRETCH_100;
+			} else {
+				txreg = NVREG_TX_DEFERRAL_RGMII_10_100;
+			}
+		}
 	} else {
-		txreg = NVREG_TX_DEFERRAL_DEFAULT;
+		if (!phy_exp && !np->duplex && (np->driver_data & DEV_HAS_COLLISION_FIX))
+			txreg = NVREG_TX_DEFERRAL_MII_STRETCH;
+		else
+			txreg = NVREG_TX_DEFERRAL_DEFAULT;
 	}
 	writel(txreg, base + NvRegTxDeferral);
 
@@ -5155,7 +5181,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 	}
 
 	np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG;
-	if (id->driver_data & DEV_HAS_PAUSEFRAME_TX) {
+	if ((id->driver_data & DEV_HAS_PAUSEFRAME_TX_V1) ||
+	    (id->driver_data & DEV_HAS_PAUSEFRAME_TX_V2) ||
+	    (id->driver_data & DEV_HAS_PAUSEFRAME_TX_V3)) {
 		np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ;
 	}
 
@@ -5559,107 +5587,107 @@ static struct pci_device_id pci_tbl[] = {
 	},
 	{	/* MCP55 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
 	},
 	{	/* MCP55 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
 	},
 	{	/* MCP61 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP61 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP61 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP61 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP65 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP65 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP65 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP65 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP67 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP67 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP67 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP67 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
 	},
 	{	/* MCP73 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP73 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP73 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP73 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP77 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP77 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP77 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP77 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP79 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP79 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP79 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{	/* MCP79 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
 	},
 	{0,},
 };
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index 6b3384a..26aa8fe 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -33,20 +33,20 @@
  * I have also done a look in the following sources: (mail me if you need them)
  *   crynwr-packet-driver by Russ Nelson
  *   Garret A. Wollman's (fourth) i82586-driver for BSD
- *   (before getting an i82596 (yes 596 not 586) manual, the existing drivers helped
- *    me a lot to understand this tricky chip.)
+ *   (before getting an i82596 (yes 596 not 586) manual, the existing drivers
+ *    helped me a lot to understand this tricky chip.)
  *
  * Known Problems:
  *   The internal sysbus seems to be slow. So we often lose packets because of
  *   overruns while receiving from a fast remote host.
- *   This can slow down TCP connections. Maybe the newer ni5210 cards are better.
- *   my experience is, that if a machine sends with more than about 500-600K/s
- *   the fifo/sysbus overflows.
+ *   This can slow down TCP connections. Maybe the newer ni5210 cards are
+ *   better. My experience is, that if a machine sends with more than about
+ *   500-600K/s the fifo/sysbus overflows.
  *
  * IMPORTANT NOTE:
  *   On fast networks, it's a (very) good idea to have 16K shared memory. With
- *   8K, we can store only 4 receive frames, so it can (easily) happen that a remote
- *   machine 'overruns' our system.
+ *   8K, we can store only 4 receive frames, so it can (easily) happen that a
+ *   remote machine 'overruns' our system.
  *
  * Known i82586/card problems (I'm sure, there are many more!):
  *   Running the NOP-mode, the i82586 sometimes seems to forget to report
@@ -60,7 +60,8 @@
  *
  * results from ftp performance tests with Linux 1.2.5
  *   send and receive about 350-400 KByte/s (peak up to 460 kbytes/s)
- *   sending in NOP-mode: peak performance up to 530K/s (but better don't run this mode)
+ *   sending in NOP-mode: peak performance up to 530K/s (but better don't
+ *   run this mode)
  */
 
 /*
@@ -94,7 +95,8 @@
  *
  * 26.March.94: patches for Linux 1.0 and iomem-auto-probe (MH)
  *
- * 30.Sep.93: Added nop-chain .. driver now runs with only one Xmit-Buff, too (MH)
+ * 30.Sep.93: Added nop-chain .. driver now runs with only one Xmit-Buff,
+ *				too (MH)
  *
  * < 30.Sep.93: first versions
  */
@@ -102,7 +104,7 @@
 static int debuglevel;	/* debug-printk 0: off 1: a few 2: more */
 static int automatic_resume; /* experimental .. better should be zero */
 static int rfdadd;	/* rfdadd=1 may be better for 8K MEM cards */
-static int fifo=0x8;	/* don't change */
+static int fifo = 0x8;	/* don't change */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -127,14 +129,15 @@ static int fifo=0x8;	/* don't change */
 #define DEBUG       /* debug on */
 #define SYSBUSVAL 1 /* 8 Bit */
 
-#define ni_attn586()  {outb(0,dev->base_addr+NI52_ATTENTION);}
-#define ni_reset586() {outb(0,dev->base_addr+NI52_RESET);}
-#define ni_disint()   {outb(0,dev->base_addr+NI52_INTDIS);}
-#define ni_enaint()   {outb(0,dev->base_addr+NI52_INTENA);}
+#define ni_attn586()  { outb(0, dev->base_addr + NI52_ATTENTION); }
+#define ni_reset586() { outb(0, dev->base_addr + NI52_RESET); }
+#define ni_disint()   { outb(0, dev->base_addr + NI52_INTDIS); }
+#define ni_enaint()   { outb(0, dev->base_addr + NI52_INTENA); }
 
-#define make32(ptr16) (p->memtop + (short) (ptr16) )
-#define make24(ptr32) ( ((char *) (ptr32)) - p->base)
-#define make16(ptr32) ((unsigned short) ((unsigned long)(ptr32) - (unsigned long) p->memtop ))
+#define make32(ptr16) (p->memtop + (short) (ptr16))
+#define make24(ptr32) ((unsigned long)(ptr32)) - p->base
+#define make16(ptr32) ((unsigned short) ((unsigned long)(ptr32)\
+					- (unsigned long) p->memtop))
 
 /******************* how to calculate the buffers *****************************
 
@@ -159,96 +162,112 @@ sizeof(nop_cmd) = 8;
 
 /**************************************************************************/
 
-/* different DELAYs */
-#define DELAY(x) mdelay(32 * x);
-#define DELAY_16(); { udelay(16); }
-#define DELAY_18(); { udelay(4); }
-
-/* wait for command with timeout: */
-#define WAIT_4_SCB_CMD() \
-{ int i; \
-  for(i=0;i<16384;i++) { \
-    if(!p->scb->cmd_cuc) break; \
-    DELAY_18(); \
-    if(i == 16383) { \
-      printk("%s: scb_cmd timed out: %04x,%04x .. disabling i82586!!\n",dev->name,p->scb->cmd_cuc,p->scb->cus); \
-       if(!p->reseted) { p->reseted = 1; ni_reset586(); } } } }
-
-#define WAIT_4_SCB_CMD_RUC() { int i; \
-  for(i=0;i<16384;i++) { \
-    if(!p->scb->cmd_ruc) break; \
-    DELAY_18(); \
-    if(i == 16383) { \
-      printk("%s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!!\n",dev->name,p->scb->cmd_ruc,p->scb->rus); \
-       if(!p->reseted) { p->reseted = 1; ni_reset586(); } } } }
-
-#define WAIT_4_STAT_COMPL(addr) { int i; \
-   for(i=0;i<32767;i++) { \
-     if((addr)->cmd_status & STAT_COMPL) break; \
-     DELAY_16(); DELAY_16(); } }
 
 #define NI52_TOTAL_SIZE 16
 #define NI52_ADDR0 0x02
 #define NI52_ADDR1 0x07
 #define NI52_ADDR2 0x01
 
-static int     ni52_probe1(struct net_device *dev,int ioaddr);
-static irqreturn_t ni52_interrupt(int irq,void *dev_id);
+static int     ni52_probe1(struct net_device *dev, int ioaddr);
+static irqreturn_t ni52_interrupt(int irq, void *dev_id);
 static int     ni52_open(struct net_device *dev);
 static int     ni52_close(struct net_device *dev);
-static int     ni52_send_packet(struct sk_buff *,struct net_device *);
+static int     ni52_send_packet(struct sk_buff *, struct net_device *);
 static struct  net_device_stats *ni52_get_stats(struct net_device *dev);
 static void    set_multicast_list(struct net_device *dev);
 static void    ni52_timeout(struct net_device *dev);
-#if 0
-static void    ni52_dump(struct net_device *,void *);
-#endif
 
 /* helper-functions */
 static int     init586(struct net_device *dev);
-static int     check586(struct net_device *dev,char *where,unsigned size);
+static int     check586(struct net_device *dev, char *where, unsigned size);
 static void    alloc586(struct net_device *dev);
 static void    startrecv586(struct net_device *dev);
-static void   *alloc_rfa(struct net_device *dev,void *ptr);
+static void   *alloc_rfa(struct net_device *dev, void *ptr);
 static void    ni52_rcv_int(struct net_device *dev);
 static void    ni52_xmt_int(struct net_device *dev);
 static void    ni52_rnr_int(struct net_device *dev);
 
-struct priv
-{
+struct priv {
 	struct net_device_stats stats;
 	unsigned long base;
 	char *memtop;
-	long int lock;
-	int reseted;
-	volatile struct rfd_struct	*rfd_last,*rfd_top,*rfd_first;
-	volatile struct scp_struct	*scp;	/* volatile is important */
-	volatile struct iscp_struct	*iscp;	/* volatile is important */
-	volatile struct scb_struct	*scb;	/* volatile is important */
-	volatile struct tbd_struct	*xmit_buffs[NUM_XMIT_BUFFS];
+	spinlock_t spinlock;
+	int reset;
+	struct rfd_struct *rfd_last, *rfd_top, *rfd_first;
+	struct scp_struct *scp;
+	struct iscp_struct *iscp;
+	struct scb_struct *scb;
+	struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS];
 #if (NUM_XMIT_BUFFS == 1)
-	volatile struct transmit_cmd_struct *xmit_cmds[2];
-	volatile struct nop_cmd_struct *nop_cmds[2];
+	struct transmit_cmd_struct *xmit_cmds[2];
+	struct nop_cmd_struct *nop_cmds[2];
 #else
-	volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
-	volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
+	struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
+	struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
 #endif
-	volatile int		nop_point,num_recv_buffs;
-	volatile char		*xmit_cbuffs[NUM_XMIT_BUFFS];
-	volatile int		xmit_count,xmit_last;
+	int nop_point, num_recv_buffs;
+	char *xmit_cbuffs[NUM_XMIT_BUFFS];
+	int xmit_count, xmit_last;
 };
 
+/* wait for command with timeout: */
+static void wait_for_scb_cmd(struct net_device *dev)
+{
+	struct priv *p = dev->priv;
+	int i;
+	for (i = 0; i < 16384; i++) {
+		if (readb(&p->scb->cmd_cuc) == 0)
+		      break;
+		udelay(4);
+		if (i == 16383) {
+			printk(KERN_ERR "%s: scb_cmd timed out: %04x,%04x .. disabling i82586!!\n",
+				dev->name, readb(&p->scb->cmd_cuc), readb(&p->scb->cus));
+			if (!p->reset) {
+				p->reset = 1;
+				ni_reset586();
+			}
+		}
+	}
+}
+
+static void wait_for_scb_cmd_ruc(struct net_device *dev)
+{
+	struct priv *p = dev->priv;
+	int i;
+	for (i = 0; i < 16384; i++) {
+		if (readb(&p->scb->cmd_ruc) == 0)
+			break;
+		udelay(4);
+		if (i == 16383) {
+			printk(KERN_ERR "%s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!!\n",
+				dev->name, p->scb->cmd_ruc, p->scb->rus);
+			if (!p->reset) {
+				p->reset = 1;
+				ni_reset586();
+			}
+		}
+	}
+}
+
+static void wait_for_stat_compl(void *p)
+{
+	struct nop_cmd_struct *addr = p;
+	int i;
+	for (i = 0; i < 32767; i++) {
+		if (readw(&((addr)->cmd_status)) & STAT_COMPL)
+			break;
+		udelay(32);
+	}
+}
+
 /**********************************************
  * close device
  */
 static int ni52_close(struct net_device *dev)
 {
 	free_irq(dev->irq, dev);
-
 	ni_reset586(); /* the hard way to stop the receiver */
-
 	netif_stop_queue(dev);
-
 	return 0;
 }
 
@@ -265,55 +284,53 @@ static int ni52_open(struct net_device *dev)
 	startrecv586(dev);
 	ni_enaint();
 
-	ret = request_irq(dev->irq, &ni52_interrupt,0,dev->name,dev);
-	if (ret)
-	{
+	ret = request_irq(dev->irq, &ni52_interrupt, 0, dev->name, dev);
+	if (ret) {
 		ni_reset586();
 		return ret;
 	}
-
 	netif_start_queue(dev);
-
 	return 0; /* most done by init */
 }
 
 /**********************************************
  * Check to see if there's an 82586 out there.
  */
-static int check586(struct net_device *dev,char *where,unsigned size)
+static int check586(struct net_device *dev, char *where, unsigned size)
 {
 	struct priv pb;
 	struct priv *p = /* (struct priv *) dev->priv*/ &pb;
 	char *iscp_addrs[2];
 	int i;
 
-	p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + size - 0x01000000;
+	p->base = (unsigned long) isa_bus_to_virt((unsigned long)where)
+							+ size - 0x01000000;
 	p->memtop = isa_bus_to_virt((unsigned long)where) + size;
 	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
-	memset((char *)p->scp,0, sizeof(struct scp_struct));
-	for(i=0;i<sizeof(struct scp_struct);i++) /* memory was writeable? */
-		if(((char *)p->scp)[i])
+	memset_io((char *)p->scp, 0, sizeof(struct scp_struct));
+	for (i = 0; i < sizeof(struct scp_struct); i++)
+		/* memory was writeable? */
+		if (readb((char *)p->scp + i))
 			return 0;
-	p->scp->sysbus = SYSBUSVAL;				/* 1 = 8Bit-Bus, 0 = 16 Bit */
-	if(p->scp->sysbus != SYSBUSVAL)
+	writeb(SYSBUSVAL, &p->scp->sysbus);	/* 1 = 8Bit-Bus, 0 = 16 Bit */
+	if (readb(&p->scp->sysbus) != SYSBUSVAL)
 		return 0;
 
 	iscp_addrs[0] = isa_bus_to_virt((unsigned long)where);
-	iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct);
+	iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
 
-	for(i=0;i<2;i++)
-	{
+	for (i = 0; i < 2; i++) {
 		p->iscp = (struct iscp_struct *) iscp_addrs[i];
-		memset((char *)p->iscp,0, sizeof(struct iscp_struct));
+		memset_io((char *)p->iscp, 0, sizeof(struct iscp_struct));
 
-		p->scp->iscp = make24(p->iscp);
-		p->iscp->busy = 1;
+		writel(make24(p->iscp), &p->scp->iscp);
+		writeb(1, &p->iscp->busy);
 
 		ni_reset586();
 		ni_attn586();
-		DELAY(1);	/* wait a while... */
-
-		if(p->iscp->busy) /* i82586 clears 'busy' after successful init */
+		mdelay(32);	/* wait a while... */
+		/* i82586 clears 'busy' after successful init */
+		if (readb(&p->iscp->busy))
 			return 0;
 	}
 	return 1;
@@ -327,36 +344,39 @@ static void alloc586(struct net_device *dev)
 	struct priv *p =	(struct priv *) dev->priv;
 
 	ni_reset586();
-	DELAY(1);
+	mdelay(32);
+
+	spin_lock_init(&p->spinlock);
 
 	p->scp	= (struct scp_struct *)	(p->base + SCP_DEFAULT_ADDRESS);
 	p->scb	= (struct scb_struct *)	isa_bus_to_virt(dev->mem_start);
-	p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct));
+	p->iscp = (struct iscp_struct *)
+			((char *)p->scp - sizeof(struct iscp_struct));
 
-	memset((char *) p->iscp,0,sizeof(struct iscp_struct));
-	memset((char *) p->scp ,0,sizeof(struct scp_struct));
+	memset_io(p->iscp, 0, sizeof(struct iscp_struct));
+	memset_io(p->scp , 0, sizeof(struct scp_struct));
 
-	p->scp->iscp = make24(p->iscp);
-	p->scp->sysbus = SYSBUSVAL;
-	p->iscp->scb_offset = make16(p->scb);
+	writel(make24(p->iscp), &p->scp->iscp);
+	writeb(SYSBUSVAL, &p->scp->sysbus);
+	writew(make16(p->scb), &p->iscp->scb_offset);
 
-	p->iscp->busy = 1;
+	writeb(1, &p->iscp->busy);
 	ni_reset586();
 	ni_attn586();
 
-	DELAY(1);
+	mdelay(32);
 
-	if(p->iscp->busy)
-		printk("%s: Init-Problems (alloc).\n",dev->name);
+	if (readb(&p->iscp->busy))
+		printk(KERN_ERR "%s: Init-Problems (alloc).\n", dev->name);
 
-	p->reseted = 0;
+	p->reset = 0;
 
-	memset((char *)p->scb,0,sizeof(struct scb_struct));
+	memset_io((char *)p->scb, 0, sizeof(struct scb_struct));
 }
 
 /* set: io,irq,memstart,memend or set it when calling insmod */
-static int irq=9;
-static int io=0x300;
+static int irq = 9;
+static int io = 0x300;
 static long memstart;	/* e.g 0xd0000 */
 static long memend;	/* e.g 0xd4000 */
 
@@ -413,7 +433,7 @@ out:
 	return ERR_PTR(err);
 }
 
-static int __init ni52_probe1(struct net_device *dev,int ioaddr)
+static int __init ni52_probe1(struct net_device *dev, int ioaddr)
 {
 	int i, size, retval;
 
@@ -425,90 +445,96 @@ static int __init ni52_probe1(struct net_device *dev,int ioaddr)
 	if (!request_region(ioaddr, NI52_TOTAL_SIZE, DRV_NAME))
 		return -EBUSY;
 
-	if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) ||
+	if (!(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) ||
 	    !(inb(ioaddr+NI52_MAGIC2) == NI52_MAGICVAL2)) {
 		retval = -ENODEV;
 		goto out;
 	}
 
-	for(i=0;i<ETH_ALEN;i++)
+	for (i = 0; i < ETH_ALEN; i++)
 		dev->dev_addr[i] = inb(dev->base_addr+i);
 
-	if(dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1
+	if (dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1
 		 || dev->dev_addr[2] != NI52_ADDR2) {
 		retval = -ENODEV;
 		goto out;
 	}
 
-	printk(KERN_INFO "%s: NI5210 found at %#3lx, ",dev->name,dev->base_addr);
+	printk(KERN_INFO "%s: NI5210 found at %#3lx, ",
+				dev->name, dev->base_addr);
 
 	/*
 	 * check (or search) IO-Memory, 8K and 16K
 	 */
 #ifdef MODULE
 	size = dev->mem_end - dev->mem_start;
-	if(size != 0x2000 && size != 0x4000) {
-		printk("\n%s: Illegal memory size %d. Allowed is 0x2000 or 0x4000 bytes.\n",dev->name,size);
+	if (size != 0x2000 && size != 0x4000) {
+		printk("\n");
+		printk(KERN_ERR "%s: Invalid memory size %d. Allowed is 0x2000 or 0x4000 bytes.\n", dev->name, size);
 		retval = -ENODEV;
 		goto out;
 	}
-	if(!check586(dev,(char *) dev->mem_start,size)) {
-		printk("?memcheck, Can't find memory at 0x%lx with size %d!\n",dev->mem_start,size);
+	if (!check586(dev, (char *)dev->mem_start, size)) {
+		printk(KERN_ERR "?memcheck, Can't find memory at 0x%lx with size %d!\n", dev->mem_start, size);
 		retval = -ENODEV;
 		goto out;
 	}
 #else
-	if(dev->mem_start != 0) /* no auto-mem-probe */
-	{
+	if (dev->mem_start != 0) {
+		/* no auto-mem-probe */
 		size = 0x4000; /* check for 16K mem */
-		if(!check586(dev,(char *) dev->mem_start,size)) {
+		if (!check586(dev, (char *) dev->mem_start, size)) {
 			size = 0x2000; /* check for 8K mem */
-			if(!check586(dev,(char *) dev->mem_start,size)) {
-				printk("?memprobe, Can't find memory at 0x%lx!\n",dev->mem_start);
+			if (!check586(dev, (char *)dev->mem_start, size)) {
+				printk(KERN_ERR "?memprobe, Can't find memory at 0x%lx!\n", dev->mem_start);
 				retval = -ENODEV;
 				goto out;
 			}
 		}
-	}
-	else
-	{
-		static long memaddrs[] = { 0xc8000,0xca000,0xcc000,0xce000,0xd0000,0xd2000,
-					0xd4000,0xd6000,0xd8000,0xda000,0xdc000, 0 };
-		for(i=0;;i++)
-		{
-			if(!memaddrs[i]) {
-				printk("?memprobe, Can't find io-memory!\n");
+	} else {
+		static const unsigned long memaddrs[] = {
+			0xc8000, 0xca000, 0xcc000, 0xce000, 0xd0000, 0xd2000,
+			0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0
+		};
+		for (i = 0;; i++) {
+			if (!memaddrs[i]) {
+				printk(KERN_ERR "?memprobe, Can't find io-memory!\n");
 				retval = -ENODEV;
 				goto out;
 			}
 			dev->mem_start = memaddrs[i];
 			size = 0x2000; /* check for 8K mem */
-			if(check586(dev,(char *)dev->mem_start,size)) /* 8K-check */
+			if (check586(dev, (char *)dev->mem_start, size))
+				/* 8K-check */
 				break;
 			size = 0x4000; /* check for 16K mem */
-			if(check586(dev,(char *)dev->mem_start,size)) /* 16K-check */
+			if (check586(dev, (char *)dev->mem_start, size))
+				/* 16K-check */
 				break;
 		}
 	}
-	dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */
+	/* set mem_end showed by 'ifconfig' */
+	dev->mem_end = dev->mem_start + size;
 #endif
 
-	memset((char *) dev->priv,0,sizeof(struct priv));
+	memset((char *)dev->priv, 0, sizeof(struct priv));
 
-	((struct priv *) (dev->priv))->memtop = isa_bus_to_virt(dev->mem_start) + size;
-	((struct priv *) (dev->priv))->base =	(unsigned long) isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
+	((struct priv *)(dev->priv))->memtop =
+				isa_bus_to_virt(dev->mem_start) + size;
+	((struct priv *)(dev->priv))->base =  (unsigned long)
+			isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
 	alloc586(dev);
 
 	/* set number of receive-buffs according to memsize */
-	if(size == 0x2000)
+	if (size == 0x2000)
 		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;
 	else
 		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
 
-	printk("Memaddr: 0x%lx, Memsize: %d, ",dev->mem_start,size);
+	printk(KERN_DEBUG "Memaddr: 0x%lx, Memsize: %d, ",
+				dev->mem_start, size);
 
-	if(dev->irq < 2)
-	{
+	if (dev->irq < 2) {
 		unsigned long irq_mask;
 
 		irq_mask = probe_irq_on();
@@ -517,18 +543,16 @@ static int __init ni52_probe1(struct net_device *dev,int ioaddr)
 
 		mdelay(20);
 		dev->irq = probe_irq_off(irq_mask);
-		if(!dev->irq)
-		{
+		if (!dev->irq) {
 			printk("?autoirq, Failed to detect IRQ line!\n");
 			retval = -EAGAIN;
 			goto out;
 		}
-		printk("IRQ %d (autodetected).\n",dev->irq);
-	}
-	else	{
-		if(dev->irq == 2)
+		printk("IRQ %d (autodetected).\n", dev->irq);
+	} else {
+		if (dev->irq == 2)
 			dev->irq = 9;
-		printk("IRQ %d (assigned and not checked!).\n",dev->irq);
+		printk("IRQ %d (assigned and not checked!).\n", dev->irq);
 	}
 
 	dev->open		= ni52_open;
@@ -555,56 +579,58 @@ out:
 static int init586(struct net_device *dev)
 {
 	void *ptr;
-	int i,result=0;
-	struct priv *p = (struct priv *) dev->priv;
-	volatile struct configure_cmd_struct	*cfg_cmd;
-	volatile struct iasetup_cmd_struct *ias_cmd;
-	volatile struct tdr_cmd_struct *tdr_cmd;
-	volatile struct mcsetup_cmd_struct *mc_cmd;
-	struct dev_mc_list *dmi=dev->mc_list;
-	int num_addrs=dev->mc_count;
+	int i, result = 0;
+	struct priv *p = (struct priv *)dev->priv;
+	struct configure_cmd_struct *cfg_cmd;
+	struct iasetup_cmd_struct *ias_cmd;
+	struct tdr_cmd_struct *tdr_cmd;
+	struct mcsetup_cmd_struct *mc_cmd;
+	struct dev_mc_list *dmi = dev->mc_list;
+	int num_addrs = dev->mc_count;
 
 	ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));
 
 	cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */
-	cfg_cmd->cmd_status	= 0;
-	cfg_cmd->cmd_cmd	= CMD_CONFIGURE | CMD_LAST;
-	cfg_cmd->cmd_link	= 0xffff;
-
-	cfg_cmd->byte_cnt	= 0x0a; /* number of cfg bytes */
-	cfg_cmd->fifo		= fifo; /* fifo-limit (8=tx:32/rx:64) */
-	cfg_cmd->sav_bf		= 0x40; /* hold or discard bad recv frames (bit 7) */
-	cfg_cmd->adr_len	= 0x2e; /* addr_len |!src_insert |pre-len |loopback */
-	cfg_cmd->priority	= 0x00;
-	cfg_cmd->ifs		= 0x60;
-	cfg_cmd->time_low	= 0x00;
-	cfg_cmd->time_high	= 0xf2;
-	cfg_cmd->promisc	= 0;
-	if(dev->flags & IFF_ALLMULTI) {
+	writew(0, &cfg_cmd->cmd_status);
+	writew(CMD_CONFIGURE | CMD_LAST, &cfg_cmd->cmd_cmd);
+	writew(0xFFFF, &cfg_cmd->cmd_link);
+
+	/* number of cfg bytes */
+	writeb(0x0a, &cfg_cmd->byte_cnt);
+	/* fifo-limit (8=tx:32/rx:64) */
+	writeb(fifo, &cfg_cmd->fifo);
+	/* hold or discard bad recv frames (bit 7) */
+	writeb(0x40, &cfg_cmd->sav_bf);
+	/* addr_len |!src_insert |pre-len |loopback */
+	writeb(0x2e, &cfg_cmd->adr_len);
+	writeb(0x00, &cfg_cmd->priority);
+	writeb(0x60, &cfg_cmd->ifs);;
+	writeb(0x00, &cfg_cmd->time_low);
+	writeb(0xf2, &cfg_cmd->time_high);
+	writeb(0x00, &cfg_cmd->promisc);;
+	if (dev->flags & IFF_ALLMULTI) {
 		int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
-		if(num_addrs > len)	{
-			printk("%s: switching to promisc. mode\n",dev->name);
-			dev->flags|=IFF_PROMISC;
+		if (num_addrs > len) {
+			printk(KERN_ERR "%s: switching to promisc. mode\n",
+				dev->name);
+			dev->flags |= IFF_PROMISC;
 		}
 	}
-	if(dev->flags&IFF_PROMISC)
-	{
-			 cfg_cmd->promisc=1;
-			 dev->flags|=IFF_PROMISC;
-	}
-	cfg_cmd->carr_coll	= 0x00;
+	if (dev->flags & IFF_PROMISC)
+		writeb(0x01, &cfg_cmd->promisc);
+	writeb(0x00, &cfg_cmd->carr_coll);
+	writew(make16(cfg_cmd), &p->scb->cbl_offset);
+	writew(0, &p->scb->cmd_ruc);
 
-	p->scb->cbl_offset	= make16(cfg_cmd);
-	p->scb->cmd_ruc		= 0;
-
-	p->scb->cmd_cuc		= CUC_START; /* cmd.-unit start */
+	writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */
 	ni_attn586();
 
-	WAIT_4_STAT_COMPL(cfg_cmd);
+	wait_for_stat_compl(cfg_cmd);
 
-	if((cfg_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK))
-	{
-		printk("%s: configure command failed: %x\n",dev->name,cfg_cmd->cmd_status);
+	if ((readw(&cfg_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) !=
+							(STAT_COMPL|STAT_OK)) {
+		printk(KERN_ERR "%s: configure command failed: %x\n",
+				dev->name, readw(&cfg_cmd->cmd_status));
 		return 1;
 	}
 
@@ -614,21 +640,22 @@ static int init586(struct net_device *dev)
 
 	ias_cmd = (struct iasetup_cmd_struct *)ptr;
 
-	ias_cmd->cmd_status	= 0;
-	ias_cmd->cmd_cmd	= CMD_IASETUP | CMD_LAST;
-	ias_cmd->cmd_link	= 0xffff;
+	writew(0, &ias_cmd->cmd_status);
+	writew(CMD_IASETUP | CMD_LAST, &ias_cmd->cmd_cmd);
+	writew(0xffff, &ias_cmd->cmd_link);
 
-	memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN);
+	memcpy_toio((char *)&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN);
 
-	p->scb->cbl_offset = make16(ias_cmd);
+	writew(make16(ias_cmd), &p->scb->cbl_offset);
 
-	p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */
+	writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */
 	ni_attn586();
 
-	WAIT_4_STAT_COMPL(ias_cmd);
+	wait_for_stat_compl(ias_cmd);
 
-	if((ias_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) {
-		printk("%s (ni52): individual address setup command failed: %04x\n",dev->name,ias_cmd->cmd_status);
+	if ((readw(&ias_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) !=
+							(STAT_OK|STAT_COMPL)) {
+		printk(KERN_ERR "%s (ni52): individual address setup command failed: %04x\n", dev->name, readw(&ias_cmd->cmd_status));
 		return 1;
 	}
 
@@ -638,117 +665,119 @@ static int init586(struct net_device *dev)
 
 	tdr_cmd = (struct tdr_cmd_struct *)ptr;
 
-	tdr_cmd->cmd_status	= 0;
-	tdr_cmd->cmd_cmd	= CMD_TDR | CMD_LAST;
-	tdr_cmd->cmd_link	= 0xffff;
-	tdr_cmd->status		= 0;
+	writew(0, &tdr_cmd->cmd_status);
+	writew(CMD_TDR | CMD_LAST, &tdr_cmd->cmd_cmd);
+	writew(0xffff, &tdr_cmd->cmd_link);
+	writew(0, &tdr_cmd->status);
 
-	p->scb->cbl_offset = make16(tdr_cmd);
-	p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */
+	writew(make16(tdr_cmd), &p->scb->cbl_offset);
+	writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */
 	ni_attn586();
 
-	WAIT_4_STAT_COMPL(tdr_cmd);
-
-	if(!(tdr_cmd->cmd_status & STAT_COMPL))
-	{
-		printk("%s: Problems while running the TDR.\n",dev->name);
-	}
-	else
-	{
-		DELAY_16(); /* wait for result */
-		result = tdr_cmd->status;
+	wait_for_stat_compl(tdr_cmd);
 
-		p->scb->cmd_cuc = p->scb->cus & STAT_MASK;
+	if (!(readw(&tdr_cmd->cmd_status) & STAT_COMPL))
+		printk(KERN_ERR "%s: Problems while running the TDR.\n",
+				dev->name);
+	else {
+		udelay(16);
+		result = readw(&tdr_cmd->status);
+		writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc);
 		ni_attn586(); /* ack the interrupts */
 
-		if(result & TDR_LNK_OK)
+		if (result & TDR_LNK_OK)
 			;
-		else if(result & TDR_XCVR_PRB)
-			printk("%s: TDR: Transceiver problem. Check the cable(s)!\n",dev->name);
-		else if(result & TDR_ET_OPN)
-			printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK);
-		else if(result & TDR_ET_SRT)
-		{
-			if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */
-				printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK);
-		}
-		else
-			printk("%s: TDR: Unknown status %04x\n",dev->name,result);
+		else if (result & TDR_XCVR_PRB)
+			printk(KERN_ERR "%s: TDR: Transceiver problem. Check the cable(s)!\n",
+				dev->name);
+		else if (result & TDR_ET_OPN)
+			printk(KERN_ERR "%s: TDR: No correct termination %d clocks away.\n",
+				dev->name, result & TDR_TIMEMASK);
+		else if (result & TDR_ET_SRT) {
+			/* time == 0 -> strange :-) */
+			if (result & TDR_TIMEMASK)
+				printk(KERN_ERR "%s: TDR: Detected a short circuit %d clocks away.\n",
+					dev->name, result & TDR_TIMEMASK);
+		} else
+			printk(KERN_ERR "%s: TDR: Unknown status %04x\n",
+						dev->name, result);
 	}
 
 	/*
 	 * Multicast setup
 	 */
-	if(num_addrs && !(dev->flags & IFF_PROMISC) )
-	{
+	if (num_addrs && !(dev->flags & IFF_PROMISC)) {
 		mc_cmd = (struct mcsetup_cmd_struct *) ptr;
-		mc_cmd->cmd_status = 0;
-		mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST;
-		mc_cmd->cmd_link = 0xffff;
-		mc_cmd->mc_cnt = num_addrs * 6;
+		writew(0, &mc_cmd->cmd_status);
+		writew(CMD_MCSETUP | CMD_LAST, &mc_cmd->cmd_cmd);
+		writew(0xffff, &mc_cmd->cmd_link);
+		writew(num_addrs * 6, &mc_cmd->mc_cnt);
 
-		for(i=0;i<num_addrs;i++,dmi=dmi->next)
-			memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6);
+		for (i = 0; i < num_addrs; i++, dmi = dmi->next)
+			memcpy_toio((char *) mc_cmd->mc_list[i],
+							dmi->dmi_addr, 6);
 
-		p->scb->cbl_offset = make16(mc_cmd);
-		p->scb->cmd_cuc = CUC_START;
+		writew(make16(mc_cmd), &p->scb->cbl_offset);
+		writeb(CUC_START, &p->scb->cmd_cuc);
 		ni_attn586();
 
-		WAIT_4_STAT_COMPL(mc_cmd);
+		wait_for_stat_compl(mc_cmd);
 
-		if( (mc_cmd->cmd_status & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) )
-			printk("%s: Can't apply multicast-address-list.\n",dev->name);
+		if ((readw(&mc_cmd->cmd_status) & (STAT_COMPL|STAT_OK))
+						 != (STAT_COMPL|STAT_OK))
+			printk(KERN_ERR "%s: Can't apply multicast-address-list.\n", dev->name);
 	}
 
 	/*
 	 * alloc nop/xmit-cmds
 	 */
 #if (NUM_XMIT_BUFFS == 1)
-	for(i=0;i<2;i++)
-	{
-		p->nop_cmds[i] 			= (struct nop_cmd_struct *)ptr;
-		p->nop_cmds[i]->cmd_cmd		= CMD_NOP;
-		p->nop_cmds[i]->cmd_status 	= 0;
-		p->nop_cmds[i]->cmd_link	= make16((p->nop_cmds[i]));
+	for (i = 0; i < 2; i++) {
+		p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
+		writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd);
+		writew(0, &p->nop_cmds[i]->cmd_status);
+		writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link);
 		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
 	}
 #else
-	for(i=0;i<NUM_XMIT_BUFFS;i++)
-	{
-		p->nop_cmds[i]			= (struct nop_cmd_struct *)ptr;
-		p->nop_cmds[i]->cmd_cmd		= CMD_NOP;
-		p->nop_cmds[i]->cmd_status	= 0;
-		p->nop_cmds[i]->cmd_link	= make16((p->nop_cmds[i]));
+	for (i = 0; i < NUM_XMIT_BUFFS; i++) {
+		p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
+		writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd);
+		writew(0, &p->nop_cmds[i]->cmd_status);
+		writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link);
 		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
 	}
 #endif
 
-	ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */
+	ptr = alloc_rfa(dev, (void *)ptr); /* init receive-frame-area */
 
 	/*
 	 * alloc xmit-buffs / init xmit_cmds
 	 */
-	for(i=0;i<NUM_XMIT_BUFFS;i++)
-	{
-		p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/
+	for (i = 0; i < NUM_XMIT_BUFFS; i++) {
+		/* Transmit cmd/buff 0 */
+		p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr;
 		ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
 		p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */
 		ptr = (char *) ptr + XMIT_BUFF_SIZE;
 		p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */
 		ptr = (char *) ptr + sizeof(struct tbd_struct);
-		if((void *)ptr > (void *)p->iscp)
-		{
-			printk("%s: not enough shared-mem for your configuration!\n",dev->name);
+		if ((void *)ptr > (void *)p->iscp) {
+			printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n",
+				dev->name);
 			return 1;
 		}
-		memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct));
-		memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct));
-		p->xmit_cmds[i]->cmd_link = make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]);
-		p->xmit_cmds[i]->cmd_status = STAT_COMPL;
-		p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT;
-		p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));
-		p->xmit_buffs[i]->next = 0xffff;
-		p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));
+		memset_io((char *)(p->xmit_cmds[i]), 0,
+					sizeof(struct transmit_cmd_struct));
+		memset_io((char *)(p->xmit_buffs[i]), 0,
+					sizeof(struct tbd_struct));
+		writew(make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]),
+					&p->xmit_cmds[i]->cmd_link);
+		writew(STAT_COMPL, &p->xmit_cmds[i]->cmd_status);
+		writew(CMD_XMIT|CMD_INT, &p->xmit_cmds[i]->cmd_cmd);
+		writew(make16(p->xmit_buffs[i]), &p->xmit_cmds[i]->tbd_offset);
+		writew(0xffff, &p->xmit_buffs[i]->next);
+		writel(make24(p->xmit_cbuffs[i]), &p->xmit_buffs[i]->buffer);
 	}
 
 	p->xmit_count = 0;
@@ -761,21 +790,21 @@ static int init586(struct net_device *dev)
 		* 'start transmitter'
 		*/
 #ifndef NO_NOPCOMMANDS
-	p->scb->cbl_offset = make16(p->nop_cmds[0]);
-	p->scb->cmd_cuc = CUC_START;
+	writew(make16(p->nop_cmds[0]), &p->scb->cbl_offset);
+	writeb(CUC_START, &p->scb->cmd_cuc);
 	ni_attn586();
-	WAIT_4_SCB_CMD();
+	wait_for_scb_cmd(dev);
 #else
-	p->xmit_cmds[0]->cmd_link = make16(p->xmit_cmds[0]);
-	p->xmit_cmds[0]->cmd_cmd	= CMD_XMIT | CMD_SUSPEND | CMD_INT;
+	writew(make16(p->xmit_cmds[0]), &p->xmit_cmds[0]->cmd_link);
+	writew(CMD_XMIT | CMD_SUSPEND | CMD_INT, &p->xmit_cmds[0]->cmd_cmd);
 #endif
 
 	/*
 	 * ack. interrupts
 	 */
-	p->scb->cmd_cuc = p->scb->cus & STAT_MASK;
+	writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc);
 	ni_attn586();
-	DELAY_16();
+	udelay(16);
 
 	ni_enaint();
 
@@ -787,43 +816,45 @@ static int init586(struct net_device *dev)
  * It sets up the Receive Frame Area (RFA).
  */
 
-static void *alloc_rfa(struct net_device *dev,void *ptr)
+static void *alloc_rfa(struct net_device *dev, void *ptr)
 {
-	volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr;
-	volatile struct rbd_struct *rbd;
+	struct rfd_struct *rfd = (struct rfd_struct *)ptr;
+	struct rbd_struct *rbd;
 	int i;
 	struct priv *p = (struct priv *) dev->priv;
 
-	memset((char *) rfd,0,sizeof(struct rfd_struct)*(p->num_recv_buffs+rfdadd));
+	memset_io((char *) rfd, 0,
+		sizeof(struct rfd_struct) * (p->num_recv_buffs + rfdadd));
 	p->rfd_first = rfd;
 
-	for(i = 0; i < (p->num_recv_buffs+rfdadd); i++) {
-		rfd[i].next = make16(rfd + (i+1) % (p->num_recv_buffs+rfdadd) );
-		rfd[i].rbd_offset = 0xffff;
+	for (i = 0; i < (p->num_recv_buffs + rfdadd); i++) {
+		writew(make16(rfd + (i+1) % (p->num_recv_buffs+rfdadd)),
+			&rfd[i].next);
+		writew(0xffff, &rfd[i].rbd_offset);
 	}
-	rfd[p->num_recv_buffs-1+rfdadd].last = RFD_SUSP;	 /* RU suspend */
+	/* RU suspend */
+	writeb(RFD_SUSP, &rfd[p->num_recv_buffs-1+rfdadd].last);
 
-	ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd) );
+	ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd));
 
 	rbd = (struct rbd_struct *) ptr;
 	ptr = (void *) (rbd + p->num_recv_buffs);
 
 	 /* clr descriptors */
-	memset((char *) rbd,0,sizeof(struct rbd_struct)*(p->num_recv_buffs));
+	memset_io((char *)rbd, 0,
+			sizeof(struct rbd_struct) * (p->num_recv_buffs));
 
-	for(i=0;i<p->num_recv_buffs;i++)
-	{
-		rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs));
-		rbd[i].size = RECV_BUFF_SIZE;
-		rbd[i].buffer = make24(ptr);
+	for (i = 0; i < p->num_recv_buffs; i++) {
+		writew(make16(rbd + (i+1) % p->num_recv_buffs), &rbd[i].next);
+		writew(RECV_BUFF_SIZE, &rbd[i].size);
+		writel(make24(ptr), &rbd[i].buffer);
 		ptr = (char *) ptr + RECV_BUFF_SIZE;
 	}
-
 	p->rfd_top	= p->rfd_first;
 	p->rfd_last = p->rfd_first + (p->num_recv_buffs - 1 + rfdadd);
 
-	p->scb->rfa_offset		= make16(p->rfd_first);
-	p->rfd_first->rbd_offset	= make16(rbd);
+	writew(make16(p->rfd_first), &p->scb->rfa_offset);
+	writew(make16(rbd), &p->rfd_first->rbd_offset);
 
 	return ptr;
 }
@@ -833,73 +864,71 @@ static void *alloc_rfa(struct net_device *dev,void *ptr)
  * Interrupt Handler ...
  */
 
-static irqreturn_t ni52_interrupt(int irq,void *dev_id)
+static irqreturn_t ni52_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
-	unsigned short stat;
-	int cnt=0;
+	unsigned int stat;
+	int cnt = 0;
 	struct priv *p;
 
-	if (!dev) {
-		printk ("ni5210-interrupt: irq %d for unknown device.\n",irq);
-		return IRQ_NONE;
-	}
 	p = (struct priv *) dev->priv;
 
-	if(debuglevel > 1)
+	if (debuglevel > 1)
 		printk("I");
 
-	WAIT_4_SCB_CMD(); /* wait for last command	*/
+	spin_lock(&p->spinlock);
 
-	while((stat=p->scb->cus & STAT_MASK))
-	{
-		p->scb->cmd_cuc = stat;
+	wait_for_scb_cmd(dev); /* wait for last command	*/
+
+	while ((stat = readb(&p->scb->cus) & STAT_MASK)) {
+		writeb(stat, &p->scb->cmd_cuc);
 		ni_attn586();
 
-		if(stat & STAT_FR)	 /* received a frame */
+		if (stat & STAT_FR)	 /* received a frame */
 			ni52_rcv_int(dev);
 
-		if(stat & STAT_RNR) /* RU went 'not ready' */
-		{
+		if (stat & STAT_RNR) { /* RU went 'not ready' */
 			printk("(R)");
-			if(p->scb->rus & RU_SUSPEND) /* special case: RU_SUSPEND */
-			{
-				WAIT_4_SCB_CMD();
+			if (readb(&p->scb->rus) & RU_SUSPEND) {
+				/* special case: RU_SUSPEND */
+				wait_for_scb_cmd(dev);
 				p->scb->cmd_ruc = RUC_RESUME;
 				ni_attn586();
-				WAIT_4_SCB_CMD_RUC();
-			}
-			else
-			{
-				printk("%s: Receiver-Unit went 'NOT READY': %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->rus);
+				wait_for_scb_cmd_ruc(dev);
+			} else {
+				printk(KERN_ERR "%s: Receiver-Unit went 'NOT READY': %04x/%02x.\n",
+					dev->name, stat, readb(&p->scb->rus));
 				ni52_rnr_int(dev);
 			}
 		}
 
-		if(stat & STAT_CX)		/* command with I-bit set complete */
+		/* Command with I-bit set complete */
+		if (stat & STAT_CX)
 			 ni52_xmt_int(dev);
 
 #ifndef NO_NOPCOMMANDS
-		if(stat & STAT_CNA)	/* CU went 'not ready' */
-		{
-			if(netif_running(dev))
-				printk("%s: oops! CU has left active state. stat: %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->cus);
+		if (stat & STAT_CNA) {	/* CU went 'not ready' */
+			if (netif_running(dev))
+				printk(KERN_ERR "%s: oops! CU has left active state. stat: %04x/%02x.\n",
+					dev->name, stat, readb(&p->scb->cus));
 		}
 #endif
 
-		if(debuglevel > 1)
-			printk("%d",cnt++);
+		if (debuglevel > 1)
+			printk("%d", cnt++);
 
-		WAIT_4_SCB_CMD(); /* wait for ack. (ni52_xmt_int can be faster than ack!!) */
-		if(p->scb->cmd_cuc)	 /* timed out? */
-		{
-			printk("%s: Acknowledge timed out.\n",dev->name);
+		/* Wait for ack. (ni52_xmt_int can be faster than ack!!) */
+		wait_for_scb_cmd(dev);
+		if (p->scb->cmd_cuc) {	 /* timed out? */
+			printk(KERN_ERR "%s: Acknowledge timed out.\n",
+				dev->name);
 			ni_disint();
 			break;
 		}
 	}
+	spin_unlock(&p->spinlock);
 
-	if(debuglevel > 1)
+	if (debuglevel > 1)
 		printk("i");
 	return IRQ_HANDLED;
 }
@@ -910,121 +939,91 @@ static irqreturn_t ni52_interrupt(int irq,void *dev_id)
 
 static void ni52_rcv_int(struct net_device *dev)
 {
-	int status,cnt=0;
+	int status, cnt = 0;
 	unsigned short totlen;
 	struct sk_buff *skb;
 	struct rbd_struct *rbd;
-	struct priv *p = (struct priv *) dev->priv;
+	struct priv *p = (struct priv *)dev->priv;
 
-	if(debuglevel > 0)
+	if (debuglevel > 0)
 		printk("R");
 
-	for(;(status = p->rfd_top->stat_high) & RFD_COMPL;)
-	{
-			rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
-
-			if(status & RFD_OK) /* frame received without error? */
-			{
-				if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */
-				{
-					totlen &= RBD_MASK; /* length of this frame */
-					rbd->status = 0;
-					skb = (struct sk_buff *) dev_alloc_skb(totlen+2);
-					if(skb != NULL)
-					{
-						skb_reserve(skb,2);
-						skb_put(skb,totlen);
-						skb_copy_to_linear_data(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen);
-						skb->protocol=eth_type_trans(skb,dev);
-						netif_rx(skb);
-						dev->last_rx = jiffies;
-						p->stats.rx_packets++;
-						p->stats.rx_bytes += totlen;
+	for (; (status = readb(&p->rfd_top->stat_high)) & RFD_COMPL;) {
+		rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
+		if (status & RFD_OK) { /* frame received without error? */
+			totlen = readw(&rbd->status);
+			if (totlen & RBD_LAST) {
+				/* the first and the last buffer? */
+				totlen &= RBD_MASK; /* length of this frame */
+				writew(0x00, &rbd->status);
+				skb = (struct sk_buff *)dev_alloc_skb(totlen+2);
+				if (skb != NULL) {
+					skb_reserve(skb, 2);
+					skb_put(skb, totlen);
+					skb_copy_to_linear_data(skb, (char *)p->base + (unsigned long) rbd->buffer, totlen);
+					skb->protocol = eth_type_trans(skb, dev);
+					netif_rx(skb);
+					dev->last_rx = jiffies;
+					p->stats.rx_packets++;
+					p->stats.rx_bytes += totlen;
+				} else
+					p->stats.rx_dropped++;
+			} else {
+				int rstat;
+				 /* free all RBD's until RBD_LAST is set */
+				totlen = 0;
+				while (!((rstat = readw(&rbd->status)) & RBD_LAST)) {
+					totlen += rstat & RBD_MASK;
+					if (!rstat) {
+						printk(KERN_ERR "%s: Whoops .. no end mark in RBD list\n", dev->name);
+						break;
 					}
-					else
-						p->stats.rx_dropped++;
+					writew(0, &rbd->status);
+					rbd = (struct rbd_struct *) make32(readl(&rbd->next));
 				}
-				else
-				{
-					int rstat;
-						 /* free all RBD's until RBD_LAST is set */
-					totlen = 0;
-					while(!((rstat=rbd->status) & RBD_LAST))
-					{
-						totlen += rstat & RBD_MASK;
-						if(!rstat)
-						{
-							printk("%s: Whoops .. no end mark in RBD list\n",dev->name);
-							break;
-						}
-						rbd->status = 0;
-						rbd = (struct rbd_struct *) make32(rbd->next);
-					}
-					totlen += rstat & RBD_MASK;
-					rbd->status = 0;
-					printk("%s: received oversized frame! length: %d\n",dev->name,totlen);
-					p->stats.rx_dropped++;
+				totlen += rstat & RBD_MASK;
+				writew(0, &rbd->status);
+				printk(KERN_ERR "%s: received oversized frame! length: %d\n",
+					dev->name, totlen);
+				p->stats.rx_dropped++;
 			 }
-		}
-		else /* frame !(ok), only with 'save-bad-frames' */
-		{
-			printk("%s: oops! rfd-error-status: %04x\n",dev->name,status);
+		} else {/* frame !(ok), only with 'save-bad-frames' */
+			printk(KERN_ERR "%s: oops! rfd-error-status: %04x\n",
+				dev->name, status);
 			p->stats.rx_errors++;
 		}
-		p->rfd_top->stat_high = 0;
-		p->rfd_top->last = RFD_SUSP; /* maybe exchange by RFD_LAST */
-		p->rfd_top->rbd_offset = 0xffff;
-		p->rfd_last->last = 0;				/* delete RFD_SUSP	*/
+		writeb(0, &p->rfd_top->stat_high);
+		writeb(RFD_SUSP, &p->rfd_top->last); /* maybe exchange by RFD_LAST */
+		writew(0xffff, &p->rfd_top->rbd_offset);
+		writeb(0, &p->rfd_last->last);	/* delete RFD_SUSP	*/
 		p->rfd_last = p->rfd_top;
 		p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */
-		p->scb->rfa_offset = make16(p->rfd_top);
+		writew(make16(p->rfd_top), &p->scb->rfa_offset);
 
-		if(debuglevel > 0)
-			printk("%d",cnt++);
+		if (debuglevel > 0)
+			printk("%d", cnt++);
 	}
 
-	if(automatic_resume)
-	{
-		WAIT_4_SCB_CMD();
-		p->scb->cmd_ruc = RUC_RESUME;
+	if (automatic_resume) {
+		wait_for_scb_cmd(dev);
+		writeb(RUC_RESUME, &p->scb->cmd_ruc);
 		ni_attn586();
-		WAIT_4_SCB_CMD_RUC();
+		wait_for_scb_cmd_ruc(dev);
 	}
 
 #ifdef WAIT_4_BUSY
 	{
 		int i;
-		for(i=0;i<1024;i++)
-		{
-			if(p->rfd_top->status)
+		for (i = 0; i < 1024; i++) {
+			if (p->rfd_top->status)
 				break;
-			DELAY_16();
-			if(i == 1023)
-				printk("%s: RU hasn't fetched next RFD (not busy/complete)\n",dev->name);
+			udelay(16);
+			if (i == 1023)
+				printk(KERN_ERR "%s: RU hasn't fetched next RFD (not busy/complete)\n", dev->name);
 		}
 	}
 #endif
-
-#if 0
-	if(!at_least_one)
-	{
-		int i;
-		volatile struct rfd_struct *rfds=p->rfd_top;
-		volatile struct rbd_struct *rbds;
-		printk("%s: received a FC intr. without having a frame: %04x %d\n",dev->name,status,old_at_least);
-		for(i=0;i< (p->num_recv_buffs+4);i++)
-		{
-			rbds = (struct rbd_struct *) make32(rfds->rbd_offset);
-			printk("%04x:%04x ",rfds->status,rbds->status);
-			rfds = (struct rfd_struct *) make32(rfds->next);
-		}
-		printk("\nerrs: %04x %04x stat: %04x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->status);
-		printk("\nerrs: %04x %04x rus: %02x, cus: %02x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->rus,(int)p->scb->cus);
-	}
-	old_at_least = at_least_one;
-#endif
-
-	if(debuglevel > 0)
+	if (debuglevel > 0)
 		printk("r");
 }
 
@@ -1038,16 +1037,16 @@ static void ni52_rnr_int(struct net_device *dev)
 
 	p->stats.rx_errors++;
 
-	WAIT_4_SCB_CMD();		/* wait for the last cmd, WAIT_4_FULLSTAT?? */
-	p->scb->cmd_ruc = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */
+	wait_for_scb_cmd(dev);		/* wait for the last cmd, WAIT_4_FULLSTAT?? */
+	writeb(RUC_ABORT, &p->scb->cmd_ruc); /* usually the RU is in the 'no resource'-state .. abort it now. */
 	ni_attn586();
-	WAIT_4_SCB_CMD_RUC();		/* wait for accept cmd. */
+	wait_for_scb_cmd_ruc(dev);		/* wait for accept cmd. */
 
-	alloc_rfa(dev,(char *)p->rfd_first);
-/* maybe add a check here, before restarting the RU */
+	alloc_rfa(dev, (char *)p->rfd_first);
+	/* maybe add a check here, before restarting the RU */
 	startrecv586(dev); /* restart RU */
 
-	printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->rus);
+	printk(KERN_ERR "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->rus);
 
 }
 
@@ -1060,43 +1059,41 @@ static void ni52_xmt_int(struct net_device *dev)
 	int status;
 	struct priv *p = (struct priv *) dev->priv;
 
-	if(debuglevel > 0)
+	if (debuglevel > 0)
 		printk("X");
 
-	status = p->xmit_cmds[p->xmit_last]->cmd_status;
-	if(!(status & STAT_COMPL))
-		printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name);
+	status = readw(&p->xmit_cmds[p->xmit_last]->cmd_status);
+	if (!(status & STAT_COMPL))
+		printk(KERN_ERR "%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
 
-	if(status & STAT_OK)
-	{
+	if (status & STAT_OK) {
 		p->stats.tx_packets++;
 		p->stats.collisions += (status & TCMD_MAXCOLLMASK);
-	}
-	else
-	{
+	} else {
 		p->stats.tx_errors++;
-		if(status & TCMD_LATECOLL) {
-			printk("%s: late collision detected.\n",dev->name);
+		if (status & TCMD_LATECOLL) {
+			printk(KERN_ERR "%s: late collision detected.\n",
+				dev->name);
 			p->stats.collisions++;
-		}
-		else if(status & TCMD_NOCARRIER) {
+		} else if (status & TCMD_NOCARRIER) {
 			p->stats.tx_carrier_errors++;
-			printk("%s: no carrier detected.\n",dev->name);
-		}
-		else if(status & TCMD_LOSTCTS)
-			printk("%s: loss of CTS detected.\n",dev->name);
-		else if(status & TCMD_UNDERRUN) {
+			printk(KERN_ERR "%s: no carrier detected.\n",
+				dev->name);
+		} else if (status & TCMD_LOSTCTS)
+			printk(KERN_ERR "%s: loss of CTS detected.\n",
+				dev->name);
+		else if (status & TCMD_UNDERRUN) {
 			p->stats.tx_fifo_errors++;
-			printk("%s: DMA underrun detected.\n",dev->name);
-		}
-		else if(status & TCMD_MAXCOLL) {
-			printk("%s: Max. collisions exceeded.\n",dev->name);
+			printk(KERN_ERR "%s: DMA underrun detected.\n",
+				dev->name);
+		} else if (status & TCMD_MAXCOLL) {
+			printk(KERN_ERR "%s: Max. collisions exceeded.\n",
+				dev->name);
 			p->stats.collisions += 16;
 		}
 	}
-
 #if (NUM_XMIT_BUFFS > 1)
-	if( (++p->xmit_last) == NUM_XMIT_BUFFS)
+	if ((++p->xmit_last) == NUM_XMIT_BUFFS)
 		p->xmit_last = 0;
 #endif
 	netif_wake_queue(dev);
@@ -1110,41 +1107,51 @@ static void startrecv586(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 
-	WAIT_4_SCB_CMD();
-	WAIT_4_SCB_CMD_RUC();
-	p->scb->rfa_offset = make16(p->rfd_first);
-	p->scb->cmd_ruc = RUC_START;
+	wait_for_scb_cmd(dev);
+	wait_for_scb_cmd_ruc(dev);
+	writew(make16(p->rfd_first), &p->scb->rfa_offset);
+	writeb(RUC_START, &p->scb->cmd_ruc);
 	ni_attn586();		/* start cmd. */
-	WAIT_4_SCB_CMD_RUC();	/* wait for accept cmd. (no timeout!!) */
+	wait_for_scb_cmd_ruc(dev);
+	/* wait for accept cmd. (no timeout!!) */
 }
 
 static void ni52_timeout(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 #ifndef NO_NOPCOMMANDS
-	if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */
-	{
+	if (readb(&p->scb->cus) & CU_ACTIVE) { /* COMMAND-UNIT active? */
 		netif_wake_queue(dev);
 #ifdef DEBUG
-		printk("%s: strange ... timeout with CU active?!?\n",dev->name);
-		printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point);
+		printk(KERN_ERR "%s: strange ... timeout with CU active?!?\n",
+			dev->name);
+		printk(KERN_ERR "%s: X0: %04x N0: %04x N1: %04x %d\n",
+			dev->name, (int)p->xmit_cmds[0]->cmd_status,
+			readw(&p->nop_cmds[0]->cmd_status),
+			readw(&p->nop_cmds[1]->cmd_status),
+			p->nop_point);
 #endif
-		p->scb->cmd_cuc = CUC_ABORT;
+		writeb(CUC_ABORT, &p->scb->cmd_cuc);
 		ni_attn586();
-		WAIT_4_SCB_CMD();
-		p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
-		p->scb->cmd_cuc = CUC_START;
+		wait_for_scb_cmd(dev);
+		writew(make16(p->nop_cmds[p->nop_point]), &p->scb->cbl_offset);
+		writeb(CUC_START, &p->scb->cmd_cuc);
 		ni_attn586();
-		WAIT_4_SCB_CMD();
+		wait_for_scb_cmd(dev);
 		dev->trans_start = jiffies;
 		return 0;
 	}
 #endif
 	{
 #ifdef DEBUG
-		printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus);
-		printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status);
-		printk("%s: check, whether you set the right interrupt number!\n",dev->name);
+		printk(KERN_ERR "%s: xmitter timed out, try to restart! stat: %02x\n",
+				dev->name, readb(&p->scb->cus));
+		printk(KERN_ERR "%s: command-stats: %04x %04x\n",
+				dev->name,
+				readw(&p->xmit_cmds[0]->cmd_status),
+				readw(&p->xmit_cmds[1]->cmd_status));
+		printk(KERN_ERR "%s: check, whether you set the right interrupt number!\n",
+				dev->name);
 #endif
 		ni52_close(dev);
 		ni52_open(dev);
@@ -1158,110 +1165,99 @@ static void ni52_timeout(struct net_device *dev)
 
 static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-	int len,i;
+	int len, i;
 #ifndef NO_NOPCOMMANDS
 	int next_nop;
 #endif
 	struct priv *p = (struct priv *) dev->priv;
 
-	if(skb->len > XMIT_BUFF_SIZE)
-	{
-		printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
+	if (skb->len > XMIT_BUFF_SIZE) {
+		printk(KERN_ERR "%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n", dev->name, XMIT_BUFF_SIZE, skb->len);
 		return 0;
 	}
 
 	netif_stop_queue(dev);
 
-#if(NUM_XMIT_BUFFS > 1)
-	if(test_and_set_bit(0,(void *) &p->lock)) {
-		printk("%s: Queue was locked\n",dev->name);
-		return 1;
+	skb_copy_from_linear_data(skb, (char *)p->xmit_cbuffs[p->xmit_count],
+							skb->len);
+	len = skb->len;
+	if (len < ETH_ZLEN) {
+		len = ETH_ZLEN;
+		memset((char *)p->xmit_cbuffs[p->xmit_count]+skb->len, 0,
+							len - skb->len);
 	}
-	else
-#endif
-	{
-		skb_copy_from_linear_data(skb, (char *) p->xmit_cbuffs[p->xmit_count], skb->len);
-		len = skb->len;
-		if (len < ETH_ZLEN) {
-			len = ETH_ZLEN;
-			memset((char *)p->xmit_cbuffs[p->xmit_count]+skb->len, 0, len - skb->len);
-		}
 
 #if (NUM_XMIT_BUFFS == 1)
 #	ifdef NO_NOPCOMMANDS
 
 #ifdef DEBUG
-		if(p->scb->cus & CU_ACTIVE)
-		{
-			printk("%s: Hmmm .. CU is still running and we wanna send a new packet.\n",dev->name);
-			printk("%s: stat: %04x %04x\n",dev->name,p->scb->cus,p->xmit_cmds[0]->cmd_status);
-		}
+	if (p->scb->cus & CU_ACTIVE) {
+		printk(KERN_ERR "%s: Hmmm .. CU is still running and we wanna send a new packet.\n", dev->name);
+		printk(KERN_ERR "%s: stat: %04x %04x\n",
+				dev->name, readb(&p->scb->cus),
+				readw(&p->xmit_cmds[0]->cmd_status));
+	}
 #endif
-
-		p->xmit_buffs[0]->size = TBD_LAST | len;
-		for(i=0;i<16;i++)
-		{
-			p->xmit_cmds[0]->cmd_status = 0;
-			WAIT_4_SCB_CMD();
-			if( (p->scb->cus & CU_STATUS) == CU_SUSPEND)
-				p->scb->cmd_cuc = CUC_RESUME;
-			else
-			{
-				p->scb->cbl_offset = make16(p->xmit_cmds[0]);
-				p->scb->cmd_cuc = CUC_START;
-			}
-
-			ni_attn586();
-			dev->trans_start = jiffies;
-			if(!i)
-				dev_kfree_skb(skb);
-			WAIT_4_SCB_CMD();
-			if( (p->scb->cus & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */
-				break;
-			if(p->xmit_cmds[0]->cmd_status)
-				break;
-			if(i==15)
-				printk("%s: Can't start transmit-command.\n",dev->name);
+	writew(TBD_LAST | len, &p->xmit_buffs[0]->size);;
+	for (i = 0; i < 16; i++) {
+		writew(0, &p->xmit_cmds[0]->cmd_status);
+		wait_for_scb_cmd(dev);
+		if ((readb(&p->scb->cus) & CU_STATUS) == CU_SUSPEND)
+			writeb(CUC_RESUME, &p->scb->cmd_cuc);
+		else {
+			writew(make16(p->xmit_cmds[0]), &p->scb->cbl_offset);
+			writeb(CUC_START, &p->scb->cmd_cuc);
 		}
-#	else
-		next_nop = (p->nop_point + 1) & 0x1;
-		p->xmit_buffs[0]->size = TBD_LAST | len;
-
-		p->xmit_cmds[0]->cmd_link	 = p->nop_cmds[next_nop]->cmd_link
-																= make16((p->nop_cmds[next_nop]));
-		p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
-
-		p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
+		ni_attn586();
 		dev->trans_start = jiffies;
-		p->nop_point = next_nop;
-		dev_kfree_skb(skb);
+		if (!i)
+			dev_kfree_skb(skb);
+		wait_for_scb_cmd(dev);
+		/* test it, because CU sometimes doesn't start immediately */
+		if (readb(&p->scb->cus) & CU_ACTIVE)
+			break;
+		if (readw(&p->xmit_cmds[0]->cmd_status))
+			break;
+		if (i == 15)
+			printk(KERN_WARNING "%s: Can't start transmit-command.\n", dev->name);
+	}
+#	else
+	next_nop = (p->nop_point + 1) & 0x1;
+	writew(TBD_LAST | len, &p->xmit_buffs[0]->size);
+	writew(make16(p->nop_cmds[next_nop]), &p->xmit_cmds[0]->cmd_link);
+	writew(make16(p->nop_cmds[next_nop]),
+				&p->nop_cmds[next_nop]->cmd_link);
+	writew(0, &p->xmit_cmds[0]->cmd_status);
+	writew(0, &p->nop_cmds[next_nop]->cmd_status);
+
+	writew(make16(p->xmit_cmds[0]), &p->nop_cmds[p->nop_point]->cmd_link);
+	dev->trans_start = jiffies;
+	p->nop_point = next_nop;
+	dev_kfree_skb(skb);
 #	endif
 #else
-		p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
-		if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS )
-			next_nop = 0;
-
-		p->xmit_cmds[p->xmit_count]->cmd_status	= 0;
-		/* linkpointer of xmit-command already points to next nop cmd */
-		p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop]));
-		p->nop_cmds[next_nop]->cmd_status = 0;
-
-		p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
-		dev->trans_start = jiffies;
-		p->xmit_count = next_nop;
-
-		{
-			unsigned long flags;
-			save_flags(flags);
-			cli();
-			if(p->xmit_count != p->xmit_last)
-				netif_wake_queue(dev);
-			p->lock = 0;
-			restore_flags(flags);
-		}
-		dev_kfree_skb(skb);
-#endif
+	writew(TBD_LAST | len, &p->xmit_buffs[p->xmit_count]->size);
+	next_nop = p->xmit_count + 1
+	if (next_nop == NUM_XMIT_BUFFS)
+		next_nop = 0;
+	writew(0, &p->xmit_cmds[p->xmit_count]->cmd_status);
+	/* linkpointer of xmit-command already points to next nop cmd */
+	writew(make16(p->nop_cmds[next_nop]),
+				&p->nop_cmds[next_nop]->cmd_link);
+	writew(0, &p->nop_cmds[next_nop]->cmd_status);
+	writew(make16(p->xmit_cmds[p->xmit_count]),
+				&p->nop_cmds[p->xmit_count]->cmd_link);
+	dev->trans_start = jiffies;
+	p->xmit_count = next_nop;
+	{
+		unsigned long flags;
+		spin_lock_irqsave(&p->spinlock);
+		if (p->xmit_count != p->xmit_last)
+			netif_wake_queue(dev);
+		spin_unlock_irqrestore(&p->spinlock);
 	}
+	dev_kfree_skb(skb);
+#endif
 	return 0;
 }
 
@@ -1272,16