patch-2.3.36 linux/drivers/net/com90xx.c

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

diff -u --recursive --new-file v2.3.35/linux/drivers/net/com90xx.c linux/drivers/net/com90xx.c
@@ -1,1164 +0,0 @@
-/*      $Id: com90xx.c,v 1.9 1998/03/21 18:02:51 alan Exp $
-
-   Derived from the original arcnet.c,
-   Written 1994-1996 by Avery Pennarun,
-   which was in turn derived from skeleton.c by Donald Becker.
-
-   **********************
-
-   The original copyright of skeleton.c was as follows:
-
-   skeleton.c Written 1993 by Donald Becker.
-   Copyright 1993 United States Government as represented by the
-   Director, National Security Agency.  This software may only be used
-   and distributed according to the terms of the GNU Public License as
-   modified by SRC, incorporated herein by reference.
-
-   **********************
-
-   For more details, see drivers/net/arcnet.c
-
-   **********************
- */
-
-
-#include <linux/module.h>
-#include <linux/version.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/if_arcnet.h>
-#include <linux/arcdevice.h>
-
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include <net/arp.h>
-
-/**************************************************************************/
-
-/* On a fast computer, the buffer copy from memory to the ARCnet card during
- * a transmit can hog the bus just a little too long.  SLOW_XMIT_COPY
- * replaces the fast memcpy() with a slower for() loop that seems to solve
- * my problems with ftape.
- *
- * Probably a better solution would be to use memcpy_toio (more portable
- * anyway) and modify that routine to support REALLY_SLOW_IO-style
- * defines; ARCnet probably is not the only driver that can screw up an
- * ftape DMA transfer.
- *
- * Turn this on if you have timing-sensitive DMA (ie. a tape drive) and
- * would like to sacrifice a little bit of network speed to reduce tape
- * write retries or some related problem.
- */
-#undef SLOW_XMIT_COPY
-
-
-/* Define this to speed up the autoprobe by assuming if only one io port and
- * shmem are left in the list at Stage 5, they must correspond to each
- * other.
- *
- * This is undefined by default because it might not always be true, and the
- * extra check makes the autoprobe even more careful.  Speed demons can turn
- * it on - I think it should be fine if you only have one ARCnet card
- * installed.
- *
- * If no ARCnet cards are installed, this delay never happens anyway and thus
- * the option has no effect.
- */
-#undef FAST_PROBE
-
-
-/* Internal function declarations */
-#ifdef MODULE
-static
-#endif
-int arc90xx_probe(struct net_device *dev);
-static void arc90xx_rx(struct net_device *dev, int recbuf);
-static int arc90xx_found(struct net_device *dev, int ioaddr, int airq, void * shmem, int more);
-static void arc90xx_inthandler(struct net_device *dev);
-static int arc90xx_reset(struct net_device *dev, int reset_delay);
-static void arc90xx_setmask(struct net_device *dev, u_char mask);
-static void arc90xx_command(struct net_device *dev, u_char command);
-static u_char arc90xx_status(struct net_device *dev);
-static void arc90xx_prepare_tx(struct net_device *dev, u_char * hdr, int hdrlen,
-	     char *data, int length, int daddr, int exceptA, int offset);
-static void arc90xx_openclose(int open);
-
-
-/* Module parameters */
-
-#ifdef MODULE
-static int io = 0x0;		/* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
-static int irq = 0;		/* or use the insmod io= irq= shmem= options */
-static int shmem = 0;
-static char *device;		/* use eg. device="arc1" to change name */
-
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(shmem, "i");
-MODULE_PARM(device, "s");
-#else
-void __init com90xx_setup(char *str, int *ints);
-char __initdata com90xx_explicit = 0;
-
-extern struct net_device arcnet_devs[];
-extern char arcnet_dev_names[][10];
-extern int arcnet_num_devs;
-#endif
-
-
-/* Handy defines for ARCnet specific stuff */
-
-/* The number of low I/O ports used by the card. */
-#define ARCNET_TOTAL_SIZE	16
-
-/* COM 9026 controller chip --> ARCnet register addresses */
-#define _INTMASK (ioaddr+0)	/* writable */
-#define _STATUS  (ioaddr+0)	/* readable */
-#define _COMMAND (ioaddr+1)	/* writable, returns random vals on read (?) */
-#define _RESET  (ioaddr+8)	/* software reset (on read) */
-#define _MEMDATA  (ioaddr+12)	/* Data port for IO-mapped memory */
-#define _ADDR_HI  (ioaddr+15)	/* Control registers for said */
-#define _ADDR_LO  (ioaddr+14)
-#define _CONFIG  (ioaddr+2)	/* Configuration register */
-
-#define RDDATAflag      0x00	/* Next access is a read/~write */
-
-#define ARCSTATUS	inb(_STATUS)
-#define ACOMMAND(cmd) 	outb((cmd),_COMMAND)
-#define AINTMASK(msk)	outb((msk),_INTMASK)
-#define SETCONF		outb(lp->config,_CONFIG)
-#define ARCRESET	inb(_RESET)
-
-static const char *version =
-"com90xx.c: v3.00 97/11/09 Avery Pennarun <apenwarr@worldvisions.ca> et al.\n";
-
-
-/****************************************************************************
- *                                                                          *
- * Probe and initialization                                                 *
- *                                                                          *
- ****************************************************************************/
-
-/* Check for an ARCnet network adaptor, and return '0' if one exists.
- *  If dev->base_addr == 0, probe all likely locations.
- *  If dev->base_addr == 1, always return failure.
- *  If dev->base_addr == 2, allocate space for the device and return success
- *                          (detachable devices only).
- *
- * NOTE: the list of possible ports/shmems is static, so it is retained
- * across calls to arcnet_probe.  So, if more than one ARCnet probe is made,
- * values that were discarded once will not even be tried again.
- *
- * FIXME: grab all devices in one shot and eliminate the big static array.
- */
-
-static int ports[(0x3f0 - 0x200) / 16 + 1] __initdata = {
-	0
-};
-static void * shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata = {
-	0
-};
-
-int __init arc90xx_probe(struct net_device *dev)
-{
-	static int init_once = 0;
-	static int numports = sizeof(ports) / sizeof(ports[0]), numshmems = sizeof(shmems) / sizeof(shmems[0]);
-	int count, status, delayval, ioaddr, numprint, airq, retval = -ENODEV,
-	 openparen = 0;
-	unsigned long airqmask;
-	int *port;
-	void **shmem;
-
-	if (!init_once) {
-		for (count = 0x200; count <= 0x3f0; count += 16)
-			ports[(count - 0x200) / 16] = count;
-		for (count = 0xA0000; count <= 0xFF800; count += 2048)
-			shmems[(count - 0xA0000) / 2048] = ioremap(count, 2048);
-		BUGLVL(D_NORMAL) printk(version);
-		BUGMSG(D_DURING, "space used for probe buffers: %d+%d=%d bytes\n",
-		       sizeof(ports), sizeof(shmems),
-		       sizeof(ports) + sizeof(shmems));
-	}
-	init_once++;
-
-	BUGMSG(D_INIT, "given: base %lXh, IRQ %d, shmem %lXh\n",
-	       dev->base_addr, dev->irq, dev->mem_start);
-
-	if (dev->base_addr > 0x1ff) {	/* Check a single specified port */
-		ports[0] = dev->base_addr;
-		numports = 1;
-	} else if (dev->base_addr > 0)	/* Don't probe at all. */
-		return -ENXIO;
-
-	if (dev->mem_start) {
-		shmems[0] = ioremap(dev->mem_start, 2048);
-		numshmems = 1;
-	}
-	/* Stage 1: abandon any reserved ports, or ones with status==0xFF
-	 * (empty), and reset any others by reading the reset port.
-	 */
-	BUGMSG(D_INIT, "Stage 1: ");
-	numprint = 0;
-	for (port = &ports[0]; port - ports < numports; port++) {
-		numprint++;
-		if (numprint > 8) {
-			BUGMSG2(D_INIT, "\n");
-			BUGMSG(D_INIT, "Stage 1: ");
-			numprint = 1;
-		}
-		BUGMSG2(D_INIT, "%Xh ", *port);
-
-		ioaddr = *port;
-
-		if (check_region(*port, ARCNET_TOTAL_SIZE)) {
-			BUGMSG2(D_INIT_REASONS, "(check_region)\n");
-			BUGMSG(D_INIT_REASONS, "Stage 1: ");
-			BUGLVL(D_INIT_REASONS) numprint = 0;
-			*port = ports[numports - 1];
-			numports--;
-			port--;
-			continue;
-		}
-		if (ARCSTATUS == 0xFF) {
-			BUGMSG2(D_INIT_REASONS, "(empty)\n");
-			BUGMSG(D_INIT_REASONS, "Stage 1: ");
-			BUGLVL(D_INIT_REASONS) numprint = 0;
-			*port = ports[numports - 1];
-			numports--;
-			port--;
-			continue;
-		}
-		ARCRESET;	/* begin resetting card */
-
-		BUGMSG2(D_INIT_REASONS, "\n");
-		BUGMSG(D_INIT_REASONS, "Stage 1: ");
-		BUGLVL(D_INIT_REASONS) numprint = 0;
-	}
-	BUGMSG2(D_INIT, "\n");
-
-	if (!numports) {
-		BUGMSG(D_NORMAL, "Stage 1: No ARCnet cards found.\n");
-		return -ENODEV;
-	}
-	/* Stage 2: we have now reset any possible ARCnet cards, so we can't
-	 * do anything until they finish.  If D_INIT, print the list of
-	 * cards that are left.
-	 */
-	BUGMSG(D_INIT, "Stage 2: ");
-	numprint = 0;
-	for (port = &ports[0]; port - ports < numports; port++) {
-		numprint++;
-		if (numprint > 8) {
-			BUGMSG2(D_INIT, "\n");
-			BUGMSG(D_INIT, "Stage 2: ");
-			numprint = 1;
-		}
-		BUGMSG2(D_INIT, "%Xh ", *port);
-	}
-	BUGMSG2(D_INIT, "\n");
-	JIFFER(RESETtime);
-
-	/* Stage 3: abandon any shmem addresses that don't have the signature
-	 * 0xD1 byte in the right place, or are read-only.
-	 */
-	BUGMSG(D_INIT, "Stage 3: ");
-	numprint = 0;
-	for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) {
-		void * ptr;
-
-		numprint++;
-		if (numprint > 8) {
-			BUGMSG2(D_INIT, "\n");
-			BUGMSG(D_INIT, "Stage 3: ");
-			numprint = 1;
-		}
-		BUGMSG2(D_INIT, "%ph ", *shmem);
-
-		ptr = *shmem;
-
-		if (readb(ptr) != TESTvalue) {
-			BUGMSG2(D_INIT_REASONS, "(mem=%02Xh, not %02Xh)\n",
-				readb(ptr), TESTvalue);
-			BUGMSG(D_INIT_REASONS, "Stage 3: ");
-			BUGLVL(D_INIT_REASONS) numprint = 0;
-			*shmem = shmems[numshmems - 1];
-			numshmems--;
-			shmem--;
-			continue;
-		}
-		/* By writing 0x42 to the TESTvalue location, we also make
-		 * sure no "mirror" shmem areas show up - if they occur
-		 * in another pass through this loop, they will be discarded
-		 * because *cptr != TESTvalue.
-		 */
-		writeb(0x42, ptr);
-		if (readb(ptr) != 0x42) {
-			BUGMSG2(D_INIT_REASONS, "(read only)\n");
-			BUGMSG(D_INIT_REASONS, "Stage 3: ");
-			*shmem = shmems[numshmems - 1];
-			numshmems--;
-			shmem--;
-			continue;
-		}
-		BUGMSG2(D_INIT_REASONS, "\n");
-		BUGMSG(D_INIT_REASONS, "Stage 3: ");
-		BUGLVL(D_INIT_REASONS) numprint = 0;
-	}
-	BUGMSG2(D_INIT, "\n");
-
-	if (!numshmems) {
-		BUGMSG(D_NORMAL, "Stage 3: No ARCnet cards found.\n");
-		return -ENODEV;
-	}
-	/* Stage 4: something of a dummy, to report the shmems that are
-	 * still possible after stage 3.
-	 */
-	BUGMSG(D_INIT, "Stage 4: ");
-	numprint = 0;
-	for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) {
-		numprint++;
-		if (numprint > 8) {
-			BUGMSG2(D_INIT, "\n");
-			BUGMSG(D_INIT, "Stage 4: ");
-			numprint = 1;
-		}
-		BUGMSG2(D_INIT, "%ph ", *shmem);
-	}
-	BUGMSG2(D_INIT, "\n");
-
-	/* Stage 5: for any ports that have the correct status, can disable
-	 * the RESET flag, and (if no irq is given) generate an autoirq,
-	 * register an ARCnet device.
-	 *
-	 * Currently, we can only register one device per probe, so quit
-	 * after the first one is found.
-	 */
-	BUGMSG(D_INIT, "Stage 5: ");
-	numprint = 0;
-	for (port = &ports[0]; port - ports < numports; port++) {
-		numprint++;
-		if (numprint > 8) {
-			BUGMSG2(D_INIT, "\n");
-			BUGMSG(D_INIT, "Stage 5: ");
-			numprint = 1;
-		}
-		BUGMSG2(D_INIT, "%Xh ", *port);
-
-		ioaddr = *port;
-		status = ARCSTATUS;
-
-		if ((status & 0x9D)
-		    != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
-			BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status);
-			BUGMSG(D_INIT_REASONS, "Stage 5: ");
-			BUGLVL(D_INIT_REASONS) numprint = 0;
-			*port = ports[numports - 1];
-			numports--;
-			port--;
-			continue;
-		}
-		ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
-		status = ARCSTATUS;
-		if (status & RESETflag) {
-			BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n",
-				status);
-			BUGMSG(D_INIT_REASONS, "Stage 5: ");
-			BUGLVL(D_INIT_REASONS) numprint = 0;
-			*port = ports[numports - 1];
-			numports--;
-			port--;
-			continue;
-		}
-		/* skip this completely if an IRQ was given, because maybe
-		 * we're on a machine that locks during autoirq!
-		 */
-		if (!dev->irq) {
-			/* if we do this, we're sure to get an IRQ since the
-			 * card has just reset and the NORXflag is on until
-			 * we tell it to start receiving.
-			 */
-			airqmask = probe_irq_on();
-			AINTMASK(NORXflag);
-			mdelay(1);
-			AINTMASK(0);
-			airq = probe_irq_off(airqmask);
-
-			if (airq <= 0) {
-				BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq);
-				BUGMSG(D_INIT_REASONS, "Stage 5: ");
-				BUGLVL(D_INIT_REASONS) numprint = 0;
-				*port = ports[numports - 1];
-				numports--;
-				port--;
-				continue;
-			}
-		} else {
-			airq = dev->irq;
-		}
-
-		BUGMSG2(D_INIT, "(%d,", airq);
-		openparen = 1;
-
-		/* Everything seems okay.  But which shmem, if any, puts
-		 * back its signature byte when the card is reset?
-		 *
-		 * If there are multiple cards installed, there might be
-		 * multiple shmems still in the list.
-		 */
-#ifdef FAST_PROBE
-		if (numports > 1 || numshmems > 1) {
-			ARCRESET;
-			JIFFER(RESETtime);
-		} else {
-			/* just one shmem and port, assume they match */
-			writeb(TESTvalue, shmems[0]);
-		}
-#else
-		ARCRESET;
-		JIFFER(RESETtime);
-#endif
-
-		for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) {
-			void * ptr;
-			ptr = *shmem;
-
-			if (readb(ptr) == TESTvalue) {	/* found one */
-				int probe_more;
-				BUGMSG2(D_INIT, "%ph)\n", *shmem);
-				openparen = 0;
-
-				/* register the card */
-				if (init_once == 1 && numshmems > 1)
-					probe_more = numshmems - 1;
-				else
-					probe_more = 0;
-				retval = arc90xx_found(dev, *port, airq, *shmem, probe_more);
-				if (retval)
-					openparen = 0;
-
-				/* remove shmem from the list */
-				*shmem = shmems[numshmems - 1];
-				numshmems--;
-
-				break;
-			} else {
-				BUGMSG2(D_INIT_REASONS, "%Xh-", readb(ptr));
-			}
-		}
-
-		if (openparen) {
-			BUGMSG2(D_INIT, "no matching shmem)\n");
-			BUGMSG(D_INIT_REASONS, "Stage 5: ");
-			BUGLVL(D_INIT_REASONS) numprint = 0;
-		}
-		*port = ports[numports - 1];
-		numports--;
-		port--;
-
-		if (!retval)
-			break;
-	}
-	BUGMSG(D_INIT_REASONS, "\n");
-
-	/* Now put back TESTvalue on all leftover shmems.
-	 */
-	for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++)
-		writeb(TESTvalue, *shmem);
-
-	if (retval)
-		BUGMSG(D_NORMAL, "Stage 5: No ARCnet cards found.\n");
-	return retval;
-}
-
-/* Set up the struct net_device associated with this card.  Called after
- * probing succeeds.
- */
-static int __init arc90xx_found(struct net_device *dev, int ioaddr, int airq, void * shmem, int more)
-{
-	struct arcnet_local *lp;
-	void *first_mirror, *last_mirror;
-	int mirror_size;
-
-	/* reserve the irq */
-	if (request_irq(airq, &arcnet_interrupt, 0, "arcnet (90xx)", dev)) {
-		BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq);
-		return -ENODEV;
-	}
-	dev->irq = airq;
-
-	/* reserve the I/O region - guaranteed to work by check_region */
-	request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (90xx)");
-	dev->base_addr = ioaddr;
-
-	/* find the real shared memory start/end points, including mirrors */
-#define BUFFER_SIZE (512)
-#define MIRROR_SIZE (BUFFER_SIZE*4)
-
-	/* guess the actual size of one "memory mirror" - the number of
-	 * bytes between copies of the shared memory.  On most cards, it's
-	 * 2k (or there are no mirrors at all) but on some, it's 4k.
-	 */
-	mirror_size = MIRROR_SIZE;
-	if (readb(shmem) == TESTvalue
-	    && readb(shmem - mirror_size) != TESTvalue
-	    && readb(shmem - 2 * mirror_size) == TESTvalue)
-		mirror_size *= 2;
-
-	first_mirror = last_mirror = shmem;
-	while (readb(first_mirror) == TESTvalue)
-		first_mirror -= mirror_size;
-	first_mirror += mirror_size;
-
-	while (readb(last_mirror) == TESTvalue)
-		last_mirror += mirror_size;
-	last_mirror -= mirror_size;
-
-	dev->mem_start = (unsigned long) first_mirror;
-	dev->mem_end = (unsigned long) last_mirror + MIRROR_SIZE - 1;
-	dev->rmem_start = dev->mem_start + BUFFER_SIZE * 0;
-	dev->rmem_end = dev->mem_start + BUFFER_SIZE * 2 - 1;
-
-	/* Initialize the rest of the device structure. */
-
-	dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
-	if (dev->priv == NULL) {
-		free_irq(airq, dev);
-		release_region(ioaddr, ARCNET_TOTAL_SIZE);
-		return -ENOMEM;
-	}
-	memset(dev->priv, 0, sizeof(struct arcnet_local));
-	lp = (struct arcnet_local *) (dev->priv);
-	lp->card_type = ARC_90xx;
-	lp->card_type_str = "COM 90xx";
-	lp->arcnet_reset = arc90xx_reset;
-	lp->asetmask = arc90xx_setmask;
-	lp->astatus = arc90xx_status;
-	lp->acommand = arc90xx_command;
-	lp->openclose_device = arc90xx_openclose;
-	lp->prepare_tx = arc90xx_prepare_tx;
-	lp->inthandler = arc90xx_inthandler;
-
-	/* Fill in the fields of the device structure with generic
-	 * values.
-	 */
-	arcnet_setup(dev);
-
-	/* And now fill particular fields with arcnet values */
-	dev->mtu = 1500;	/* completely arbitrary - agrees with ether, though */
-	dev->hard_header_len = sizeof(struct ClientData);
-	lp->sequence = 1;
-	lp->recbuf = 0;
-
-	BUGMSG(D_DURING, "ClientData header size is %d.\n",
-	       sizeof(struct ClientData));
-	BUGMSG(D_DURING, "HardHeader size is %d.\n",
-	       sizeof(struct archdr));
-
-	/* get and check the station ID from offset 1 in shmem */
-	lp->stationid = readb(first_mirror + 1);
-
-	if (lp->stationid == 0)
-		BUGMSG(D_NORMAL, "WARNING!  Station address 00 is reserved "
-		       "for broadcasts!\n");
-	else if (lp->stationid == 255)
-		BUGMSG(D_NORMAL, "WARNING!  Station address FF may confuse "
-		       "DOS networking programs!\n");
-	dev->dev_addr[0] = lp->stationid;
-
-	BUGMSG(D_NORMAL, "ARCnet COM90xx: station %02Xh found at %03lXh, IRQ %d, "
-	       "ShMem %lXh (%ld*%xh).\n",
-	       lp->stationid,
-	       dev->base_addr, dev->irq, dev->mem_start,
-	 (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size);
-
-	/* OK. We're finished. If there are probably other cards, add other
-	 * COM90xx drivers to the device chain, so they get probed later.
-	 */
-
-#ifndef MODULE
-	while (!com90xx_explicit && more--) {
-		if (arcnet_num_devs < MAX_ARCNET_DEVS) {
-			arcnet_devs[arcnet_num_devs].next = dev->next;
-			dev->next = &arcnet_devs[arcnet_num_devs];
-			dev = dev->next;
-			dev->name = (char *) &arcnet_dev_names[arcnet_num_devs];
-			arcnet_num_devs++;
-		} else {
-			BUGMSG(D_NORMAL, "Too many arcnet devices - no more will be probed for.\n");
-			return 0;
-		}
-		arcnet_makename(dev->name);
-		dev->init = arc90xx_probe;
-	}
-#endif
-
-	return 0;
-}
-
-
-/* Do a hardware reset on the card, and set up necessary registers.
-
- * This should be called as little as possible, because it disrupts the
- * token on the network (causes a RECON) and requires a significant delay.
- *
- * However, it does make sure the card is in a defined state.
- */
-int arc90xx_reset(struct net_device *dev, int reset_delay)
-{
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	short ioaddr = dev->base_addr;
-	int delayval, recbuf = lp->recbuf;
-
-	if (reset_delay == 3) {
-		ARCRESET;
-		return 0;
-	}
-	/* no IRQ's, please! */
-	lp->intmask = 0;
-	SETMASK;
-
-	BUGMSG(D_INIT, "Resetting %s (status=%Xh)\n",
-	       dev->name, ARCSTATUS);
-
-	if (reset_delay) {
-		/* reset the card */
-		ARCRESET;
-		JIFFER(RESETtime);
-	}
-	ACOMMAND(CFLAGScmd | RESETclear);	/* clear flags & end reset */
-	ACOMMAND(CFLAGScmd | CONFIGclear);
-
-	/* verify that the ARCnet signature byte is present */
-	if (readb(dev->mem_start) != TESTvalue) {
-		BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
-		return 1;
-	}
-	/* clear out status variables */
-	recbuf = lp->recbuf = 0;
-	lp->txbuf = 2;
-
-	/* enable extended (512-byte) packets */
-	ACOMMAND(CONFIGcmd | EXTconf);
-
-#ifndef SLOW_XMIT_COPY
-	/* clean out all the memory to make debugging make more sense :) */
-	BUGLVL(D_DURING)
-	    memset_io(dev->mem_start, 0x42, 2048);
-#endif
-
-	/* and enable receive of our first packet to the first buffer */
-	EnableReceiver();
-
-	/* re-enable interrupts */
-	lp->intmask |= NORXflag;
-#ifdef DETECT_RECONFIGS
-	lp->intmask |= RECONflag;
-#endif
-	SETMASK;
-
-	/* done!  return success. */
-	return 0;
-}
-
-
-static void arc90xx_openclose(int open)
-{
-	if (open)
-		MOD_INC_USE_COUNT;
-	else
-		MOD_DEC_USE_COUNT;
-}
-
-
-static void arc90xx_setmask(struct net_device *dev, u_char mask)
-{
-	short ioaddr = dev->base_addr;
-
-	AINTMASK(mask);
-}
-
-
-static u_char arc90xx_status(struct net_device *dev)
-{
-	short ioaddr = dev->base_addr;
-
-	return ARCSTATUS;
-}
-
-
-static void arc90xx_command(struct net_device *dev, u_char cmd)
-{
-	short ioaddr = dev->base_addr;
-
-	ACOMMAND(cmd);
-}
-
-
-/* The actual interrupt handler routine - handle various IRQ's generated
- * by the card.
- */
-static void arc90xx_inthandler(struct net_device *dev)
-{
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	int ioaddr = dev->base_addr, status, boguscount = 3, didsomething;
-
-	AINTMASK(0);
-
-	BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
-	       ARCSTATUS, lp->intmask);
-
-	do {
-		status = ARCSTATUS;
-		didsomething = 0;
-
-		/* RESET flag was enabled - card is resetting and if RX
-		 * is disabled, it's NOT because we just got a packet.
-		 */
-		if (status & RESETflag) {
-			BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n",
-			       status);
-			arc90xx_reset(dev, 0);
-
-			/* all other flag values are just garbage */
-			break;
-		}
-		/* RX is inhibited - we must have received something. */
-		if (status & lp->intmask & NORXflag) {
-			int recbuf = lp->recbuf = !lp->recbuf;
-
-			BUGMSG(D_DURING, "receive irq (status=%Xh)\n",
-			       status);
-
-			/* enable receive of our next packet */
-			EnableReceiver();
-
-			/* Got a packet. */
-			arc90xx_rx(dev, !recbuf);
-
-			didsomething++;
-		}
-		/* it can only be an xmit-done irq if we're xmitting :) */
-		/*if (status&TXFREEflag && !lp->in_txhandler && lp->sending) */
-		if (status & lp->intmask & TXFREEflag) {
-			struct Outgoing *out = &(lp->outgoing);
-			int was_sending = lp->sending;
-
-			lp->intmask &= ~TXFREEflag;
-
-			lp->in_txhandler++;
-			if (was_sending)
-				lp->sending--;
-
-			BUGMSG(D_DURING, "TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
-			    status, out->numsegs, out->segnum, out->skb);
-
-			if (was_sending && !(status & TXACKflag)) {
-				if (lp->lasttrans_dest != 0) {
-					BUGMSG(D_EXTRA, "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
-					     status, lp->lasttrans_dest);
-					lp->stats.tx_errors++;
-					lp->stats.tx_carrier_errors++;
-				} else {
-					BUGMSG(D_DURING, "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
-					       status,
-					       lp->lasttrans_dest);
-				}
-			}
-			/* send packet if there is one */
-			arcnet_go_tx(dev, 0);
-			didsomething++;
-
-			if (lp->intx) {
-				BUGMSG(D_DURING, "TXDONE while intx! (status=%Xh, intx=%d)\n",
-				       ARCSTATUS, lp->intx);
-				lp->in_txhandler--;
-				continue;
-			}
-			if (!lp->outgoing.skb) {
-				BUGMSG(D_DURING, "TX IRQ done: no split to continue.\n");
-
-				/* inform upper layers */
-				if (!lp->txready)
-					arcnet_tx_done(dev, lp);
-				lp->in_txhandler--;
-				continue;
-			}
-			/* if more than one segment, and not all segments
-			 * are done, then continue xmit.
-			 */
-			if (out->segnum < out->numsegs)
-				arcnetA_continue_tx(dev);
-			arcnet_go_tx(dev, 0);
-
-			/* if segnum==numsegs, the transmission is finished;
-			 * free the skb.
-			 */
-			if (out->segnum >= out->numsegs) {
-				/* transmit completed */
-				out->segnum++;
-				if (out->skb) {
-					lp->stats.tx_bytes += out->skb->len;
-					dev_kfree_skb(out->skb);
-				}
-				out->skb = NULL;
-
-				/* inform upper layers */
-				if (!lp->txready)
-					arcnet_tx_done(dev, lp);
-			}
-			didsomething++;
-
-			lp->in_txhandler--;
-		} else if (lp->txready && !lp->sending && !lp->intx) {
-			BUGMSG(D_NORMAL, "recovery from silent TX (status=%Xh)\n",
-			       status);
-			arcnet_go_tx(dev, 0);
-			didsomething++;
-		}
-#ifdef DETECT_RECONFIGS
-		if (status & (lp->intmask) & RECONflag) {
-			ACOMMAND(CFLAGScmd | CONFIGclear);
-			lp->stats.tx_carrier_errors++;
-
-#ifdef SHOW_RECONFIGS
-			BUGMSG(D_NORMAL, "Network reconfiguration detected (status=%Xh)\n",
-			       status);
-#endif				/* SHOW_RECONFIGS */
-
-#ifdef RECON_THRESHOLD
-			/* is the RECON info empty or old? */
-			if (!lp->first_recon || !lp->last_recon ||
-			    jiffies - lp->last_recon > HZ * 10) {
-				if (lp->network_down)
-					BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n");
-				lp->first_recon = lp->last_recon = jiffies;
-				lp->num_recons = lp->network_down = 0;
-
-				BUGMSG(D_DURING, "recon: clearing counters.\n");
-			} else {	/* add to current RECON counter */
-				lp->last_recon = jiffies;
-				lp->num_recons++;
-
-				BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n",
-				       lp->num_recons,
-				 (lp->last_recon - lp->first_recon) / HZ,
-				       lp->network_down);
-
-				/* if network is marked up;
-				 * and first_recon and last_recon are 60+ sec
-				 *   apart;
-				 * and the average no. of recons counted is
-				 *   > RECON_THRESHOLD/min;
-				 * then print a warning message.
-				 */
-				if (!lp->network_down
-				    && (lp->last_recon - lp->first_recon) <= HZ * 60
-				  && lp->num_recons >= RECON_THRESHOLD) {
-					lp->network_down = 1;
-					BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n");
-				} else if (!lp->network_down
-					   && lp->last_recon - lp->first_recon > HZ * 60) {
-					/* reset counters if we've gone for
-					 * over a minute.
-					 */
-					lp->first_recon = lp->last_recon;
-					lp->num_recons = 1;
-				}
-			}
-		} else if (lp->network_down && jiffies - lp->last_recon > HZ * 10) {
-			if (lp->network_down)
-				BUGMSG(D_NORMAL, "cabling restored?\n");
-			lp->first_recon = lp->last_recon = 0;
-			lp->num_recons = lp->network_down = 0;
-
-			BUGMSG(D_DURING, "not recon: clearing counters anyway.\n");
-#endif
-		}
-#endif				/* DETECT_RECONFIGS */
-	} while (--boguscount && didsomething);
-
-	BUGMSG(D_DURING, "net_interrupt complete (status=%Xh, count=%d)\n",
-	       ARCSTATUS, boguscount);
-	BUGMSG(D_DURING, "\n");
-
-	SETMASK;		/* put back interrupt mask */
-}
-
-
-/* A packet has arrived; grab it from the buffers and pass it to the generic
- * arcnet_rx routing to deal with it.
- */
-
-static void arc90xx_rx(struct net_device *dev, int recbuf)
-{
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	int ioaddr = dev->base_addr;
-	union ArcPacket *arcpacket =
-	(union ArcPacket *) phys_to_virt(dev->mem_start + recbuf * 512);
-	u_char *arcsoft;
-	short length, offset;
-	u_char daddr, saddr;
-
-	lp->stats.rx_packets++;
-
-	saddr = arcpacket->hardheader.source;
-
-	/* if source is 0, it's a "used" packet! */
-	if (saddr == 0) {
-		BUGMSG(D_NORMAL, "discarding old packet. (status=%Xh)\n",
-		       ARCSTATUS);
-		lp->stats.rx_errors++;
-		return;
-	}
-	/* Set source address to zero to mark it as old */
-
-	arcpacket->hardheader.source = 0;
-
-	daddr = arcpacket->hardheader.destination;
-
-	if (arcpacket->hardheader.offset1) {	/* Normal Packet */
-		offset = arcpacket->hardheader.offset1;
-		arcsoft = &arcpacket->raw[offset];
-		length = 256 - offset;
-	} else {		/* ExtendedPacket or ExceptionPacket */
-		offset = arcpacket->hardheader.offset2;
-		arcsoft = &arcpacket->raw[offset];
-
-		length = 512 - offset;
-	}
-
-	arcnet_rx(lp, arcsoft, length, saddr, daddr);
-
-	BUGLVL(D_RX) arcnet_dump_packet(lp->adev, arcpacket->raw, length > 240, "rx");
-
-#ifndef SLOW_XMIT_COPY
-	/* clean out the page to make debugging make more sense :) */
-	BUGLVL(D_DURING)
-	    memset((void *) arcpacket->raw, 0x42, 512);
-#endif
-}
-
-
-/* Given an skb, copy a packet into the ARCnet buffers for later transmission
- * by arcnet_go_tx.
- */
-static void arc90xx_prepare_tx(struct net_device *dev, u_char * hdr, int hdrlen,
-	      char *data, int length, int daddr, int exceptA, int offset)
-{
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	union ArcPacket *arcpacket =
-	(union ArcPacket *) phys_to_virt(dev->mem_start + 512 * (lp->txbuf ^ 1));
-
-#ifdef SLOW_XMIT_COPY
-	char *iptr, *iend, *optr;
-#endif
-
-	lp->txbuf = lp->txbuf ^ 1;	/* XOR with 1 to alternate between 2 and 3 */
-
-	length += hdrlen;
-
-	BUGMSG(D_TX, "arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
-	       hdr, length, data);
-
-#ifndef SLOW_XMIT_COPY
-	/* clean out the page to make debugging make more sense :) */
-	BUGLVL(D_DURING)
-	    memset_io(dev->mem_start + lp->txbuf * 512, 0x42, 512);
-#endif
-
-	arcpacket->hardheader.destination = daddr;
-
-	/* load packet into shared memory */
-	if (length <= MTU)	/* Normal (256-byte) Packet */
-		arcpacket->hardheader.offset1 = offset = offset ? offset : 256 - length;
-
-	else if (length >= MinTU || offset) {	/* Extended (512-byte) Packet */
-		arcpacket->hardheader.offset1 = 0;
-		arcpacket->hardheader.offset2 = offset = offset ? offset : 512 - length;
-	} else if (exceptA) {	/* RFC1201 Exception Packet */
-		arcpacket->hardheader.offset1 = 0;
-		arcpacket->hardheader.offset2 = offset = 512 - length - 4;
-
-		/* exception-specific stuff - these four bytes
-		 * make the packet long enough to fit in a 512-byte
-		 * frame.
-		 */
-
-		arcpacket->raw[offset + 0] = hdr[0];
-		arcpacket->raw[offset + 1] = 0xFF;	/* FF flag */
-		arcpacket->raw[offset + 2] = 0xFF;	/* FF padding */
-		arcpacket->raw[offset + 3] = 0xFF;	/* FF padding */
-		offset += 4;
-	} else {		/* "other" Exception packet */
-		/* RFC1051 - set 4 trailing bytes to 0 */
-		memset(&arcpacket->raw[508], 0, 4);
-
-		/* now round up to MinTU */
-		arcpacket->hardheader.offset1 = 0;
-		arcpacket->hardheader.offset2 = offset = 512 - MinTU;
-	}
-
-	/* copy the packet into ARCnet shmem
-	 *  - the first bytes of ClientData header are skipped
-	 */
-
-	memcpy((u_char *) arcpacket + offset, (u_char *) hdr, hdrlen);
-#ifdef SLOW_XMIT_COPY
-	for (iptr = data, iend = iptr + length - hdrlen, optr = (char *) arcpacket + offset + hdrlen;
-	     iptr < iend; iptr++, optr++) {
-		*optr = *iptr;
-		/*udelay(5); */
-	}
-#else
-	memcpy((u_char *) arcpacket + offset + hdrlen, data, length - hdrlen);
-#endif
-
-	BUGMSG(D_DURING, "transmitting packet to station %02Xh (%d bytes)\n",
-	       daddr, length);
-
-	BUGLVL(D_TX) arcnet_dump_packet(dev, arcpacket->raw, length > MTU, "tx");
-
-	lp->lastload_dest = daddr;
-	lp->txready = lp->txbuf;	/* packet is ready for sending */
-}
-
-
-/****************************************************************************
- *                                                                          *
- * Kernel Loadable Module Support                                           *
- *                                                                          *
- ****************************************************************************/
-
-
-#ifdef MODULE
-
-static char devicename[9] = "";
-static struct net_device thiscard =
-{
-	devicename,		/* device name is inserted by linux/drivers/net/net_init.c */
-	0, 0, 0, 0,
-	0, 0,			/* I/O address, IRQ */
-	0, 0, 0, NULL, arc90xx_probe
-};
-
-
-int init_module(void)
-{
-	struct net_device *dev = &thiscard;
-	if (device)
-		strcpy(dev->name, device);
-	else
-		arcnet_makename(dev->name);
-
-	dev->base_addr = io;
-
-	dev->irq = irq;
-	if (dev->irq == 2)
-		dev->irq = 9;
-
-	if (shmem) {
-		dev->mem_start = shmem;
-		dev->mem_end = thiscard.mem_start + 512 * 4 - 1;
-		dev->rmem_start = thiscard.mem_start + 512 * 0;
-		dev->rmem_end = thiscard.mem_start + 512 * 2 - 1;
-	}
-	if (register_netdev(dev) != 0)
-		return -EIO;
-	arcnet_use_count(1);
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	struct net_device *dev = &thiscard;
-	int ioaddr = dev->mem_start;
-
-	if (dev->start)
-		(*dev->stop) (dev);
-
-	/* Flush TX and disable RX */
-	if (ioaddr) {
-		AINTMASK(0);	/* disable IRQ's */
-		ACOMMAND(NOTXcmd);	/* stop transmit */
-		ACOMMAND(NORXcmd);	/* disable receive */
-
-#if defined(IO_MAPPED_BUFFERS) && !defined(COM20020)
-		/* Set the thing back to MMAP mode, in case the old
-		   driver is loaded later */
-		outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
-#endif
-	}
-	if (dev->irq) {
-		free_irq(dev->irq, dev);
-	}
-	if (dev->base_addr)
-		release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
-	unregister_netdev(dev);
-	kfree(dev->priv);
-	dev->priv = NULL;
-	arcnet_use_count(0);
-}
-
-#else
-
-void __init com90xx_setup(char *str, int *ints)
-{
-	struct net_device *dev;
-
-	if (arcnet_num_devs == MAX_ARCNET_DEVS) {
-		printk("com90xx: Too many ARCnet devices registered (max %d).\n",
-		       MAX_ARCNET_DEVS);
-		return;
-	}
-	if (!ints[0] && (!str || !*str)) {
-		printk("com90xx: Disabled.\n");
-		com90xx_explicit++;
-		return;
-	}
-	dev = &arcnet_devs[arcnet_num_devs];
-
-	dev->dev_addr[3] = 3;
-	dev->init = arc90xx_probe;
-
-	switch (ints[0]) {
-	case 4:		/* ERROR */
-		printk("com20020: Too many arguments.\n");
-
-	case 3:		/* Mem address */
-		dev->mem_start = ints[3];
-
-	case 2:		/* IRQ */
-		dev->irq = ints[2];
-
-	case 1:		/* IO address */
-		dev->base_addr = ints[1];
-	}
-
-	dev->name = (char *) &arcnet_dev_names[arcnet_num_devs];
-
-	if (str)
-		strncpy(dev->name, str, 9);
-
-	arcnet_num_devs++;
-}
-#endif				/* MODULE */

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