ArcNet patch [PATCH]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,
 I have made some updates to the ArcNet driver - mostly com20020.
I wonder who is the actual maintainer but I hope he reads this mailing
list and will take a look of the patches I have made.

I based it on RedHat's 2.4.20-31.9 kernel.

First: I got the com20020-pcmcia driver to work. It had to do with double
allocation of the IO-region. Both the cardmgr layer and the driver itself
tried to allocate the region -> error. Now the driver works but you
still can't unload it.

Second: I made minor changes to make the com20020-isa work on our special
SA1110-based hardware. The main thing is that the bus is 16 bit not 8 bit
as the isa-driver assumes.

Third and most important: I made the driver be able to send back  
information about the transmit status of the packets (not acknowledged,
acknowledged or excnak'ed) so I could build a highlevel protocol which
needs that information in userspace using a raw socket. I made a new
protocol driver (capmode.c) for that perpose.
What this protocol does it that it adds a "cookie" of 4 (sizeof(int))
bytes to each packet. These are not transmitted but used to identify the
packets between the driver and userspace. When a packet is sent the result
is sent back to userspace as a packet with protocol byte 0 containing the
cookie and the byte 0-2 to identicate how the transmission was completed.

Esben Nielsen
Vestas Wind Systems A/S
Denmark


diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/arcnet.c linux-2.4.20-31.9custom/drivers/net/arcnet/arcnet.c
--- linux-2.4.20-31.9/drivers/net/arcnet/arcnet.c	2004-04-13 23:07:11.000000000 +0200
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/arcnet.c	2004-05-27 17:56:08.000000000 +0200
@@ -52,7 +52,10 @@
 #include <net/arp.h>
 #include <linux/init.h>
 #include <linux/arcdevice.h>
-
+#ifdef CONFIG_SA1100_CT6001
+#include <asm/arch/hardware.h>
+#endif
+  
 
 /* "do nothing" functions for protocol drivers */
 static void null_rx(struct net_device *dev, int bufnum,
@@ -69,15 +72,19 @@
  * 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;
+struct ArcProto *arc_proto_map[256], *arc_proto_default, 
+  *arc_bcast_proto, *arc_raw_proto;
 
 struct ArcProto arc_proto_null =
 {
 	'?',
 	XMTU,
+	0, /* Is not an IP protocol */
 	null_rx,
 	null_build_header,
-	null_prepare_tx
+	null_prepare_tx,
+	NULL,
+	NULL
 };
 
 
@@ -87,6 +94,7 @@
 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);
@@ -127,7 +135,7 @@
 #endif
 
 	/* initialize the protocol map */
-	arc_proto_default = arc_bcast_proto = &arc_proto_null;
+	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;
 
@@ -251,6 +259,8 @@
 		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)
@@ -344,7 +354,7 @@
 	dev->mtu = choose_mtu();
 
 	dev->addr_len = 1;
-	dev->tx_queue_len = 30;
+	dev->tx_queue_len = 50;
 	dev->broadcast[0] = 0x00;	/* for us, broadcasts are address 0 */
 	dev->watchdog_timeo = TX_TIMEOUT;
 
@@ -393,8 +403,11 @@
 	/* try to put the card in a defined state - if it fails the first
 	 * time, actually reset it.
 	 */
-	if (ARCRESET(0) && ARCRESET(1))
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+	if (ARCRESET(0) && ARCRESET(1)) {
+	  	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 		return -ENODEV;
+	}
 
 	newmtu = choose_mtu();
 	if (newmtu < dev->mtu)
@@ -413,6 +426,7 @@
 
 	/* initialize buffers */
 	atomic_set(&lp->buf_lock, 1);
+
 	lp->next_buf = lp->first_free_buf = 0;
 	release_arcbuf(dev, 0);
 	release_arcbuf(dev, 1);
@@ -423,8 +437,11 @@
 
 	lp->rfc1201.sequence = 1;
 
+
 	/* bring up the hardware driver */
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 	ARCOPEN(1);
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 
 	if (dev->dev_addr[0] == 0)
 		BUGMSG(D_NORMAL, "WARNING!  Station address 00 is reserved "
@@ -433,17 +450,24 @@
 		BUGMSG(D_NORMAL, "WARNING!  Station address FF may confuse "
 		       "DOS networking programs!\n");
 
-	if (ASTATUS() & RESETflag)
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+	if (ASTATUS() & RESETflag) {
+	  	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 		ACOMMAND(CFLAGScmd | RESETclear);
+	}
 
+
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 	/* make sure we're ready to receive IRQ's. */
 	AINTMASK(0);
 	udelay(1);		/* give it time to set the mask before
 				 * we reset it again. (may not even be
 				 * necessary)
 				 */
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 	lp->intmask = NORXflag | RECONflag;
 	AINTMASK(lp->intmask);
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 
 	netif_start_queue(dev);
 
@@ -489,28 +513,36 @@
 		BUGMSG(D_NORMAL, "arcnet_header: Yikes!  skb->len(%d) != len(%d)!\n",
 		       skb->len, len);
 
-	/*
-	 * if the dest addr isn't provided, we can't choose an encapsulation!
-	 * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a
-	 * real header when we do rebuild_header. 
-	 */
-	if (!daddr) {
+ 	/* Type is host order - ? */
+ 	if(type == ETH_P_ARCNET) {
+ 		proto = arc_raw_proto;
+ 		BUGMSG(D_DEBUG, "arc_raw_proto used. proto=%x\n",proto);
+ 		_daddr = daddr ? *(uint8_t *) daddr : 0;
+ 	}
+ 	else if (!daddr) {
+		/*
+		 * if the dest addr isn't provided, we can't choose an encapsulation!
+		 * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a
+		 * real header when we do rebuild_header. 
+		 */
 		*(uint16_t *) skb_push(skb, 2) = type;
 		if (skb->nh.raw - skb->mac.raw != 2)
-			BUGMSG(D_NORMAL, "arcnet_header: Yikes!  diff (%d) is not 2!\n",
+			BUGMSG(D_EXTRA, "arcnet_header: Yikes!  diff (%d) is not 2!\n",
 			       skb->nh.raw - skb->mac.raw);
 		return -2;	/* return error -- can't transmit yet! */
 	}
-	/* otherwise, we can just add the header as usual. */
-	_daddr = *(uint8_t *) daddr;
-	proto_num = lp->default_proto[_daddr];
-	proto = arc_proto_map[proto_num];
-	BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n",
-	       proto_num, proto->suffix);
-	if (proto == &arc_proto_null && arc_bcast_proto != proto) {
-		BUGMSG(D_DURING, "actually, let's use '%c' instead.\n",
-		       arc_bcast_proto->suffix);
-		proto = arc_bcast_proto;
+	else {
+		/* otherwise, we can just add the header as usual. */
+		_daddr = *(uint8_t *) daddr;
+		proto_num = lp->default_proto[_daddr];
+		proto = arc_proto_map[proto_num];
+		BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n",
+		       proto_num, proto->suffix);
+		if (proto == &arc_proto_null && arc_bcast_proto != proto) {
+			BUGMSG(D_DURING, "actually, let's use '%c' instead.\n",
+			       arc_bcast_proto->suffix);
+			proto = arc_bcast_proto;
+		}
 	}
 	return proto->build_header(skb, dev, type, _daddr);
 }
@@ -537,6 +569,7 @@
 		return 0;
 	}
 	type = *(uint16_t *) skb_pull(skb, 2);
