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

Next file: linux/drivers/net/arcnet.c
Previous file: linux/drivers/char/lp.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.45/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
@@ -79,9 +79,9 @@
     "3c501.c: 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov).\n";
 
 /*
-  Braindamage remaining:
-  The 3c501 board.
-  */
+ *	Braindamage remaining:
+ *	The 3c501 board.
+ */
 
 #include <linux/module.h>
 
@@ -110,7 +110,10 @@
    { 0x280, 0x300, 0};
 
 
-/* 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);
@@ -129,8 +132,12 @@
 #endif			/* Anything above 5 is wordy death! */
 static int el_debug = EL_DEBUG;
  
-/* Board-specific info in dev->priv. */
-struct net_local {
+/* 
+ *	Board-specific info in dev->priv. 
+ */
+ 
+struct net_local 
+{
     struct enet_statistics stats;
     int tx_pkt_start;		/* The length of the current Tx packet. */
     int collisions;		/* Tx collisions this packet */
@@ -158,7 +165,10 @@
 #define EL1_SAPROM	0x0C
 #define EL1_DATAPORT 	0x0f
 
-/* Writes to the ax command register. */
+/*
+ *	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 */
@@ -166,14 +176,20 @@
 #define AX_LOOP	0x0C			/* Loopback mode */
 #define AX_RESET 0x80
 
-/* Normal receive mode written to RX_STATUS.  We must intr on short packets
-   to avoid bogus rx lockups. */
+/*
+ *	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 */
+#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
@@ -183,468 +199,551 @@
 #define RX_GOOD	0x30		/* Good packet 0x20, or simple overflow 0x10. */
 
 
-/* The boilerplate probe code. */
+/*
+ *	The boilerplate probe code.
+ */
+ 
 #ifdef HAVE_DEVLIST
-struct netdev_entry el1_drv =
-{"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist};
+struct netdev_entry el1_drv = {"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist};
 #else
-int
-el1_probe(struct device *dev)
+
+int el1_probe(struct device *dev)
 {
-    int i;
-    int base_addr = dev ? dev->base_addr : 0;
+	int i;
+	int base_addr = dev ? dev->base_addr : 0;
 
-    if (base_addr > 0x1ff)	/* Check a single specified location. */
-	return el1_probe1(dev, base_addr);
-    else if (base_addr != 0)	/* Don't probe at all. */
-	return ENXIO;
-
-    for (i = 0; netcard_portlist[i]; i++) {
-	int ioaddr = netcard_portlist[i];
-	if (check_region(ioaddr, EL1_IO_EXTENT))
-	    continue;
-	if (el1_probe1(dev, ioaddr) == 0)
-	    return 0;
-    }
+	if (base_addr > 0x1ff)	/* Check a single specified location. */
+		return el1_probe1(dev, base_addr);
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return ENXIO;
 
-    return ENODEV;
+	for (i = 0; netcard_portlist[i]; i++) 
+	{
+		int ioaddr = netcard_portlist[i];
+		if (check_region(ioaddr, EL1_IO_EXTENT))
+			continue;
+		if (el1_probe1(dev, ioaddr) == 0)
+			return 0;
+	}
+
+	return ENODEV;
 }
 #endif
 
-/* The actual probe. */ 
-static int
-el1_probe1(struct device *dev, int ioaddr)
-{
-    #ifndef MODULE
-
-    const char *mname;		/* Vendor name */
-    unsigned char station_addr[6];
-    int autoirq = 0;
-    int i;
-
-    /* Read the station address PROM data from the special port.  */
-    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. */ 
-    if (station_addr[0] == 0x02  &&  station_addr[1] == 0x60
-	&& station_addr[2] == 0x8c) {
-	mname = "3c501";
-    } else if (station_addr[0] == 0x00  &&  station_addr[1] == 0x80
-	&& station_addr[2] == 0xC8) {
-	mname = "NP943";
-    } else
-	return ENODEV;
+/*
+ *	The actual probe. 
+ */ 
 
-    /* Grab the region so we can find the another board if autoIRQ fails. */
-    request_region(ioaddr, EL1_IO_EXTENT,"3c501");
+static int el1_probe1(struct device *dev, int ioaddr)
+{
+#ifndef MODULE
 
-    /* We auto-IRQ by shutting off the interrupt line and letting it float
-       high. */
-    if (dev->irq < 2) {
+	const char *mname;		/* Vendor name */
+	unsigned char station_addr[6];
+	int autoirq = 0;
+	int i;
 
-	autoirq_setup(2);
+	/*
+	 *	Read the station address PROM data from the special port.  
+	 */
+	 
+	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. 
+	 */ 
+	 
+	if (station_addr[0] == 0x02  &&  station_addr[1] == 0x60
+		&& station_addr[2] == 0x8c) 
+	{
+		mname = "3c501";
+	} else if (station_addr[0] == 0x00  &&  station_addr[1] == 0x80
+	&& station_addr[2] == 0xC8) 
+	{
+		mname = "NP943";
+    	}
+    	else
+		return ENODEV;
 
-	inb(RX_STATUS);		/* Clear pending interrupts. */
-	inb(TX_STATUS);
-	outb(AX_LOOP + 1, AX_CMD);
+	/*
+	 *	Grab the region so we can find the another board if autoIRQ fails. 
+	 */
 
-	outb(0x00, AX_CMD);
+	request_region(ioaddr, EL1_IO_EXTENT,"3c501");
 
-	autoirq = autoirq_report(1);
+	/*	
+	 *	We auto-IRQ by shutting off the interrupt line and letting it float
+	 *	high.
+	 */
 
-	if (autoirq == 0) {
-	    printk("%s probe at %#x failed to detect IRQ line.\n",
-		   mname, ioaddr);
-	    return EAGAIN;
-	}
-    }
+	if (dev->irq < 2) 
+	{
+		autoirq_setup(2);
+		inb(RX_STATUS);		/* Clear pending interrupts. */
+		inb(TX_STATUS);
+		outb(AX_LOOP + 1, AX_CMD);
+
+		outb(0x00, AX_CMD);
+	
+		autoirq = autoirq_report(1);
 
-    outb(AX_RESET+AX_LOOP, AX_CMD);			/* Loopback mode. */
+		if (autoirq == 0) 
+		{
+			printk("%s probe at %#x failed to detect IRQ line.\n",
+				mname, ioaddr);
+			return EAGAIN;
+		}
+	}
 
-    dev->base_addr = ioaddr;
-    memcpy(dev->dev_addr, station_addr, ETH_ALEN);
-    if (dev->mem_start & 0xf)
-	el_debug = dev->mem_start & 0x7;
-    if (autoirq)
-	dev->irq = autoirq;
+	outb(AX_RESET+AX_LOOP, AX_CMD);			/* Loopback mode. */
+	dev->base_addr = ioaddr;
+	memcpy(dev->dev_addr, station_addr, ETH_ALEN);
+
+	if (dev->mem_start & 0xf)
+		el_debug = dev->mem_start & 0x7;
+	if (autoirq)
+		dev->irq = autoirq;
 
-    printk("%s: %s EtherLink at %#lx, using %sIRQ %d.\n",
-	   dev->name, mname, dev->base_addr,
-	   autoirq ? "auto":"assigned ", dev->irq);
+	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");
+	printk("WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n");
 #endif    
 
-    if (el_debug)
-	printk("%s", version);
+	if (el_debug)
+		printk("%s", version);
+
+	/*
+	 *	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. 
+	 */
+	 
+	dev->open = &el_open;
+	dev->hard_start_xmit = &el_start_xmit;
+	dev->stop = &el1_close;
+	dev->get_stats = &el1_get_stats;
+	dev->set_multicast_list = &set_multicast_list;
+
+	/*
+	 *	Setup the generic properties 
+	 */
 
-    /* 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. */
-    dev->open = &el_open;
-    dev->hard_start_xmit = &el_start_xmit;
-    dev->stop = &el1_close;
-    dev->get_stats = &el1_get_stats;
-    dev->set_multicast_list = &set_multicast_list;
-    /* Setup the generic properties */
-    ether_setup(dev);
+	ether_setup(dev);
 
 #endif /* !MODULE */
-    return 0;
+
+	return 0;
 }
 
-/* Open/initialize the board. */
-static int
-el_open(struct device *dev)
+/*
+ *	Open/initialize the board. 
+ */
+ 
+static int el_open(struct device *dev)
 {
-    int ioaddr = dev->base_addr;
+	int ioaddr = dev->base_addr;
 
-    if (el_debug > 2)
-	printk("%s: Doing el_open()...", dev->name);
+	if (el_debug > 2)
+		printk("%s: Doing el_open()...", dev->name);
 
-    if (request_irq(dev->irq, &el_interrupt, 0, "3c501")) {
-	return -EAGAIN;
-    }
-    irq2dev_map[dev->irq] = dev;
+	if (request_irq(dev->irq, &el_interrupt, 0, "3c501")) 
+		return -EAGAIN;
 
-    el_reset(dev);
+	irq2dev_map[dev->irq] = dev;
+	el_reset(dev);
 
-    dev->start = 1;
+	dev->start = 1;
 
-    outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
-    MOD_INC_USE_COUNT;
-    return 0;
+	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
+	MOD_INC_USE_COUNT;
+	return 0;
 }
 
-static int
-el_start_xmit(struct sk_buff *skb, struct device *dev)
+static int el_start_xmit(struct sk_buff *skb, struct device *dev)
 {
-    struct net_local *lp = (struct net_local *)dev->priv;
-    int ioaddr = dev->base_addr;
-    unsigned long flags;
+	struct net_local *lp = (struct net_local *)dev->priv;
+	int ioaddr = dev->base_addr;
+	unsigned long flags;
 
-    if (dev->tbusy) {
-	if (jiffies - dev->trans_start < 20) {
-	    if (el_debug > 2)
-		printk(" transmitter busy, deferred.\n");
-	    return 1;
+	if (dev->tbusy) 
+	{
+		if (jiffies - dev->trans_start < 20) 
+		{
+			if (el_debug > 2)
+				printk(" transmitter busy, deferred.\n");
+			return 1;
+		}
+		if (el_debug)
+			printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
+				dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
+		lp->stats.tx_errors++;
+		outb(TX_NORM, TX_CMD);
+		outb(RX_NORM, RX_CMD);
+		outb(AX_OFF, AX_CMD);	/* Just trigger a false interrupt. */
+		outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
+		dev->tbusy = 0;
+		dev->trans_start = jiffies;
 	}
-	if (el_debug)
-	    printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
-		    dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
-	lp->stats.tx_errors++;
-	outb(TX_NORM, TX_CMD);
-	outb(RX_NORM, RX_CMD);
-	outb(AX_OFF, AX_CMD);	/* Just trigger a false interrupt. */
-	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
-	dev->tbusy = 0;
-	dev->trans_start = jiffies;
-    }
 
-    if (skb == NULL) {
-	dev_tint(dev);
-	return 0;
-    }
-
-    save_flags(flags);
-    /* Avoid incoming interrupts between us flipping tbusy and flipping
-       mode as the driver assumes tbusy is a faithful indicator of card
-       state */
-    cli();
-    /* Avoid timer-based retransmission conflicts. */
-    if (set_bit(0, (void*)&dev->tbusy) != 0)
-    {
-    	restore_flags(flags);
-	printk("%s: Transmitter access conflict.\n", dev->name);
-    }
-    else {
-	int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
-	unsigned char *buf = skb->data;
+	if (skb == NULL) 
+	{
+		dev_tint(dev);
+		return 0;
+	}
 
-load_it_again_sam:
-	lp->tx_pkt_start = gp_start;
-    	lp->collisions = 0;
+	save_flags(flags);
 
 	/*
-	 *	Command mode with status cleared should [in theory]
-	 *	mean no more interrupts can be pending on the card.
+	 *	Avoid incoming interrupts between us flipping tbusy and flipping
+	 *	mode as the driver assumes tbusy is a faithful indicator of card
+	 *	state
 	 */
-	outb(AX_SYS, AX_CMD);
-	inb(RX_STATUS);
-	inb(TX_STATUS);
+	 
+	cli();
+	
+	/*
+	 *	Avoid timer-based retransmission conflicts. 
+	 */
+	 
+	if (set_bit(0, (void*)&dev->tbusy) != 0)
+	{
+		restore_flags(flags);
+		printk("%s: Transmitter access conflict.\n", dev->name);
+	}
+	else
+	{
+		int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
+		unsigned char *buf = skb->data;
+
+load_it_again_sam:
+		lp->tx_pkt_start = gp_start;
+    		lp->collisions = 0;
+
+		/*
+		 *	Command mode with status cleared should [in theory]
+		 *	mean no more interrupts can be pending on the card.
+		 */
 	
-	lp->loading=1;
+		outb(AX_SYS, AX_CMD);
+		inb(RX_STATUS);
+		inb(TX_STATUS);
 	
-	/* 
-	 *	Turn interrupts back on while we spend a pleasant afternoon
-	 *	loading bytes into the board 
-	 */
-	restore_flags(flags);
-	outw(0x00, RX_BUF_CLR);		/* Set rx packet area to 0. */
-	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 */
-	if(lp->loading==2)		/* A receive upset our load, despite our best efforts */
-	{
-		if(el_debug>2)
-			printk("%s: burped during tx load.\n", dev->name);
-		goto load_it_again_sam;	/* Sigh... */
-	}
-	outb(AX_XMIT, AX_CMD);		/* fire ... Trigger xmit.  */
-	dev->trans_start = jiffies;
-    }
-
-    if (el_debug > 2)
-	printk(" queued xmit.\n");
-    dev_kfree_skb (skb, FREE_WRITE);
-    return 0;
+		lp->loading=1;
+	
+		/* 
+		 *	Turn interrupts back on while we spend a pleasant afternoon
+		 *	loading bytes into the board 
+		 */
+
+		restore_flags(flags);
+		outw(0x00, RX_BUF_CLR);		/* Set rx packet area to 0. */
+		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 */
+		if(lp->loading==2)		/* A receive upset our load, despite our best efforts */
+		{
+			if(el_debug>2)
+				printk("%s: burped during tx load.\n", dev->name);
+			goto load_it_again_sam;	/* Sigh... */
+		}
+		outb(AX_XMIT, AX_CMD);		/* fire ... Trigger xmit.  */
+		dev->trans_start = jiffies;
+	}
+
+	if (el_debug > 2)
+		printk(" queued xmit.\n");
+	dev_kfree_skb (skb, FREE_WRITE);
+	return 0;
 }
 
 
-/* The typical workload of the driver:
-   Handle the ether interface interrupts. */
-static void
-el_interrupt(int irq, struct pt_regs *regs)
-{
-    struct device *dev = (struct device *)(irq2dev_map[irq]);
-    struct net_local *lp;
-    int ioaddr;
-    int axsr;			/* Aux. status reg. */
+/*
+ *	The typical workload of the driver:
+ *	Handle the ether interface interrupts. 
+ */
+
+static void el_interrupt(int irq, struct pt_regs *regs)
+{
+	struct device *dev = (struct device *)(irq2dev_map[irq]);
+	struct net_local *lp;
+	int ioaddr;
+	int axsr;			/* Aux. status reg. */
 
-    if (dev == NULL  ||  dev->irq != irq) {
-	printk ("3c501 driver: irq %d for unknown device.\n", irq);
-	return;
-    }
+	if (dev == NULL  ||  dev->irq != irq) 
+	{
+		printk ("3c501 driver: irq %d for unknown device.\n", irq);
+		return;
+	}
+
+	ioaddr = dev->base_addr;
+	lp = (struct net_local *)dev->priv;
+
+	/*
+	 *	What happened ?
+	 */
+	 
+	axsr = inb(AX_STATUS);
 
-    ioaddr = dev->base_addr;
-    lp = (struct net_local *)dev->priv;
-    axsr = inb(AX_STATUS);
-
-    if (el_debug > 3)
-      printk("%s: el_interrupt() aux=%#02x", dev->name, axsr);
-    if (dev->interrupt)
-	printk("%s: Reentering the interrupt driver!\n", dev->name);
-    dev->interrupt = 1;
+	/*
+	 *	Log it
+	 */
+
+	if (el_debug > 3)
+		printk("%s: el_interrupt() aux=%#02x", dev->name, axsr);
+	if (dev->interrupt)
+		printk("%s: Reentering the interrupt driver!\n", dev->name);
+	dev->interrupt = 1;
     
-    lp->loading=2;		/* So we can spot loading interruptions */
+	lp->loading=2;		/* So we can spot loading interruptions */
 
-    if (dev->tbusy) {
+	if (dev->tbusy) 
+	{
     
-    	/*
-    	 *	Board in transmit mode.
-    	 */
+    		/*
+    		 *	Board in transmit mode.
+    		 */
     	 
-	int txsr = inb(TX_STATUS);
+		int txsr = inb(TX_STATUS);
 
-	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) {
-	/*
-	 *	FIXME: is there a logic to whether to keep on trying or
-	 *	reset immediately ?
-	 */
-	    printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x"
-		   " gp=%03x rp=%03x.\n", dev->name, txsr, axsr,
-		   inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR));
-	    dev->tbusy = 0;
-	    mark_bh(NET_BH);
-	} else if (txsr & TX_16COLLISIONS) {
-	/*
-	 *	Timed out
-	 */
-	    if (el_debug)
-		printk("%s: Transmit failed 16 times, ethernet jammed?\n",
-		       dev->name);
-	    outb(AX_SYS, AX_CMD);
-	    lp->stats.tx_aborted_errors++;
-	} else if (txsr & TX_COLLISION) {	/* 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);
-	    lp->stats.collisions++;
-	    dev->interrupt = 0;
-	    return;
-	} else {
-	/*
-	 *	It worked.. we will now fall through and receive
-	 */
-	    lp->stats.tx_packets++;
-	    if (el_debug > 6)
-		printk(" Tx succeeded %s\n",
-		       (txsr & TX_RDY) ? "." : "but tx is busy!");
-	/*
-	 *	This is safe the interrupt is atomic WRT itself.
-	 */
-	    dev->tbusy = 0;
-	    mark_bh(NET_BH);	/* In case more to transmit */
+		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) 
+		{
+			/*
+			 *	FIXME: is there a logic to whether to keep on trying or
+			 *	reset immediately ?
+			 */
+			printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x"
+			   " gp=%03x rp=%03x.\n", dev->name, txsr, axsr,
+			inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR));
+			dev->tbusy = 0;
+			mark_bh(NET_BH);
+		} 
+		else if (txsr & TX_16COLLISIONS) 
+		{
+			/*
+			 *	Timed out
+			 */
+			if (el_debug)
+				printk("%s: Transmit failed 16 times, ethernet jammed?\n",dev->name);
+			outb(AX_SYS, AX_CMD);
+			lp->stats.tx_aborted_errors++;
+		}
+		else if (txsr & TX_COLLISION) 
+		{	
+			/*
+			 *	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);
+			lp->stats.collisions++;
+			dev->interrupt = 0;
+			return;
+		}
+		else
+		{
+			/*
+			 *	It worked.. we will now fall through and receive
+			 */
+			lp->stats.tx_packets++;
+			if (el_debug > 6)
+				printk(" Tx succeeded %s\n",
+		       			(txsr & TX_RDY) ? "." : "but tx is busy!");
+			/*
+			 *	This is safe the interrupt is atomic WRT itself.
+			 */
+
+			dev->tbusy = 0;
+			mark_bh(NET_BH);	/* In case more to transmit */
+		}
 	}
-    } else {
-    
-    	/*
-    	 *	In receive mode.
-    	 */
+	else
+	{
+    		/*
+    		 *	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. 
-	 */
-	if (rxsr & RX_MISSED)
-	    lp->stats.rx_missed_errors++;
-	if (rxsr & RX_RUNT) {	/* Handled to avoid board lock-up. */
-	    lp->stats.rx_length_errors++;
-	    if (el_debug > 5) printk(" runt.\n");
-	} else if (rxsr & RX_GOOD) {
-	/*
-	 *	Receive worked.
-	 */
-	    el_receive(dev);
-	} else {			/* Nothing?  Something is broken! */
-	    if (el_debug > 2)
-		printk("%s: No packet seen, rxsr=%02x **resetting 3c501***\n",
-		       dev->name, rxsr);
-	    el_reset(dev);
+		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. 
+		 */
+		if (rxsr & RX_MISSED)
+			lp->stats.rx_missed_errors++;
+		if (rxsr & RX_RUNT) 
+		{	/* Handled to avoid board lock-up. */
+			lp->stats.rx_length_errors++;
+			if (el_debug > 5) 
+				printk(" runt.\n");
+		} 
+		else if (rxsr & RX_GOOD) 
+		{
+			/*
+			 *	Receive worked.
+			 */
+			el_receive(dev);
+		}
+		else
+		{
+			/*
+			 *	Nothing?  Something is broken!
+			 */
+			if (el_debug > 2)
+				printk("%s: No packet seen, rxsr=%02x **resetting 3c501***\n",
+					dev->name, rxsr);
+			el_reset(dev);
+		}
+		if (el_debug > 3)
+			printk(".\n");
 	}
-	if (el_debug > 3)
-	    printk(".\n");
-    }
 
-    /*
-     *	Move into receive mode 
-     */
-    outb(AX_RX, AX_CMD);
-    outw(0x00, RX_BUF_CLR);
-    inb(RX_STATUS);		/* Be certain that interrupts are cleared. */
-    inb(TX_STATUS);
-    dev->interrupt = 0;
-    return;
+	/*
+	 *	Move into receive mode 
+	 */
+
+	outb(AX_RX, AX_CMD);
+	outw(0x00, RX_BUF_CLR);
+	inb(RX_STATUS);		/* Be certain that interrupts are cleared. */
+	inb(TX_STATUS);
+	dev->interrupt = 0;
+	return;
 }
 
 
-/* We have a good packet. Well, not really "good", just mostly not broken.
-   We must check everything to see if it is good. */
-static void
-el_receive(struct device *dev)
+/*
+ *	We have a good packet. Well, not really "good", just mostly not broken.
+ *	We must check everything to see if it is good. 
+ */
+
+static void el_receive(struct device *dev)
 {
-    struct net_local *lp = (struct net_local *)dev->priv;
-    int ioaddr = dev->base_addr;
-    int pkt_len;
-    struct sk_buff *skb;
+	struct net_local *lp = (struct net_local *)dev->priv;
+	int ioaddr = dev->base_addr;
+	int pkt_len;
+	struct sk_buff *skb;
 
-    pkt_len = inw(RX_LOW);
+	pkt_len = inw(RX_LOW);
 
-    if (el_debug > 4)
-      printk(" el_receive %d.\n", pkt_len);
+	if (el_debug > 4)
+		printk(" el_receive %d.\n", pkt_len);
 
-    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;
-    }
+	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
-     */
+	/*
+	 *	Command mode so we can empty the buffer
+	 */
      
-    outb(AX_SYS, AX_CMD);
-
-    skb = dev_alloc_skb(pkt_len+2);
-    /*
-     *	Start of frame
-     */
-    outw(0x00, GP_LOW);
-    if (skb == NULL) {
-	printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-	lp->stats.rx_dropped++;
-	return;
-    } else {
-    	skb_reserve(skb,2);	/* Force 16 byte alignment */
-	skb->dev = dev;
+	outb(AX_SYS, AX_CMD);
+	skb = dev_alloc_skb(pkt_len+2);
 
 	/*
-	 *	The read increments through the bytes. The interrupt
-	 *	handler will fix the pointer when it returns to 
-	 *	receive mode.
+	 *	Start of frame
 	 */
-	 
-	insb(DATAPORT, skb_put(skb,pkt_len), pkt_len);
-	skb->protocol=eth_type_trans(skb,dev);
-	netif_rx(skb);
-	lp->stats.rx_packets++;
-    }
-    return;
-}
-
-static void 
-el_reset(struct device *dev)
-{
-    int ioaddr = dev->base_addr;
-
-    if (el_debug> 2)
-	printk("3c501 reset...");
-    outb(AX_RESET, AX_CMD);	/* Reset the chip */
-    outb(AX_LOOP, AX_CMD);	/* Aux control, irq and loopback enabled */
-    {
-	int i;
-	for (i = 0; i < 6; i++)	/* Set the station address. */
-	    outb(dev->dev_addr[i], ioaddr + i);
-    }
+
+	outw(0x00, GP_LOW);
+	if (skb == NULL) 
+	{
+		printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+		lp->stats.rx_dropped++;
+		return;
+	}
+	else
+	{
+    		skb_reserve(skb,2);	/* Force 16 byte alignment */
+		skb->dev = dev;
+		/*
+		 *	The read increments through the bytes. The interrupt
+		 *	handler will fix the pointer when it returns to 
+		 *	receive mode.
+		 */
+		insb(DATAPORT, skb_put(skb,pkt_len), pkt_len);
+		skb->protocol=eth_type_trans(skb,dev);
+		netif_rx(skb);
+		lp->stats.rx_packets++;
+	}
+	return;
+}
+
+static void  el_reset(struct device *dev)
+{
+	int ioaddr = dev->base_addr;
+
+	if (el_debug> 2)
+		printk("3c501 reset...");
+	outb(AX_RESET, AX_CMD);		/* Reset the chip */
+	outb(AX_LOOP, AX_CMD);		/* Aux control, irq and loopback enabled */
+	{
+		int i;
+		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 */
-    outb(RX_NORM, RX_CMD);	/* Set Rx commands. */
-    inb(RX_STATUS);		/* Clear status. */
-    inb(TX_STATUS);
-    dev->interrupt = 0;
-    dev->tbusy = 0;
-    sti();
+	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 */
+	outb(RX_NORM, RX_CMD);		/* Set Rx commands. */
+	inb(RX_STATUS);			/* Clear status. */
+	inb(TX_STATUS);
+	dev->interrupt = 0;
+	dev->tbusy = 0;
+	sti();
 }
 
-static int
-el1_close(struct device *dev)
+static int el1_close(struct device *dev)
 {
-    int ioaddr = dev->base_addr;
+	int ioaddr = dev->base_addr;
 
-    if (el_debug > 2)
-	printk("%s: Shutting down ethercard at %#x.\n", dev->name, ioaddr);
+	if (el_debug > 2)
+		printk("%s: Shutting down ethercard at %#x.\n", dev->name, ioaddr);
 
-    dev->tbusy = 1;
-    dev->start = 0;
+	dev->tbusy = 1;
+	dev->start = 0;
 
-    /* Free and disable the IRQ. */
-    free_irq(dev->irq);
-    outb(AX_RESET, AX_CMD);	/* Reset the chip */
-    irq2dev_map[dev->irq] = 0;
+	/*
+	 *	Free and disable the IRQ. 
+	 */
 
-    MOD_DEC_USE_COUNT;
-    return 0;
+	free_irq(dev->irq);
+	outb(AX_RESET, AX_CMD);		/* Reset the chip */
+	irq2dev_map[dev->irq] = 0;
+
+	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
-static struct enet_statistics *
-el1_get_stats(struct device *dev)
+static struct enet_statistics *el1_get_stats(struct device *dev)
 {
-    struct net_local *lp = (struct net_local *)dev->priv;
-    return &lp->stats;
+	struct net_local *lp = (struct net_local *)dev->priv;
+	return &lp->stats;
 }
 
 /*
@@ -674,18 +773,21 @@
 }
 
 #ifdef MODULE
+
 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;
 	
-int
-init_module(void)
+int init_module(void)
 {
 	dev_3c501.irq=irq;
 	dev_3c501.base_addr=io;
@@ -694,19 +796,27 @@
 	return 0;
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
-	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+	/*
+	 *	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);
 }
+
 #endif /* MODULE */
 
 /*

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this