patch-2.3.43 linux/drivers/net/3c59x.c

Next file: linux/drivers/net/8390.c
Previous file: linux/drivers/net/3c527.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.42/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
@@ -1,4 +1,4 @@
-/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
+/* 3c59x.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
 /*
 	Written 1996-1998 by Donald Becker.
 
@@ -12,10 +12,16 @@
 	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
-*/
+
+ Version history:
+ 	0.99H+lk1.0 - Jeff Garzik <jgarzik@mandrakesoft.com>
+		Remove compatibility defines for kernel versions < 2.2.x.
+		Update for new 2.3.x module interface
+		
+ */
 
 static char *version =
-"3c59x.c:v0.99H 11/17/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c59x.c:v0.99H+lk1.0 Feb 9, 2000 The Linux Kernel Team http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
 
 /* "Knobs" that adjust features and parameters. */
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
@@ -49,22 +55,14 @@
 
 #include <linux/config.h>
 #include <linux/version.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/in.h>
+#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
@@ -72,9 +70,6 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)
-#include <linux/bios32.h>
-#endif
 #include <asm/irq.h>			/* For NR_IRQS only. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -86,35 +81,9 @@
 
 #include <linux/delay.h>
 
-#if (LINUX_VERSION_CODE <= 0x20100)
-#ifndef __alpha__
-#define ioremap(a,b) \
-	(((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b))
-#define iounmap(v) \
-	do { if ((u_long)(v) > 0x100000) vfree(v); } while (0)
-#endif
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define	net_device_stats enet_statistics
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20138
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#define le32_to_cpu(val) (val)
-#define cpu_to_le32(val) (val)
-#endif
-#if LINUX_VERSION_CODE < 0x20155
-#define PCI_SUPPORT_VER1
-#else
 #define PCI_SUPPORT_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb (skb, FREE_WRITE);
-#else  /* Grrr, unneeded incompatible change. */
 #define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
 
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
 MODULE_PARM(debug, "i");
@@ -125,7 +94,6 @@
 MODULE_PARM(compaq_ioaddr, "i");
 MODULE_PARM(compaq_irq, "i");
 MODULE_PARM(compaq_device_id, "i");
-#endif
 
 /* Operational parameter that usually are not changed. */
 
@@ -229,12 +197,12 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int drv_flags, io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
 enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
 	   HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, int dev_id, int card_idx);
