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

Next file: linux/drivers/net/eql.c
Previous file: linux/drivers/net/eexpress.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.2/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
@@ -1,6 +1,6 @@
 /* epic100.c: A SMC 83c170 EPIC/100 Fast Ethernet driver for Linux. */
 /*
-	Written/copyright 1997-2000 by Donald Becker.
+	Written/copyright 1997-2001 by Donald Becker.
 
 	This software may be used and distributed according to the terms of
 	the GNU General Public License (GPL), incorporated herein by reference.
@@ -37,15 +37,19 @@
 	* Fix locking (jgarzik)
 	* Limit 83c175 probe to ethernet-class PCI devices (rgooch)
 
+	LK1.1.6:
+	* Merge becker version 1.11
+	* Move pci_enable_device before any PCI BAR len checks
+
 */
 
 /* These identify the driver base version and may not be removed. */
 static const char version[] =
-"epic100.c:v1.09 5/29/2000 Written by Donald Becker <becker@scyld.com>\n";
+"epic100.c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>\n";
 static const char version2[] =
 "  http://www.scyld.com/network/epic100.html\n";
 static const char version3[] =
-" (unofficial 2.4.x kernel port, version 1.1.5, September 7, 2000)\n";
+" (unofficial 2.4.x kernel port, version 1.1.6, January 11, 2001)\n";
 
 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
@@ -61,7 +65,7 @@
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
-static int rx_copybreak = 0;
+static int rx_copybreak;
 
 /* Operational parameters that are set at compile time. */
 
@@ -73,6 +77,8 @@
 #define TX_RING_SIZE	16
 #define TX_QUEUE_LEN	10		/* Limit ring entries actually used.  */
 #define RX_RING_SIZE	32
+#define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct epic_tx_desc)
+#define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct epic_rx_desc)
 
 /* Operational parameters that usually are not changed. */
 /* Time in jiffies before concluding the transmitter is hung. */
@@ -161,14 +167,13 @@
 enum chip_capability_flags { MII_PWRDWN=1, TYPE2_INTR=2, NO_MII=4 };
 
 #define EPIC_TOTAL_SIZE 0x100
+#define USE_IO_OPS 1
 #ifdef USE_IO_OPS
 #define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR0
 #else
 #define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR1
 #endif
 