+	BUGMSG(D_DURING, "rebuild header for protocol %Xh\n", type);
 
 	if (type == ETH_P_IP) {
 #ifdef CONFIG_INET
@@ -575,8 +608,8 @@
 	int txbuf;
 
 	BUGMSG(D_DURING,
-	       "transmit requested (status=%Xh, txbufs=%d/%d, len=%d)\n",
-	       ASTATUS(), lp->cur_tx, lp->next_tx, skb->len);
+	       "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
+	       ASTATUS(), lp->cur_tx, lp->next_tx, skb->len,skb->protocol);
 
 	pkt = (struct archdr *) skb->data;
 	soft = &pkt->soft.rfc1201;
@@ -600,8 +633,10 @@
 
 	txbuf = get_arcbuf(dev);
 	if (txbuf != -1) {
-		if (proto->prepare_tx(dev, pkt, skb->len, txbuf)) {
-			/* done right away */
+		if (proto->prepare_tx(dev, pkt, skb->len, txbuf) &&
+		    !proto->ack_tx) {
+			/* done right away and we don't want to acknowledge
+			   the package later - forget about it now */
 			lp->stats.tx_bytes += skb->len;
 			dev_kfree_skb(skb);
 		} else {
@@ -610,12 +645,11 @@
 			lp->outgoing.skb = skb;
 			lp->outgoing.pkt = pkt;
 
-			if (!proto->continue_tx)
-				BUGMSG(D_NORMAL, "bug! prep_tx==0, but no continue_tx!\n");
-			else if (proto->continue_tx(dev, txbuf)) {
-				BUGMSG(D_NORMAL,
-				       "bug! continue_tx finished the first time! "
-				       "(proto='%c')\n", proto->suffix);
+			if (proto->continue_tx &&
+			    proto->continue_tx(dev, txbuf)) {
+			  BUGMSG(D_NORMAL,
+				 "bug! continue_tx finished the first time! "
+				 "(proto='%c')\n", proto->suffix);
 			}
 		}
 
@@ -623,10 +657,19 @@
 	} else
 		dev_kfree_skb(skb);
 
+	BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
 	/* make sure we didn't ignore a TX IRQ while we were in here */
 	AINTMASK(0);
-	lp->intmask |= TXFREEflag;
+#ifdef CONFIG_SA1100_CT6001_NOT
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+	/* Clear the irq pin as well to enforce a the edge to go up
+	   to get the IRQ on the edge triggered irq-controller. */
+	GEDR|=GPIO_ARC_IRQ;
+#endif
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+	lp->intmask |= TXFREEflag|EXCNAKflag;
 	AINTMASK(lp->intmask);
+	BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
 
 	return 0;		/* no need to try again */
 }
@@ -658,7 +701,8 @@
 	lp->stats.tx_packets++;
 	lp->lasttrans_dest = lp->lastload_dest;
 	lp->lastload_dest = 0;
-	lp->intmask |= TXFREEflag;
+	lp->excnak_pending = 0;
+	lp->intmask |= TXFREEflag|EXCNAKflag;
 
 	return 1;
 }
@@ -672,6 +716,7 @@
 	int status = ASTATUS();
 	char *msg;
 
+	BUGMSG(D_DEBUG, "%s: %d: %s: status: %x\n",__FILE__,__LINE__,__FUNCTION__,status);
 	save_flags(flags);
 	cli();
 
@@ -685,9 +730,9 @@
 	}
 	lp->stats.tx_errors++;
 
-	/* make sure we didn't miss a TX IRQ */
+	/* make sure we didn't miss a TX or a EXC NAK IRQ */
 	AINTMASK(0);
-	lp->intmask |= TXFREEflag;
+	lp->intmask |= TXFREEflag|EXCNAKflag;
 	AINTMASK(lp->intmask);
 
 	restore_flags(flags);