+static struct net_device *vortex_probe1(struct pci_dev *pdev, long ioaddr, int irq, int dev_id, int card_idx);
 
 static struct pci_id_info pci_tbl[] = {
 	{"3c590 Vortex 10Mbps",			0x10B7, 0x5900, 0xffff,
@@ -426,22 +394,27 @@
 
 struct vortex_private {
 	/* The Rx and Tx rings should be quad-word-aligned. */
-	struct boom_rx_desc rx_ring[RX_RING_SIZE];
-	struct boom_tx_desc tx_ring[TX_RING_SIZE];
+	struct boom_rx_desc* rx_ring;
+	struct boom_tx_desc* tx_ring;
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_ring_dma;
 	/* The addresses of transmit- and receive-in-place skbuffs. */
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
 	struct net_device *next_module;
 	void *priv_addr;
+	dma_addr_t ring_dma;
 	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
 	struct net_device_stats stats;
 	struct sk_buff *tx_skb;		/* Packet being eaten by bus master ctrl.  */
+	dma_addr_t tx_skb_dma;	/* Allocated DMA address for bus master ctrl DMA.   */
 
 	/* PCI configuration space information. */
 	u8 pci_bus, pci_devfn;		/* PCI bus location, for power management. */
 	char *cb_fn_base;			/* CardBus function status addr space. */
 	int chip_id;
+	struct pci_dev *pdev;			/* Device for DMA mapping */
 
 	/* The remainder are related to chip state, mostly media selection. */
 	unsigned long in_interrupt;
@@ -499,6 +472,7 @@
 static void mdio_write(long ioaddr, int phy_id, int location, int value);
 static void vortex_timer(unsigned long arg);
 static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void vortex_tx_timeout(struct net_device *dev);
 static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int vortex_rx(struct net_device *dev);
 static int boomerang_rx(struct net_device *dev);
@@ -518,7 +492,6 @@
 /* A list of all installed Vortex devices, for removing the driver module. */
 static struct net_device *root_vortex_dev = NULL;
 
-#ifdef MODULE
 #ifndef CARDBUS
 /* Variables to work-around the Compaq PCI BIOS32 problem. */
 static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
@@ -532,18 +505,20 @@
 {
 	u16 dev_id, vendor_id;
 	u32 io;
-	u8 bus, devfn, irq;
+	u8 irq;
 	struct net_device *dev;
+	struct pci_dev *pdev;
 	int chip_idx;
 
 	if (loc->bus != LOC_PCI) return NULL;
-	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
-	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
-	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
-	pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
-	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+	pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+	if (!pdev) return NULL;
+	io = pdev->resource[0].start;
+	irq = pdev->irq;
+	vendor_id = pdev->vendor;
+	dev_id = pdev->device;
 	printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
-		   bus, devfn, dev_id);
+		   pdev->bus->number, pdev->devfn, dev_id);
 	io &= ~3;
 	if (io == 0 || irq == 0) {
 		printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
@@ -561,7 +536,7 @@
 			   "vortex_attach().\n", vendor_id, dev_id);
 		return NULL;
 	}
-	dev = vortex_probe1(bus, devfn, io, irq, chip_idx, MAX_UNITS+1);
+	dev = vortex_probe1(pdev, io, irq, chip_idx, MAX_UNITS+1);
 	if (dev) {
 		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
 		strcpy(node->dev_name, dev->name);
@@ -604,7 +579,7 @@
 #endif  /* Cardbus support */
 
 
-int init_module(void)
+static int __init vortex_init_module (void)
 {
 	if (vortex_debug)
 		printk(KERN_INFO "%s", version);
@@ -616,17 +591,6 @@
 #endif
 }
 
-#else
-int tc59x_probe(void)
-{
-	static int scanned=0;
-	if(scanned++)
-		return -ENODEV;
-	printk(KERN_INFO "%s", version);
-	return vortex_scan(pci_tbl);
-}
-#endif  /* not MODULE */
-
 #ifndef CARDBUS
 static int vortex_scan(struct pci_id_info pci_tbl[])
 {
@@ -639,7 +603,7 @@
 	   be best done a central PCI probe dispatch, which wouldn't work
 	   well with the current structure.  So instead we detect 3Com cards
 	   in slot order. */
-	if (pcibios_present()) {
+	if (pci_present()) {
 		static int pci_index = 0;
 		unsigned char pci_bus, pci_device_fn;
 
@@ -647,15 +611,16 @@
 			u16 vendor, device, pci_command, new_command, pwr_cmd;
 			int chip_idx, irq;
 			long ioaddr;
+			struct pci_dev *pdev;
 
 			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
 									&pci_bus, &pci_device_fn)
 				!= PCIBIOS_SUCCESSFUL)
 				break;
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_VENDOR_ID, &vendor);
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_DEVICE_ID, &device);
+			pdev = pci_find_slot (pci_bus, pci_device_fn);
+			if (!pdev) continue;
+			vendor = pdev->vendor;
+			device = pdev->device;
 			for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
 				if (vendor == pci_tbl[chip_idx].vendor_id
 					&& (device & pci_tbl[chip_idx].device_id_mask) ==
@@ -671,21 +636,18 @@
 			}
 
 			/* Power-up the card. */
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-										 0xe0, &pwr_cmd);
+			pci_read_config_word(pdev, 0xe0, &pwr_cmd);
+			
 			if (pwr_cmd & 0x3) {
 				/* Save the ioaddr and IRQ info! */
 				printk(KERN_INFO "  A 3Com network adapter is powered down!"
 					   "  Setting the power state %4.4x->%4.4x.\n",
 					   pwr_cmd, pwr_cmd & ~3);
-				pcibios_write_config_word(pci_bus, pci_device_fn,
-										  0xe0, pwr_cmd & ~3);
+				pci_write_config_word(pdev, 0xe0, pwr_cmd & ~3);
 				printk(KERN_INFO "  Setting the IRQ to %d, IOADDR to %#lx.\n",
 					   irq, ioaddr);
-				pcibios_write_config_byte(pci_bus, pci_device_fn,
-										 PCI_INTERRUPT_LINE, irq);
-				pcibios_write_config_dword(pci_bus, pci_device_fn,
-										  PCI_BASE_ADDRESS_0, ioaddr);
+				pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+				pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, ioaddr);
 			}
 
 			if (ioaddr == 0) {
@@ -700,19 +662,18 @@
 				continue;
 
 			/* Activate the card. */
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_COMMAND, &pci_command);
+			pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+
 			new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
 			if (pci_command != new_command) {
 				printk(KERN_INFO "  The PCI BIOS has not enabled the device "
 					   "at %d/%d. Updating PCI command %4.4x->%4.4x.\n",
 					   pci_bus, pci_device_fn, pci_command, new_command);
-				pcibios_write_config_word(pci_bus, pci_device_fn,
-										  PCI_COMMAND, new_command);
+				pci_write_config_word(pdev, PCI_COMMAND, new_command);
 			}
 