-#define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
-
 typedef enum {
 	SMSC_83C170_0,
 	SMSC_83C170,
@@ -185,7 +190,7 @@
 
 
 /* indexed by chip_t */
-static struct epic_chip_info epic_chip_info[] __devinitdata = {
+static struct epic_chip_info pci_id_tbl[] = {
 	{ "SMSC EPIC/100 83c170",
 	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, TYPE2_INTR | NO_MII | MII_PWRDWN },
 	{ "SMSC EPIC/100 83c170",
@@ -269,16 +274,18 @@
 	DescOwn=0x8000,
 };
 
-
+#define PRIV_ALIGN	15 	/* Required alignment mask */
 struct epic_private {
-	/* Tx and Rx rings first so that they remain paragraph aligned. */
-	struct epic_rx_desc rx_ring[RX_RING_SIZE];
-	struct epic_tx_desc tx_ring[TX_RING_SIZE];
+	struct epic_rx_desc *rx_ring;
+	struct epic_tx_desc *tx_ring;
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
 	/* The addresses of receive-in-place skbuffs. */
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
 
+	dma_addr_t tx_ring_dma;
+	dma_addr_t rx_ring_dma;
+
 	/* Ring pointers. */
 	spinlock_t lock;				/* Group with Tx control cache line. */
 	unsigned int cur_tx, dirty_tx;
@@ -290,7 +297,7 @@
 	long last_rx_time;					/* Last Rx, in jiffies. */
 
 	struct pci_dev *pci_dev;			/* PCI bus location. */
-	int chip_flags;
+	int chip_id, chip_flags;
 
 	struct net_device_stats stats;
 	struct timer_list timer;			/* Media selection timer. */
@@ -301,7 +308,7 @@
 	int mii_phy_cnt;
 	unsigned int tx_full:1;				/* The Tx queue is full. */
 	unsigned int full_duplex:1;			/* Current duplex setting. */
-	unsigned int force_fd:1;			/* Full-duplex operation requested. */
+	unsigned int duplex_lock:1;			/* Duplex forced by the user. */
 	unsigned int default_port:4;		/* Last dev->if_port value. */
 	unsigned int media2:4;				/* Secondary monitored media port. */
 	unsigned int medialock:1;			/* Don't sense media type. */
@@ -310,8 +317,8 @@
 
 static int epic_open(struct net_device *dev);
 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);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *dev, int phy_id, int loc, int val);
 static void epic_restart(struct net_device *dev);
 static void epic_timer(unsigned long data);
 static void epic_tx_timeout(struct net_device *dev);
@@ -330,13 +337,15 @@
 				    const struct pci_device_id *ent)
 {
 	static int card_idx = -1;
-	static int printed_version = 0;
+	static int printed_version;
+	long ioaddr;
+	int chip_idx = (int) ent->driver_data;
+	int irq;
 	struct net_device *dev;
 	struct epic_private *ep;
 	int i, option = 0, duplex = 0;
-	struct epic_chip_info *ci = &epic_chip_info[ent->driver_data];
-	long ioaddr;
-	int chip_idx = (int) ent->driver_data;
+	void *ring_space;
+	dma_addr_t ring_dma;
 
 	card_idx++;
 	
@@ -344,37 +353,27 @@
 		printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
 			version, version2, version3);
 	
-	if ((pci_resource_len(pdev, 0) < ci->io_size) ||
-	    (pci_resource_len(pdev, 1) < ci->io_size)) {
+	i = pci_enable_device(pdev);
+	if (i)
+		return i;
+	irq = pdev->irq;
+
+	if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) {
 		printk (KERN_ERR "card %d: no PCI region space\n", card_idx);
 		return -ENODEV;
 	}
 	
-	i = pci_enable_device(pdev);
-	if (i)
-		return i;
-		
 	pci_set_master(pdev);
 
-	dev = init_etherdev(NULL, sizeof (*ep));
+	dev = alloc_etherdev(sizeof (*ep));
 	if (!dev) {
 		printk (KERN_ERR "card %d: no memory for eth device\n", card_idx);
 		return -ENOMEM;
 	}
+	SET_MODULE_OWNER(dev);
 
-	/* request 100% of both regions 0 and 1, just to make
-	 * sure noone else steals our regions while we are talking
-	 * to them */
-	if (!request_region (pci_resource_start (pdev, 0),
-			     pci_resource_len (pdev, 0), dev->name)) {
-		printk (KERN_ERR "epic100 %d: I/O region busy\n", card_idx);
+	if (pci_request_regions(pdev, "epic100"))
 		goto err_out_free_netdev;
-	}
-	if (!request_mem_region (pci_resource_start (pdev, 1),
-				 pci_resource_len (pdev, 1), dev->name)) {
-		printk (KERN_ERR "epic100 %d: I/O region busy\n", card_idx);
-		goto err_out_free_pio;
-	}
 
 #ifdef USE_IO_OPS
 	ioaddr = pci_resource_start (pdev, 0);
@@ -383,10 +382,25 @@
 	ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
 	if (!ioaddr) {
 		printk (KERN_ERR "epic100 %d: ioremap failed\n", card_idx);
-		goto err_out_free_mmio;
+		goto err_out_free_res;
 	}
 #endif
 
+	pci_set_drvdata(pdev, dev);
+	ep = dev->priv;
+
+	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_iounmap;
+	ep->tx_ring = (struct epic_tx_desc *)ring_space;
+	ep->tx_ring_dma = ring_dma;
+
+	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_unmap_tx;
+	ep->rx_ring = (struct epic_rx_desc *)ring_space;
+	ep->rx_ring_dma = ring_dma;
+
 	if (dev->mem_start) {
 		option = dev->mem_start;
 		duplex = (dev->mem_start & 16) ? 1 : 0;
@@ -397,69 +411,62 @@
 			duplex = full_duplex[card_idx];
 	}
 
-	pdev->driver_data = dev;
-
 	dev->base_addr = ioaddr;
-	dev->irq = pdev->irq;
+	dev->irq = irq;
 
-	ep = dev->priv;
-	ep->pci_dev = pdev;
-	ep->chip_flags = ci->drv_flags;
 	spin_lock_init (&ep->lock);
 
-	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
-		   dev->name, ci->name, ioaddr, dev->irq);
-
 	/* Bring the chip out of low-power mode. */
 	outl(0x4200, ioaddr + GENCTL);
 	/* Magic?!  If we don't set this bit the MII interface won't work. */
 	outl(0x0008, ioaddr + TEST1);
 
 	/* Turn on the MII transceiver. */