@@ -712,7 +757,7 @@
 {
 	struct net_device *dev = dev_id;
 	struct arcnet_local *lp;
-	int recbuf, status, didsomething, boguscount;
+	int recbuf, status, diagstatus, didsomething, boguscount;
 
 	BUGMSG(D_DURING, "\n");
 
@@ -744,6 +789,10 @@
 	boguscount = 5;
 	do {
 		status = ASTATUS();
+                diagstatus = (status >> 8) & 0xFF;
+
+		BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n",
+			__FILE__,__LINE__,__FUNCTION__,status);
 		didsomething = 0;
 
 		/*
@@ -783,24 +832,55 @@
 			}
 			didsomething++;
 		}
+
+		if((diagstatus & EXCNAKflag)) {
+			BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n", 
+			       diagstatus);
+
+                        ACOMMAND(NOTXcmd);      /* disable transmit */
+                        lp->excnak_pending = 1;
+
+                        ACOMMAND(EXCNAKclear);
+			lp->intmask &= ~(EXCNAKflag);
+                        didsomething++;
+                }
+
+
 		/* a transmit finished, and we're interested in it. */
 		if ((status & lp->intmask & TXFREEflag) || lp->timed_out) {
-			lp->intmask &= ~TXFREEflag;
+			lp->intmask &= ~(TXFREEflag|EXCNAKflag);
 
 			BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status);
 
-			if (lp->cur_tx != -1 && !(status & TXACKflag) && !lp->timed_out) {
-				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);
+			if (lp->cur_tx != -1 && !lp->timed_out) {
+				if(!(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);
+					}
+				}
+
+				if (lp->outgoing.proto && 
+				    lp->outgoing.proto->ack_tx) {
+				  int ackstatus;
+				  if(status & TXACKflag)
+                                    ackstatus=2;
+                                  else if(lp->excnak_pending)
+                                    ackstatus=1;
+                                  else
+                                    ackstatus=0;
+
+                                  lp->outgoing.proto
+                                    ->ack_tx(dev, ackstatus);
 				}
 			}
 			if (lp->cur_tx != -1)
@@ -820,8 +900,11 @@
 					if (lp->outgoing.proto->continue_tx(dev, txbuf)) {
 						/* that was the last segment */
 						lp->stats.tx_bytes += lp->outgoing.skb->len;
-						dev_kfree_skb_irq(lp->outgoing.skb);
-						lp->outgoing.proto = NULL;
+						if(!lp->outgoing.proto->ack_tx)
+						  {
+						    dev_kfree_skb_irq(lp->outgoing.skb);
+						    lp->outgoing.proto = NULL;
+						  }
 					}
 					lp->next_tx = txbuf;
 				}
@@ -927,7 +1010,7 @@
 	}
 
 	/* get the full header, if possible */
-	if (sizeof(pkt.soft) < length)
+	if (sizeof(pkt.soft) <= length)
 		lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft));
 	else {
 		memset(&pkt.soft, 0, sizeof(pkt.soft));
@@ -942,7 +1025,7 @@
 	lp->stats.rx_bytes += length + ARC_HDR_SIZE;
 
 	/* call the right receiver for the protocol */
-	if (arc_proto_map[soft->proto] != &arc_proto_null) {
+	if (arc_proto_map[soft->proto]->is_ip) {
 		BUGLVL(D_PROTO) {
 			struct ArcProto
 			*oldp = arc_proto_map[lp->default_proto[pkt.hard.source]],
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/arc-rawmode.c linux-2.4.20-31.9custom/drivers/net/arcnet/arc-rawmode.c
--- linux-2.4.20-31.9/drivers/net/arcnet/arc-rawmode.c	2004-04-13 23:07:11.000000000 +0200
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/arc-rawmode.c	2004-05-27 17:56:08.000000000 +0200
@@ -41,15 +41,18 @@
 			unsigned short type, uint8_t daddr);
 static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
 		      int bufnum);
-
+static int ack_tx(struct net_device *dev, int acked);
 
 struct ArcProto rawmode_proto =
 {
 	'r',
 	XMTU,
+	0, /* Isn't IP */
 	rx,
 	build_header,
-	prepare_tx
+	prepare_tx,
+	NULL,
+	ack_tx
 };
 
 
@@ -127,7 +130,8 @@
 
 	BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
 
-	skb->protocol = 0;
+	skb->protocol = __constant_htons(ETH_P_ARCNET);
+;
 	netif_rx(skb);
 	dev->last_rx = jiffies;
 }
@@ -196,6 +200,9 @@
 	} 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);
 
@@ -203,3 +210,44 @@
 
 	return 1;		/* done */
 }
