patch-2.1.19 linux/drivers/net/3c501.c

Next file: linux/drivers/net/3c503.c
Previous file: linux/drivers/char/tty_ioctl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.18/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
@@ -9,15 +9,15 @@
 
     This is a device driver for the 3Com Etherlink 3c501.
     Do not purchase this card, even as a joke.  It's performance is horrible,
-    and it breaks in many ways.  
+    and it breaks in many ways.
 
     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
-       
+
     Fixed (again!) the missing interrupt locking on TX/RX shifting.
     		Alan Cox <Alan.Cox@linux.org>
-    		
+
     Removed calls to init_etherdev since they are no longer needed, and
     cleaned up modularization just a bit. The driver still allows only
     the default address for cards when loaded as a module, but that's
@@ -29,50 +29,50 @@
     with a TX-TX optimisation to see if we can touch 180-200K/second as seems
     theoretically maximum.
     		19950402 Alan Cox <Alan.Cox@linux.org>
-    		
+
     Some notes on this thing if you have to hack it.  [Alan]
-    
+
     1]	Some documentation is available from 3Com. Due to the boards age
     	standard responses when you ask for this will range from 'be serious'
     	to 'give it to a museum'. The documentation is incomplete and mostly
     	of historical interest anyway.
-    	
+
     2]  The basic system is a single buffer which can be used to receive or
     	transmit a packet. A third command mode exists when you are setting
     	things up.
-    	
-    3]	If it's transmitting it's not receiving and vice versa. In fact the 
+
+    3]	If it's transmitting it's not receiving and vice versa. In fact the
     	time to get the board back into useful state after an operation is
     	quite large.
-    	
+
     4]	The driver works by keeping the board in receive mode waiting for a
     	packet to arrive. When one arrives it is copied out of the buffer
     	and delivered to the kernel. The card is reloaded and off we go.
-    	
+
     5]	When transmitting dev->tbusy is set and the card is reset (from
     	receive mode) [possibly losing a packet just received] to command
     	mode. A packet is loaded and transmit mode triggered. The interrupt
     	handler runs different code for transmit interrupts and can handle
     	returning to receive mode or retransmissions (yes you have to help
     	out with those too).
-    	
+
     Problems:
     	There are a wide variety of undocumented error returns from the card
-    and you basically have to kick the board and pray if they turn up. Most 
+    and you basically have to kick the board and pray if they turn up. Most
     only occur under extreme load or if you do something the board doesn't
     like (eg touching a register at the wrong time).
-    
+
     	The driver is less efficient than it could be. It switches through
     receive mode even if more transmits are queued. If this worries you buy
     a real ethernet card.
-    
+
     	The combination of slow receive restart and no real multicast
     filter makes the board unusable with a kernel compiled for IP
-    multicasting in a real multicast environment. That's down to the board, 
+    multicasting in a real multicast environment. That's down to the board,
     but even with no multicast programs running a multicast IP kernel is
     in group 224.0.0.1 and you will therefore be listening to all multicasts.
     One nv conference running over that ethernet and you can give up.
-    
+
 */
 
 static const char *version =
@@ -112,9 +112,9 @@
 
 
 /*
- *	Index to functions. 
+ *	Index to functions.
  */
- 
+
 int el1_probe(struct device *dev);
 static int  el1_probe1(struct device *dev, int ioaddr);
 static int  el_open(struct device *dev);
@@ -132,12 +132,12 @@
 #define EL_DEBUG  0	/* use 0 for production, 1 for devel., >2 for debug */
 #endif			/* Anything above 5 is wordy death! */
 static int el_debug = EL_DEBUG;
- 
-/* 
- *	Board-specific info in dev->priv. 
+
+/*
+ *	Board-specific info in dev->priv.
  */