-	outl(0x12, ioaddr + MIICfg);
+	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
 	if (chip_idx == 1)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 	outl(0x0200, ioaddr + GENCTL);
 
-	/* This could also be read from the EEPROM. */
+	/* Note: the '175 does not have a serial EEPROM. */
 	for (i = 0; i < 3; i++)
 		((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));
 
-	for (i = 0; i < 5; i++)
-		printk("%2.2x:", dev->dev_addr[i]);
-	printk("%2.2x.\n", dev->dev_addr[i]);
-
 	if (debug > 2) {
-		printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name);
+		printk(KERN_DEBUG "epic100(%s): EEPROM contents\n",
+		       pdev->slot_name);
 		for (i = 0; i < 64; i++)
 			printk(" %4.4x%s", read_eeprom(ioaddr, i),
 				   i % 16 == 15 ? "\n" : "");
 	}
 
+	ep->pci_dev = pdev;
+	ep->chip_id = chip_idx;
+	ep->chip_flags = pci_id_tbl[chip_idx].drv_flags;
+
 	/* Find the connected MII xcvrs.
 	   Doing this in open() would allow detecting external xcvrs later, but
 	   takes much time and no cards have external MII. */
 	{
 		int phy, phy_idx = 0;
 		for (phy = 1; phy < 32 && phy_idx < sizeof(ep->phys); phy++) {
-			int mii_status = mdio_read(ioaddr, phy, 1);
+			int mii_status = mdio_read(dev, phy, 1);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				ep->phys[phy_idx++] = phy;
-				printk(KERN_INFO "%s: MII transceiver #%d control "
+				printk(KERN_INFO "epic100(%s): MII transceiver #%d control "
 					   "%4.4x status %4.4x.\n",
-					   dev->name, phy, mdio_read(ioaddr, phy, 0), mii_status);
+					   pdev->slot_name, phy, mdio_read(dev, phy, 0), mii_status);
 			}
 		}
 		ep->mii_phy_cnt = phy_idx;
 		if (phy_idx != 0) {
 			phy = ep->phys[0];
-			ep->advertising = mdio_read(ioaddr, phy, 4);
-			printk( KERN_INFO "%s: Autonegotiation advertising %4.4x link "
-					"partner %4.4x.\n",
-					dev->name, ep->advertising, mdio_read(ioaddr, phy, 5));
+			ep->advertising = mdio_read(dev, phy, 4);
+			printk(KERN_INFO "epic100(%s): Autonegotiation advertising %4.4x link "
+				   "partner %4.4x.\n",
+				   pdev->slot_name, ep->advertising, mdio_read(dev, phy, 5));
 		} else if ( ! (ep->chip_flags & NO_MII)) {
-			printk(KERN_WARNING "%s: ***WARNING***: No MII transceiver found!\n",
-				   dev->name);
+			printk(KERN_WARNING "epic100(%s): ***WARNING***: No MII transceiver found!\n",
+			       pdev->slot_name);
 			/* Use the known PHY address of the EPII. */
 			ep->phys[0] = 3;
 		}
@@ -471,7 +478,11 @@
 	outl(0x0008, ioaddr + GENCTL);
 
 	/* The lower four bits are the media type. */
-	ep->force_fd = duplex;
+	if (duplex) {
+		ep->duplex_lock = ep->full_duplex = 1;
+		printk(KERN_INFO "epic100(%s):  Forced full duplex operation requested.\n",
+		       pdev->slot_name);
+	}
 	dev->if_port = ep->default_port = option;
 	if (ep->default_port)
 		ep->medialock = 1;
@@ -486,18 +497,27 @@
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->tx_timeout = &epic_tx_timeout;
 
+	i = register_netdev(dev);
+	if (i)
+		goto err_out_unmap_tx;
+
+	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
+		   dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq);
+	for (i = 0; i < 5; i++)
+		printk("%2.2x:", dev->dev_addr[i]);
+	printk("%2.2x.\n", dev->dev_addr[i]);
+
 	return 0;
 
+err_out_unmap_tx:
+	pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
+err_out_iounmap:
 #ifndef USE_IO_OPS
-err_out_free_mmio:
-	release_mem_region (pci_resource_start (pdev, 1),
-			    pci_resource_len (pdev, 1));
+	iounmap(ioaddr);
+err_out_free_res:
 #endif