+
+
+static int ack_tx(struct net_device *dev, int acked)
+{
+  struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+  struct sk_buff *skb;
+  struct archdr *pkt;
+  int ofs,length=2;
+  
+  BUGMSG(D_NORMAL, "arc-rawmode: ack_tx: protocol: %x: result: %s\n",
+	 lp->outgoing.skb->protocol, acked ? "OK":"Failed");
+  
+  /* Now alloc a skb to send back up through the layers: */
+  skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
+  if (skb == NULL) {
+	  BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+	  return -1;
+  }
+
+  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);
+
+  memcpy(pkt, lp->outgoing.skb->data, sizeof(struct archdr));
+  pkt->soft.raw[0]=0;
+  pkt->soft.raw[1]=acked;
+
+  skb->protocol = __constant_htons(ETH_P_ARCNET);
+
+  netif_rx(skb);
+
+
+  dev_kfree_skb_irq(lp->outgoing.skb);
+  lp->outgoing.proto = NULL; /* We are always finished when in this protocol */
+  
+  return 0;
+}
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/capmode.c linux-2.4.20-31.9custom/drivers/net/arcnet/capmode.c
--- linux-2.4.20-31.9/drivers/net/arcnet/capmode.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/capmode.c	2004-06-17 11:53:04.000000000 +0200
@@ -0,0 +1,296 @@
+/*
+ * Linux ARCnet driver - "cap mode" packet encapsulation.
+ * It adds sequence numbers to packets for communicating between a user space 
+ * application and the driver. After a transmit it sends a packet with protocol
+ * byte 0 back up to the userspace containing the sequence number of the packet
+ * plus the transmit-status on the ArcNet.
+ * 
+ * Written 2002-4 by Esben Nielsen, Vestas Wind Systems A/S
+ * Derived from arc-rawmode.c by Avery Pennarun.
+ * arc-rawmode was in turned based on skeleton.c, see below.
+ *
+ * **********************
+ *
+ * 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: cap mode (`c') 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);
+static int ack_tx(struct net_device *dev, int acked);
+
+
+struct ArcProto capmode_proto =
+{
+	'r',
+	XMTU,
+	0,
+       	rx,
+	build_header,
+	prepare_tx,
+	NULL,
+	ack_tx
+};
+
+
+void arcnet_cap_init(void)
+{
+	int count;
+
+	for (count = 1; count <= 8; count++)
+		if (arc_proto_map[count] == arc_proto_default)
+			arc_proto_map[count] = &capmode_proto;
+
+	/* for cap mode, we only set the bcast proto if there's no better one */
+	if (arc_bcast_proto == arc_proto_default)
+		arc_bcast_proto = &capmode_proto;
+
+	arc_proto_default = &capmode_proto; 
+	arc_raw_proto = &capmode_proto;
+}
+
+
+#ifdef MODULE
+
+int __init init_module(void)
+{
+	printk(VERSION);
+	arcnet_cap_init();
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	arcnet_unregister_proto(&capmode_proto);
+}
+
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
+
+
+
+/* packet receiver */
+static void rx(struct net_device *dev, int bufnum,
+	       struct archdr *pkthdr, int length)
+{
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct sk_buff *skb;
+	struct archdr *pkt = pkthdr;
+	char *pktbuf, *pkthdrbuf;
+	int ofs;
+
+	BUGMSG(D_DURING, "it's a raw(cap) packet (length=%d)\n", length);
+
+	if (length >= MinTU)
+		ofs = 512 - length;
+	else
+		ofs = 256 - length;
+
+	skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), 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 + sizeof(int));
+	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 */
+	/* squeeze in an int for the cap encapsulation */
+
+	/* use these variables to be sure we count in bytes, not in 
+	   sizeof(struct archdr) */
+	pktbuf=(char*)pkt;
+	pkthdrbuf=(char*)pkthdr;
+	memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto));
+	memcpy(pktbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)+sizeof(int), 
+	       pkthdrbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto), 
+	       sizeof(struct archdr)-ARC_HDR_SIZE-sizeof(pkt->soft.cap.proto));
+	
+	if (length > sizeof(pkt->soft))
+		lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
+				      pkt->soft.raw + sizeof(pkt->soft) 
+				      + sizeof(int),
+				      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 cap mode.
+ * There aren't any soft headers in cap 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);
+
+	BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n",
+	       *((int*)&pkt->soft.cap.cookie[0]));
+	/*
+	 * 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 = (struct arcnet_local *) dev->priv;
+	struct arc_hardware *hard = &pkt->hard;
+	int ofs;
+
+
+	/* hard header is not included in packet length */
+	length -= ARC_HDR_SIZE;	
+	/* And neither is the cookie field */
+	length -= sizeof(int);
+
+	BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
+	       lp->next_tx, lp->cur_tx, bufnum);
+
+	BUGMSG(D_PROTO, "Sending for cap packet %x.\n",
+	       *((int*)&pkt->soft.cap.cookie[0]));
+
+	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);
+
+	// Copy the arcnet-header + the protocol byte down:
+	lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
+	lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft.cap.proto,
+			    sizeof(pkt->soft.cap.proto));
+
+	// Skip the extra integer we have written into it as a cookie
+	// but write the rest of the message:
+	lp->hw.copy_to_card(dev, bufnum, ofs+1, 
+			    ((unsigned char*)&pkt->soft.cap.mes),length-1);
+
+	lp->lastload_dest = hard->dest;
+
+	return 1;		/* done */
+}
+
+
+static int ack_tx(struct net_device *dev, int acked)
+{
+  struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+  struct sk_buff *ackskb;
+  struct archdr *ackpkt;
+  int length=sizeof(struct arc_cap);
+  
+  BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n",
+	 lp->outgoing.skb->protocol, acked);
+  
+  BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx");
+
+  /* Now alloc a skb to send back up through the layers: */
+  ackskb = alloc_skb(length + ARC_HDR_SIZE , GFP_ATOMIC);
+  if (ackskb == NULL) {
+	  BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n");
+	  goto free_outskb;
+  }
+
+  skb_put(ackskb, length + ARC_HDR_SIZE );
+  ackskb->dev = dev;
+  
+  ackpkt = (struct archdr *) ackskb->data;
+
+  ackskb->mac.raw = ackskb->data;
+  /* skb_pull(ackskb, ARC_HDR_SIZE); */
+  
+  
+  memcpy(ackpkt, lp->outgoing.skb->data, ARC_HDR_SIZE+sizeof(struct arc_cap));
+  ackpkt->soft.cap.proto=0; /* using protocol 0 for acknowledge */
+  ackpkt->soft.cap.mes.ack=acked;
+
+  BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n",
+	 *((int*)&ackpkt->soft.cap.cookie[0]));
+
+  ackskb->protocol = __constant_htons(ETH_P_ARCNET);
+
+  BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv");
+  netif_rx(ackskb);
+
+ free_outskb:
+  dev_kfree_skb_irq(lp->outgoing.skb);
+  lp->outgoing.proto = NULL; /* We are always finished when in this protocol */
+  
+  return 0;
+}
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/com20020.c linux-2.4.20-31.9custom/drivers/net/arcnet/com20020.c
--- linux-2.4.20-31.9/drivers/net/arcnet/com20020.c	2004-04-13 23:07:09.000000000 +0200
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/com20020.c	2004-05-27 17:56:40.000000000 +0200
@@ -117,7 +117,7 @@
 	lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2);
 	/* set node ID to 0x42 (but transmitter is disabled, so it's okay) */
 	SETCONF;
