patch-2.4.3 linux/drivers/net/yellowfin.c

Next file: linux/drivers/net/zlib.c
Previous file: linux/drivers/net/winbond-840.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.2/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
@@ -1,33 +1,54 @@
 /* yellowfin.c: A Packet Engines G-NIC ethernet driver for linux. */
 /*
-	Written 1997-1999 by Donald Becker.
+	Written 1997-2001 by Donald Becker.
 
-	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	This software may be used and distributed according to the terms of
+	the GNU General Public License (GPL), incorporated herein by reference.
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
 
 	This driver is for the Packet Engines G-NIC PCI Gigabit Ethernet adapter.
 	It also supports the Symbios Logic version of the same chip core.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	Support and updates available at
-	http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html
+	http://www.scyld.com/network/yellowfin.html
+
+
+	Linux kernel changelog:
+	-----------------------
+
+	LK1.1.1 (jgarzik): Port to 2.4 kernel
+
+	LK1.1.2 (jgarzik):
+	* Merge in becker version 1.05
+
 */
 
-static const char *version =
-"yellowfin.c:v1.03a 7/30/99  Written by Donald Becker, becker@cesdis.edu\n"
-" http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html\n";
+/* These identify the driver base version and may not be removed. */
+static const char version1[] =
+"yellowfin.c:v1.05  1/09/2001  Written by Donald Becker <becker@scyld.com>\n";
+static const char version2[] =
+"  http://www.scyld.com/network/yellowfin.html\n";
+static const char version3[] =
+"  (unofficial 2.4.x port, LK1.1.2, January 11, 2001)\n";
 
-/* A few user-configurable values. */
+/* The user-configurable values.
+   These may be modified when a driver module is loaded.*/
 
-static int debug = 1;
+static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 20;
-static int mtu = 0;
+static int mtu;
 #ifdef YF_PROTOTYPE			/* Support for prototype hardware errata. */
 /* System-wide count of bogus-rx frames. */
-static int bogus_rx = 0;
+static int bogus_rx;
 static int dma_ctrl = 0x004A0263; 			/* Constrained by errata */
 static int fifo_cfg = 0x0020;				/* Bypass external Tx FIFO. */
 #elif YF_NEW					/* A future perfect board :->.  */
@@ -40,7 +61,7 @@
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1514 effectively disables this feature. */
-static int rx_copybreak = 0;
+static int rx_copybreak;
 
 /* Used to pass the media type, etc.
    No media types are currently defined.  These exist for driver
@@ -51,12 +72,12 @@
 static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
 /* Do ugly workaround for GX server chipset errata. */
-static int gx_fix = 0;
+static int gx_fix;
 
 /* Operational parameters that are set at compile time. */
 
 /* Keep the ring sizes a power of two for efficiency.
-   Making the Tx queue too long decreases the effectiveness of channel
+   Making the Tx ring too long decreases the effectiveness of channel
    bonding and packet priority.
    There are no ill effects from too-large receive rings. */
 #define TX_RING_SIZE	16
@@ -66,57 +87,61 @@
 /* Operational parameters that usually are not changed. */
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (2*HZ)
+#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
 #define yellowfin_debug debug
 
-#if !defined(__OPTIMIZE__)  ||  !defined(__KERNEL__)
+#if !defined(__OPTIMIZE__)
 #warning  You must compile this file with the correct options!
 #warning  See the last lines of the source file.
 #error You must compile this driver with "-O".
 #endif
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/unaligned.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-/* Condensed operations for readability.
-   Compatibility defines are now in drv_compat.h */
-
+/* Condensed operations for readability. */
 #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
 #define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
 