-err_out_free_pio:
-	release_region (pci_resource_start (pdev, 0),
-			pci_resource_len (pdev, 0));
+	pci_release_regions(pdev);
 err_out_free_netdev:
-	unregister_netdev(dev);
 	kfree(dev);
 	return -ENODEV;
 }
@@ -514,7 +534,7 @@
 #define EE_ENB			(0x0001 | EE_CS)
 
 /* Delay between EEPROM clock transitions.
-   No extra delay is needed with 33Mhz PCI, but 66Mhz is untested.
+   This serves to flush the operation to the PCI bus.
  */
 
 #define eeprom_delay()	inl(ee_addr)
@@ -561,25 +581,38 @@
 
 #define MII_READOP		1
 #define MII_WRITEOP		2
-static int mdio_read(long ioaddr, int phy_id, int location)
+static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
+	long ioaddr = dev->base_addr;
+	int read_cmd = (phy_id << 9) | (location << 4) | MII_READOP;
 	int i;
 
-	outl((phy_id << 9) | (location << 4) | MII_READOP, ioaddr + MIICtrl);
-	/* Typical operation takes < 50 ticks. */
-	for (i = 4000; i > 0; i--)
-		if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0)
+	outl(read_cmd, ioaddr + MIICtrl);
+	/* Typical operation takes 25 loops. */
+	for (i = 400; i > 0; i--) {
+		barrier();
+		if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0) {
+			/* Work around read failure bug. */
+			if (phy_id == 1 && location < 6
+				&& inw(ioaddr + MIIData) == 0xffff) {
+				outl(read_cmd, ioaddr + MIICtrl);
+				continue;
+			}
 			return inw(ioaddr + MIIData);
+		}
+	}
 	return 0xffff;
 }
 
-static void mdio_write(long ioaddr, int phy_id, int location, int value)
+static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
 {
+	long ioaddr = dev->base_addr;
 	int i;
 
 	outw(value, ioaddr + MIIData);
-	outl((phy_id << 9) | (location << 4) | MII_WRITEOP, ioaddr + MIICtrl);
-	for (i = 10000; i > 0; i--) {
+	outl((phy_id << 9) | (loc << 4) | MII_WRITEOP, ioaddr + MIICtrl);
+	for (i = 10000; i > 0; i--) { 
+		barrier();
 		if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0)
 			break;
 	}
@@ -589,27 +622,21 @@
 
 static int epic_open(struct net_device *dev)
 {
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
 	int i;
 	int retval;
 
-	ep->full_duplex = ep->force_fd;
-
 	/* Soft reset the chip. */
 	outl(0x4001, ioaddr + GENCTL);
 
-	MOD_INC_USE_COUNT;
-
-	if ((retval = request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, dev->name, dev))) {
-		MOD_DEC_USE_COUNT;
+	if ((retval = request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, dev->name, dev)))
 		return retval;
-	}
 
 	epic_init_ring(dev);
 
 	outl(0x4000, ioaddr + GENCTL);
-	/* This next magic! line by Ken Yamaguchi.. ?? */
+	/* This magic is documented in SMSC app note 7.15 */
 	outl(0x0008, ioaddr + TEST1);
 
 	/* Pull the chip out of low-power mode, enable interrupts, and set for
@@ -617,7 +644,7 @@
 	   required by the details of which bits are reset and the transceiver
 	   wiring on the Ositech CardBus card.
 	*/
-	outl(0x12, ioaddr + MIICfg);
+	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
 	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
@@ -639,21 +666,20 @@
 
 	if (media2miictl[dev->if_port & 15]) {
 		if (ep->mii_phy_cnt)
-			mdio_write(ioaddr, ep->phys[0], 0, media2miictl[dev->if_port&15]);
+			mdio_write(dev, ep->phys[0], 0, media2miictl[dev->if_port&15]);
 		if (dev->if_port == 1) {
 			if (debug > 1)
 				printk(KERN_INFO "%s: Using the 10base2 transceiver, MII "
 					   "status %4.4x.\n",
-					   dev->name, mdio_read(ioaddr, ep->phys[0], 1));
-			outl(0x13, ioaddr + MIICfg);
+					   dev->name, mdio_read(dev, ep->phys[0], 1));
 		}
 	} else {
-		int mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
+		int mii_reg5 = mdio_read(dev, ep->phys[0], 5);
 		if (mii_reg5 != 0xffff) {
 			if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)
 				ep->full_duplex = 1;
 			else if (! (mii_reg5 & 0x4000))
-				mdio_write(ioaddr, ep->phys[0], 0, 0x1200);
+				mdio_write(dev, ep->phys[0], 0, 0x1200);
 			if (debug > 1)
 				printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
 					   " register read of %4.4x.\n", dev->name,
@@ -663,8 +689,8 @@
 	}
 
 	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
-	outl(virt_to_bus(ep->rx_ring), ioaddr + PRxCDAR);
-	outl(virt_to_bus(ep->tx_ring), ioaddr + PTxCDAR);
+	outl(ep->rx_ring_dma, ioaddr + PRxCDAR);
+	outl(ep->tx_ring_dma, ioaddr + PTxCDAR);
 
 	/* Start the chip's Rx process. */
 	set_rx_mode(dev);
@@ -700,7 +726,7 @@
 static void epic_pause(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 
 	netif_stop_queue (dev);
 	
@@ -723,17 +749,19 @@
 static void epic_restart(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 	int i;
 
-	printk(KERN_DEBUG "%s: Restarting the EPIC chip, Rx %d/%d Tx %d/%d.\n",
-		   dev->name, ep->cur_rx, ep->dirty_rx, ep->dirty_tx, ep->cur_tx);
 	/* Soft reset the chip. */
-	outl(0x0001, ioaddr + GENCTL);
+	outl(0x4001, ioaddr + GENCTL);
 
+	printk(KERN_DEBUG "%s: Restarting the EPIC chip, Rx %d/%d Tx %d/%d.\n",
+		   dev->name, ep->cur_rx, ep->dirty_rx, ep->dirty_tx, ep->cur_tx);
 	udelay(1);
-	/* Duplicate code from epic_open(). */
-	outl(0x0008, ioaddr + TEST1);
+
+	/* This magic is documented in SMSC app note 7.15 */
+	for (i = 16; i > 0; i--)
+		outl(0x0008, ioaddr + TEST1);
 
 #if defined(__powerpc__) || defined(__sparc__)		/* Big endian */
 	outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
@@ -750,9 +778,10 @@
 	ep->tx_threshold = TX_FIFO_THRESH;
 	outl(ep->tx_threshold, ioaddr + TxThresh);
 	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
-	outl(virt_to_bus(&ep->rx_ring[ep->cur_rx%RX_RING_SIZE]), ioaddr + PRxCDAR);
-	outl(virt_to_bus(&ep->tx_ring[ep->dirty_tx%TX_RING_SIZE]),
-		 ioaddr + PTxCDAR);
+	outl(ep->rx_ring_dma + (ep->cur_rx%RX_RING_SIZE)*
+		sizeof(struct epic_rx_desc), ioaddr + PRxCDAR);
+	outl(ep->tx_ring_dma + (ep->dirty_tx%TX_RING_SIZE)*
+		 sizeof(struct epic_tx_desc), ioaddr + PTxCDAR);
 
 	/* Start the chip's Rx process. */
 	set_rx_mode(dev);
@@ -770,16 +799,34 @@
 	return;
 }
 
-static void epic_timer(unsigned long data)
+static void check_media(struct net_device *dev)
 {
-	struct net_device *dev = (struct net_device *)data;
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
-	int next_tick = 60*HZ;
-	int mii_reg5 = ep->mii_phy_cnt ? mdio_read(ioaddr, ep->phys[0], 5) : 0;
+	int mii_reg5 = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], 5) : 0;
 	int negotiated = mii_reg5 & ep->advertising;
 	int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
 
+	if (ep->duplex_lock)
+		return;
+	if (mii_reg5 == 0xffff)		/* Bogus read */
+		return;
+	if (ep->full_duplex != duplex) {
+		ep->full_duplex = duplex;
+		printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
+			   " partner capability of %4.4x.\n", dev->name,
+			   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
+		outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	}
+}
+
+static void epic_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct epic_private *ep = dev->priv;
+	long ioaddr = dev->base_addr;
+	int next_tick = 5*HZ;
+
 	if (debug > 3) {
 		printk(KERN_DEBUG "%s: Media monitor tick, Tx status %8.8x.\n",
 			   dev->name, (int)inl(ioaddr + TxSTAT));
@@ -789,15 +836,7 @@
 			   (int)inl(ioaddr + INTSTAT), (int)inl(ioaddr + RxSTAT));
 	}
 
-	if (! ep->force_fd) {
-		if (ep->full_duplex != duplex) {
-			ep->full_duplex = duplex;
-			printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
-				   " partner capability of %4.4x.\n", dev->name,
-				   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
-			outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
-		}
-	}
+	check_media(dev);
 
 	ep->timer.expires = jiffies + next_tick;
 	add_timer(&ep->timer);
@@ -805,7 +844,7 @@
 
 static void epic_tx_timeout(struct net_device *dev)
 {
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
 
 	if (debug > 0) {
@@ -827,13 +866,14 @@
 
 	dev->trans_start = jiffies;
 	ep->stats.tx_errors++;
-	return;
+	if (!ep->tx_full)
+		netif_wake_queue(dev);
 }
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void epic_init_ring(struct net_device *dev)
 {
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 	int i;
 
 	ep->tx_full = 0;
@@ -847,11 +887,12 @@
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		ep->rx_ring[i].rxstatus = 0;
 		ep->rx_ring[i].buflength = cpu_to_le32(ep->rx_buf_sz);
-		ep->rx_ring[i].next = virt_to_le32desc(&ep->rx_ring[i+1]);
+		ep->rx_ring[i].next = ep->rx_ring_dma + 
+				      (i+1)*sizeof(struct epic_rx_desc);
 		ep->rx_skbuff[i] = 0;
 	}
 	/* Mark the last entry as wrapping the ring. */
-	ep->rx_ring[i-1].next = virt_to_le32desc(&ep->rx_ring[0]);
+	ep->rx_ring[i-1].next = ep->rx_ring_dma;
 
 	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
@@ -861,7 +902,8 @@
 			break;
 		skb->dev = dev;			/* Mark as being used by this device. */
 		skb_reserve(skb, 2);	/* 16 byte align the IP header. */
-		ep->rx_ring[i].bufaddr = virt_to_le32desc(skb->tail);
+		ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev, 
+			skb->tail, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 		ep->rx_ring[i].rxstatus = cpu_to_le32(DescOwn);
 	}
 	ep->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -871,29 +913,31 @@
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		ep->tx_skbuff[i] = 0;
 		ep->tx_ring[i].txstatus = 0x0000;
-		ep->tx_ring[i].next = virt_to_le32desc(&ep->tx_ring[i+1]);
+		ep->tx_ring[i].next = ep->tx_ring_dma + 
+			(i+1)*sizeof(struct epic_tx_desc);
 	}
-	ep->tx_ring[i-1].next = virt_to_le32desc(&ep->tx_ring[0]);
+	ep->tx_ring[i-1].next = ep->tx_ring_dma;
 	return;
 }
 
 static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 	int entry, free_count;
 	u32 ctrl_word;
+	long flags;
 
 	/* Caution: the write order is important here, set the field with the
 	   "ownership" bit last. */
-	spin_lock_irq(&ep->lock);
 
 	/* Calculate the next Tx descriptor entry. */
+	spin_lock_irqsave(&ep->lock, flags);
 	free_count = ep->cur_tx - ep->dirty_tx;
 	entry = ep->cur_tx % TX_RING_SIZE;
 
 	ep->tx_skbuff[entry] = skb;