-			dev = vortex_probe1(pci_bus, pci_device_fn, ioaddr, irq,
-								chip_idx, cards_found);
+			dev = vortex_probe1(pdev, ioaddr, irq,
+					    chip_idx, cards_found);
 
 			if (dev) {
 				/* Get and check the latency values.  On the 3c590 series
@@ -722,14 +683,12 @@
 				u8 pci_latency;
 				u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32;
 				
-				pcibios_read_config_byte(pci_bus, pci_device_fn,
-										 PCI_LATENCY_TIMER, &pci_latency);
+				pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 				if (pci_latency < new_latency) {
 					printk(KERN_INFO "%s: Overriding PCI latency"
 						   " timer (CFLT) setting of %d, new value is %d.\n",
 						   dev->name, pci_latency, new_latency);
-					pcibios_write_config_byte(pci_bus, pci_device_fn,
-											  PCI_LATENCY_TIMER, new_latency);
+					pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
 				}
 				dev = 0;
 				cards_found++;
@@ -752,27 +711,33 @@
 			device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
 			if ((device_id & 0xFF00) != 0x5900)
 				continue;
-			vortex_probe1(0, 0, ioaddr, inw(ioaddr + 0xC88) >> 12,
-						  4, cards_found);
+			vortex_probe1(NULL, ioaddr, inw(ioaddr + 0xC88) >> 12,
+				      4, cards_found);
 			cards_found++;
 		}
 	}
 
-#ifdef MODULE
 	/* Special code to work-around the Compaq PCI BIOS32 problem. */
 	if (compaq_ioaddr) {
-		vortex_probe1(0, 0, compaq_ioaddr, compaq_irq,
+		vortex_probe1(NULL, compaq_ioaddr, compaq_irq,
 					  compaq_device_id, cards_found++);
 		dev = 0;
 	}
-#endif
 
 	return cards_found ? 0 : -ENODEV;
 }
 #endif  /* ! Cardbus */
 
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
-					long ioaddr, int irq, int chip_idx, int card_idx)
+/*
+ * vortex_probe1 - initialize one vortex board, after probing
+ *		   has located one during bus scan.
+ *
+ * NOTE: pdev==NULL is a valid condition, indicating
+ * non-PCI (generally EISA) bus device
+ */
+static struct net_device *vortex_probe1(struct pci_dev *pdev,
+					long ioaddr, int irq,
+					int chip_idx, int card_idx)
 {
 	struct vortex_private *vp;
 	int option;
@@ -790,11 +755,8 @@
 	dev->mtu = mtu;
 
 	/* Make certain the descriptor lists are aligned. */
-	{
-		void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);
-		vp =  (void *)(((long)mem + 15) & ~15);
-		vp->priv_addr = mem;
-	}
+	vp = kmalloc(sizeof(*vp), GFP_KERNEL);
+
 	memset(vp, 0, sizeof(*vp));
 	dev->priv = vp;
 
@@ -802,8 +764,18 @@
 	root_vortex_dev = dev;
 
 	vp->chip_id = chip_idx;
-	vp->pci_bus = pci_bus;
-	vp->pci_devfn = pci_devfn;
+	vp->pci_bus = pdev == NULL ? 0 : pdev->bus->number;
+	vp->pci_devfn = pdev == NULL ? 0 : pdev->devfn;
+	vp->pdev = pdev;
+
+	vp->priv_addr = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
+					     + sizeof(struct boom_tx_desc) * TX_RING_SIZE
+					     + 15, &vp->ring_dma);
+	/* Make sure rings are 16 byte aligned. */
+	vp->rx_ring = (void *)(((long)vp->priv_addr + 15) & ~15);
+	vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE);
+	vp->rx_ring_dma = (vp->ring_dma + 15) & ~15;
+	vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE;
 
 	/* The lower four bits are the media type. */
 	if (dev->mem_start)