- 
-struct net_local 
+
+struct net_local
 {
     struct enet_statistics stats;
     int tx_pkt_start;		/* The length of the current Tx packet. */
@@ -169,7 +169,7 @@
 /*
  *	Writes to the ax command register.
  */
- 
+
 #define AX_OFF	0x00			/* Irq off, buffer access on */
 #define AX_SYS  0x40			/* Load the buffer */
 #define AX_XMIT 0x44			/* Transmit a packet */
@@ -181,16 +181,16 @@
  *	Normal receive mode written to RX_STATUS.  We must intr on short packets
  *	to avoid bogus rx lockups.
  */
- 
+
 #define RX_NORM 0xA8		/* 0x68 == all addrs, 0xA8 only to me. */
 #define RX_PROM 0x68		/* Senior Prom, uhmm promiscuous mode. */
 #define RX_MULT 0xE8		/* Accept multicast packets. */
 #define TX_NORM 0x0A		/* Interrupt on everything that might hang the chip */
 
 /*
- *	TX_STATUS register. 
+ *	TX_STATUS register.
  */
- 
+
 #define TX_COLLISION 0x02
 #define TX_16COLLISIONS 0x04
 #define TX_READY 0x08
@@ -203,7 +203,7 @@
 /*
  *	The boilerplate probe code.
  */
- 
+
 #ifdef HAVE_DEVLIST
 struct netdev_entry el1_drv = {"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist};
 #else
@@ -218,7 +218,7 @@
 	else if (base_addr != 0)	/* Don't probe at all. */
 		return ENXIO;
 
-	for (i = 0; netcard_portlist[i]; i++) 
+	for (i = 0; netcard_portlist[i]; i++)
 	{
 		int ioaddr = netcard_portlist[i];
 		if (check_region(ioaddr, EL1_IO_EXTENT))
@@ -232,8 +232,8 @@
 #endif
 
 /*
- *	The actual probe. 
- */ 
+ *	The actual probe.
+ */
 
 static int el1_probe1(struct device *dev, int ioaddr)
 {
@@ -243,25 +243,25 @@
 	int i;
 
 	/*
-	 *	Read the station address PROM data from the special port.  
+	 *	Read the station address PROM data from the special port.
 	 */
-	 
-	for (i = 0; i < 6; i++) 
+
+	for (i = 0; i < 6; i++)
 	{
 		outw(i, ioaddr + EL1_DATAPTR);
 		station_addr[i] = inb(ioaddr + EL1_SAPROM);
 	}
 	/*
 	 *	Check the first three octets of the S.A. for 3Com's prefix, or
-	 *	for the Sager NP943 prefix. 
-	 */ 
-	 
+	 *	for the Sager NP943 prefix.
+	 */
+
 	if (station_addr[0] == 0x02  &&  station_addr[1] == 0x60
-		&& station_addr[2] == 0x8c) 
+		&& station_addr[2] == 0x8c)
 	{
 		mname = "3c501";
 	} else if (station_addr[0] == 0x00  &&  station_addr[1] == 0x80
-	&& station_addr[2] == 0xC8) 
+	&& station_addr[2] == 0xC8)
 	{
 		mname = "NP943";
     	}
@@ -269,17 +269,17 @@
 		return ENODEV;
 
 	/*
-	 *	Grab the region so we can find the another board if autoIRQ fails. 
+	 *	Grab the region so we can find the another board if autoIRQ fails.
 	 */
 
 	request_region(ioaddr, EL1_IO_EXTENT,"3c501");
 
-	/*	
+	/*
 	 *	We auto-IRQ by shutting off the interrupt line and letting it float
 	 *	high.
 	 */
 
-	if (dev->irq < 2) 
+	if (dev->irq < 2)
 	{
 		autoirq_setup(2);
 		inb(RX_STATUS);		/* Clear pending interrupts. */
@@ -287,10 +287,10 @@
 		outb(AX_LOOP + 1, AX_CMD);
 
 		outb(0x00, AX_CMD);
-	
+
 		autoirq = autoirq_report(1);
 
-		if (autoirq == 0) 
+		if (autoirq == 0)
 		{
 			printk("%s probe at %#x failed to detect IRQ line.\n",
 				mname, ioaddr);
@@ -309,27 +309,27 @@
 
 	printk("%s: %s EtherLink at %#lx, using %sIRQ %d.\n", dev->name, mname, dev->base_addr,
 			autoirq ? "auto":"assigned ", dev->irq);
-	   
+
 #ifdef CONFIG_IP_MULTICAST
 	printk("WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n");
-#endif    
+#endif
 
 	if (el_debug)
 		printk("%s", version);
 
 	/*
-	 *	Initialize the device structure. 
+	 *	Initialize the device structure.
 	 */
-	 
+
 	dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
 	if (dev->priv == NULL)
 		return -ENOMEM;
 	memset(dev->priv, 0, sizeof(struct net_local));
 
 	/*
-	 *	The EL1-specific entries in the device structure. 
+	 *	The EL1-specific entries in the device structure.
 	 */
-	 
+
 	dev->open = &el_open;
 	dev->hard_start_xmit = &el_start_xmit;
 	dev->stop = &el1_close;
@@ -337,7 +337,7 @@
 	dev->set_multicast_list = &set_multicast_list;
 
 	/*
-	 *	Setup the generic properties 
+	 *	Setup the generic properties
 	 */
 
 	ether_setup(dev);
@@ -346,9 +346,9 @@
 }
 
 /*
- *	Open/initialize the board. 
+ *	Open/initialize the board.
  */
- 
+
 static int el_open(struct device *dev)
 {
 	int ioaddr = dev->base_addr;
@@ -356,7 +356,7 @@
 	if (el_debug > 2)
 		printk("%s: Doing el_open()...", dev->name);
 
-	if (request_irq(dev->irq, &el_interrupt, 0, "3c501", NULL)) 
+	if (request_irq(dev->irq, &el_interrupt, 0, "3c501", NULL))
 		return -EAGAIN;
 
 	irq2dev_map[dev->irq] = dev;
@@ -374,13 +374,13 @@
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
 	unsigned long flags;
-	
+
 	if(dev->interrupt)		/* May be unloading, don't stamp on */
 		return 1;		/* the packet buffer this time      */
 
-	if (dev->tbusy) 
+	if (dev->tbusy)
 	{
-		if (jiffies - dev->trans_start < 20) 
+		if (jiffies - dev->trans_start < 20)
 		{
 			if (el_debug > 2)
 				printk(" transmitter busy, deferred.\n");
@@ -398,7 +398,7 @@
 		dev->trans_start = jiffies;
 	}
 
-	if (skb == NULL) 
+	if (skb == NULL)
 	{
 		dev_tint(dev);
 		return 0;
@@ -411,13 +411,13 @@
 	 *	mode as the driver assumes tbusy is a faithful indicator of card
 	 *	state
 	 */
-	 
+
 	cli();
-	
+
 	/*
-	 *	Avoid timer-based retransmission conflicts. 
+	 *	Avoid timer-based retransmission conflicts.
 	 */
-	 
+
 	if (set_bit(0, (void*)&dev->tbusy) != 0)
 	{
 		restore_flags(flags);
@@ -436,19 +436,19 @@
 		 *	Command mode with status cleared should [in theory]
 		 *	mean no more interrupts can be pending on the card.
 		 */
-		 
+
 #ifdef BLOCKOUT_1
-		disable_irq(dev->irq);		 
-#endif	
+		disable_irq(dev->irq);
+#endif
 		outb_p(AX_SYS, AX_CMD);
 		inb_p(RX_STATUS);
 		inb_p(TX_STATUS);
-	
+
 		lp->loading=1;
-	
-		/* 
+
+		/*
 		 *	Turn interrupts back on while we spend a pleasant afternoon
-		 *	loading bytes into the board 
+		 *	loading bytes into the board
 		 */
 
 		restore_flags(flags);
@@ -456,7 +456,7 @@
 		outw(gp_start, GP_LOW);		/* aim - packet will be loaded into buffer start */
 		outsb(DATAPORT,buf,skb->len);	/* load buffer (usual thing each byte increments the pointer) */
 		outw(gp_start, GP_LOW);		/* the board reuses the same register */
-#ifndef BLOCKOUT_1		
+#ifndef BLOCKOUT_1
 		if(lp->loading==2)		/* A receive upset our load, despite our best efforts */
 		{
 			if(el_debug>2)
@@ -466,9 +466,9 @@
 #endif
 		outb(AX_XMIT, AX_CMD);		/* fire ... Trigger xmit.  */
 		lp->loading=0;
-#ifdef BLOCKOUT_1		
+#ifdef BLOCKOUT_1
 		enable_irq(dev->irq);
-#endif		
+#endif
 		dev->trans_start = jiffies;
 	}
 
@@ -481,7 +481,7 @@
 
 /*
  *	The typical workload of the driver:
- *	Handle the ether interface interrupts. 
+ *	Handle the ether interface interrupts.
  */
 
 static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -491,7 +491,7 @@
 	int ioaddr;
 	int axsr;			/* Aux. status reg. */
 
-	if (dev == NULL  ||  dev->irq != irq) 
+	if (dev == NULL  ||  dev->irq != irq)
 	{
 		printk ("3c501 driver: irq %d for unknown device.\n", irq);
 		return;
@@ -503,7 +503,7 @@
 	/*
 	 *	What happened ?
 	 */
-	 
+
 	axsr = inb(AX_STATUS);
 
 	/*
@@ -515,25 +515,25 @@
 	if (dev->interrupt)
 		printk("%s: Reentering the interrupt driver!\n", dev->name);
 	dev->interrupt = 1;
-#ifndef BLOCKOUT_1    
+#ifndef BLOCKOUT_1
         if(lp->loading==1 && !dev->tbusy)
         	printk("%s: Inconsistent state loading while not in tx\n",
         		dev->name);
-#endif        		
+#endif
 #ifdef BLOCKOUT_3
 	lp->loading=2;		/* So we can spot loading interruptions */
 #endif
 
-	if (dev->tbusy) 
+	if (dev->tbusy)
 	{
-    
+
     		/*
     		 *	Board in transmit mode. May be loading. If we are
     		 *	loading we shouldn't have got this.
     		 */
-    	 
+
 		int txsr = inb(TX_STATUS);
-#ifdef BLOCKOUT_2		
+#ifdef BLOCKOUT_2
 		if(lp->loading==1)
 		{
 			if(el_debug > 2)
@@ -549,7 +549,7 @@
 		if (el_debug > 6)
 			printk(" txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW),inw(RX_LOW));
 
-		if ((axsr & 0x80) && (txsr & TX_READY) == 0) 
+		if ((axsr & 0x80) && (txsr & TX_READY) == 0)
 		{
 			/*
 			 *	FIXME: is there a logic to whether to keep on trying or
@@ -561,8 +561,8 @@
 			inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR));
 			dev->tbusy = 0;
 			mark_bh(NET_BH);
-		} 
-		else if (txsr & TX_16COLLISIONS) 
+		}
+		else if (txsr & TX_16COLLISIONS)
 		{
 			/*
 			 *	Timed out
@@ -572,18 +572,18 @@
 			outb(AX_SYS, AX_CMD);
 			lp->stats.tx_aborted_errors++;
 		}
-		else if (txsr & TX_COLLISION) 
-		{	
+		else if (txsr & TX_COLLISION)
+		{
 			/*
-			 *	Retrigger xmit. 
+			 *	Retrigger xmit.
 			 */
-			 
+
 			if (el_debug > 6)
 				printk(" retransmitting after a collision.\n");
 			/*
 			 *	Poor little chip can't reset its own start pointer
 			 */
-			
+
 			outb(AX_SYS, AX_CMD);
 			outw(lp->tx_pkt_start, GP_LOW);
 			outb(AX_XMIT, AX_CMD);
@@ -613,22 +613,22 @@
     		/*
     		 *	In receive mode.
     		 */
-    	 
+
 		int rxsr = inb(RX_STATUS);
 		if (el_debug > 5)
 			printk(" rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS),inw(RX_LOW));
 		/*
-		 *	Just reading rx_status fixes most errors. 
+		 *	Just reading rx_status fixes most errors.
 		 */
 		if (rxsr & RX_MISSED)
 			lp->stats.rx_missed_errors++;
-		else if (rxsr & RX_RUNT) 
+		else if (rxsr & RX_RUNT)
 		{	/* Handled to avoid board lock-up. */
 			lp->stats.rx_length_errors++;
-			if (el_debug > 5) 
+			if (el_debug > 5)
 				printk(" runt.\n");
-		} 
-		else if (rxsr & RX_GOOD) 
+		}
+		else if (rxsr & RX_GOOD)
 		{
 			/*
 			 *	Receive worked.
@@ -650,7 +650,7 @@
 	}
 
 	/*
-	 *	Move into receive mode 
+	 *	Move into receive mode
 	 */
 
 	outb(AX_RX, AX_CMD);
@@ -664,7 +664,7 @@
 
 /*
  *	We have a good packet. Well, not really "good", just mostly not broken.
- *	We must check everything to see if it is good. 
+ *	We must check everything to see if it is good.
  */
 
 static void el_receive(struct device *dev)
@@ -679,18 +679,18 @@
 	if (el_debug > 4)
 		printk(" el_receive %d.\n", pkt_len);
 
-	if ((pkt_len < 60)  ||  (pkt_len > 1536)) 
+	if ((pkt_len < 60)  ||  (pkt_len > 1536))
 	{
 		if (el_debug)
 			printk("%s: bogus packet, length=%d\n", dev->name, pkt_len);
 		lp->stats.rx_over_errors++;
 		return;
 	}
-    
+
 	/*
 	 *	Command mode so we can empty the buffer
 	 */
-     
+
 	outb(AX_SYS, AX_CMD);
 	skb = dev_alloc_skb(pkt_len+2);
 
@@ -699,7 +699,7 @@
 	 */
 
 	outw(0x00, GP_LOW);
-	if (skb == NULL) 
+	if (skb == NULL)
 	{
 		printk("%s: Memory squeeze, dropping packet.\n", dev->name);
 		lp->stats.rx_dropped++;
@@ -711,7 +711,7 @@
 		skb->dev = dev;
 		/*
 		 *	The read increments through the bytes. The interrupt
-		 *	handler will fix the pointer when it returns to 
+		 *	handler will fix the pointer when it returns to
 		 *	receive mode.
 		 */
 		insb(DATAPORT, skb_put(skb,pkt_len), pkt_len);
@@ -735,7 +735,7 @@
 		for (i = 0; i < 6; i++)	/* Set the station address. */
 			outb(dev->dev_addr[i], ioaddr + i);
 	}
-    
+
 	outw(0, RX_BUF_CLR);		/* Set rx packet area to 0. */
 	cli();				/* Avoid glitch on writes to CMD regs */
 	outb(TX_NORM, TX_CMD);		/* tx irq on done, collision */
@@ -758,7 +758,7 @@
 	dev->start = 0;
 
 	/*
-	 *	Free and disable the IRQ. 
+	 *	Free and disable the IRQ.
 	 */
 
 	free_irq(dev->irq, NULL);
@@ -785,7 +785,7 @@
 	int ioaddr = dev->base_addr;
 
 	if(dev->flags&IFF_PROMISC)
-	{    
+	{
 		outb(RX_PROM, RX_CMD);
 		inb(RX_STATUS);
 	}
@@ -794,7 +794,7 @@
 		outb(RX_MULT, RX_CMD);	/* Multicast or all multicast is the same */
 		inb(RX_STATUS);		/* Clear status. */
 	}
-	else 
+	else
 	{
 		outb(RX_NORM, RX_CMD);
 		inb(RX_STATUS);
@@ -805,17 +805,19 @@
 
 static char devicename[9] = { 0, };
 
-static struct device dev_3c501 = 
+static struct device dev_3c501 =
 {
 	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
 	0x280, 5,
-	0, 0, 0, NULL, el1_probe 
+	0, 0, 0, NULL, el1_probe
 };
 
 static int io=0x280;
 static int irq=5;
-	
+MODULE_PARM(io, "i");
+MODULE_PARM(irq, "i");
+
 int init_module(void)
 {
 	dev_3c501.irq=irq;
@@ -830,18 +832,18 @@
 	/*
 	 *	No need to check MOD_IN_USE, as sys_delete_module() checks.
 	 */
-	 
+
 	unregister_netdev(&dev_3c501);
 
 	/*
-	 *	Free up the private structure, or leak memory :-) 
+	 *	Free up the private structure, or leak memory :-)
 	 */
-	 
+
 	kfree(dev_3c501.priv);
 	dev_3c501.priv = NULL;	/* gets re-allocated by el1_probe1 */
 
 	/*
-	 *	If we don't do this, we can't re-insmod it later. 
+	 *	If we don't do this, we can't re-insmod it later.
 	 */
 	release_region(dev_3c501.base_addr, EL1_IO_EXTENT);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov