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

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

diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/drivers/net/epic100.c linux/drivers/net/epic100.c
@@ -53,11 +53,18 @@
 	LK1.1.10:
 	* revert MII transceiver init change (jgarzik)
 
+	LK1.1.11:
+	* implement ETHTOOL_[GS]SET, _NWAY_RST, _[GS]MSGLVL, _GLINK (jgarzik)
+	* replace some MII-related magic numbers with constants
+
+	LK1.1.12:
+	* fix power-up sequence
+
 */
 
 #define DRV_NAME	"epic100"
-#define DRV_VERSION	"1.11+LK1.1.10"
-#define DRV_RELDATE	"July 6, 2001"
+#define DRV_VERSION	"1.11+LK1.1.12"
+#define DRV_RELDATE	"Jan 18, 2002"
 
 
 /* The user-configurable values.
@@ -317,12 +324,9 @@
 	/* Ring pointers. */
 	spinlock_t lock;				/* Group with Tx control cache line. */
 	unsigned int cur_tx, dirty_tx;
-	struct descriptor  *last_tx_desc;
 
 	unsigned int cur_rx, dirty_rx;
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
-	struct descriptor  *last_rx_desc;
-	long last_rx_time;					/* Last Rx, in jiffies. */
 
 	struct pci_dev *pci_dev;			/* PCI bus location. */
 	int chip_id, chip_flags;
@@ -334,13 +338,9 @@
 	signed char phys[4];				/* MII device addresses. */
 	u16 advertising;					/* NWay media advertisement */
 	int mii_phy_cnt;
+	struct mii_if_info mii;
 	unsigned int tx_full:1;				/* The Tx queue is full. */
-	unsigned int full_duplex:1;			/* Current duplex setting. */
-	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. */
-	unsigned int mediasense:1;			/* Media sensing in progress. */
 };
 
 static int epic_open(struct net_device *dev);
@@ -419,6 +419,9 @@
 
 	pci_set_drvdata(pdev, dev);
 	ep = dev->priv;
+	ep->mii.dev = dev;
+	ep->mii.mdio_read = mdio_read;
+	ep->mii.mdio_write = mdio_write;
 
 	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
@@ -480,7 +483,7 @@
 	{
 		int phy, phy_idx = 0;
 		for (phy = 1; phy < 32 && phy_idx < sizeof(ep->phys); phy++) {
-			int mii_status = mdio_read(dev, phy, 1);
+			int mii_status = mdio_read(dev, phy, MII_BMSR);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				ep->phys[phy_idx++] = phy;
 				printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control "
@@ -491,16 +494,17 @@
 		ep->mii_phy_cnt = phy_idx;
 		if (phy_idx != 0) {
 			phy = ep->phys[0];
-			ep->advertising = mdio_read(dev, phy, 4);
+			ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE);
 			printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link "
 				   "partner %4.4x.\n",
-				   pdev->slot_name, ep->advertising, mdio_read(dev, phy, 5));
+				   pdev->slot_name, ep->mii.advertising, mdio_read(dev, phy, 5));
 		} else if ( ! (ep->chip_flags & NO_MII)) {
 			printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n",
 			       pdev->slot_name);
 			/* Use the known PHY address of the EPII. */
 			ep->phys[0] = 3;
 		}
+		ep->mii.phy_id = ep->phys[0];
 	}
 
 	/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
@@ -510,13 +514,11 @@
 
 	/* The lower four bits are the media type. */
 	if (duplex) {
-		ep->duplex_lock = ep->full_duplex = 1;
+		ep->mii.duplex_lock = ep->mii.full_duplex = 1;
 		printk(KERN_INFO DRV_NAME "(%s):  Forced full duplex operation requested.\n",
 		       pdev->slot_name);
 	}
 	dev->if_port = ep->default_port = option;
-	if (ep->default_port)
-		ep->medialock = 1;
 
 	/* The Epic-specific entries in the device structure. */
 	dev->open = &epic_open;