@@ -872,8 +844,7 @@
 
 	if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
 		u32 fn_st_addr;			/* Cardbus function status space */
-		pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
-								  &fn_st_addr);
+		fn_st_addr = pdev == NULL ? 0 : pdev->resource[2].start;
 		if (fn_st_addr)
 			vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);
 		printk("%s: CardBus functions mapped %8.8x->%p (PCMCIA committee"
@@ -963,6 +934,8 @@
 	/* The 3c59x-specific entries in the device structure. */
 	dev->open = &vortex_open;
 	dev->hard_start_xmit = &vortex_start_xmit;
+	dev->tx_timeout = &vortex_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT; 
 	dev->stop = &vortex_close;
 	dev->get_stats = &vortex_get_stats;
 	dev->do_ioctl = &vortex_ioctl;
@@ -1106,7 +1079,7 @@
 			printk(KERN_DEBUG "%s:  Filling in the Rx ring.\n", dev->name);
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			struct sk_buff *skb;
-			vp->rx_ring[i].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[i+1]));
+			vp->rx_ring[i].next = cpu_to_le32(vp->rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1));
 			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
 			vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);
 			skb = dev_alloc_skb(PKT_BUF_SZ);
@@ -1115,11 +1088,11 @@
 				break;			/* Bad news!  */
 			skb->dev = dev;			/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail));
+			vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ));
 		}
 		/* Wrap the ring. */
-		vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0]));
-		outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
+		vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma);
+		outl(vp->rx_ring_dma, ioaddr + UpListPtr);
 	}
 	if (vp->full_bus_master_tx) { 		/* Boomerang bus master Tx. */
 		dev->hard_start_xmit = &boomerang_start_xmit;
@@ -1135,9 +1108,6 @@
 	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
 	vp->in_interrupt = 0;
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
 
 	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
 	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
@@ -1157,6 +1127,8 @@
 	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
 		writel(0x8000, vp->cb_fn_base + 4);
 
+	netif_start_queue(dev);
+
 	MOD_INC_USE_COUNT;
 
 	return 0;
@@ -1313,11 +1285,11 @@
 			printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n",
 				   dev->name);
 		if (vp->cur_tx - vp->dirty_tx > 0  &&  inl(ioaddr + DownListPtr) == 0)
-			outl(virt_to_bus(&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]),
+			outl(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
 				 ioaddr + DownListPtr);
 		if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) {
 			vp->tx_full = 0;
-			clear_bit(0, (void*)&dev->tbusy);
+			netif_wake_queue(dev);
 		}
 		outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
 		outw(DownUnstall, ioaddr + EL3_CMD);
@@ -1431,27 +1403,23 @@
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start >= TX_TIMEOUT)
-			vortex_tx_timeout(dev);
-		return 1;
-	}
+	netif_stop_queue(dev);
 
 	/* Put out the doubleword header... */
 	outl(skb->len, ioaddr + TX_FIFO);
 	if (vp->bus_master) {
 		/* Set the bus-master controller to transfer the packet. */
-		outl(virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr);
-		outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+		int len = (skb->len + 3) & ~3;
+		outl(vp->tx_skb_dma = pci_map_single(vp->pdev, skb->data, len), ioaddr + Wn7_MasterAddr);
+		outw(len, ioaddr + Wn7_MasterLen);
 		vp->tx_skb = skb;
 		outw(StartDMADown, ioaddr + EL3_CMD);
-		/* dev->tbusy will be cleared at the DMADone interrupt. */
 	} else {
 		/* ... and the packet rounded to a doubleword. */
 		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
 		DEV_FREE_SKB(skb);
 		if (inw(ioaddr + TxFree) > 1536) {
-			clear_bit(0, (void*)&dev->tbusy);
+			netif_wake_queue(dev);
 		} else
 			/* Interrupt us when the FIFO has room for max-sized packet. */
 			outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
@@ -1493,11 +1461,9 @@
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start >= TX_TIMEOUT)
-			vortex_tx_timeout(dev);
-		return 1;
-	} else {
+	netif_stop_queue(dev);
+
+	if (1) {
 		/* Calculate the next Tx descriptor entry. */
 		int entry = vp->cur_tx % TX_RING_SIZE;
 		struct boom_tx_desc *prev_entry =
@@ -1516,10 +1482,11 @@
 		}
 		vp->tx_skbuff[entry] = skb;
 		vp->tx_ring[entry].next = 0;
-		vp->tx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->data));
+		vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, skb->len));
 		vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
 		vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
 