-	ep->tx_ring[entry].bufaddr = virt_to_le32desc(skb->data);
-
+	ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data, 
+		 			            skb->len, PCI_DMA_TODEVICE);
 	if (free_count < TX_QUEUE_LEN/2) {/* Typical path */
 		ctrl_word = cpu_to_le32(0x100000); /* No interrupt */
 	} else if (free_count == TX_QUEUE_LEN/2) {
@@ -914,8 +958,7 @@
 	if (ep->tx_full)
 		netif_stop_queue(dev);
 
-	spin_unlock_irq(&ep->lock);
-
+	spin_unlock_irqrestore(&ep->lock, flags);
 	/* Trigger an immediate transmit demand. */
 	outl(TxQueued, dev->base_addr + COMMAND);
 
@@ -933,13 +976,11 @@
    after the Tx thread. */
 static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-	struct net_device *dev = (struct net_device *)dev_instance;
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct net_device *dev = dev_instance;
+	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
 	int status, boguscnt = max_interrupt_work;
 
-	spin_lock(&ep->lock);
-
 	do {
 		status = inl(ioaddr + INTSTAT);
 		/* Acknowledge all of the current interrupt sources ASAP. */
@@ -962,9 +1003,11 @@
 			/* Note: if this lock becomes a problem we can narrow the locked
 			   region at the cost of occasionally grabbing the lock more
 			   times. */
+			spin_lock(&ep->lock);
 			cur_tx = ep->cur_tx;
 			dirty_tx = ep->dirty_tx;
 			for (; cur_tx - dirty_tx > 0; dirty_tx++) {
+				struct sk_buff *skb;
 				int entry = dirty_tx % TX_RING_SIZE;
 				int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus);
 
@@ -975,7 +1018,7 @@
 					/* There was an major error, log it. */
 #ifndef final_version
 					if (debug > 1)
-						printk("%s: Transmit error, Tx status %8.8x.\n",
+						printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
 							   dev->name, txstatus);
 #endif
 					ep->stats.tx_errors++;
@@ -996,13 +1039,16 @@
 				}
 
 				/* Free the original skb. */
-				dev_kfree_skb_irq(ep->tx_skbuff[entry]);
+				skb = ep->tx_skbuff[entry];
+				pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
+						 skb->len, PCI_DMA_TODEVICE);
+				dev_kfree_skb_irq(skb);
 				ep->tx_skbuff[entry] = 0;
 			}
 
 #ifndef final_version
 			if (cur_tx - dirty_tx > TX_RING_SIZE) {
-				printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+				printk(KERN_WARNING "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
 					   dev->name, dirty_tx, cur_tx, ep->tx_full);
 				dirty_tx += TX_RING_SIZE;
 			}
@@ -1010,10 +1056,12 @@
 			ep->dirty_tx = dirty_tx;
 			if (ep->tx_full
 				&& cur_tx - dirty_tx < TX_QUEUE_LEN - 4) {
-				/* The ring is no longer full, clear tbusy. */
+				/* The ring is no longer full, allow new TX entries. */
 				ep->tx_full = 0;
+				spin_unlock(&ep->lock);
 				netif_wake_queue(dev);
-			}
+			} else
+				spin_unlock(&ep->lock);
 		}
 
 		/* Check uncommon events all at once. */
@@ -1060,12 +1108,12 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n",
 			   dev->name, status);
 
-	spin_unlock(&ep->lock);
+	return;
 }
 
 static int epic_rx(struct net_device *dev)
 {
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 	int entry = ep->cur_rx % RX_RING_SIZE;
 	int rx_work_limit = ep->dirty_rx + RX_RING_SIZE - ep->cur_rx;
 	int work_done = 0;
@@ -1074,7 +1122,7 @@
 		printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
 			   ep->rx_ring[entry].rxstatus);
 	/* If we own the next entry, it's a new packet. Send it up. */
