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