@@ -675,9 +677,8 @@
 	   required by the details of which bits are reset and the transceiver
 	   wiring on the Ositech CardBus card.
 	*/
-#if 0
-	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
-#endif
+
+	outl(0x12, ioaddr + MIICfg);
 	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
@@ -699,29 +700,29 @@
 
 	if (media2miictl[dev->if_port & 15]) {
 		if (ep->mii_phy_cnt)
-			mdio_write(dev, ep->phys[0], 0, media2miictl[dev->if_port&15]);
+			mdio_write(dev, ep->phys[0], MII_BMCR, 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(dev, ep->phys[0], 1));
+					   dev->name, mdio_read(dev, ep->phys[0], MII_BMSR));
 		}
 	} else {
-		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(dev, ep->phys[0], 0, 0x1200);
+		int mii_lpa = mdio_read(dev, ep->phys[0], MII_LPA);
+		if (mii_lpa != 0xffff) {
+			if ((mii_lpa & LPA_100FULL) || (mii_lpa & 0x01C0) == LPA_10FULL)
+				ep->mii.full_duplex = 1;
+			else if (! (mii_lpa & LPA_LPACK))
+				mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART);
 			if (debug > 1)
 				printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
 					   " register read of %4.4x.\n", dev->name,
-					   ep->full_duplex ? "full" : "half",
-					   ep->phys[0], mii_reg5);
+					   ep->mii.full_duplex ? "full" : "half",
+					   ep->phys[0], mii_lpa);
 		}
 	}
 
-	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	outl(ep->rx_ring_dma, ioaddr + PRxCDAR);
 	outl(ep->tx_ring_dma, ioaddr + PTxCDAR);
 
@@ -741,7 +742,7 @@
 		printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
 			   "%s-duplex.\n",
 			   dev->name, ioaddr, dev->irq, (int)inl(ioaddr + GENCTL),
-			   ep->full_duplex ? "full" : "half");
+			   ep->mii.full_duplex ? "full" : "half");
 
 	/* Set the timer to switch to check for link beat and perhaps switch
 	   to an alternate media type. */
@@ -810,7 +811,7 @@
 
 	ep->tx_threshold = TX_FIFO_THRESH;
 	outl(ep->tx_threshold, ioaddr + TxThresh);
-	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	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)*
@@ -836,20 +837,20 @@
 {
 	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
-	int mii_reg5 = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], 5) : 0;
-	int negotiated = mii_reg5 & ep->advertising;
+	int mii_lpa = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], MII_LPA) : 0;
+	int negotiated = mii_lpa & ep->mii.advertising;
 	int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
 
-	if (ep->duplex_lock)
+	if (ep->mii.duplex_lock)
 		return;
-	if (mii_reg5 == 0xffff)		/* Bogus read */
+	if (mii_lpa == 0xffff)		/* Bogus read */
 		return;
-	if (ep->full_duplex != duplex) {
-		ep->full_duplex = duplex;
+	if (ep->mii.full_duplex != duplex) {
+		ep->mii.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);
+			   ep->mii.full_duplex ? "full" : "half", ep->phys[0], mii_lpa);
+		outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	}
 }
 
@@ -913,7 +914,6 @@
 	ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 	ep->dirty_tx = ep->cur_tx = 0;
 	ep->cur_rx = ep->dirty_rx = 0;
-	ep->last_rx_time = jiffies;
 	ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
 
 	/* Initialize all Rx descriptors. */
@@ -1371,17 +1371,66 @@
 		return -EFAULT;
 
 	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, np->pci_dev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
 
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
 	default:
 		break;
 	}
@@ -1432,11 +1481,11 @@
 			switch (data->reg_num) {
 			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;
+				ep->mii.duplex_lock = (value & 0x9000) ? 0 : 1;
+				if (ep->mii.duplex_lock)
+					ep->mii.full_duplex = (value & 0x0100) ? 1 : 0;
 				break;
-			case 4: ep->advertising = value; break;
+			case 4: ep->mii.advertising = value; break;
 			}
 			/* Perhaps check_duplex(dev), depending on chip semantics. */
 		}

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