-	while (!(le32_to_cpu(ep->rx_ring[entry].rxstatus) & DescOwn)) { 
+	while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) {
 		int status = le32_to_cpu(ep->rx_ring[entry].rxstatus);
 
 		if (debug > 4)
@@ -1098,6 +1146,10 @@
 			short pkt_len = (status >> 16) - 4;
 			struct sk_buff *skb;
 
+			pci_dma_sync_single(ep->pci_dev, ep->rx_ring[entry].bufaddr, 
+					    ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
+			pci_unmap_single(ep->pci_dev, ep->rx_ring[entry].bufaddr, 
+					 ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 			if (pkt_len > PKT_BUF_SZ - 4) {
 				printk(KERN_ERR "%s: Oversized Ethernet frame, status %x "
 					   "%d bytes.\n",
@@ -1141,7 +1193,8 @@
 				break;
 			skb->dev = dev;			/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			ep->rx_ring[entry].bufaddr = virt_to_le32desc(skb->tail);
+			ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, 
+				skb->tail, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 			work_done++;
 		}
 		ep->rx_ring[entry].rxstatus = cpu_to_le32(DescOwn);
@@ -1152,7 +1205,8 @@
 static int epic_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
+	struct sk_buff *skb;
 	int i;
 
 	netif_stop_queue(dev);
@@ -1167,31 +1221,36 @@
 
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb = ep->rx_skbuff[i];
+		skb = ep->rx_skbuff[i];
 		ep->rx_skbuff[i] = 0;
 		ep->rx_ring[i].rxstatus = 0;		/* Not owned by Epic chip. */
 		ep->rx_ring[i].buflength = 0;
-		ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
 		if (skb) {
+			pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr, 
+				 	 ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 			dev_kfree_skb(skb);
 		}
+		ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (ep->tx_skbuff[i])
-			dev_kfree_skb(ep->tx_skbuff[i]);
+		skb = ep->tx_skbuff[i];
 		ep->tx_skbuff[i] = 0;
+		if (!skb)
+			continue;
+		pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr, 
+				 skb->len, PCI_DMA_TODEVICE);
+		dev_kfree_skb(skb);
 	}
 
 	/* Green! Leave the chip in low-power mode. */
 	outl(0x0008, ioaddr + GENCTL);
 
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
 static struct net_device_stats *epic_get_stats(struct net_device *dev)
 {
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
 
 	if (netif_running(dev)) {
@@ -1233,7 +1292,7 @@
 static void set_rx_mode(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct epic_private *ep = (struct epic_private *)dev->priv;
+	struct epic_private *ep = dev->priv;
 	unsigned char mc_filter[8];		 /* Multicast hash filter */
 	int i;
 
@@ -1271,25 +1330,26 @@
 
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
+	struct epic_private *ep = 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 epic_private *)dev->priv)->phys[0] & 0x1f;
+		data[0] = ep->phys[0] & 0x1f;
 		/* Fall Through */
 	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
 		if (! netif_running(dev)) {
 			outl(0x0200, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 		}
-		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+#if 0					/* Just leave on if the ioctl() is ever used. */
 		if (! netif_running(dev)) {
-#ifdef notdef					/* Leave on if the ioctl() is used. */
 			outl(0x0008, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
-#endif
 		}
+#endif
 		return 0;
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
 		if (!capable(CAP_NET_ADMIN))
@@ -1298,13 +1358,26 @@
 			outl(0x0200, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 		}
-		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		if (data[0] == ep->phys[0]) {
+			u16 value = data[2];
+			switch (data[1]) {
+			case 0:
+				/* Check for autonegotiation on or reset. */
+				ep->duplex_lock = (value & 0x9000) ? 0 : 1;
+				if (ep->duplex_lock)
+					ep->full_duplex = (value & 0x0100) ? 1 : 0;
+				break;
+			case 4: ep->advertising = value; break;
+			}
+			/* Perhaps check_duplex(dev), depending on chip semantics. */
+		}
+		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+#if 0					/* Leave on if the ioctl() is used. */
 		if (! netif_running(dev)) {
-#ifdef notdef					/* Leave on if the ioctl() is used. */
 			outl(0x0008, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
-#endif
 		}
+#endif
 		return 0;
 	default:
 		return -EOPNOTSUPP;
@@ -1314,36 +1387,44 @@
 
 static void __devexit epic_remove_one (struct pci_dev *pdev)
 {
-	struct net_device *dev = pdev->driver_data;
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct epic_private *ep = dev->priv;
 	
+	pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
+	pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
 	unregister_netdev(dev);
 #ifndef USE_IO_OPS
-	iounmap ((void*) dev->base_addr);
+	iounmap((void*) dev->base_addr);
 #endif
-	release_mem_region (pci_resource_start (pdev, 1),
-			    pci_resource_len (pdev, 1));
-	release_region (pci_resource_start (pdev, 0),
-			pci_resource_len (pdev, 0));
+	pci_release_regions(pdev);
 	kfree(dev);
+	pci_set_drvdata(pdev, NULL);
+	/* pci_power_off(pdev, -1); */
 }
 
 
 static void epic_suspend (struct pci_dev *pdev)
 {
-	struct net_device *dev = pdev->driver_data;
+	struct net_device *dev = pci_get_drvdata(pdev);
 	long ioaddr = dev->base_addr;
 
+	if (!netif_running(dev))
+		return;
 	epic_pause(dev);
 	/* Put the chip into low-power mode. */
 	outl(0x0008, ioaddr + GENCTL);
+	/* pci_power_off(pdev, -1); */
 }
 
 
 static void epic_resume (struct pci_dev *pdev)
 {
-	struct net_device *dev = pdev->driver_data;
+	struct net_device *dev = pci_get_drvdata(pdev);
 
-	epic_restart (dev);
+	if (!netif_running(dev))
+		return;
+	epic_restart(dev);
+	/* pci_power_on(pdev); */
 }
 
 

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