-	outb(0x42, ioaddr + 7);
+	outb(0x42, ioaddr + BUS_ALIGN*7);
 
 	status = ASTATUS();
 
@@ -129,7 +129,7 @@
 
 	/* Enable TX */
 	outb(0x39, _CONFIG);
-	outb(inb(ioaddr + 8), ioaddr + 7);
+	outb(inb(ioaddr + BUS_ALIGN*8), ioaddr + BUS_ALIGN*7);
 
 	ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
 
@@ -152,7 +152,8 @@
 /* Set up the struct net_device associated with this card.  Called after
  * probing succeeds.
  */
-int __devinit com20020_found(struct net_device *dev, int shared)
+int __devinit com20020_found(struct net_device *dev, int shared, 
+			     int request_io)
 {
 	struct arcnet_local *lp;
 	int ioaddr = dev->base_addr;
@@ -177,7 +178,7 @@
 	arcdev_setup(dev);
 
 	if (!dev->dev_addr[0])
-		dev->dev_addr[0] = inb(ioaddr + 8);	/* FIXME: do this some other way! */
+		dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8);	/* FIXME: do this some other way! */
 
 	SET_SUBADR(SUB_SETUP1);
 	outb(lp->setup, _XREG);
@@ -191,7 +192,7 @@
 		mdelay(1);
 		outb(0x18, _COMMAND);
 	}
-
+	printk("%s: %d\n",__FILE__,__LINE__);
 
 	lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 1;
 	/* Default 0x38 + register: Node ID */
@@ -205,7 +206,9 @@
 		return -ENODEV;
 	}
 	/* reserve the I/O region */
-	if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
+	if (request_io &&
+	    !request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
+		BUGMSG(D_NORMAL, "Can't get region 0x%x!\n", ioaddr);
 		free_irq(dev->irq, dev);
 		return -EBUSY;
 	}
@@ -244,15 +247,19 @@
 static int com20020_reset(struct net_device *dev, int really_reset)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	short ioaddr = dev->base_addr;
+	u_int ioaddr = dev->base_addr;
 	u_char inbyte;
 
+	BUGMSG(D_DEBUG, "%s: %d: %s: dev: %x, lp: %x, dev->name: %x\n",
+		__FILE__,__LINE__,__FUNCTION__,dev,lp,dev->name);
 	BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n",
 	       dev->name, ASTATUS());
 
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 	lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2);
 	/* power-up defaults */
 	SETCONF;
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 
 	if (really_reset) {
 		/* reset the card */
@@ -260,17 +267,22 @@
 		mdelay(RESETtime * 2);	/* COM20020 seems to be slower sometimes */
 	}
 	/* clear flags & end reset */
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 	ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
 
 	/* verify that the ARCnet signature byte is present */
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 
 	com20020_copy_from_card(dev, 0, 0, &inbyte, 1);
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 	if (inbyte != TESTvalue) {
+		BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 		BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
 		return 1;
 	}
 	/* enable extended (512-byte) packets */
 	ACOMMAND(CONFIGcmd | EXTconf);
+	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 
 	/* done!  return success. */
 	return 0;
@@ -279,22 +291,24 @@
 
 static void com20020_setmask(struct net_device *dev, int mask)
 {
-	short ioaddr = dev->base_addr;
+	u_int ioaddr = dev->base_addr;
+	BUGMSG(D_DURING, "Setting mask to %x at %x\n",mask,ioaddr);
 	AINTMASK(mask);
 }
 
 
 static void com20020_command(struct net_device *dev, int cmd)
 {
-	short ioaddr = dev->base_addr;
+	u_int ioaddr = dev->base_addr;
 	ACOMMAND(cmd);
 }
 
 
 static int com20020_status(struct net_device *dev)
 {
-	short ioaddr = dev->base_addr;
-	return ASTATUS();
+	u_int ioaddr = dev->base_addr;
+	
+	return ASTATUS() + (ADIAGSTATUS()<<8);
 }
 
 
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/com20020-isa.c linux-2.4.20-31.9custom/drivers/net/arcnet/com20020-isa.c
--- linux-2.4.20-31.9/drivers/net/arcnet/com20020-isa.c	2002-08-03 02:39:44.000000000 +0200
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/com20020-isa.c	2004-05-27 17:56:40.000000000 +0200
@@ -40,6 +40,10 @@
 
 #include <asm/io.h>
 
+#ifdef CONFIG_ARCH_SA1100
+#include <asm/hardware.h>
+#include <asm/arch-sa1100/irqs.h>
+#endif
 
 #define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n"
 
@@ -60,6 +64,23 @@
 
 	BUGLVL(D_NORMAL) printk(VERSION);
 
+#if defined(CONFIG_SA1100_CT6001)
+	if (machine_is_ct6001()) {
+		if(!dev->base_addr)
+			dev->base_addr = ADS_ARCNET;
+
+		/* Set the GPIO pin 4 to input: */
+		GPDR &= ~(GPIO_ARC_IRQ);  
+		/* Make ready to take the raising edge as an interrupt: */
+		set_GPIO_IRQ_edge( GPIO_ARC_IRQ, GPIO_FALLING_EDGE );
+		/* And remember this interrupt number on the device : */
+		dev->irq = IRQ_GPIO_ARC;
+
+		// Taken from vxWorks:
+		MSC1 = 0xE835E835;
+	}
+#endif
+
 	ioaddr = dev->base_addr;
 	if (!ioaddr) {
 		BUGMSG(D_NORMAL, "No autoprobe (yet) for IO mapped cards; you "
@@ -105,8 +126,9 @@
 		}
 	}
 
+	printk("%s: %d\n",__FILE__,__LINE__);
 	lp->card_name = "ISA COM20020";