-
-#ifdef USE_IO_OPS
-#define YF_INB	inb
-#define YF_INW	inw
-#define YF_INL	inl
-#define YF_OUTB	outb
-#define YF_OUTW	outw
-#define YF_OUTL	outl
-#else
-#define YF_INB	readb
-#define YF_INW	readw
-#define YF_INL	readl
-#define YF_OUTB	writeb
-#define YF_OUTW	writew
-#define YF_OUTL	writel
-#endif
+#ifndef USE_IO_OPS
+#undef inb
+#undef inw
+#undef inl
+#undef outb
+#undef outw
+#undef outl
+#define inb readb
+#define inw readw
+#define inl readl
+#define outb writeb
+#define outw writew
+#define outl writel
+#endif /* !USE_IO_OPS */
+MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
+MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(mtu, "i");
+MODULE_PARM(debug, "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(gx_fix, "i");
 
 /*
 				Theory of Operation
@@ -193,50 +218,53 @@
 IVc. Errata
 
 See Packet Engines confidential appendix (prototype chips only).
-
 */
-
-/* A few values that may be tweaked. */
-#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
-/* The rest of these values should never change. */
+
 
+enum pci_id_flags_bits {
+	/* Set PCI command register bits before calling probe1(). */
+	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+	/* Read and map the single following PCI BAR. */
+	PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
+	PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
+	PCI_UNUSED_IRQ=0x800,
+};
 enum capability_flags {
 	HasMII=1, FullTxStatus=2, IsGigabit=4, HasMulticastBug=8, FullRxStatus=16,
-	HasMACAddrBug=32,			/* Really only on early revs.  */
+	HasMACAddrBug=32,			/* Only on early revs.  */
 };
-
-
 /* The PCI I/O space extent. */
 #define YELLOWFIN_SIZE 0x100
+#ifdef USE_IO_OPS
+#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO  | PCI_ADDR0)
+#else
+#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)
+#endif
 
-#define YELLOWFIN_MODULE_NAME "yellowfin"
-#define PFX YELLOWFIN_MODULE_NAME ": "
-
-
-typedef enum {
-	YELLOWFIN_GNIC,
-	SYM83C885,
-} chip_t;
-
-
-struct chip_info {
-	const char *name;
-	int flags;
+struct pci_id_info {
+        const char *name;
+        struct match_info {
+                int     pci, pci_mask, subsystem, subsystem_mask;
+                int revision, revision_mask;                            /* Only 8 bits. */
+        } id;
+        enum pci_id_flags_bits pci_flags;
+        int io_size;                            /* Needed for I/O region check or ioremap(). */
+        int drv_flags;                          /* Driver use, intended as capability flags. */
 };
 
-
-/* index by chip_t */
-static struct chip_info chip_info[] = {
-	{"Yellowfin G-NIC Gigabit Ethernet",
+static struct pci_id_info pci_id_tbl[] = {
+	{"Yellowfin G-NIC Gigabit Ethernet", { 0x07021000, 0xffffffff},
+	 PCI_IOTYPE, YELLOWFIN_SIZE,
 	 FullTxStatus | IsGigabit | HasMulticastBug | HasMACAddrBug},
-	{"Symbios SYM83C885", HasMII },
+	{"Symbios SYM83C885", { 0x07011000, 0xffffffff},
+	 PCI_IOTYPE, YELLOWFIN_SIZE, HasMII },
+	{0,},
 };
 
-
 static struct pci_device_id yellowfin_pci_tbl[] __devinitdata = {
-	{ 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, YELLOWFIN_GNIC },
-	{ 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SYM83C885 },
+	{ 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE (pci, yellowfin_pci_tbl);
@@ -300,21 +328,22 @@
 	IntrEarlyRx=0x100, IntrWakeup=0x200, };
 
 #define PRIV_ALIGN	31 	/* Required alignment mask */
+#define MII_CNT		4
 struct yellowfin_private {
-	/* Descriptor rings first for alignment.  Tx requires a second descriptor
-	   for status. */
+	/* Descriptor rings first for alignment.
+	   Tx requires a second descriptor for status. */
 	struct yellowfin_desc rx_ring[RX_RING_SIZE];
 	struct yellowfin_desc tx_ring[TX_RING_SIZE*2];
 	/* The addresses of receive-in-place skbuffs. */
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	/* The saved address of a sent-in-place packet/buffer, for later free(). */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
 	struct tx_status_words tx_status[TX_RING_SIZE];
 	struct timer_list timer;	/* Media selection timer. */
 	struct net_device_stats stats;
 	/* Frequently used and paired value: keep adjacent for cache effect. */
+	int chip_id, drv_flags;
 	struct pci_dev *pci_dev;
-	int chip_id, flags;
 	struct yellowfin_desc *rx_head_desc;
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
@@ -329,29 +358,14 @@
 	/* MII transceiver section. */
 	int mii_cnt;						/* MII device addresses. */
 	u16 advertising;					/* NWay media advertisement */
-	unsigned char phys[2];				/* MII device addresses. */
-	u32 pad[4];							/* Used for 32-byte alignment */
+	unsigned char phys[MII_CNT];		/* MII device addresses, only first one used */
 	spinlock_t lock;
 };
 
-
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver");
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(mtu, "i");
-MODULE_PARM(debug, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(gx_fix, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-
-
 static int read_eeprom(long ioaddr, int location);
 static int mdio_read(long ioaddr, int phy_id, int location);
 static void mdio_write(long ioaddr, int phy_id, int location, int value);
-#ifdef HAVE_PRIVATE_IOCTL
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#endif
 static int yellowfin_open(struct net_device *dev);
 static void yellowfin_timer(unsigned long data);
 static void yellowfin_tx_timeout(struct net_device *dev);
@@ -365,15 +379,147 @@
 static void set_rx_mode(struct net_device *dev);
 
 
+static int __devinit yellowfin_init_one(struct pci_dev *pdev,
+					const struct pci_device_id *ent)
+{
+	struct net_device *dev;
+	struct yellowfin_private *np;
+	int irq;
+	int chip_idx = ent->driver_data;
+	static int find_cnt = 0;
+	long ioaddr, real_ioaddr;
+	int i, option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;
+	int drv_flags = pci_id_tbl[chip_idx].drv_flags;
+	
+	i = pci_enable_device(pdev);
+	if (i) return i;
+
+	dev = alloc_etherdev(sizeof(*np));
+	if (!dev) {
+		printk (KERN_ERR "yellowfin: cannot allocate ethernet device\n");
+		return -ENOMEM;
+	}
+	SET_MODULE_OWNER(dev);
+
+	np = dev->priv;
+
+	if (pci_request_regions(pdev, dev->name))
+		goto err_out_free_netdev;
+
+	pci_set_master (pdev);
+
+#ifdef USE_IO_OPS
+	real_ioaddr = ioaddr = pci_resource_start (pdev, 0);
+#else
+	real_ioaddr = ioaddr = pci_resource_start (pdev, 1);
+	ioaddr = (long) ioremap(ioaddr, YELLOWFIN_SIZE);
+	if (!ioaddr)
+		goto err_out_free_res;
+#endif
+	irq = pdev->irq;
+
+	if (drv_flags & IsGigabit)
+		for (i = 0; i < 6; i++)
+			dev->dev_addr[i] = inb(ioaddr + StnAddr + i);
+	else {
+		int ee_offset = (read_eeprom(ioaddr, 6) == 0xff ? 0x100 : 0);
+		for (i = 0; i < 6; i++)
+			dev->dev_addr[i] = read_eeprom(ioaddr, ee_offset + i);
+	}
+
+	/* Reset the chip. */
+	outl(0x80000000, ioaddr + DMACtrl);
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+
+	pci_set_drvdata(pdev, dev);
+	np->lock = SPIN_LOCK_UNLOCKED;
+
+	np->pci_dev = pdev;
+	np->chip_id = chip_idx;
+	np->drv_flags = drv_flags;
+
+	if (dev->mem_start)
+		option = dev->mem_start;
+
+	/* The lower four bits are the media type. */
+	if (option > 0) {
+		if (option & 0x200)
+			np->full_duplex = 1;
+		np->default_port = option & 15;
+		if (np->default_port)
+			np->medialock = 1;
+	}
+	if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)
+		np->full_duplex = 1;
+
+	if (np->full_duplex)
+		np->duplex_lock = 1;
+
+	/* The Yellowfin-specific entries in the device structure. */
+	dev->open = &yellowfin_open;
+	dev->hard_start_xmit = &yellowfin_start_xmit;
+	dev->stop = &yellowfin_close;
+	dev->get_stats = &yellowfin_get_stats;
+	dev->set_multicast_list = &set_rx_mode;
+	dev->do_ioctl = &mii_ioctl;
+	dev->tx_timeout = yellowfin_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+
+	if (mtu)
+		dev->mtu = mtu;
+
+	i = register_netdev(dev);
+	if (i)
+		goto err_out_cleardev;
+
+	printk(KERN_INFO "%s: %s type %8x at 0x%lx, ",
+		   dev->name, pci_id_tbl[chip_idx].name, inl(ioaddr + ChipRev), ioaddr);
+	for (i = 0; i < 5; i++)
+			printk("%2.2x:", dev->dev_addr[i]);
+	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
+
+	if (np->drv_flags & HasMII) {
+		int phy, phy_idx = 0;
+		for (phy = 0; phy < 32 && phy_idx < MII_CNT; phy++) {
+			int mii_status = mdio_read(ioaddr, phy, 1);
+			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
+				np->phys[phy_idx++] = phy;
+				np->advertising = mdio_read(ioaddr, phy, 4);
+				printk(KERN_INFO "%s: MII PHY found at address %d, status "
+					   "0x%4.4x advertising %4.4x.\n",
+					   dev->name, phy, mii_status, np->advertising);
+			}
+		}
+		np->mii_cnt = phy_idx;
+	}
+
+	find_cnt++;
+	
+	return 0;
+
+err_out_cleardev:
+	pci_set_drvdata(pdev, NULL);
+#ifndef USE_IO_OPS
+	iounmap((void *)ioaddr);
+err_out_free_res:
+#endif
+	pci_release_regions(pdev);
+err_out_free_netdev:
+	kfree (dev);
+	return -ENODEV;
+}
+
 static int __devinit read_eeprom(long ioaddr, int location)
 {
 	int bogus_cnt = 10000;		/* Typical 33Mhz: 1050 ticks */
 
-	YF_OUTB(location, ioaddr + EEAddr);
-	YF_OUTB(0x30 | ((location >> 8) & 7), ioaddr + EECtrl);
-	while ((YF_INB(ioaddr + EEStatus) & 0x80)  &&  --bogus_cnt > 0)
+	outb(location, ioaddr + EEAddr);
+	outb(0x30 | ((location >> 8) & 7), ioaddr + EECtrl);
+	while ((inb(ioaddr + EEStatus) & 0x80)  &&  --bogus_cnt > 0)
 		;
-	return YF_INB(ioaddr + EERead);
+	return inb(ioaddr + EERead);
 }
 
 /* MII Managemen Data I/O accesses.
@@ -384,24 +530,24 @@
 {
 	int i;
 
-	YF_OUTW((phy_id<<8) + location, ioaddr + MII_Addr);
-	YF_OUTW(1, ioaddr + MII_Cmd);
+	outw((phy_id<<8) + location, ioaddr + MII_Addr);
+	outw(1, ioaddr + MII_Cmd);
 	for (i = 10000; i >= 0; i--)
-		if ((YF_INW(ioaddr + MII_Status) & 1) == 0)
+		if ((inw(ioaddr + MII_Status) & 1) == 0)
 			break;
-	return YF_INW(ioaddr + MII_Rd_Data);
+	return inw(ioaddr + MII_Rd_Data);
 }
 
 static void mdio_write(long ioaddr, int phy_id, int location, int value)
 {
 	int i;
 
-	YF_OUTW((phy_id<<8) + location, ioaddr + MII_Addr);
-	YF_OUTW(value, ioaddr + MII_Wr_Data);
+	outw((phy_id<<8) + location, ioaddr + MII_Addr);
+	outw(value, ioaddr + MII_Wr_Data);
 
 	/* Wait for the command to finish. */
 	for (i = 10000; i >= 0; i--)
-		if ((YF_INW(ioaddr + MII_Status) & 1) == 0)
+		if ((inw(ioaddr + MII_Status) & 1) == 0)
 			break;
 	return;
 }
@@ -409,15 +555,15 @@
 
 static int yellowfin_open(struct net_device *dev)
 {
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 	long ioaddr = dev->base_addr;
 	int i;
 
 	/* Reset the chip. */
-	YF_OUTL(0x80000000, ioaddr + DMACtrl);
+	outl(0x80000000, ioaddr + DMACtrl);
 
-	if (request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ, dev->name, dev))
-		return -EAGAIN;
+	i = request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ, dev->name, dev);
+	if (i) return i;
 
 	if (yellowfin_debug > 1)
 		printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n",
@@ -425,58 +571,59 @@
 
 	yellowfin_init_ring(dev);
 
-	YF_OUTL(virt_to_bus(yp->rx_ring), ioaddr + RxPtr);
-	YF_OUTL(virt_to_bus(yp->tx_ring), ioaddr + TxPtr);
+	outl(virt_to_bus(yp->rx_ring), ioaddr + RxPtr);
+	outl(virt_to_bus(yp->tx_ring), ioaddr + TxPtr);
 
 	for (i = 0; i < 6; i++)
-		YF_OUTB(dev->dev_addr[i], ioaddr + StnAddr + i);
+		outb(dev->dev_addr[i], ioaddr + StnAddr + i);
 
 	/* Set up various condition 'select' registers.
 	   There are no options here. */
-	YF_OUTL(0x00800080, ioaddr + TxIntrSel); 	/* Interrupt on Tx abort */
-	YF_OUTL(0x00800080, ioaddr + TxBranchSel);	/* Branch on Tx abort */
-	YF_OUTL(0x00400040, ioaddr + TxWaitSel); 	/* Wait on Tx status */
-	YF_OUTL(0x00400040, ioaddr + RxIntrSel);	/* Interrupt on Rx done */
-	YF_OUTL(0x00400040, ioaddr + RxBranchSel);	/* Branch on Rx error */
-	YF_OUTL(0x00400040, ioaddr + RxWaitSel);	/* Wait on Rx done */
+	outl(0x00800080, ioaddr + TxIntrSel); 	/* Interrupt on Tx abort */
+	outl(0x00800080, ioaddr + TxBranchSel);	/* Branch on Tx abort */
+	outl(0x00400040, ioaddr + TxWaitSel); 	/* Wait on Tx status */
+	outl(0x00400040, ioaddr + RxIntrSel);	/* Interrupt on Rx done */
+	outl(0x00400040, ioaddr + RxBranchSel);	/* Branch on Rx error */
+	outl(0x00400040, ioaddr + RxWaitSel);	/* Wait on Rx done */
 
 	/* Initialize other registers: with so many this eventually this will
 	   converted to an offset/value list. */
-	YF_OUTL(dma_ctrl, ioaddr + DMACtrl);
-	YF_OUTW(fifo_cfg, ioaddr + FIFOcfg);
+	outl(dma_ctrl, ioaddr + DMACtrl);
+	outw(fifo_cfg, ioaddr + FIFOcfg);
 	/* Enable automatic generation of flow control frames, period 0xffff. */
-	YF_OUTL(0x0030FFFF, ioaddr + FlowCtrl);
+	outl(0x0030FFFF, ioaddr + FlowCtrl);
 
 	yp->tx_threshold = 32;
-	YF_OUTL(yp->tx_threshold, ioaddr + TxThreshold);
+	outl(yp->tx_threshold, ioaddr + TxThreshold);
 
 	if (dev->if_port == 0)
 		dev->if_port = yp->default_port;
 
-	netif_start_queue (dev);
+	netif_start_queue(dev);
 
 	/* Setting the Rx mode will start the Rx process. */
-	if (yp->flags & IsGigabit) {
+	if (yp->drv_flags & IsGigabit) {
 		/* We are always in full-duplex mode with gigabit! */
 		yp->full_duplex = 1;
-		YF_OUTW(0x01CF, ioaddr + Cnfg);
+		outw(0x01CF, ioaddr + Cnfg);
 	} else {
-		YF_OUTW(0x0018, ioaddr + FrameGap0); /* 0060/4060 for non-MII 10baseT */
-		YF_OUTW(0x1018, ioaddr + FrameGap1);
-		YF_OUTW(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
+		outw(0x0018, ioaddr + FrameGap0); /* 0060/4060 for non-MII 10baseT */
+		outw(0x1018, ioaddr + FrameGap1);
+		outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
 	}
 	set_rx_mode(dev);
 
 	/* Enable interrupts by setting the interrupt mask. */
-	YF_OUTW(0x81ff, ioaddr + IntrEnb);			/* See enum intr_status_bits */
-	YF_OUTW(0x0000, ioaddr + EventStatus);		/* Clear non-interrupting events */
-	YF_OUTL(0x80008000, ioaddr + RxCtrl);		/* Start Rx and Tx channels. */
-	YF_OUTL(0x80008000, ioaddr + TxCtrl);
+	outw(0x81ff, ioaddr + IntrEnb);			/* See enum intr_status_bits */
+	outw(0x0000, ioaddr + EventStatus);		/* Clear non-interrupting events */
+	outl(0x80008000, ioaddr + RxCtrl);		/* Start Rx and Tx channels. */
+	outl(0x80008000, ioaddr + TxCtrl);
 
 	if (yellowfin_debug > 2) {
 		printk(KERN_DEBUG "%s: Done yellowfin_open().\n",
 			   dev->name);
 	}
+
 	/* Set the timer to check for link beat. */
 	init_timer(&yp->timer);
 	yp->timer.expires = jiffies + 3*HZ;
@@ -490,13 +637,13 @@
 static void yellowfin_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 	long ioaddr = dev->base_addr;
 	int next_tick = 60*HZ;
 
 	if (yellowfin_debug > 3) {
 		printk(KERN_DEBUG "%s: Yellowfin timer tick, status %8.8x.\n",
-			   dev->name, YF_INW(ioaddr + IntrStatus));
+			   dev->name, inw(ioaddr + IntrStatus));
 	}
 
 	if (yp->mii_cnt) {
@@ -513,7 +660,7 @@
 			  || (negotiated & 0x00C0) == 0x0040)) {
 			yp->full_duplex = 1;
 		}
-		YF_OUTW(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
+		outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
 
 		if (mii_reg1 & 0x0004)
 			next_tick = 60*HZ;
@@ -527,13 +674,13 @@
 
 static void yellowfin_tx_timeout(struct net_device *dev)
 {
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 	long ioaddr = dev->base_addr;
 
 	printk(KERN_WARNING "%s: Yellowfin transmit timed out at %d/%d Tx "
 		   "status %4.4x, Rx status %4.4x, resetting...\n",
 		   dev->name, yp->cur_tx, yp->dirty_tx,
-		   YF_INL(ioaddr + TxStatus), YF_INL(ioaddr + RxStatus));
+		   inl(ioaddr + TxStatus), inl(ioaddr + RxStatus));
 
 	/* Note: these should be KERN_DEBUG. */
 	if (yellowfin_debug) {
@@ -553,19 +700,18 @@
 	dev->if_port = 0;
 
 	/* Wake the potentially-idle transmit channel. */
-	YF_OUTL(0x10001000, dev->base_addr + TxCtrl);
+	outl(0x10001000, dev->base_addr + TxCtrl);
 	if (yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE)
 		netif_wake_queue (dev);		/* Typical path */
 
 	dev->trans_start = jiffies;
 	yp->stats.tx_errors++;
-	return;
 }
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void yellowfin_init_ring(struct net_device *dev)
 {
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 	int i;
 
 	yp->tx_full = 0;
@@ -637,13 +783,13 @@
 
 static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 	unsigned entry;
 
 	netif_stop_queue (dev);
 
-	/* Caution: the write order is important here, set the base address
-	   with the "ownership" bits last. */
+	/* Note: Ordering is important here, set the field with the
+	   "ownership" bit last, and only then increment cur_tx. */
 
 	/* Calculate the next Tx descriptor entry. */
 	entry = yp->cur_tx % TX_RING_SIZE;
@@ -691,7 +837,7 @@
 	/* Non-x86 Todo: explicitly flush cache lines here. */
 
 	/* Wake the potentially-idle transmit channel. */
-	YF_OUTL(0x10001000, dev->base_addr + TxCtrl);
+	outl(0x10001000, dev->base_addr + TxCtrl);
 
 	if (yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE)
 		netif_start_queue (dev);		/* Typical path */
@@ -710,9 +856,10 @@
    after the Tx thread. */
 static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-	struct net_device *dev = (struct net_device *)dev_instance;
+	struct net_device *dev = dev_instance;
 	struct yellowfin_private *yp;
-	long ioaddr, boguscnt = max_interrupt_work;
+	long ioaddr;
+	int boguscnt = max_interrupt_work;
 
 #ifndef final_version			/* Can never occur. */
 	if (dev == NULL) {
@@ -722,12 +869,12 @@
 #endif
 
 	ioaddr = dev->base_addr;
-	yp = (struct yellowfin_private *)dev->priv;
+	yp = dev->priv;
 	
 	spin_lock (&yp->lock);
 
 	do {
-		u16 intr_status = YF_INW(ioaddr + IntrClear);
+		u16 intr_status = inw(ioaddr + IntrClear);
 
 		if (yellowfin_debug > 4)
 			printk(KERN_DEBUG "%s: Yellowfin interrupt, status %4.4x.\n",
@@ -738,7 +885,7 @@
 
 		if (intr_status & (IntrRxDone | IntrEarlyRx)) {
 			yellowfin_rx(dev);
-			YF_OUTL(0x10001000, ioaddr + RxCtrl);		/* Wake Rx engine. */
+			outl(0x10001000, ioaddr + RxCtrl);		/* Wake Rx engine. */
 		}
 
 #ifdef NO_TXSTATS
@@ -746,8 +893,8 @@
 			int entry = yp->dirty_tx % TX_RING_SIZE;
 			if (yp->tx_ring[entry].result_status == 0)
 				break;
-			yp->stats.tx_bytes += yp->tx_skbuff[entry]->len;
 			yp->stats.tx_packets++;
+			yp->stats.tx_bytes += yp->tx_skbuff[entry]->len;
 			/* Free the original skb. */
 			dev_kfree_skb_irq(yp->tx_skbuff[entry]);
 			yp->tx_skbuff[entry] = 0;
@@ -756,11 +903,8 @@
 			&& yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE - 4) {
 			/* The ring is no longer full, clear tbusy. */
 			yp->tx_full = 0;
-		}
-		if (yp->tx_full)
-			netif_stop_queue(dev);
-		else
 			netif_wake_queue(dev);
+		}
 #else
 		if (intr_status & IntrTxDone
 			|| yp->tx_tail_desc->tx_errs) {
@@ -831,11 +975,8 @@
 				&& yp->cur_tx - dirty_tx < TX_QUEUE_SIZE - 2) {
 				/* The ring is no longer full, clear tbusy. */
 				yp->tx_full = 0;
-			}
-			if (yp->tx_full)
-				netif_stop_queue(dev);
-			else
 				netif_wake_queue(dev);
+			}
 
 			yp->dirty_tx = dirty_tx;
 			yp->tx_tail_desc = &yp->tx_status[dirty_tx % TX_RING_SIZE];
@@ -847,7 +988,8 @@
 			yellowfin_error(dev, intr_status);
 
 		if (--boguscnt < 0) {
-			printk(KERN_WARNING "%s: Too much work at interrupt, status=0x%4.4x.\n",
+			printk(KERN_WARNING "%s: Too much work at interrupt, "
+				   "status=0x%4.4x.\n",
 				   dev->name, intr_status);
 			break;
 		}
@@ -855,28 +997,19 @@
 
 	if (yellowfin_debug > 3)
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
-			   dev->name, YF_INW(ioaddr + IntrStatus));
-
-	/* Code that should never be run!  Perhaps remove after testing.. */
-	{
-		static int stopit = 10;
-		if ((!(netif_running(dev)))  &&  --stopit < 0) {
-			printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
-				   dev->name);
-			free_irq(irq, dev);
-		}
-	}
+			   dev->name, inw(ioaddr + IntrStatus));
 
 	spin_unlock (&yp->lock);
+	return;
 }
 
 /* This routine is logically part of the interrupt handler, but separated
    for clarity and better register allocation. */
 static int yellowfin_rx(struct net_device *dev)
 {
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 	int entry = yp->cur_rx % RX_RING_SIZE;
-	int boguscnt = 20;
+	int boguscnt = yp->dirty_rx + RX_RING_SIZE - yp->cur_rx;
 
 	if (yellowfin_debug > 4) {
 		printk(KERN_DEBUG " In yellowfin_rx(), entry %d status %8.8x.\n",
@@ -905,7 +1038,7 @@
 			printk(KERN_WARNING "%s: Oversized Ethernet frame spanned multiple buffers,"
 				   " status %4.4x!\n", dev->name, desc_status);
 			yp->stats.rx_length_errors++;
-		} else if ((yp->flags & IsGigabit)  &&  (frame_status & 0x0038)) {
+		} else if ((yp->drv_flags & IsGigabit)  &&  (frame_status & 0x0038)) {
 			/* There was a error. */
 			if (yellowfin_debug > 3)
 				printk(KERN_DEBUG "  yellowfin_rx() Rx error was %4.4x.\n",
@@ -915,7 +1048,7 @@
 			if (frame_status & 0x0008) yp->stats.rx_frame_errors++;
 			if (frame_status & 0x0010) yp->stats.rx_crc_errors++;
 			if (frame_status < 0) yp->stats.rx_dropped++;
-		} else if ( !(yp->flags & IsGigabit)  &&
+		} else if ( !(yp->drv_flags & IsGigabit)  &&
 				   ((buf_addr[data_size-1] & 0x85) || buf_addr[data_size-2] & 0xC0)) {
 			u8 status1 = buf_addr[data_size-2];
 			u8 status2 = buf_addr[data_size-1];
@@ -952,21 +1085,22 @@
 			   without copying to a properly sized skbuff. */
 			if (pkt_len > rx_copybreak) {
 				char *temp = skb_put(skb = yp->rx_skbuff[entry], pkt_len);
-#ifndef final_verison				/* Remove after testing. */
+				yp->rx_skbuff[entry] = NULL;
+#ifndef final_version				/* Remove after testing. */
 				if (le32desc_to_virt(yp->rx_ring[entry].addr) != temp)
-					printk(KERN_WARNING "%s: Warning -- the skbuff addresses "
+					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
 						   "do not match in yellowfin_rx: %p vs. %p / %p.\n",
-						   dev->name, le32desc_to_virt(yp->rx_ring[entry].addr),
+						   dev->name,
+						   le32desc_to_virt(yp->rx_ring[entry].addr),
 						   skb->head, temp);
 #endif
-				yp->rx_skbuff[entry] = NULL;
 			} else {
 				skb = dev_alloc_skb(pkt_len + 2);
 				if (skb == NULL)
 					break;
 				skb->dev = dev;
-				skb_reserve(skb, 2);	/* 16 byte align the data fields */
-#if 1 || USE_IP_CSUM
+				skb_reserve(skb, 2);	/* 16 byte align the IP header */
+#if HAS_IP_COPYSUM
 				eth_copy_and_sum(skb, yp->rx_skbuff[entry]->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
 #else
@@ -989,9 +1123,9 @@
 		entry = yp->dirty_rx % RX_RING_SIZE;
 		if (yp->rx_skbuff[entry] == NULL) {
 			struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz);
-			if (skb == NULL)
-				break;			/* Better luck next round. */
 			yp->rx_skbuff[entry] = skb;
+			if (skb == NULL)
+				break;				/* Better luck next round. */
 			skb->dev = dev;			/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
 			yp->rx_ring[entry].addr = virt_to_le32desc(skb->tail);
@@ -1012,7 +1146,7 @@
 
 static void yellowfin_error(struct net_device *dev, int intr_status)
 {
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 
 	printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
 		   dev->name, intr_status);
@@ -1026,35 +1160,36 @@
 static int yellowfin_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 	int i;
 
 	netif_stop_queue (dev);
 
 	if (yellowfin_debug > 1) {
-		printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n",
-			   dev->name, YF_INW(ioaddr + TxStatus),
-			   YF_INW(ioaddr + RxStatus),
-			   YF_INW(ioaddr + IntrStatus));
+		printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x "
+			   "Rx %4.4x Int %2.2x.\n",
+			   dev->name, inw(ioaddr + TxStatus),
+			   inw(ioaddr + RxStatus), inw(ioaddr + IntrStatus));
 		printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d,  Rx %d / %d.\n",
 			   dev->name, yp->cur_tx, yp->dirty_tx, yp->cur_rx, yp->dirty_rx);
 	}
 
 	/* Disable interrupts by clearing the interrupt mask. */
-	YF_OUTW(0x0000, ioaddr + IntrEnb);
+	outw(0x0000, ioaddr + IntrEnb);
 
 	/* Stop the chip's Tx and Rx processes. */
-	YF_OUTL(0x80000000, ioaddr + RxCtrl);
-	YF_OUTL(0x80000000, ioaddr + TxCtrl);
+	outl(0x80000000, ioaddr + RxCtrl);
+	outl(0x80000000, ioaddr + TxCtrl);
 
 	del_timer(&yp->timer);
 
-#if !defined(final_version) && defined(__i386__)
+#if defined(__i386__)
 	if (yellowfin_debug > 2) {
-		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n", (int)virt_to_bus(yp->tx_ring));
+		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
+			   (int)virt_to_bus(yp->tx_ring));
 		for (i = 0; i < TX_RING_SIZE*2; i++)
 			printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n",
-				   YF_INL(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ',
+				   inl(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ',
 				   i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr,
 				   yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status);
 		printk(KERN_DEBUG "  Tx status %p:\n", yp->tx_status);
@@ -1063,10 +1198,11 @@
 				   i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs,
 				   yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused);
 
-		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n", (int)virt_to_bus(yp->rx_ring));
+		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
+			   (int)virt_to_bus(yp->rx_ring));
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n",
-				   YF_INL(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ',
+				   inl(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ',
 				   i, yp->rx_ring[i].dbdma_cmd, yp->rx_ring[i].addr,
 				   yp->rx_ring[i].result_status);
 			if (yellowfin_debug > 6) {
@@ -1105,12 +1241,13 @@
 			   dev->name, bogus_rx);
 	}
 #endif
+
 	return 0;
 }
 
 static struct net_device_stats *yellowfin_get_stats(struct net_device *dev)
 {
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 	return &yp->stats;
 }
 
@@ -1141,19 +1278,19 @@
 
 static void set_rx_mode(struct net_device *dev)
 {
-	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = dev->priv;
 	long ioaddr = dev->base_addr;
-	u16 cfg_value = YF_INW(ioaddr + Cnfg);
+	u16 cfg_value = inw(ioaddr + Cnfg);
 
 	/* Stop the Rx process to change any value. */
-	YF_OUTW(cfg_value & ~0x1000, ioaddr + Cnfg);
+	outw(cfg_value & ~0x1000, ioaddr + Cnfg);
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
 		/* Unconditionally log net taps. */
 		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
-		YF_OUTW(0x000F, ioaddr + AddrMode);
+		outw(0x000F, ioaddr + AddrMode);
 	} else if ((dev->mc_count > 64)  ||  (dev->flags & IFF_ALLMULTI)) {
 		/* Too many to filter well, or accept all multicasts. */
-		YF_OUTW(0x000B, ioaddr + AddrMode);
+		outw(0x000B, ioaddr + AddrMode);
 	} else if (dev->mc_count > 0) { /* Must use the multicast hash table. */
 		struct dev_mc_list *mclist;
 		u16 hash_table[4];
@@ -1163,7 +1300,7 @@
 			 i++, mclist = mclist->next) {
 			/* Due to a bug in the early chip versions, multiple filter
 			   slots must be set for each address. */
-			if (yp->flags & HasMulticastBug) {
+			if (yp->drv_flags & HasMulticastBug) {
 				set_bit((ether_crc_le(3, mclist->dmi_addr) >> 3) & 0x3f,
 						hash_table);
 				set_bit((ether_crc_le(4, mclist->dmi_addr) >> 3) & 0x3f,
@@ -1176,24 +1313,24 @@
 		}
 		/* Copy the hash table to the chip. */
 		for (i = 0; i < 4; i++)
-			YF_OUTW(hash_table[i], ioaddr + HashTbl + i*2);
-		YF_OUTW(0x0003, ioaddr + AddrMode);
+			outw(hash_table[i], ioaddr + HashTbl + i*2);
+		outw(0x0003, ioaddr + AddrMode);
 	} else {					/* Normal, unicast/broadcast-only mode. */
-		YF_OUTW(0x0001, ioaddr + AddrMode);
+		outw(0x0001, ioaddr + AddrMode);
 	}
 	/* Restart the Rx process. */
-	YF_OUTW(cfg_value | 0x1000, ioaddr + Cnfg);
+	outw(cfg_value | 0x1000, ioaddr + Cnfg);
 }
 
-#ifdef HAVE_PRIVATE_IOCTL
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
+	struct yellowfin_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
 
 	switch(cmd) {
 	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
-		data[0] = ((struct yellowfin_private *)dev->priv)->phys[0] & 0x1f;
+		data[0] = np->phys[0] & 0x1f;
 		/* Fall Through */
 	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
 		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
@@ -1201,155 +1338,30 @@
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
+		if (data[0] == np->phys[0]) {
+			u16 value = data[2];
+			switch (data[1]) {
+			case 0:
+				/* Check for autonegotiation on or reset. */
+				np->medialock = (value & 0x9000) ? 0 : 1;
+				if (np->medialock)
+					np->full_duplex = (value & 0x0100) ? 1 : 0;
+				break;
+			case 4: np->advertising = value; break;
+			}
+			/* Perhaps check_duplex(dev), depending on chip semantics. */
+		}
 		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
 	}
 }
-#endif  /* HAVE_PRIVATE_IOCTL */
-
-
-static int __devinit yellowfin_init_one(struct pci_dev *pdev,
-					const struct pci_device_id *ent)
-{
-	struct net_device *dev;
-	struct yellowfin_private *yp;
-	int option, i, irq;
-	int flags, chip_idx;
-	static int find_cnt = 0;
-	long ioaddr, real_ioaddr;
-	
-	chip_idx = ent->driver_data;
-	flags = chip_info[chip_idx].flags;
-
-	dev = init_etherdev(NULL, sizeof(*yp));
-	if (!dev) {
-		printk (KERN_ERR PFX "cannot allocate ethernet device\n");
-		return -ENOMEM;
-	}
-	SET_MODULE_OWNER(dev);
-
-	yp = dev->priv;
-
-	if (!request_region (pci_resource_start (pdev, 0),
-			     YELLOWFIN_SIZE, YELLOWFIN_MODULE_NAME)) {
-		printk (KERN_ERR PFX "cannot obtain I/O port region\n");
-		goto err_out_free_netdev;
-	}
-	if (!request_mem_region (pci_resource_start (pdev, 1),
-			         YELLOWFIN_SIZE, YELLOWFIN_MODULE_NAME)) {
-		printk (KERN_ERR PFX "cannot obtain MMIO region\n");
-		goto err_out_free_pio_region;
-	}
-	
-	if (pci_enable_device (pdev))
-		goto err_out_free_mmio_region;
-	pci_set_master (pdev);
-
-#ifdef USE_IO_OPS
-	real_ioaddr = ioaddr = pci_resource_start (pdev, 0);
-#else
-	real_ioaddr = ioaddr = pci_resource_start (pdev, 1);
-	ioaddr = (long) ioremap(ioaddr, YELLOWFIN_SIZE);
-	if (!ioaddr)
-		goto err_out_free_mmio_region;
-#endif
-	irq = pdev->irq;
-
-	printk(KERN_INFO "%s: %s type %8x at 0x%lx, ",
-	       dev->name, chip_info[chip_idx].name,
-	       YF_INL(ioaddr + ChipRev), real_ioaddr);
-
-	if (flags & IsGigabit)
-		for (i = 0; i < 6; i++)
-			dev->dev_addr[i] = YF_INB(ioaddr + StnAddr + i);
-	else {
-		int ee_offset = (read_eeprom(ioaddr, 6) == 0xff ? 0x100 : 0);
-		for (i = 0; i < 6; i++)
-			dev->dev_addr[i] = read_eeprom(ioaddr, ee_offset + i);
-	}
-	for (i = 0; i < 5; i++)
-			printk("%2.2x:", dev->dev_addr[i]);
-	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
-
-	/* Reset the chip. */
-	YF_OUTL(0x80000000, ioaddr + DMACtrl);
-
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-
-	pdev->driver_data = dev;
-	yp->chip_id = chip_idx;
-	yp->flags = flags;
-	yp->lock = SPIN_LOCK_UNLOCKED;
-
-	option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;
-	if (dev->mem_start)
-		option = dev->mem_start;
-
-	/* The lower four bits are the media type. */
-	if (option > 0) {
-		if (option & 0x200)
-			yp->full_duplex = 1;
-		yp->default_port = option & 15;
-		if (yp->default_port)
-			yp->medialock = 1;
-	}
-	if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)
-		yp->full_duplex = 1;
-
-	if (yp->full_duplex)
-		yp->duplex_lock = 1;
-
-	/* The Yellowfin-specific entries in the device structure. */
-	dev->open = &yellowfin_open;
-	dev->hard_start_xmit = &yellowfin_start_xmit;
-	dev->stop = &yellowfin_close;
-	dev->get_stats = &yellowfin_get_stats;
-	dev->set_multicast_list = &set_rx_mode;
-#ifdef HAVE_PRIVATE_IOCTL
-	dev->do_ioctl = &mii_ioctl;
-#endif
-	dev->tx_timeout = yellowfin_tx_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
 
-	if (mtu)
-		dev->mtu = mtu;
-
-	if (yp->flags & HasMII) {
-		int phy, phy_idx = 0;
-		for (phy = 0; phy < 32 && phy_idx < 4; phy++) {
-			int mii_status = mdio_read(ioaddr, phy, 1);
-			if (mii_status != 0xffff  &&
-				mii_status != 0x0000) {
-				yp->phys[phy_idx++] = phy;
-				yp->advertising = mdio_read(ioaddr, phy, 4);
-				printk(KERN_INFO "%s: MII PHY found at address %d, status "
-					   "0x%4.4x advertising %4.4x.\n",
-					   dev->name, phy, mii_status, yp->advertising);
-			}
-		}
-		yp->mii_cnt = phy_idx;
-	}
-
-	find_cnt++;
-	
-	return 0;
-
-err_out_free_mmio_region:
-	release_mem_region (pci_resource_start (pdev, 1), YELLOWFIN_SIZE);
-err_out_free_pio_region:
-	release_region (pci_resource_start (pdev, 0), YELLOWFIN_SIZE);
-err_out_free_netdev:
-	unregister_netdev (dev);
-	kfree (dev);
-	return -ENODEV;
-}
 
 static void __devexit yellowfin_remove_one (struct pci_dev *pdev)
 {
-	struct net_device *dev = pdev->driver_data;
+	struct net_device *dev = pci_get_drvdata(pdev);
 	struct yellowfin_private *np;
 
 	if (!dev)
@@ -1358,19 +1370,19 @@
 
 	unregister_netdev (dev);
 
-	release_region (dev->base_addr, YELLOWFIN_SIZE);
-	release_mem_region (dev->base_addr, YELLOWFIN_SIZE);
+	pci_release_regions (pdev);
 
 #ifndef USE_IO_OPS
 	iounmap ((void *) dev->base_addr);
 #endif
 
 	kfree (dev);
+	pci_set_drvdata(pdev, NULL);
 }
 
 
 static struct pci_driver yellowfin_driver = {
-	name:		YELLOWFIN_MODULE_NAME,
+	name:		"yellowfin",
 	id_table:	yellowfin_pci_tbl,
 	probe:		yellowfin_init_one,
 	remove:		yellowfin_remove_one,
@@ -1380,7 +1392,8 @@
 static int __init yellowfin_init (void)
 {
 	if (debug)					/* Emit version even if no cards detected. */
-		printk(KERN_INFO "%s", version);
+		printk(KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
+		       version1, version2, version3);
 
 	return pci_module_init (&yellowfin_driver);
 }
@@ -1394,12 +1407,12 @@
 
 module_init(yellowfin_init);
 module_exit(yellowfin_cleanup);
-
-
+
 /*
  * Local variables:
- *  compile-command: "gcc -DMODULE -D__KERNEL__  -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  compile-command-alphaLX: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`  -fomit-frame-pointer -fno-strength-reduce -mno-fp-regs -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED"
+ *  compile-command: "gcc -DMODULE -Wall -Wstrict-prototypes -O6 -c yellowfin.c"
+ *  compile-command-alphaLX: "gcc -DMODULE -Wall -Wstrict-prototypes -O2 -c yellowfin.c -fomit-frame-pointer -fno-strength-reduce -mno-fp-regs -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED"
+ *  simple-compile-command: "gcc -DMODULE -O6 -c yellowfin.c"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)