aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/arcnet
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/arcnet
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/net/arcnet')
-rw-r--r--drivers/net/arcnet/Kconfig140
-rw-r--r--drivers/net/arcnet/Makefile14
-rw-r--r--drivers/net/arcnet/arc-rawmode.c204
-rw-r--r--drivers/net/arcnet/arc-rimi.c368
-rw-r--r--drivers/net/arcnet/arcnet.c1102
-rw-r--r--drivers/net/arcnet/capmode.c296
-rw-r--r--drivers/net/arcnet/com20020-isa.c219
-rw-r--r--drivers/net/arcnet/com20020-pci.c189
-rw-r--r--drivers/net/arcnet/com20020.c357
-rw-r--r--drivers/net/arcnet/com90io.c435
-rw-r--r--drivers/net/arcnet/com90xx.c646
-rw-r--r--drivers/net/arcnet/rfc1051.c253
-rw-r--r--drivers/net/arcnet/rfc1201.c549
13 files changed, 4772 insertions, 0 deletions
diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig
new file mode 100644
index 00000000000..948de2532a1
--- /dev/null
+++ b/drivers/net/arcnet/Kconfig
@@ -0,0 +1,140 @@
+#
+# Arcnet configuration
+#
+
+menu "ARCnet devices"
+ depends on NETDEVICES && (ISA || PCI)
+
+config ARCNET
+ tristate "ARCnet support"
+ ---help---
+ If you have a network card of this type, say Y and check out the
+ (arguably) beautiful poetry in
+ <file:Documentation/networking/arcnet.txt>.
+
+ You need both this driver, and the driver for the particular ARCnet
+ chipset of your card. If you don't know, then it's probably a
+ COM90xx type card, so say Y (or M) to "ARCnet COM90xx chipset
+ support" below.
+
+ You might also want to have a look at the Ethernet-HOWTO, available
+ from <http://www.tldp.org/docs.html#howto>(even though ARCnet
+ is not really Ethernet).
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module will
+ be called arcnet.
+
+config ARCNET_1201
+ tristate "Enable standard ARCNet packet format (RFC 1201)"
+ depends on ARCNET
+ help
+ This allows you to use RFC1201 with your ARCnet card via the virtual
+ arc0 device. You need to say Y here to communicate with
+ industry-standard RFC1201 implementations, like the arcether.com
+ packet driver or most DOS/Windows ODI drivers. Please read the
+ ARCnet documentation in <file:Documentation/networking/arcnet.txt>
+ for more information about using arc0.
+
+config ARCNET_1051
+ tristate "Enable old ARCNet packet format (RFC 1051)"
+ depends on ARCNET
+ ---help---
+ This allows you to use RFC1051 with your ARCnet card via the virtual
+ arc0s device. You only need arc0s if you want to talk to ARCnet
+ software complying with the "old" standard, specifically, the DOS
+ arcnet.com packet driver, Amigas running AmiTCP, and some variants
+ of NetBSD. You do not need to say Y here to communicate with
+ industry-standard RFC1201 implementations, like the arcether.com
+ packet driver or most DOS/Windows ODI drivers. RFC1201 is included
+ automatically as the arc0 device. Please read the ARCnet
+ documentation in <file:Documentation/networking/arcnet.txt> for more
+ information about using arc0e and arc0s.
+
+config ARCNET_RAW
+ tristate "Enable raw mode packet interface"
+ depends on ARCNET
+ help
+ ARCnet "raw mode" packet encapsulation, no soft headers. Unlikely
+ to work unless talking to a copy of the same Linux arcnet driver,
+ but perhaps marginally faster in that case.
+
+config ARCNET_CAP
+ tristate "Enable CAP mode packet interface"
+ depends on ARCNET
+ help
+ ARCnet "cap mode" packet encapsulation. Used to get the hardware
+ acknowledge back to userspace. After the initial protocol byte every
+ packet is stuffed with an extra 4 byte "cookie" which doesn't
+ actually appear on the network. After transmit the driver will send
+ back a packet with protocol byte 0 containing the status of the
+ transmition:
+ 0=no hardware acknowledge
+ 1=excessive nak
+ 2=transmition accepted by the reciever hardware
+
+ Received packets are also stuffed with the extra 4 bytes but it will
+ be random data.
+
+ Cap only listens to protocol 1-8.
+
+config ARCNET_COM90xx
+ tristate "ARCnet COM90xx (normal) chipset driver"
+ depends on ARCNET
+ help
+ This is the chipset driver for the standard COM90xx cards. If you
+ have always used the old ARCnet driver without knowing what type of
+ card you had, this is probably the one for you.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module will
+ be called com90xx.
+
+config ARCNET_COM90xxIO
+ tristate "ARCnet COM90xx (IO mapped) chipset driver"
+ depends on ARCNET
+ ---help---
+ This is the chipset driver for the COM90xx cards, using them in
+ IO-mapped mode instead of memory-mapped mode. This is slower than
+ the normal driver. Only use it if your card doesn't support shared
+ memory.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module will
+ be called com90io.
+
+config ARCNET_RIM_I
+ tristate "ARCnet COM90xx (RIM I) chipset driver"
+ depends on ARCNET
+ ---help---
+ This is yet another chipset driver for the COM90xx cards, but this
+ time only using memory-mapped mode, and no IO ports at all. This
+ driver is completely untested, so if you have one of these cards,
+ please mail <dwmw2@infradead.org>, especially if it works!
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module will
+ be called arc-rimi.
+
+config ARCNET_COM20020
+ tristate "ARCnet COM20020 chipset driver"
+ depends on ARCNET
+ help
+ This is the driver for the new COM20020 chipset. It supports such
+ things as promiscuous mode, so packet sniffing is possible, and
+ extra diagnostic information.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module will
+ be called com20020.
+
+config ARCNET_COM20020_ISA
+ tristate "Support for COM20020 on ISA"
+ depends on ARCNET_COM20020 && ISA
+
+config ARCNET_COM20020_PCI
+ tristate "Support for COM20020 on PCI"
+ depends on ARCNET_COM20020 && PCI
+
+endmenu
+
diff --git a/drivers/net/arcnet/Makefile b/drivers/net/arcnet/Makefile
new file mode 100644
index 00000000000..5861af543d4
--- /dev/null
+++ b/drivers/net/arcnet/Makefile
@@ -0,0 +1,14 @@
+# Makefile for linux/drivers/net/arcnet
+#
+
+obj-$(CONFIG_ARCNET) += arcnet.o
+obj-$(CONFIG_ARCNET_1201) += rfc1201.o
+obj-$(CONFIG_ARCNET_1051) += rfc1051.o
+obj-$(CONFIG_ARCNET_RAW) += arc-rawmode.o
+obj-$(CONFIG_ARCNET_CAP) += capmode.o
+obj-$(CONFIG_ARCNET_COM90xx) += com90xx.o
+obj-$(CONFIG_ARCNET_COM90xxIO) += com90io.o
+obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o
+obj-$(CONFIG_ARCNET_COM20020) += com20020.o
+obj-$(CONFIG_ARCNET_COM20020_ISA) += com20020-isa.o
+obj-$(CONFIG_ARCNET_COM20020_PCI) += com20020-pci.o
diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c
new file mode 100644
index 00000000000..e1ea29b0cd1
--- /dev/null
+++ b/drivers/net/arcnet/arc-rawmode.c
@@ -0,0 +1,204 @@
+/*
+ * Linux ARCnet driver - "raw mode" packet encapsulation (no soft headers)
+ *
+ * Written 1994-1999 by Avery Pennarun.
+ * Derived from skeleton.c by Donald Becker.
+ *
+ * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
+ * for sponsoring the further development of this driver.
+ *
+ * **********************
+ *
+ * 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 General Public License as
+ * modified by SRC, incorporated herein by reference.
+ *
+ * **********************
+ *
+ * For more details, see drivers/net/arcnet.c
+ *
+ * **********************
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/arcdevice.h>
+
+#define VERSION "arcnet: raw mode (`r') encapsulation support loaded.\n"
+
+
+static void rx(struct net_device *dev, int bufnum,
+ struct archdr *pkthdr, int length);
+static int build_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, uint8_t daddr);
+static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
+ int bufnum);
+
+struct ArcProto rawmode_proto =
+{
+ .suffix = 'r',
+ .mtu = XMTU,
+ .rx = rx,
+ .build_header = build_header,
+ .prepare_tx = prepare_tx,
+ .continue_tx = NULL,
+ .ack_tx = NULL
+};
+
+
+static int __init arcnet_raw_init(void)
+{
+ int count;
+
+ printk(VERSION);
+
+ for (count = 0; count < 256; count++)
+ if (arc_proto_map[count] == arc_proto_default)
+ arc_proto_map[count] = &rawmode_proto;
+
+ /* for raw mode, we only set the bcast proto if there's no better one */
+ if (arc_bcast_proto == arc_proto_default)
+ arc_bcast_proto = &rawmode_proto;
+
+ arc_proto_default = &rawmode_proto;
+ return 0;
+}
+
+static void __exit arcnet_raw_exit(void)
+{
+ arcnet_unregister_proto(&rawmode_proto);
+}
+
+module_init(arcnet_raw_init);
+module_exit(arcnet_raw_exit);
+
+MODULE_LICENSE("GPL");
+
+
+/* packet receiver */
+static void rx(struct net_device *dev, int bufnum,
+ struct archdr *pkthdr, int length)
+{
+ struct arcnet_local *lp = dev->priv;
+ struct sk_buff *skb;
+ struct archdr *pkt = pkthdr;
+ int ofs;
+
+ BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
+
+ if (length >= MinTU)
+ ofs = 512 - length;
+ else
+ ofs = 256 - length;
+
+ skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
+ if (skb == NULL) {
+ BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+ lp->stats.rx_dropped++;
+ return;
+ }
+ skb_put(skb, length + ARC_HDR_SIZE);
+ skb->dev = dev;
+
+ pkt = (struct archdr *) skb->data;
+
+ skb->mac.raw = skb->data;
+ skb_pull(skb, ARC_HDR_SIZE);
+
+ /* up to sizeof(pkt->soft) has already been copied from the card */
+ memcpy(pkt, pkthdr, sizeof(struct archdr));
+ if (length > sizeof(pkt->soft))
+ lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
+ pkt->soft.raw + sizeof(pkt->soft),
+ length - sizeof(pkt->soft));
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+
+ skb->protocol = __constant_htons(ETH_P_ARCNET);
+;
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+}
+
+
+/*
+ * Create the ARCnet hard/soft headers for raw mode.
+ * There aren't any soft headers in raw mode - not even the protocol id.
+ */
+static int build_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, uint8_t daddr)
+{
+ int hdr_size = ARC_HDR_SIZE;
+ struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
+
+ /*
+ * Set the source hardware address.
+ *
+ * This is pretty pointless for most purposes, but it can help in
+ * debugging. ARCnet does not allow us to change the source address in
+ * the actual packet sent)
+ */
+ pkt->hard.source = *dev->dev_addr;
+
+ /* see linux/net/ethernet/eth.c to see where I got the following */
+
+ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
+ /*
+ * FIXME: fill in the last byte of the dest ipaddr here to better
+ * comply with RFC1051 in "noarp" mode.
+ */
+ pkt->hard.dest = 0;
+ return hdr_size;
+ }
+ /* otherwise, just fill it in and go! */
+ pkt->hard.dest = daddr;
+
+ return hdr_size; /* success */
+}
+
+
+static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
+ int bufnum)
+{
+ struct arcnet_local *lp = dev->priv;
+ struct arc_hardware *hard = &pkt->hard;
+ int ofs;
+
+ BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
+ lp->next_tx, lp->cur_tx, bufnum);
+
+ length -= ARC_HDR_SIZE; /* hard header is not included in packet length */
+
+ if (length > XMTU) {
+ /* should never happen! other people already check for this. */
+ BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n",
+ length, XMTU);
+ length = XMTU;
+ }
+ if (length > MinTU) {
+ hard->offset[0] = 0;
+ hard->offset[1] = ofs = 512 - length;
+ } else if (length > MTU) {
+ hard->offset[0] = 0;
+ hard->offset[1] = ofs = 512 - length - 3;
+ } else
+ hard->offset[0] = ofs = 256 - length;
+
+ BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n",
+ length,ofs);
+
+ lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
+ lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length);
+
+ lp->lastload_dest = hard->dest;
+
+ return 1; /* done */
+}
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
new file mode 100644
index 00000000000..38c3f033f73
--- /dev/null
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -0,0 +1,368 @@
+/*
+ * Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards
+ *
+ * Written 1994-1999 by Avery Pennarun.
+ * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
+ * Derived from skeleton.c by Donald Becker.
+ *
+ * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
+ * for sponsoring the further development of this driver.
+ *
+ * **********************
+ *
+ * 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 General Public License as
+ * modified by SRC, incorporated herein by reference.
+ *
+ * **********************
+ *
+ * For more details, see drivers/net/arcnet.c
+ *
+ * **********************
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <linux/arcdevice.h>
+
+
+#define VERSION "arcnet: RIM I (entirely mem-mapped) support\n"
+
+
+/* Internal function declarations */
+
+static int arcrimi_probe(struct net_device *dev);
+static int arcrimi_found(struct net_device *dev);
+static void arcrimi_command(struct net_device *dev, int command);
+static int arcrimi_status(struct net_device *dev);
+static void arcrimi_setmask(struct net_device *dev, int mask);
+static int arcrimi_reset(struct net_device *dev, int really_reset);
+static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
+ void *buf, int count);
+static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset,
+ void *buf, int count);
+
+/* Handy defines for ARCnet specific stuff */
+
+/* Amount of I/O memory used by the card */
+#define BUFFER_SIZE (512)
+#define MIRROR_SIZE (BUFFER_SIZE*4)
+
+/* 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 */
+
+#undef ASTATUS
+#undef ACOMMAND
+#undef AINTMASK
+
+#define ASTATUS() readb(_STATUS)
+#define ACOMMAND(cmd) writeb((cmd),_COMMAND)
+#define AINTMASK(msk) writeb((msk),_INTMASK)
+#define SETCONF() writeb(lp->config,_CONFIG)
+
+
+/*
+ * We cannot probe for a RIM I card; one reason is I don't know how to reset
+ * them. In fact, we can't even get their node ID automatically. So, we
+ * need to be passed a specific shmem address, IRQ, and node ID.
+ */
+static int __init arcrimi_probe(struct net_device *dev)
+{
+ BUGLVL(D_NORMAL) printk(VERSION);
+ BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n");
+
+ BUGMSG(D_NORMAL, "Given: node %02Xh, shmem %lXh, irq %d\n",
+ dev->dev_addr[0], dev->mem_start, dev->irq);
+
+ if (dev->mem_start <= 0 || dev->irq <= 0) {
+ BUGMSG(D_NORMAL, "No autoprobe for RIM I; you "
+ "must specify the shmem and irq!\n");
+ return -ENODEV;
+ }
+ /*
+ * Grab the memory region at mem_start for BUFFER_SIZE bytes.
+ * Later in arcrimi_found() the real size will be determined
+ * and this reserve will be released and the correct size
+ * will be taken.
+ */
+ if (!request_mem_region(dev->mem_start, BUFFER_SIZE, "arcnet (90xx)")) {
+ BUGMSG(D_NORMAL, "Card memory already allocated\n");
+ return -ENODEV;
+ }
+ if (dev->dev_addr[0] == 0) {
+ release_mem_region(dev->mem_start, BUFFER_SIZE);
+ BUGMSG(D_NORMAL, "You need to specify your card's station "
+ "ID!\n");
+ return -ENODEV;
+ }
+ return arcrimi_found(dev);
+}
+
+
+/*
+ * Set up the struct net_device associated with this card. Called after
+ * probing succeeds.
+ */
+static int __init arcrimi_found(struct net_device *dev)
+{
+ struct arcnet_local *lp;
+ unsigned long first_mirror, last_mirror, shmem;
+ int mirror_size;
+ int err;
+
+ /* reserve the irq */
+ if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet (RIM I)", dev)) {
+ release_mem_region(dev->mem_start, BUFFER_SIZE);
+ BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
+ return -ENODEV;
+ }
+
+ shmem = dev->mem_start;
+ isa_writeb(TESTvalue, shmem);
+ isa_writeb(dev->dev_addr[0], shmem + 1); /* actually the node ID */
+
+ /* find the real shared memory start/end points, including mirrors */
+
+ /* 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 (isa_readb(shmem) == TESTvalue
+ && isa_readb(shmem - mirror_size) != TESTvalue
+ && isa_readb(shmem - 2 * mirror_size) == TESTvalue)
+ mirror_size *= 2;
+
+ first_mirror = last_mirror = shmem;
+ while (isa_readb(first_mirror) == TESTvalue)
+ first_mirror -= mirror_size;
+ first_mirror += mirror_size;
+
+ while (isa_readb(last_mirror) == TESTvalue)
+ last_mirror += mirror_size;
+ last_mirror -= mirror_size;
+
+ dev->mem_start = first_mirror;
+ dev->mem_end = last_mirror + MIRROR_SIZE - 1;
+
+ /* initialize the rest of the device structure. */
+
+ lp = dev->priv;
+ lp->card_name = "RIM I";
+ lp->hw.command = arcrimi_command;
+ lp->hw.status = arcrimi_status;
+ lp->hw.intmask = arcrimi_setmask;
+ lp->hw.reset = arcrimi_reset;
+ lp->hw.owner = THIS_MODULE;
+ lp->hw.copy_to_card = arcrimi_copy_to_card;
+ lp->hw.copy_from_card = arcrimi_copy_from_card;
+
+ /*
+ * re-reserve the memory region - arcrimi_probe() alloced this reqion
+ * but didn't know the real size. Free that region and then re-get
+ * with the correct size. There is a VERY slim chance this could
+ * fail.
+ */
+ release_mem_region(shmem, BUFFER_SIZE);
+ if (!request_mem_region(dev->mem_start,
+ dev->mem_end - dev->mem_start + 1,
+ "arcnet (90xx)")) {
+ BUGMSG(D_NORMAL, "Card memory already allocated\n");
+ goto err_free_irq;
+ }
+
+ lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1);
+ if (!lp->mem_start) {
+ BUGMSG(D_NORMAL, "Can't remap device memory!\n");
+ goto err_release_mem;
+ }
+
+ /* get and check the station ID from offset 1 in shmem */
+ dev->dev_addr[0] = readb(lp->mem_start + 1);
+
+ BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, "
+ "ShMem %lXh (%ld*%d bytes).\n",
+ dev->dev_addr[0],
+ dev->irq, dev->mem_start,
+ (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size);
+
+ err = register_netdev(dev);
+ if (err)
+ goto err_unmap;
+
+ return 0;
+
+err_unmap:
+ iounmap(lp->mem_start);
+err_release_mem:
+ release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
+err_free_irq:
+ free_irq(dev->irq, dev);
+ return -EIO;
+}
+
+
+/*
+ * 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.
+ */
+static int arcrimi_reset(struct net_device *dev, int really_reset)
+{
+ struct arcnet_local *lp = dev->priv;
+ void __iomem *ioaddr = lp->mem_start + 0x800;
+
+ BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
+
+ if (really_reset) {
+ writeb(TESTvalue, ioaddr - 0x800); /* fake reset */
+ return 0;
+ }
+ ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */
+ ACOMMAND(CFLAGScmd | CONFIGclear);
+
+ /* enable extended (512-byte) packets */
+ ACOMMAND(CONFIGcmd | EXTconf);
+
+ /* done! return success. */
+ return 0;
+}
+
+static void arcrimi_setmask(struct net_device *dev, int mask)
+{
+ struct arcnet_local *lp = dev->priv;
+ void __iomem *ioaddr = lp->mem_start + 0x800;
+
+ AINTMASK(mask);
+}
+
+static int arcrimi_status(struct net_device *dev)
+{
+ struct arcnet_local *lp = dev->priv;
+ void __iomem *ioaddr = lp->mem_start + 0x800;
+
+ return ASTATUS();
+}
+
+static void arcrimi_command(struct net_device *dev, int cmd)
+{
+ struct arcnet_local *lp = dev->priv;
+ void __iomem *ioaddr = lp->mem_start + 0x800;
+
+ ACOMMAND(cmd);
+}
+
+static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
+ void *buf, int count)
+{
+ struct arcnet_local *lp = dev->priv;
+ void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
+ TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
+}
+
+
+static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset,
+ void *buf, int count)
+{
+ struct arcnet_local *lp = dev->priv;
+ void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
+ TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
+}
+
+static int node;
+static int io; /* use the insmod io= irq= node= options */
+static int irq;
+static char device[9]; /* use eg. device=arc1 to change name */
+
+module_param(node, int, 0);
+module_param(io, int, 0);
+module_param(irq, int, 0);
+module_param_string(device, device, sizeof(device), 0);
+MODULE_LICENSE("GPL");
+
+static struct net_device *my_dev;
+
+static int __init arc_rimi_init(void)
+{
+ struct net_device *dev;
+
+ dev = alloc_arcdev(device);
+ if (!dev)
+ return -ENOMEM;
+
+ if (node && node != 0xff)
+ dev->dev_addr[0] = node;
+
+ dev->mem_start = io;
+ dev->irq = irq;
+ if (dev->irq == 2)
+ dev->irq = 9;
+
+ if (arcrimi_probe(dev)) {
+ free_netdev(dev);
+ return -EIO;
+ }
+
+ my_dev = dev;
+ return 0;
+}
+
+static void __exit arc_rimi_exit(void)
+{
+ struct net_device *dev = my_dev;
+ struct arcnet_local *lp = dev->priv;
+
+ unregister_netdev(dev);
+ iounmap(lp->mem_start);
+ release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
+ free_irq(dev->irq, dev);
+ free_netdev(dev);
+}
+
+#ifndef MODULE
+static int __init arcrimi_setup(char *s)
+{
+ int ints[8];
+ s = get_options(s, 8, ints);
+ if (!ints[0])
+ return 1;
+ switch (ints[0]) {
+ default: /* ERROR */
+ printk("arcrimi: Too many arguments.\n");
+ case 3: /* Node ID */
+ node = ints[3];
+ case 2: /* IRQ */
+ irq = ints[2];
+ case 1: /* IO address */
+ io = ints[1];
+ }
+ if (*s)
+ snprintf(device, sizeof(device), "%s", s);
+ return 1;
+}
+__setup("arcrimi=", arcrimi_setup);
+#endif /* MODULE */
+
+module_init(arc_rimi_init)
+module_exit(arc_rimi_exit)
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
new file mode 100644
index 00000000000..4f9f69e22c1
--- /dev/null
+++ b/drivers/net/arcnet/arcnet.c
@@ -0,0 +1,1102 @@
+/*
+ * Linux ARCnet driver - device-independent routines
+ *
+ * Written 1997 by David Woodhouse.
+ * Written 1994-1999 by Avery Pennarun.
+ * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
+ * Derived from skeleton.c by Donald Becker.
+ *
+ * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
+ * for sponsoring the further development of this driver.
+ *
+ * **********************
+ *
+ * The original copyright 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 General Public License as
+ * modified by SRC, incorporated herein by reference.
+ *
+ * **********************
+ *
+ * The change log is now in a file called ChangeLog in this directory.
+ *
+ * Sources:
+ * - Crynwr arcnet.com/arcether.com packet drivers.
+ * - arcnet.c v0.00 dated 1/1/94 and apparently by
+ * Donald Becker - it didn't work :)
+ * - skeleton.c v0.05 dated 11/16/93 by Donald Becker
+ * (from Linux Kernel 1.1.45)
+ * - RFC's 1201 and 1051 - re: TCP/IP over ARCnet
+ * - The official ARCnet COM9026 data sheets (!) thanks to
+ * Ken Cornetet <kcornete@nyx10.cs.du.edu>
+ * - The official ARCnet COM20020 data sheets.
+ * - Information on some more obscure ARCnet controller chips, thanks
+ * to the nice people at SMSC.
+ * - net/inet/eth.c (from kernel 1.1.50) for header-building info.
+ * - Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su>
+ * - Textual information and more alternate source from Joachim Koenig
+ * <jojo@repas.de>
+ */
+
+#define VERSION "arcnet: v3.93 BETA 2000/04/29 - by Avery Pennarun et al.\n"
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+#include <linux/init.h>
+#include <linux/arcdevice.h>
+
+/* "do nothing" functions for protocol drivers */
+static void null_rx(struct net_device *dev, int bufnum,
+ struct archdr *pkthdr, int length);
+static int null_build_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, uint8_t daddr);
+static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
+ int length, int bufnum);
+
+
+/*
+ * one ArcProto per possible proto ID. None of the elements of
+ * arc_proto_map are allowed to be NULL; they will get set to
+ * arc_proto_default instead. It also must not be NULL; if you would like
+ * to set it to NULL, set it to &arc_proto_null instead.
+ */
+ struct ArcProto *arc_proto_map[256], *arc_proto_default,
+ *arc_bcast_proto, *arc_raw_proto;
+
+struct ArcProto arc_proto_null =
+{
+ .suffix = '?',
+ .mtu = XMTU,
+ .is_ip = 0,
+ .rx = null_rx,
+ .build_header = null_build_header,
+ .prepare_tx = null_prepare_tx,
+ .continue_tx = NULL,
+ .ack_tx = NULL
+};
+
+/* Exported function prototypes */
+int arcnet_debug = ARCNET_DEBUG;
+
+EXPORT_SYMBOL(arc_proto_map);
+EXPORT_SYMBOL(arc_proto_default);
+EXPORT_SYMBOL(arc_bcast_proto);
+EXPORT_SYMBOL(arc_raw_proto);
+EXPORT_SYMBOL(arc_proto_null);
+EXPORT_SYMBOL(arcnet_unregister_proto);
+EXPORT_SYMBOL(arcnet_debug);
+EXPORT_SYMBOL(alloc_arcdev);
+EXPORT_SYMBOL(arcnet_interrupt);
+
+/* Internal function prototypes */
+static int arcnet_open(struct net_device *dev);
+static int arcnet_close(struct net_device *dev);
+static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void arcnet_timeout(struct net_device *dev);
+static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, void *daddr, void *saddr,
+ unsigned len);
+static int arcnet_rebuild_header(struct sk_buff *skb);
+static struct net_device_stats *arcnet_get_stats(struct net_device *dev);
+static int go_tx(struct net_device *dev);
+
+static int debug = ARCNET_DEBUG;
+module_param(debug, int, 0);
+MODULE_LICENSE("GPL");
+
+static int __init arcnet_init(void)
+{
+ int count;
+
+ arcnet_debug = debug;
+
+ printk(VERSION);
+
+#ifdef ALPHA_WARNING
+ BUGLVL(D_EXTRA) {
+ printk("arcnet: ***\n"
+ "arcnet: * Read arcnet.txt for important release notes!\n"
+ "arcnet: *\n"
+ "arcnet: * This is an ALPHA version! (Last stable release: v3.02) E-mail\n"
+ "arcnet: * me if you have any questions, comments, or bug reports.\n"
+ "arcnet: ***\n");
+ }
+#endif
+
+ /* initialize the protocol map */
+ arc_raw_proto = arc_proto_default = arc_bcast_proto = &arc_proto_null;
+ for (count = 0; count < 256; count++)
+ arc_proto_map[count] = arc_proto_default;
+
+ BUGLVL(D_DURING)
+ printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n",
+ sizeof(struct arc_hardware), sizeof(struct arc_rfc1201),
+ sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap),
+ sizeof(struct archdr));
+
+ return 0;
+}
+
+static void __exit arcnet_exit(void)
+{
+}
+
+module_init(arcnet_init);
+module_exit(arcnet_exit);
+
+/*
+ * Dump the contents of an sk_buff
+ */
+#if ARCNET_DEBUG_MAX & D_SKB
+void arcnet_dump_skb(struct net_device *dev,
+ struct sk_buff *skb, char *desc)
+{
+ int i;
+
+ printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc);
+ for (i = 0; i < skb->len; i++) {
+ if (i % 16 == 0)
+ printk("\n" KERN_DEBUG "[%04X] ", i);
+ printk("%02X ", ((u_char *) skb->data)[i]);
+ }
+ printk("\n");
+}
+
+EXPORT_SYMBOL(arcnet_dump_skb);
+#endif
+
+
+/*
+ * Dump the contents of an ARCnet buffer
+ */
+#if (ARCNET_DEBUG_MAX & (D_RX | D_TX))
+void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc,
+ int take_arcnet_lock)
+{
+ struct arcnet_local *lp = dev->priv;
+ int i, length;
+ unsigned long flags = 0;
+ static uint8_t buf[512];
+
+ /* hw.copy_from_card expects IRQ context so take the IRQ lock
+ to keep it single threaded */
+ if(take_arcnet_lock)
+ spin_lock_irqsave(&lp->lock, flags);
+
+ lp->hw.copy_from_card(dev, bufnum, 0, buf, 512);
+ if(take_arcnet_lock)
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ /* if the offset[0] byte is nonzero, this is a 256-byte packet */
+ length = (buf[2] ? 256 : 512);
+
+ printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc);
+ for (i = 0; i < length; i++) {
+ if (i % 16 == 0)
+ printk("\n" KERN_DEBUG "[%04X] ", i);
+ printk("%02X ", buf[i]);
+ }
+ printk("\n");
+
+}
+
+EXPORT_SYMBOL(arcnet_dump_packet);
+#endif
+
+
+/*
+ * Unregister a protocol driver from the arc_proto_map. Protocol drivers
+ * are responsible for registering themselves, but the unregister routine
+ * is pretty generic so we'll do it here.
+ */
+void arcnet_unregister_proto(struct ArcProto *proto)
+{
+ int count;
+
+ if (arc_proto_default == proto)
+ arc_proto_default = &arc_proto_null;
+ if (arc_bcast_proto == proto)
+ arc_bcast_proto = arc_proto_default;
+ if (arc_raw_proto == proto)
+ arc_raw_proto = arc_proto_default;
+
+ for (count = 0; count < 256; count++) {
+ if (arc_proto_map[count] == proto)
+ arc_proto_map[count] = arc_proto_default;
+ }
+}
+
+
+/*
+ * Add a buffer to the queue. Only the interrupt handler is allowed to do
+ * this, unless interrupts are disabled.
+ *
+ * Note: we don't check for a full queue, since there aren't enough buffers
+ * to more than fill it.
+ */
+static void release_arcbuf(struct net_device *dev, int bufnum)
+{
+ struct arcnet_local *lp = dev->priv;
+ int i;
+
+ lp->buf_queue[lp->first_free_buf++] = bufnum;
+ lp->first_free_buf %= 5;
+