+		/* Hmm... And some poor people try to use it on SMP machines 8) */
 		save_flags(flags);
 		cli();
 		outw(DownStall, ioaddr + EL3_CMD);
@@ -1527,20 +1494,20 @@
 		for (i = 600; i >= 0 ; i--)
 			if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
 				break;
-		prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));
+		prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc));
 		if (inl(ioaddr + DownListPtr) == 0) {
-			outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
+			outl(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
 			queued_packet++;
 		}
 		outw(DownUnstall, ioaddr + EL3_CMD);
 		restore_flags(flags);
 
 		vp->cur_tx++;
-		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
+		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) {
 			vp->tx_full = 1;
-		else {					/* Clear previous interrupt enable. */
+		} else {					/* Clear previous interrupt enable. */
 			prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
-			clear_bit(0, (void*)&dev->tbusy);
+			netif_wake_queue(dev);
 		}
 		dev->trans_start = jiffies;
 		vp->stats.tx_bytes += skb->len;
@@ -1558,23 +1525,6 @@
 	int latency, status;
 	int work_done = max_interrupt_work;
 
-#if defined(__i386__)
-	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		dev->interrupt = 0;	/* Avoid halting machine. */
-		return;
-	}
-#else
-	if (dev->interrupt) {
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-		return;
-	}
-	dev->interrupt = 1;
-#endif
-
-	dev->interrupt = 1;
 	ioaddr = dev->base_addr;
 	latency = inb(ioaddr + Timer);
 	status = inw(ioaddr + EL3_STATUS);
@@ -1598,8 +1548,7 @@
 				printk(KERN_DEBUG "	TX room bit was handled.\n");
 			/* There's room in the FIFO for a full-sized packet. */
 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-			clear_bit(0, (void*)&dev->tbusy);
-			mark_bh(NET_BH);
+			netif_wake_queue(dev);
 		}
 
 		if (status & DownComplete) {
@@ -1608,10 +1557,13 @@
 			while (vp->cur_tx - dirty_tx > 0) {
 				int entry = dirty_tx % TX_RING_SIZE;
 				if (inl(ioaddr + DownListPtr) ==
-					virt_to_bus(&vp->tx_ring[entry]))
+					vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc))
 					break;			/* It still hasn't been processed. */
 				if (vp->tx_skbuff[entry]) {
-					DEV_FREE_SKB(vp->tx_skbuff[entry]);
+					struct sk_buff *skb = vp->tx_skbuff[entry];
+					
+					pci_unmap_single(vp->pdev, le32_to_cpu(vp->tx_ring[entry].addr), skb->len);
+					dev_kfree_skb_irq(vp->tx_skbuff[entry]);
 					vp->tx_skbuff[entry] = 0;
 				}
 				/* vp->stats.tx_packets++;  Counted below. */
@@ -1621,17 +1573,16 @@
 			outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
 			if (vp->tx_full && (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
 				vp->tx_full= 0;
-				clear_bit(0, (void*)&dev->tbusy);
-				mark_bh(NET_BH);
+				netif_wake_queue(dev);
 			}
 		}
 		if (status & DMADone) {
 			if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
 				outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
-				DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
+				pci_unmap_single(vp->pdev, vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3);
+				dev_kfree_skb_irq(vp->tx_skb); /* Release the transfered buffer */
 				if (inw(ioaddr + TxFree) > 1536) {
-					clear_bit(0, (void*)&dev->tbusy);
-					mark_bh(NET_BH);
+					netif_wake_queue(dev);
 				} else /* Interrupt when FIFO has room for max-sized packet. */
 					outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
 			}
@@ -1669,11 +1620,6 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
 			   dev->name, status);
 
-#if defined(__i386__)
-	clear_bit(0, (void*)&dev->interrupt);
-#else
-	dev->interrupt = 0;
-#endif
 	return;
 }
 
@@ -1713,12 +1659,14 @@
 				/* 'skb_put()' points to the start of sk_buff data area. */
 				if (vp->bus_master &&
 					! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) {
-					outl(virt_to_bus(skb_put(skb, pkt_len)),
-						 ioaddr + Wn7_MasterAddr);
+					dma_addr_t dma = pci_map_single(vp->pdev, skb_put(skb, pkt_len),
+									   pkt_len);
+					outl(dma, ioaddr + Wn7_MasterAddr);
 					outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
 					outw(StartDMAUp, ioaddr + EL3_CMD);
 					while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
 						;
+					pci_unmap_single(vp->pdev, dma, pkt_len);
 				} else {
 					insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
 						 (pkt_len + 3) >> 2);