-	return com20020_found(dev, 0);
+	return com20020_found(dev, 0, 1);
 }
 
 
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/com20020-pci.c linux-2.4.20-31.9custom/drivers/net/arcnet/com20020-pci.c
--- linux-2.4.20-31.9/drivers/net/arcnet/com20020-pci.c	2004-04-13 23:07:09.000000000 +0200
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/com20020-pci.c	2004-05-27 17:56:41.000000000 +0200
@@ -130,7 +130,7 @@
 		goto out_priv;
 	}
 
-	if ((err = com20020_found(dev, SA_SHIRQ)) != 0)
+	if ((err = com20020_found(dev, SA_SHIRQ, 1)) != 0)
 	        goto out_priv;
 
 	return 0;
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/Config.in linux-2.4.20-31.9custom/drivers/net/arcnet/Config.in
--- linux-2.4.20-31.9/drivers/net/arcnet/Config.in	2001-03-07 04:28:35.000000000 +0100
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/Config.in	2004-05-27 17:56:08.000000000 +0200
@@ -10,6 +10,7 @@
    dep_tristate 'Enable standard ARCNet packet format (RFC 1201)' CONFIG_ARCNET_1201 $CONFIG_ARCNET
    dep_tristate 'Enable old ARCNet packet format (RFC 1051)' CONFIG_ARCNET_1051 $CONFIG_ARCNET
    dep_tristate 'Enable raw mode packet interface' CONFIG_ARCNET_RAW $CONFIG_ARCNET
