patch-2.4.15 linux/drivers/net/pcmcia/3c574_cs.c

Next file: linux/drivers/net/pcmcia/3c589_cs.c
Previous file: linux/drivers/net/ns83820.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/3c574_cs.c linux/drivers/net/pcmcia/3c574_cs.c
@@ -14,10 +14,6 @@
 
 */
 
-/* Driver author info must always be in the binary.  Version too.. */
-static const char *tc574_version =
-"3c574_cs.c v1.08 9/24/98 Donald Becker/David Hinds, becker@scyld.com.\n";
-
 /*
 				Theory of Operation
 
@@ -63,7 +59,7 @@
 
 V. References
 
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+http://www.scyld.com/expert/NWay.html
 http://www.national.com/pf/DP/DP83840.html
 
 Thanks to Terry Murphy of 3Com for providing development information for
@@ -100,24 +96,43 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/mem_op.h>
 
-/* A few values that may be tweaked. */
-MODULE_PARM(irq_mask, "i");
-MODULE_PARM(irq_list, "1-4i");
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(full_duplex, "i");
+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("3Com 3c574 series PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
 
 /* Now-standard PC card module parameters. */
-static u_int irq_mask = 0xdeb8;			/* IRQ3,4,5,7,9,10,11,12,14,15 */
+INT_MODULE_PARM(irq_mask, 0xdeb8);
 static int irq_list[4] = { -1 };
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  ((800*HZ)/1000)
+MODULE_PARM(irq_list, "1-4i");
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 32;
+INT_MODULE_PARM(max_interrupt_work, 32);
 
 /* Force full duplex modes? */
-static int full_duplex;
+INT_MODULE_PARM(full_duplex, 0);
+
+/* Autodetect link polarity reversal? */
+INT_MODULE_PARM(auto_polarity, 1);
+
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"3c574_cs.c 1.65 2001/10/13 00:08:50 Donald Becker/David Hinds, becker@scyld.com.\n";
+#else
+#define DEBUG(n, args...)
+#endif
+
+/*====================================================================*/
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  ((800*HZ)/1000)
 
 /* To minimize the size of the driver source and make the driver more
    readable not all constants are symbolically defined.
@@ -197,7 +212,7 @@
 	dev_node_t node;
 	struct net_device_stats stats;
 	u16 advertising, partner;			/* NWay media advertisement */
-	unsigned char phys[2];				/* MII device addresses. */
+	unsigned char phys;					/* MII device address */
 	unsigned int
 	  autoselect:1, default_media:3;	/* Read from the EEPROM/Wn3_Config. */
 	/* for transceiver monitoring */
@@ -210,17 +225,7 @@
 /* Set iff a MII transceiver on any interface requires mdio preamble.
    This only set with the original DP83840 on older 3c905 boards, so the extra
    code size of a per-interface flag is not worthwhile. */
-static char mii_preamble_required;
-
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"3c574_cs.c 1.000 1998/1/8 Donald Becker, becker@scyld.com.\n";
-#else
-#define DEBUG(n, args...)
-#endif
+static char mii_preamble_required = 0;
 
 /* Index of functions. */
 
@@ -509,7 +514,7 @@
 	}
 
 	{
-		int phy, phy_idx = 0;
+		int phy;
 		
 		/* Roadrunner only: Turn on the MII transceiver */
 		outw(0x8040, ioaddr + Wn3_Options);
@@ -521,29 +526,30 @@
 		outw(0x8040, ioaddr + Wn3_Options);
 		
 		EL3WINDOW(4);
-		for (phy = 1; phy <= 32 && phy_idx < sizeof(lp->phys); phy++) {
+		for (phy = 1; phy <= 32; phy++) {
 			int mii_status;
 			mdio_sync(ioaddr, 32);
 			mii_status = mdio_read(ioaddr, phy & 0x1f, 1);
 			if (mii_status != 0xffff) {
-				lp->phys[phy_idx++] = phy & 0x1f;
+				lp->phys = phy & 0x1f;
 				DEBUG(0, "  MII transceiver at index %d, status %x.\n",
 					  phy, mii_status);
 				if ((mii_status & 0x0040) == 0)
 					mii_preamble_required = 1;
+				break;
 			}
 		}
-		if (phy_idx == 0) {
+		if (phy > 32) {
 			printk(KERN_NOTICE "  No MII transceivers found!\n");
 			goto failed;
 		}
-		i = mdio_read(ioaddr, lp->phys[0], 16) | 0x40;
-		mdio_write(ioaddr, lp->phys[0], 16, i);
-		lp->advertising = mdio_read(ioaddr, lp->phys[0], 4);
+		i = mdio_read(ioaddr, lp->phys, 16) | 0x40;
+		mdio_write(ioaddr, lp->phys, 16, i);
+		lp->advertising = mdio_read(ioaddr, lp->phys, 4);
 		if (full_duplex) {
 			/* Only advertise the FD media types. */
 			lp->advertising &= ~0x02a0;
-			mdio_write(ioaddr, lp->phys[0], 4, lp->advertising);
+			mdio_write(ioaddr, lp->phys, 4, lp->advertising);
 		}
 	}
 
@@ -807,7 +813,12 @@
 	outw(0x0040, ioaddr + Wn4_NetDiag);
 	/* .. re-sync MII and re-fill what NWay is advertising. */
 	mdio_sync(ioaddr, 32);
-	mdio_write(ioaddr, lp->phys[0], 4, lp->advertising);
+	mdio_write(ioaddr, lp->phys, 4, lp->advertising);
+	if (!auto_polarity) {
+		/* works for TDK 78Q2120 series MII's */
+		int i = mdio_read(ioaddr, lp->phys, 16) | 0x20;
+		mdio_write(ioaddr, lp->phys, 16, i);
+	}
 
 	/* Switch to register set 1 for normal use, just for TxFree. */
 	EL3WINDOW(1);
@@ -1032,8 +1043,8 @@
 	save_flags(flags);
 	cli();
 	EL3WINDOW(4);
-	media = mdio_read(ioaddr, lp->phys[0], 1);
-	partner = mdio_read(ioaddr, lp->phys[0], 5);
+	media = mdio_read(ioaddr, lp->phys, 1);
+	partner = mdio_read(ioaddr, lp->phys, 5);
 	EL3WINDOW(1);
 	restore_flags(flags);
 
@@ -1122,7 +1133,6 @@
 	/* BadSSD */					   inb(ioaddr + 12);
 	up								 = inb(ioaddr + 13);
 
-	lp->stats.rx_bytes += rx + ((up & 0x0f) << 16);
 	lp->stats.tx_bytes += tx + ((up & 0xf0) << 12);
 
 	EL3WINDOW(1);
@@ -1160,10 +1170,8 @@
 			if (skb != NULL) {
 				skb->dev = dev;
 				skb_reserve(skb, 2);
-
 				insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
 						((pkt_len+3)>>2));
-
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
 				dev->last_rx = jiffies;
@@ -1187,7 +1195,7 @@
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 	ioaddr_t ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
-	int phy = lp->phys[0] & 0x1f;
+	int phy = lp->phys & 0x1f;
 
 	DEBUG(2, "%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
 		  dev->name, rq->ifr_ifrn.ifrn_name, cmd,
@@ -1289,8 +1297,6 @@
 {
 	servinfo_t serv;
 
-	/* Always emit the version, before any failure. */
-	printk(KERN_INFO"%s", tc574_version);
 	DEBUG(0, "%s\n", version);
 	CardServices(GetCardServicesInfo, &serv);
 	if (serv.Revision != CS_RELEASE_CODE) {
@@ -1312,7 +1318,6 @@
 
 module_init(init_3c574_cs);
 module_exit(exit_3c574_cs);
-MODULE_LICENSE("GPL");
 
 /*
  * Local variables:

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