@@ -1779,6 +1727,7 @@
 			/* The packet length: up to 4.5K!. */
 			int pkt_len = rx_status & 0x1fff;
 			struct sk_buff *skb;
+			dma_addr_t dma = le32_to_cpu(vp->rx_ring[entry].addr);
 
 			vp->stats.rx_bytes += pkt_len;
 			if (vortex_debug > 4)
@@ -1791,23 +1740,18 @@
 				&& (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
 				skb->dev = dev;
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+				pci_dma_sync_single(vp->pdev, dma, PKT_BUF_SZ);
 				/* 'skb_put()' points to the start of sk_buff data area. */
 				memcpy(skb_put(skb, pkt_len),
-					   bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
+					   vp->rx_skbuff[entry]->tail,
 					   pkt_len);
 				rx_copy++;
 			} else {
-				void *temp;
 				/* Pass up the skbuff already on the Rx ring. */
 				skb = vp->rx_skbuff[entry];
 				vp->rx_skbuff[entry] = NULL;
-				temp = skb_put(skb, pkt_len);
-				/* Remove this checking code for final release. */
-				if (bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)) != temp)
-					printk(KERN_ERR "%s: Warning -- the skbuff addresses do not match"
-						   " in boomerang_rx: %p vs. %p.\n", dev->name,
-						   bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
-						   temp);
+				skb_put(skb, pkt_len);
+				pci_unmap_single(vp->pdev, dma, PKT_BUF_SZ);
 				rx_nocopy++;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
@@ -1836,7 +1780,7 @@
 				break;			/* Bad news!  */
 			skb->dev = dev;			/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->tail));
+			vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ));
 			vp->rx_skbuff[entry] = skb;
 		}
 		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
@@ -1852,8 +1796,7 @@
 	long ioaddr = dev->base_addr;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (vortex_debug > 1) {
 		printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
@@ -1885,9 +1828,7 @@
 		outl(0, ioaddr + UpListPtr);
 		for (i = 0; i < RX_RING_SIZE; i++)
 			if (vp->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
-				vp->rx_skbuff[i]->free = 1;
-#endif
+				pci_unmap_single(vp->pdev, le32_to_cpu(vp->rx_ring[i].addr), PKT_BUF_SZ);
 				DEV_FREE_SKB(vp->rx_skbuff[i]);
 				vp->rx_skbuff[i] = 0;
 			}
@@ -1896,7 +1837,10 @@
 		outl(0, ioaddr + DownListPtr);
 		for (i = 0; i < TX_RING_SIZE; i++)
 			if (vp->tx_skbuff[i]) {
-				DEV_FREE_SKB(vp->tx_skbuff[i]);
+				struct sk_buff *skb = vp->tx_skbuff[i];
+
+				pci_unmap_single(vp->pdev, le32_to_cpu(vp->tx_ring[i].addr), skb->len);
+				DEV_FREE_SKB(skb);
 				vp->tx_skbuff[i] = 0;
 			}
 	}
@@ -1911,7 +1855,7 @@
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	unsigned long flags;
 
-	if (dev->start) {
+	if (test_bit(LINK_STATE_START, &dev->state)) {
 		save_flags(flags);
 		cli();
 		update_stats(dev->base_addr, dev);
@@ -2097,9 +2041,8 @@
 	return;
 }
 
-
-#ifdef MODULE
-void cleanup_module(void)
+
+static void __exit vortex_cleanup_module (void)
 {
 	struct net_device *next_dev;
 
@@ -2116,13 +2059,18 @@
 		release_region(root_vortex_dev->base_addr,
 					   pci_tbl[vp->chip_id].io_size);
 		kfree(root_vortex_dev);
-		kfree(vp->priv_addr);
+		pci_free_consistent(vp->pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
+					    + sizeof(struct boom_tx_desc) * TX_RING_SIZE
+					    + 15, vp->priv_addr, vp->ring_dma);
+		kfree(vp);
 		root_vortex_dev = next_dev;
 	}
 }
 
-#endif  /* MODULE */
-
+module_init(vortex_init_module);
+module_exit(vortex_cleanup_module);
+
+
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"

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