+   dep_tristate 'Enable cap mode packet interface' CONFIG_ARCNET_CAP $CONFIG_ARCNET
    dep_tristate 'ARCnet COM90xx (normal) chipset driver' CONFIG_ARCNET_COM90xx $CONFIG_ARCNET
    dep_tristate 'ARCnet COM90xx (IO mapped) chipset driver' CONFIG_ARCNET_COM90xxIO $CONFIG_ARCNET
    dep_tristate 'ARCnet COM90xx (RIM I) chipset driver' CONFIG_ARCNET_RIM_I $CONFIG_ARCNET
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/Makefile linux-2.4.20-31.9custom/drivers/net/arcnet/Makefile
--- linux-2.4.20-31.9/drivers/net/arcnet/Makefile	2001-02-13 22:15:04.000000000 +0100
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/Makefile	2004-05-27 17:56:08.000000000 +0200
@@ -15,6 +15,7 @@
 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
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/rfc1051.c linux-2.4.20-31.9custom/drivers/net/arcnet/rfc1051.c
--- linux-2.4.20-31.9/drivers/net/arcnet/rfc1051.c	2004-04-13 23:07:11.000000000 +0200
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/rfc1051.c	2004-05-27 17:56:08.000000000 +0200
@@ -47,6 +47,7 @@
 {
 	's',
 	XMTU - RFC1051_HDR_SIZE,
+	1, /* Is IP protocol */
 	rx,
 	build_header,
 	prepare_tx
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/arcnet/rfc1201.c linux-2.4.20-31.9custom/drivers/net/arcnet/rfc1201.c
--- linux-2.4.20-31.9/drivers/net/arcnet/rfc1201.c	2004-04-13 23:07:11.000000000 +0200
+++ linux-2.4.20-31.9custom/drivers/net/arcnet/rfc1201.c	2004-05-27 17:56:08.000000000 +0200
@@ -45,7 +45,8 @@
 struct ArcProto rfc1201_proto =
 {
 	'a',
-	1500,			/* could be more, but some receivers can't handle it... */
+	1500,	    /* could be more, but some receivers can't handle it... */
+	1, /* Is IP protocol */
 	rx,
 	build_header,
 	prepare_tx,
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/drivers/net/pcmcia/com20020_cs.c linux-2.4.20-31.9custom/drivers/net/pcmcia/com20020_cs.c
--- linux-2.4.20-31.9/drivers/net/pcmcia/com20020_cs.c	2002-08-03 02:39:44.000000000 +0200
+++ linux-2.4.20-31.9custom/drivers/net/pcmcia/com20020_cs.c	2004-05-27 17:56:41.000000000 +0200
@@ -222,6 +222,9 @@
     memset(link, 0, sizeof(struct dev_link_t));
     dev->priv = lp;
 
+    strcpy(info->node.dev_name, dev->name);
+    link->dev = &info->node;
+
     link->release.function = &com20020_release;
     link->release.data = (u_long)link;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -453,7 +456,7 @@
     lp->card_name = "PCMCIA COM20020";
     lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
 
-    i = com20020_found(dev, 0);
+    i = com20020_found(dev, 0, 0);
     
     if (i != 0) {
 	DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/include/linux/arcdevice.h linux-2.4.20-31.9custom/include/linux/arcdevice.h
--- linux-2.4.20-31.9/include/linux/arcdevice.h	2004-04-13 23:41:44.000000000 +0200
+++ linux-2.4.20-31.9custom/include/linux/arcdevice.h	2004-05-27 18:01:47.000000000 +0200
@@ -26,6 +26,10 @@
 #endif
 
 
+#ifdef CONFIG_SA1100_CT6001
+#include <asm/arch/hardware.h>
+#endif
+
 /*
  * RECON_THRESHOLD is the maximum number of RECON messages to receive
  * within one minute before printing a "cabling problem" warning. The
@@ -75,23 +79,35 @@
 #define D_SKB_SIZE	2048	/* show skb sizes			  */
 #define D_TIMING	4096	/* show time needed to copy buffers to card */
 
+#define D_DEBUG         8192    /* Very detailed debug line for line */
+
 #ifndef ARCNET_DEBUG_MAX
-#define ARCNET_DEBUG_MAX (127)	/* change to ~0 if you want detailed debugging */
+#define ARCNET_DEBUG_MAX (~0|127)	/* change to ~0 if you want detailed debugging */
 #endif
 
 #ifndef ARCNET_DEBUG
-#define ARCNET_DEBUG (D_NORMAL|D_EXTRA)
+#define ARCNET_DEBUG (~0|D_NORMAL) 
+/* (~0|D_NORMAL|D_EXTRA|D_INIT|D_INIT_REASONS|D_PROTO) */
 #endif
 extern int arcnet_debug;
 
 /* macros to simplify debug checking */
 #define BUGLVL(x) if ((ARCNET_DEBUG_MAX)&arcnet_debug&(x))
 #define BUGMSG2(x,msg,args...) do { BUGLVL(x) printk(msg, ## args); } while (0)
+
+#ifdef CONFIG_SA1100
 #define BUGMSG(x,msg,args...) \
-	BUGMSG2(x, "%s%6s: " msg, \
+	BUGMSG2(x, "%s (%x) %6s: " msg, \
+            x==D_NORMAL	? KERN_WARNING \
+            		: x < D_DURING ? KERN_INFO : KERN_DEBUG, \
+	    OSCR , dev->name , ## args)
+#else
+#define BUGMSG(x,msg,args...) \
+	BUGMSG2(x, "%s %6s: " msg, \
             x==D_NORMAL	? KERN_WARNING \
             		: x < D_DURING ? KERN_INFO : KERN_DEBUG, \
 	    dev->name , ## args)
+#endif
 
 /* see how long a function call takes to run, expressed in CPU cycles */
 #define TIME(name, bytes, call) BUGLVL(D_TIMING) { \
@@ -135,6 +151,7 @@
 #define TXACKflag       0x02	/* transmitted msg. ackd */
 #define RECONflag       0x04	/* network reconfigured */
 #define TESTflag        0x08	/* test flag */
+#define EXCNAKflag      0x08    /* excesive nak flag */
 #define RESETflag       0x10	/* power-on-reset */
 #define RES1flag        0x20	/* reserved - usually set by jumper */
 #define RES2flag        0x40	/* reserved - usually set by jumper */
@@ -162,6 +179,8 @@
 #define RESETclear      0x08	/* power-on-reset */
 #define CONFIGclear     0x10	/* system reconfigured */
 
+#define EXCNAKclear     0x0E    /* Clear and acknowledge the excive nak bit */
+
 /* flags for "load test flags" command */
 #define TESTload        0x08	/* test flag (diagnostic) */
 
@@ -187,6 +206,7 @@
 struct ArcProto {
 	char suffix;		/* a for RFC1201, e for ether-encap, etc. */
 	int mtu;		/* largest possible packet */
+	int is_ip;              /* This is a ip plugin - not a raw thing */
 
 	void (*rx) (struct net_device * dev, int bufnum,
 		    struct archdr * pkthdr, int length);
@@ -197,9 +217,11 @@
 	int (*prepare_tx) (struct net_device * dev, struct archdr * pkt, int length,
 			   int bufnum);
 	int (*continue_tx) (struct net_device * dev, int bufnum);
+	int (*ack_tx) (struct net_device * dev, int acked);
 };
 
-extern struct ArcProto *arc_proto_map[256], *arc_proto_default, *arc_bcast_proto;
+extern struct ArcProto *arc_proto_map[256], *arc_proto_default, 
+	*arc_bcast_proto, *arc_raw_proto;
 extern struct ArcProto arc_proto_null;
 
 
@@ -279,6 +301,8 @@
 	int num_recons;		/* number of RECONs between first and last. */
 	bool network_down;	/* do we think the network is down? */
 
+	bool excnak_pending;    /* We just got an excesive nak interrupt */
+
 	struct {
 		uint16_t sequence;	/* sequence number (incs with each packet) */
 		uint16_t aborted_seq;
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/include/linux/com20020.h linux-2.4.20-31.9custom/include/linux/com20020.h
--- linux-2.4.20-31.9/include/linux/com20020.h	2004-04-13 23:07:10.000000000 +0200
+++ linux-2.4.20-31.9custom/include/linux/com20020.h	2004-05-27 17:56:41.000000000 +0200
@@ -27,24 +27,31 @@
 #ifndef __COM20020_H
 #define __COM20020_H
 
+#ifdef CONFIG_SA1100_CT6001
+#define BUS_ALIGN  2
+#else
+#define BUS_ALIGN  1
+#endif
+
 int com20020_check(struct net_device *dev);
-int com20020_found(struct net_device *dev, int shared);
+int com20020_found(struct net_device *dev, int shared, int request_io);
 void com20020_remove(struct net_device *dev);
 
 /* The number of low I/O ports used by the card. */
 #define ARCNET_TOTAL_SIZE 8
 
 /* various register addresses */
-#define _INTMASK  (ioaddr+0)	/* writable */
-#define _STATUS   (ioaddr+0)	/* readable */
-#define _COMMAND  (ioaddr+1)	/* standard arcnet commands */
-#define _DIAGSTAT (ioaddr+1)	/* diagnostic status register */
-#define _ADDR_HI  (ioaddr+2)	/* control registers for IO-mapped memory */
-#define _ADDR_LO  (ioaddr+3)
-#define _MEMDATA  (ioaddr+4)	/* data port for IO-mapped memory */
-#define _SUBADR   (ioaddr+5)	/* the extended port _XREG refers to */
-#define _CONFIG   (ioaddr+6)	/* configuration register */
-#define _XREG     (ioaddr+7)	/* extra registers (indexed by _CONFIG 
+
+#define _INTMASK  (ioaddr+BUS_ALIGN*0)	/* writable */
+#define _STATUS   (ioaddr+BUS_ALIGN*0)	/* readable */
+#define _COMMAND  (ioaddr+BUS_ALIGN*1)	/* standard arcnet commands */
+#define _DIAGSTAT (ioaddr+BUS_ALIGN*1)	/* diagnostic status register */
+#define _ADDR_HI  (ioaddr+BUS_ALIGN*2)	/* control registers for IO-mapped memory */
+#define _ADDR_LO  (ioaddr+BUS_ALIGN*3)
+#define _MEMDATA  (ioaddr+BUS_ALIGN*4)	/* data port for IO-mapped memory */
+#define _SUBADR   (ioaddr+BUS_ALIGN*5)	/* the extended port _XREG refers to */
+#define _CONFIG   (ioaddr+BUS_ALIGN*6)	/* configuration register */
+#define _XREG     (ioaddr+BUS_ALIGN*7)	/* extra registers (indexed by _CONFIG 
 					or _SUBADR) */
 
 /* in the ADDR_HI register */
@@ -100,6 +107,7 @@
                   }
 
 #define ASTATUS()	inb(_STATUS)
+#define ADIAGSTATUS()	inb(_DIAGSTAT)
 #define ACOMMAND(cmd)	outb((cmd),_COMMAND)
 #define AINTMASK(msk)	outb((msk),_INTMASK)
 
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/include/linux/if_arcnet.h linux-2.4.20-31.9custom/include/linux/if_arcnet.h
--- linux-2.4.20-31.9/include/linux/if_arcnet.h	2004-04-13 23:08:42.000000000 +0200
+++ linux-2.4.20-31.9custom/include/linux/if_arcnet.h	2004-05-27 17:56:08.000000000 +0200
@@ -19,10 +19,32 @@
 #include <linux/if_ether.h>
 
 
+struct sockaddr_arc
+{
+	/* copied from sockaddr_ll : */
+	unsigned short	sarc_family;
+	unsigned short	sarc_protocol;
+	int		sarc_ifindex;
+	unsigned short	sarc_hatype;
+	unsigned char	sarc_pkttype;
+	unsigned char	sarc_halen;
+	unsigned char	sarc_addr[8];
+
+	/* copied from sockaddr_ec : */
+	unsigned char   type;			/* Type of message.  */
+	unsigned long   cookie;
+};
+
+
 /*
  *    These are the defined ARCnet Protocol ID's.
  */
 
+#define ARCTYPE_TRANSMIT_STATUS		0x10	/* Transmit completed, 
+						   low nibble holds status */
+
+
+
 /* RFC1201 Protocol ID's */
 #define ARC_P_IP		212	/* 0xD4 */
 #define ARC_P_ARP		213	/* 0xD5 */
@@ -82,6 +104,16 @@
 #define ETH_ENCAP_HDR_SIZE 14
 
 
+struct arc_cap
+{
+	uint8_t proto;
+	uint8_t cookie[sizeof(int)];   /* Actually NOT sent over the network */
+	union {
+		uint8_t ack;
+		uint8_t raw[0];		/* 508 bytes */
+	} mes;
+};
+
 /*
  * The data needed by the actual arcnet hardware.
  *
@@ -112,8 +144,24 @@
 	struct arc_rfc1201   rfc1201;
 	struct arc_rfc1051   rfc1051;
 	struct arc_eth_encap eth_encap;
+	struct arc_cap       cap;
 	uint8_t raw[0];		/* 508 bytes				*/
     } soft;
 };
 
+#ifdef __KERNEL__
+
+
+struct arcnet_opt
+{
+  struct packet_type	prot_hook;
+  spinlock_t		bind_lock;
+  char			running;	/* prot_hook is attached*/
+  int			ifindex;	/* bound device		*/
+  struct tpacket_stats	stats;
+};
+
+#endif
+
+
 #endif				/* _LINUX_IF_ARCNET_H */
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/include/linux/if_ether.h linux-2.4.20-31.9custom/include/linux/if_ether.h
--- linux-2.4.20-31.9/include/linux/if_ether.h	2004-04-13 23:07:10.000000000 +0200
+++ linux-2.4.20-31.9custom/include/linux/if_ether.h	2004-05-27 17:56:08.000000000 +0200
@@ -86,6 +86,7 @@
 #define ETH_P_IRDA	0x0017		/* Linux-IrDA			*/
 #define ETH_P_ECONET	0x0018		/* Acorn Econet			*/
 #define ETH_P_HDLC	0x0019		/* HDLC frames			*/
+#define ETH_P_ARCNET	0x0020		/* ArcNet			*/
 
 /*
  *	This is an Ethernet frame header.
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/include/linux/netdevice.h linux-2.4.20-31.9custom/include/linux/netdevice.h
--- linux-2.4.20-31.9/include/linux/netdevice.h	2004-04-13 23:41:44.000000000 +0200
+++ linux-2.4.20-31.9custom/include/linux/netdevice.h	2004-05-27 18:01:46.000000000 +0200
@@ -39,6 +39,8 @@
 #include <net/profile.h>
 #endif
 
+#define NET_REFCNT_DEBUG        1
+
 struct divert_blk;
 struct vlan_group;
 
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/include/linux/net.h linux-2.4.20-31.9custom/include/linux/net.h
--- linux-2.4.20-31.9/include/linux/net.h	2004-04-13 23:41:43.000000000 +0200
+++ linux-2.4.20-31.9custom/include/linux/net.h	2004-05-27 18:01:45.000000000 +0200
@@ -24,7 +24,7 @@
 
 struct poll_table_struct;
 
-#define NPROTO		32		/* should be enough for now..	*/
+#define NPROTO		33		/* should be enough for now..	*/
 
 
 #define SYS_SOCKET	1		/* sys_socket(2)		*/
diff -Nur --exclude-from=linux-no-diff linux-2.4.20-31.9/include/linux/socket.h linux-2.4.20-31.9custom/include/linux/socket.h
--- linux-2.4.20-31.9/include/linux/socket.h	2004-04-13 23:41:43.000000000 +0200
+++ linux-2.4.20-31.9custom/include/linux/socket.h	2004-05-27 18:01:45.000000000 +0200
@@ -205,6 +205,7 @@
 #define PF_WANPIPE	AF_WANPIPE
 #define PF_LLC		AF_LLC
 #define PF_BLUETOOTH	AF_BLUETOOTH
+#define PF_ARCNET	AF_ARCNET
 #define PF_MAX		AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux