patch-1.3.41 linux/drivers/net/arcnet.c
Next file: linux/drivers/net/eth16i.c
Previous file: linux/drivers/net/3c505.c
Back to the patch index
Back to the overall index
- Lines: 2491
- Date:
Mon Nov 13 08:54:55 1995
- Orig file:
v1.3.40/linux/drivers/net/arcnet.c
- Orig date:
Thu Nov 9 11:23:49 1995
diff -u --recursive --new-file v1.3.40/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
@@ -1,6 +1,6 @@
/* arcnet.c
- Written 1994-95 by Avery Pennarun, derived from skeleton.c by
- Donald Becker.
+ Written 1994-95 by Avery Pennarun, derived from skeleton.c by Donald
+ Becker.
Contact Avery at: apenwarr@foxnet.net or
RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
@@ -17,6 +17,38 @@
**********************
+ v2.20 ALPHA (95/11/12)
+ - Added a bit of protocol confusion to the arc0 code to allow
+ trxnet-compatible IPX support - and the use of all that new
+ Linux-IPX stuff (including lwared). Just tell the ipx_interface
+ command that arc0 uses 802.3 (other protocols will probably also
+ work).
+ - Fixed lp->stats to update tx_packets on all devices, not just
+ arc0. Also, changed a lot of the error counting to make more
+ sense.
+ - rx_packets on arc0 was being updated for each completely received
+ packet. It now updates for each segment received, which makes
+ more sense.
+ - Removed unneeded extra check of dev->start in arcnet_inthandler.
+ - Included someone else's fixes from kernel 1.3.39. Does it still
+ work with kernel 1.2?
+ - Added a new define to disable PRINTING (not checking) of RECON
+ messages.
+ - Separated the duplicated error checking code from the various
+ arcnet??_send_packet routines into a new function.
+ - Cleaned up lock variables and ping-pong buffers a bit. This
+ should mean more stability, fewer missing packets, and less ugly
+ debug messages. Assuming it works.
+ - Changed the format of debug messages to always include the actual
+ device name instead of just "arcnet:". Used more macros to
+ shorten debugging code even more.
+ - Finally squashed the "startup NULL pointer" bug. irq2dev_map
+ wasn't being cleared to NULL when the driver was closed.
+ - Improved RECON checking; if a certain number of RECON messages
+ are received within one minute, a warning message is printed
+ to the effect of "cabling problem." One-log-message-per-recon
+ now defaults to OFF.
+
v2.12 ALPHA (95/10/27)
- Tried to improve skb handling and init code to fix problems with
the latest 1.3.x kernels. (We no longer use ether_setup except
@@ -94,16 +126,17 @@
if there aren't any ARCnet cards in the system. And why shouldn't
it work as a module again?
- Rewrite autoprobe.
+ - Make sure RESET flag is cleared during an IRQ even if dev->start==0;
+ mainly a portability fix. This will confuse autoprobe a bit, so
+ test that too.
- What about cards with shared memory that can be "turned off?"
- NFS mount freezes after several megabytes to SOSS for DOS.
unmount/remount fixes it. Is this arcnet-specific? I don't know.
- - Some newer ARCnets support promiscuous mode, supposedly.
- If someone sends me information, I'll try to implement it.
- - Find and remove excess lock variables that are probably not
- necessary anymore due to the changes in Linux 1.2.9.
+ - Some newer ARCnets support promiscuous mode, supposedly. If
+ someone sends me information, I'll try to implement it.
- Dump Linux 1.2 support and its ugly #ifdefs.
- Add support for the new 1.3.x IP header cache features.
- - ATA protocol support??
+ - ATA protocol support??
- Banyan VINES TCP/IP support??
@@ -123,11 +156,14 @@
*/
static const char *version =
- "arcnet.c:v2.12 ALPHA 95/10/27 Avery Pennarun <apenwarr@foxnet.net>\n";
+ "arcnet.c: v2.20 ALPHA 95/11/12 Avery Pennarun <apenwarr@foxnet.net>\n";
-#include <linux/module.h>
+
+#include <linux/module.h>
#include <linux/config.h>
+#include <linux/version.h>
+
/* are we Linux 1.2.x? */
#if LINUX_VERSION_CODE < 0x10300
#define LINUX12
@@ -152,7 +188,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#include <linux/config.h> /* for CONFIG_INET */
+/*#include <linux/config.h>*/ /* For CONFIG_INET */
#include <asm/system.h>
#include <asm/bitops.h>
@@ -167,18 +203,34 @@
/**************************************************************************/
-/* Define this if you want to detect network reconfigurations.
- * They may be a real nuisance on a larger ARCnet network: but if you are
- * a network administrator you probably would like to count them.
- * Reconfigurations will be recorded in stats.tx_carrier_errors
- * (the last field of the /proc/net/dev file).
- *
- * The card sends the reconfiguration signal when it loses the connection
- * to the rest of its network. It is a 'Hello, is anybody there?' cry. This
+/* The card sends the reconfiguration signal when it loses the connection to
+ * the rest of its network. It is a 'Hello, is anybody there?' cry. This
* usually happens when a new computer on the network is powered on or when
* the cable is broken.
+ *
+ * Define DETECT_RECONFIGS if you want to detect network reconfigurations.
+ * They may be a real nuisance on a larger ARCnet network; if you are a
+ * network administrator you probably would like to count them.
+ * Reconfigurations will be recorded in stats.tx_carrier_errors (the last
+ * field of the /proc/net/dev file).
+ *
+ * Define SHOW_RECONFIGS if you really want to see a log message whenever
+ * a RECON occurs.
*/
#define DETECT_RECONFIGS
+#undef SHOW_RECONFIGS
+
+/* RECON_THRESHOLD is the maximum number of RECON messages to receive within
+ * one minute before printing a "cabling problem" warning. You must have
+ * DETECT_RECONFIGS enabled if you want to use this. The default value
+ * should be fine.
+ *
+ * After that, a "cabling restored" message will be printed on the next IRQ
+ * if no RECON messages have been received for 10 seconds.
+ *
+ * Do not define RECON_THRESHOLD at all if you want to disable this feature.
+ */
+#define RECON_THRESHOLD 30
/* Define this if you want to make sure transmitted packets are "acknowledged"
* by the destination host, as long as they're not to the broadcast address.
@@ -190,26 +242,33 @@
*/
#define VERIFY_ACK
+/* Define this to the minimum "timeout" value. If a transmit takes longer
+ * than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large
+ * network, or one with heavy network traffic, this timeout may need to be
+ * increased.
+ */
+#define TX_TIMEOUT 20
+
/* Define this if you want to make it easier to use the "call trace" when
* a kernel NULL pointer assignment occurs. Hopefully unnecessary, most of
* the time. It will make all the function names (and other things) show
* up as kernel symbols. (especially handy when using arcnet as a module)
*/
-#define static
+#undef static
/**************************************************************************/
-/* new debugging bitflags: each option can be enabled individually.
+/* New debugging bitflags: each option can be enabled individually.
*
- * these can be set while the driver is running by typing:
+ * These can be set while the driver is running by typing:
* ifconfig arc0 down metric 1xxx HOSTNAME
* where 1xxx is 1000 + the debug level you want
* and HOSTNAME is your hostname/ip address
* and then resetting your routes.
*
* Note: only debug flags included in the ARCNET_DEBUG_MAX define will
- * actually be available. GCC (at least 2.7.0) will notice lines
- * using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize
+ * actually be available. GCC will (at least, GCC 2.7.0 will) notice
+ * lines using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize
* them out.
*/
#define D_NORMAL 1 /* D_NORMAL normal operational info */
@@ -233,8 +292,9 @@
#endif
int arcnet_debug = ARCNET_DEBUG;
-/* macro to simplify debug checking */
+/* macros to simplify debug checking */
#define BUGLVL(x) if ((ARCNET_DEBUG_MAX)&arcnet_debug&(x))
+#define BUGMSG(x,msg,args...) BUGLVL(x) printk("%6s: " msg, dev->name , ## args);
#ifndef HAVE_AUTOIRQ
/* From auto_irq.c, in ioport.h for later versions. */
@@ -257,16 +317,18 @@
#define IF_TBUSY (lp->adev->tbusy \
|| lp->edev->tbusy \
|| lp->sdev->tbusy)
+
#define INTERRUPT lp->adev->interrupt \
=lp->edev->interrupt \
=lp->sdev->interrupt
#define IF_INTERRUPT (lp->adev->interrupt \
|| lp->edev->interrupt \
|| lp->sdev->interrupt)
+
#define START lp->adev->start \
=lp->edev->start \
=lp->sdev->start
-
+
/* The number of low I/O ports used by the ethercard. */
#define ARCNET_TOTAL_SIZE 16
@@ -330,20 +392,20 @@
#define RESETclear 0x08 /* power-on-reset */
#define CONFIGclear 0x10 /* system reconfigured */
- /* flags for "load test flags" command */
+ /* flags for "load test flags" command */
#define TESTload 0x08 /* test flag (diagnostic) */
- /* byte deposited into first address of buffers on reset */
+ /* byte deposited into first address of buffers on reset */
#define TESTvalue 0321 /* that's octal for 0xD1 :) */
- /* for "enable receiver" command */
+ /* for "enable receiver" command */
#define RXbcasts 0x80 /* receive broadcasts */
- /* flags for "define configuration" command */
+ /* flags for "define configuration" command */
#define NORMALconf 0x00 /* 1-249 byte packets */
#define EXTconf 0x08 /* 250-504 byte packets */
- /* buffers (4 total) used for receive and xmit.
+ /* Starts receiving packets into recbuf.
*/
#define EnableReceiver() outb(RXcmd|(recbuf<<3)|RXbcasts,COMMAND)
@@ -361,7 +423,7 @@
#define ARC_P_ETHER 0xE8
/* Unsupported/indirectly supported protocols */
-#define ARC_P_LANSOFT 251 /* 0xFB */
+#define ARC_P_LANSOFT 251 /* 0xFB - what is this? */
#define ARC_P_ATALK 0xDD
/* the header required by the card itself */
@@ -460,6 +522,13 @@
in_txhandler, /* in TX_IRQ handler? */
sending; /* transmit in progress? */
short tx_left; /* segments of split packet left to TX */
+
+#if defined(DETECT_RECONFIGS) && defined(RECON_THRESHOLD)
+ time_t first_recon, /* time of "first" RECON message to count */
+ last_recon; /* time of most recent RECON */
+ int num_recons, /* number of RECONs between first and last. */
+ network_down; /* do we think the network is down? */
+#endif
struct timer_list timer; /* the timer interrupt struct */
struct Incoming incoming[256]; /* one from each address */
@@ -485,13 +554,14 @@
static int arcnet_close(struct device *dev);
static int arcnet_reset(struct device *dev);
+static int arcnet_send_packet_bad(struct sk_buff *skb,struct device *dev);
static int arcnetA_send_packet(struct sk_buff *skb, struct device *dev);
static int arcnetE_send_packet(struct sk_buff *skb, struct device *dev);
static int arcnetS_send_packet(struct sk_buff *skb, struct device *dev);
static void arcnetA_continue_tx(struct device *dev);
static void arcnetAS_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
char *data,int length,int daddr,int exceptA);
-static void arcnetAS_go_tx(struct device *dev);
+static int arcnet_go_tx(struct device *dev,int enable_irq);
static void arcnet_interrupt(int irq,struct pt_regs *regs);
static void arcnet_inthandler(struct device *dev);
@@ -585,7 +655,7 @@
struct arcnet_local *lp;
printk(version);
-
+
#if 1
BUGLVL(D_NORMAL)
{
@@ -608,8 +678,7 @@
}
#endif
- BUGLVL(D_INIT)
- printk("arcnet: given: base %lXh, IRQ %Xh, shmem %lXh\n",
+ BUGMSG(D_INIT,"given: base %lXh, IRQ %Xh, shmem %lXh\n",
dev->base_addr,dev->irq,dev->mem_start);
#ifndef MODULE
@@ -622,8 +691,7 @@
int ioaddr = *port;
if (check_region(ioaddr, ARCNET_TOTAL_SIZE))
{
- BUGLVL(D_INIT)
- printk("arcnet: Skipping %Xh because of check_region...\n",
+ BUGMSG(D_INIT,"Skipping %Xh because of check_region...\n",
ioaddr);
continue;
}
@@ -637,13 +705,11 @@
/* ioprobe turned out okay. Now give it a couple seconds to finish
* initializing...
*/
- BUGLVL(D_INIT)
- printk("arcnet: ioprobe okay! Waiting for reset...\n");
+ BUGMSG(D_INIT,"ioprobe okay! Waiting for reset...\n");
JIFFER(100);
/* okay, now we have to find the shared memory area. */
- BUGLVL(D_INIT)
- printk("arcnet: starting memory probe, given %lXh\n",
+ BUGMSG(D_INIT,"starting memory probe, given %lXh\n",
dev->mem_start);
if (dev->mem_start) /* value given - probe just that one */
{
@@ -663,9 +729,11 @@
if (!dev->base_addr || !dev->irq || !dev->mem_start
|| !dev->rmem_start)
{
- printk("arcnet: loadable modules can't autoprobe!\n");
- printk("arcnet: try using io=, irqnum=, and shmem= on the insmod line.\n");
- printk("arcnet: you may also need num= to change the device name. (ie. num=1 for arc1)\n");
+ printk("%6s: loadable modules can't autoprobe!\n",dev->name);
+ printk("%6s: try using io=, irqnum=, and shmem= on the insmod line.\n",
+ dev->name);
+ printk("%6s: you may also need num= to change the device name. (ie. num=1 for arc1)\n",
+ dev->name);
return ENODEV;
}
#endif
@@ -674,7 +742,7 @@
int irqval = request_irq(dev->irq, &arcnet_interrupt, 0,
"arcnet");
if (irqval) {
- printk("%s: unable to get IRQ %d (irqval=%d).\n",
+ printk("%6s: unable to get IRQ %d (irqval=%d).\n",
dev->name,dev->irq, irqval);
return EAGAIN;
}
@@ -683,7 +751,7 @@
/* Grab the region so we can find another board if autoIRQ fails. */
request_region(dev->base_addr, ARCNET_TOTAL_SIZE,"arcnet");
- printk("%s: ARCnet card found at %03lXh, IRQ %d, ShMem at %lXh.\n",
+ printk("%6s: ARCnet card found at %03lXh, IRQ %d, ShMem at %lXh.\n",
dev->name, dev->base_addr, dev->irq, dev->mem_start);
/* Initialize the device structure. */
@@ -709,24 +777,26 @@
/* And now fill particular fields with arcnet values */
dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
dev->hard_header_len=sizeof(struct ClientData);
- BUGLVL(D_DURING)
- printk("arcnet: ClientData header size is %d.\narcnet: HardHeader size is %d.\n",
- sizeof(struct ClientData),sizeof(struct HardHeader));
+ BUGMSG(D_DURING,"ClientData header size is %d.\n",
+ sizeof(struct ClientData));
+ BUGMSG(D_DURING,"HardHeader size is %d.\n",
+ sizeof(struct HardHeader));
/* since we strip EXTRA_CLIENTDATA bytes off before sending,
* we let Linux add that many bytes to the packet data...
*/
- BUGLVL(D_INIT) printk("arcnet: arcnet_probe: resetting card.\n");
+ BUGMSG(D_INIT,"arcnet_probe: resetting card.\n");
arcnet_reset(dev);
JIFFER(50);
- BUGLVL(D_NORMAL)
- printk("arcnet: We appear to be station %d (%02Xh)\n",
+ BUGMSG(D_NORMAL,"We appear to be station %d (%02Xh)\n",
lp->arcnum,lp->arcnum);
if (lp->arcnum==0)
- printk("arcnet: WARNING! Station address 0 is reserved for broadcasts!\n");
+ printk("%6s: WARNING! Station address 0 is reserved for broadcasts!\n",
+ dev->name);
if (lp->arcnum==255)
- printk("arcnet: WARNING! Station address 255 may confuse DOS networking programs!\n");
+ printk("%6s: WARNING! Station address 255 may confuse DOS networking programs!\n",
+ dev->name);
dev->dev_addr[0]=lp->arcnum;
lp->sequence=1;
lp->recbuf=0;
@@ -747,11 +817,8 @@
{
int delayval,airq;
- BUGLVL(D_INIT)
- {
- printk("arcnet: probing address %Xh\n",ioaddr);
- printk("arcnet: status1=%Xh\n",inb(STATUS));
- }
+ BUGMSG(D_INIT,"probing address %Xh\n",ioaddr);
+ BUGMSG(D_INIT," status1=%Xh\n",inb(STATUS));
/* very simple - all we have to do is reset the card, and if there's
@@ -766,8 +833,7 @@
/* if status port is FF, there's certainly no arcnet... give up. */
if (inb(STATUS)==0xFF)
{
- BUGLVL(D_INIT)
- printk("arcnet: probe failed. Status port empty.\n");
+ BUGMSG(D_INIT," probe failed. Status port empty.\n");
return ENODEV;
}
@@ -787,22 +853,20 @@
if (curval==initval)
{
- printk("arcnet: probe failed. never-changing command port (%02Xh).\n",
+ BUGLVL(D_INIT," probe failed. never-changing command port (%02Xh).\n",
initval);
return ENODEV;
}
}
#endif
- BUGLVL(D_INIT)
- printk("arcnet: status2=%Xh\n",inb(STATUS));
+ BUGMSG(D_INIT," status2=%Xh\n",inb(STATUS));
/* now we turn the reset bit off so we can IRQ next reset... */
outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
if (inb(STATUS) & RESETflag) /* reset flag STILL on */
{
- BUGLVL(D_INIT)
- printk("arcnet: probe failed. eternal reset flag1...(status=%Xh)\n",
+ BUGMSG(D_INIT," probe failed. eternal reset flag1...(status=%Xh)\n",
inb(STATUS));
return ENODEV;
}
@@ -827,15 +891,14 @@
airq = autoirq_report(0);
BUGLVL(D_INIT) if (airq)
- printk("arcnet: autoirq is %d\n", airq);
+ printk("%6s: autoirq is %d\n", dev->name, airq);
/* if there was no autoirq AND the user hasn't set any defaults,
* give up.
*/
if (!airq && !(dev->base_addr && dev->irq))
{
- BUGLVL(D_INIT)
- printk("arcnet: probe failed. no autoirq...\n");
+ BUGMSG(D_INIT," probe failed. no autoirq...\n");
return ENODEV;
}
@@ -849,8 +912,7 @@
if (inb(STATUS) & RESETflag) /* reset flag STILL on */
{
- BUGLVL(D_INIT)
- printk("arcnet: probe failed. eternal reset flag...(status=%Xh)\n",
+ BUGMSG(D_INIT," probe failed. eternal reset flag...(status=%Xh)\n",
inb(STATUS));
return ENODEV;
}
@@ -865,13 +927,11 @@
}
else if (dev->irq == 2)
{
- BUGLVL(D_NORMAL)
- printk("arcnet: IRQ2 == IRQ9, don't worry.\n");
+ BUGMSG(D_NORMAL,"IRQ2 == IRQ9, don't worry.\n");
dev->irq = 9;
}
- BUGLVL(D_INIT)
- printk("arcnet: irq and base address seem okay. (%lXh, IRQ %d)\n",
+ BUGMSG(D_INIT,"irq and base address seem okay. (%lXh, IRQ %d)\n",
dev->base_addr,dev->irq);
return 0;
}
@@ -883,16 +943,14 @@
*/
int arcnet_memprobe(struct device *dev,u_char *addr)
{
- BUGLVL(D_INIT)
- printk("arcnet: probing memory at %lXh\n",(u_long)addr);
+ BUGMSG(D_INIT,"probing memory at %lXh\n",(u_long)addr);
dev->mem_start=0;
/* ARCnet memory byte 0 is TESTvalue */
if (addr[0]!=TESTvalue)
{
- BUGLVL(D_INIT)
- printk("arcnet: probe failed. addr=%lXh, addr[0]=%Xh (not %Xh)\n",
+ BUGMSG(D_INIT," probe failed. addr=%lXh, addr[0]=%Xh (not %Xh)\n",
(unsigned long)addr,addr[0],TESTvalue);
return ENODEV;
}
@@ -901,8 +959,7 @@
addr[0]=0x42;
if (addr[0]!=0x42)
{
- BUGLVL(D_INIT)
- printk("arcnet: probe failed. addr=%lXh, addr[0]=%Xh (not 42h)\n",
+ BUGMSG(D_INIT," probe failed. addr=%lXh, addr[0]=%Xh (not 42h)\n",
(unsigned long)addr,addr[0]);
return ENODEV;
}
@@ -930,8 +987,7 @@
outb(0,INTMASK); /* no IRQ's, please! */
- BUGLVL(D_INIT)
- printk("arcnet: Resetting %s (status=%Xh)\n",
+ BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
dev->name,inb(STATUS));
inb(RESET); /* Reset by reading this port */
@@ -946,8 +1002,7 @@
cardmem = (u_char *) dev->mem_start;
if (cardmem[0] != TESTvalue)
{
- BUGLVL(D_INIT)
- printk("arcnet: reset failed: TESTvalue not present.\n");
+ BUGMSG(D_INIT,"reset failed: TESTvalue not present.\n");
return 1;
}
lp->arcnum=cardmem[1]; /* save address for later use */
@@ -1016,9 +1071,7 @@
dev->stop=NULL;
dev->hard_start_xmit=arcnetE_send_packet;
- BUGLVL(D_EXTRA)
- printk("%s: ARCnet Ethernet-Encap protocol initialized.\n",
- dev->name);
+ BUGMSG(D_EXTRA,"ARCnet Ethernet-Encap protocol initialized.\n");
return 0;
}
@@ -1044,9 +1097,7 @@
#ifdef LINUX12
dev->type_trans=arcnetS_type_trans;
#endif
- BUGLVL(D_EXTRA)
- printk("%s: ARCnet RFC1051 (NetBsd, AmiTCP) protocol initialized.\n",
- dev->name);
+ BUGMSG(D_EXTRA,"ARCnet RFC1051 (NetBsd, AmiTCP) protocol initialized.\n");
return 0;
}
@@ -1071,11 +1122,11 @@
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
int ioaddr=dev->base_addr,delayval;
-
+
if (dev->metric>=1000)
{
arcnet_debug=dev->metric-1000;
- printk("arcnet: debug level set to %d\n",arcnet_debug);
+ printk("%6s: debug level set to %d\n",dev->name,arcnet_debug);
dev->metric=1;
}
@@ -1083,7 +1134,7 @@
irq2dev_map[dev->irq] = dev;
- BUGLVL(D_EXTRA) printk("arcnet: arcnet_open: resetting card.\n");
+ BUGMSG(D_EXTRA,"arcnet_open: resetting card.\n");
/* try to reset - twice if it fails the first time */
if (arcnet_reset(dev) && arcnet_reset(dev))
@@ -1096,9 +1147,7 @@
/* The RFC1201 driver is the default - just store */
lp->adev=dev;
- BUGLVL(D_EXTRA)
- printk("%s: ARCnet RFC1201 protocol initialized.\n",
- lp->adev->name);
+ BUGMSG(D_EXTRA,"ARCnet RFC1201 protocol initialized.\n");
/* Initialize the ethernet-encap protocol driver */
lp->edev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
@@ -1135,7 +1184,6 @@
outb(NORXflag|RECON_flag,INTMASK);
MOD_INC_USE_COUNT;
-
return 0;
}
@@ -1151,6 +1199,10 @@
TBUSY=1;
START=0;
+ /* very important! */
+ irq2dev_map[dev->irq] = NULL;
+
+
/* Flush TX and disable RX */
outb(0,INTMASK); /* no IRQ's (except RESET, of course) */
outb(NOTXcmd,COMMAND); /* stop transmit */
@@ -1178,10 +1230,9 @@
kfree(lp->sdev);
lp->sdev=NULL;
- /* Update the statistics here. */
+ /* Update the statistics here. (not necessary in ARCnet) */
MOD_DEC_USE_COUNT;
-
return 0;
}
@@ -1193,25 +1244,28 @@
* *
****************************************************************************/
-
-/* Called by the kernel in order to transmit a packet.
+/* Generic error checking routine for arcnet??_send_packet
*/
static int
-arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
+arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
int ioaddr=dev->base_addr;
-
- lp->intx++;
- BUGLVL(D_DURING)
- printk("arcnet: transmit requested (status=%Xh, inTX=%d)\n",
+ BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
inb(STATUS),lp->intx);
if (lp->in_txhandler)
{
- printk("arcnet: send_packet called while in txhandler!\n");
- lp->intx--;
+ BUGMSG(D_NORMAL,"send_packet called while in txhandler!\n");
+ lp->stats.tx_dropped++;
+ return 1;
+ }
+
+ if (lp->intx>1)
+ {
+ BUGMSG(D_NORMAL,"send_packet called while intx!\n");
+ lp->stats.tx_dropped++;
return 1;
}
@@ -1220,34 +1274,37 @@
/* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
int tickssofar = jiffies - dev->trans_start;
- int recbuf=lp->recbuf;
+ /*int recbuf=lp->recbuf;*/
int status=inb(STATUS);
- if (tickssofar < 5)
+ if (tickssofar < TX_TIMEOUT)
{
- BUGLVL(D_DURING)
- printk("arcnet: premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
+ BUGMSG(D_DURING,"premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
status,tickssofar,lp->outgoing.skb,
lp->outgoing.numsegs,
lp->outgoing.segnum);
- lp->intx--;
return 1;
}
- BUGLVL(D_EXTRA)
- printk("arcnet: transmit timed out (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)\n",
- status,lp->intx,lp->in_txhandler,tickssofar);
-
- lp->stats.tx_errors++;
-
- /* Try to restart the adaptor. */
- /*arcnet_reset(dev);*/
-
outb(0,INTMASK);
- if (status&NORXflag) EnableReceiver();
- if (!(status&TXFREEflag))
+
+ if (status&TXFREEflag) /* transmit _DID_ finish */
+ {
+ BUGMSG(D_EXTRA,"tx timed out - missed IRQ? (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)\n",
+ status,lp->intx,
+ lp->in_txhandler,tickssofar);
+ lp->stats.tx_errors++;
+ }
+ else
+ {
+ BUGMSG(D_NORMAL,"tx timed out (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)\n",
+ status,lp->intx,
+ lp->in_txhandler,tickssofar);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+
outb(NOTXcmd,COMMAND);
- /*dev->trans_start = jiffies;*/
+ }
if (lp->outgoing.skb)
{
@@ -1257,12 +1314,8 @@
lp->outgoing.skb=NULL;
TBUSY=0;
- lp->intx--;
- /*lp->intx=0;*/
- /*lp->in_txhandler=0;*/
lp->txready=0;
lp->sending=0;
- /*mark_bh(NET_BH);*/
outb(NORXflag|RECON_flag,INTMASK);
@@ -1273,23 +1326,22 @@
we are passed NULL. Caution: dev_tint() handles the cli()/sti()
itself. */
if (skb == NULL) {
- printk("arcnet: tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)\n",
- inb(STATUS),lp->intx,jiffies-dev->trans_start);
+ printk("%6s: tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)\n",
+ dev->name,inb(STATUS),lp->intx,jiffies-dev->trans_start);
+ lp->stats.tx_errors++;
dev_tint(dev);
- lp->intx--;
return 0;
}
if (lp->txready) /* transmit already in progress! */
{
- printk("arcnet: trying to start new packet while busy! (status=%Xh)\n",
- inb(STATUS));
- /*printk("arcnet: marking as not ready.\n");*/
+ printk("%6s: trying to start new packet while busy! (status=%Xh)\n",
+ dev->name,inb(STATUS));
outb(0,INTMASK);
outb(NOTXcmd,COMMAND); /* abort current send */
arcnet_inthandler(dev); /* fake an interrupt */
lp->stats.tx_errors++;
- lp->intx--;
+ lp->stats.tx_fifo_errors++;
lp->txready=0; /* we definitely need this line! */
return 1;
@@ -1299,253 +1351,224 @@
done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
if (set_bit(0, (void*)&dev->tbusy) != 0)
{
- printk("arcnet: transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
- inb(STATUS),lp->intx,jiffies-dev->trans_start);
- lp->intx--;
+ printk("%6s: transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
+ dev->name,inb(STATUS),lp->intx,jiffies-dev->trans_start);
+ lp->stats.tx_errors++;
+ lp->stats.tx_fifo_errors++;
return -EBUSY;
}
- else {
- struct Outgoing *out=&(lp->outgoing);
-
- TBUSY=1;
+
+ return 0;
+}
+
+
+/* Called by the kernel in order to transmit a packet.
+ */
+static int
+arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
+{
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ int ioaddr=dev->base_addr,bad;
+ struct Outgoing *out=&(lp->outgoing);
+
+ BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
+ inb(STATUS),lp->intx);
+
+ lp->intx++;
+
+ bad=arcnet_send_packet_bad(skb,dev);
+ if (bad)
+ {
+ lp->intx--;
+ return bad;
+ }
+
+ TBUSY=1;
- out->length = 1 < skb->len ? skb->len : 1;
- out->hdr=(struct ClientData*)skb->data;
- out->skb=skb;
+ out->length = 1 < skb->len ? skb->len : 1;
+ out->hdr=(struct ClientData*)skb->data;
+ out->skb=skb;
- BUGLVL(D_SKB)
+ BUGLVL(D_SKB)
+ {
+ short i;
+ for( i=0; i< skb->len; i++)
{
- short i;
- for( i=0; i< skb->len; i++)
- {
- if( i%16 == 0 ) printk("\n[%04hX] ",i);
- printk("%02hX ",((unsigned char*)skb->data)[i]);
- }
- printk("\n");
+ if( i%16 == 0 ) printk("\n[%04hX] ",i);
+ printk("%02hX ",((unsigned char*)skb->data)[i]);
}
+ printk("\n");
+ }
- out->hdr->sequence=(lp->sequence++);
-
- if (lp->txready && inb(STATUS)&TXFREEflag)
- arcnetAS_go_tx(dev);
-
- /* fits in one packet? */
- if (out->length-EXTRA_CLIENTDATA<=XMTU)
- {
- BUGLVL(D_DURING)
- printk("arcnet: not splitting %d-byte packet. (split_flag=%d)\n",
- out->length,out->hdr->split_flag);
- BUGLVL(D_EXTRA) if (out->hdr->split_flag)
- printk("arcnet: short packet has split_flag set?! (split_flag=%d)\n",
- out->hdr->split_flag);
- out->numsegs=1;
- out->segnum=1;
- arcnetAS_prepare_tx(dev,
- ((char *)out->hdr)+EXTRA_CLIENTDATA,
- sizeof(struct ClientData)-EXTRA_CLIENTDATA,
- ((char *)skb->data)+sizeof(struct ClientData),
- out->length-sizeof(struct ClientData),
- out->hdr->daddr,1);
+ out->hdr->sequence=(lp->sequence++);
+
+ /*arcnet_go_tx(dev);*/ /* Make sure buffers are clear */
- /* done right away */
- dev_kfree_skb(out->skb,FREE_WRITE);
- out->skb=NULL;
+ /* fits in one packet? */
+ if (out->length-EXTRA_CLIENTDATA<=XMTU)
+ {
+ BUGMSG(D_DURING,"not splitting %d-byte packet. (split_flag=%d)\n",
+ out->length,out->hdr->split_flag);
+ BUGLVL(D_EXTRA) if (out->hdr->split_flag)
+ printk("%6s: short packet has split_flag set?! (split_flag=%d)\n",
+ dev->name,out->hdr->split_flag);
+ out->numsegs=1;
+ out->segnum=1;
+ arcnetAS_prepare_tx(dev,
+ ((char *)out->hdr)+EXTRA_CLIENTDATA,
+ sizeof(struct ClientData)-EXTRA_CLIENTDATA,
+ ((char *)skb->data)+sizeof(struct ClientData),
+ out->length-sizeof(struct ClientData),
+ out->hdr->daddr,1);
+
+ /* done right away */
+ dev_kfree_skb(out->skb,FREE_WRITE);
+ out->skb=NULL;
- if (!lp->sending)
- {
- arcnetAS_go_tx(dev);
-
- /* inform upper layers */
- TBUSY=0;
- mark_bh(NET_BH);
- }
- }
- else /* too big for one - split it */
+ if (arcnet_go_tx(dev,1))
{
- int maxsegsize=XMTU-4;
+ /* inform upper layers */
+ TBUSY=0;
+ mark_bh(NET_BH);
+ }
+ }
+ else /* too big for one - split it */
+ {
+ int maxsegsize=XMTU-4;
- out->data=(u_char *)skb->data
- + sizeof(struct ClientData);
- out->dataleft=out->length-sizeof(struct ClientData);
- out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize;
-
- out->segnum=0;
+ out->data=(u_char *)skb->data
+ + sizeof(struct ClientData);
+ out->dataleft=out->length-sizeof(struct ClientData);
+ out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize;
- BUGLVL(D_TX) printk("arcnet: packet (%d bytes) split into %d fragments:\n",
- out->length,out->numsegs);
+ out->segnum=0;
+
+ BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n",
+ out->length,out->numsegs);
- /* if a packet waiting, launch it */
- if (lp->txready && inb(STATUS)&TXFREEflag)
- arcnetAS_go_tx(dev);
+ /* if a packet waiting, launch it */
+ arcnet_go_tx(dev,1);
- if (!lp->txready)
- {
- /* prepare a packet, launch it and prepare
- * another.
- */
- arcnetA_continue_tx(dev);
- if (!lp->sending)
- {
- arcnetAS_go_tx(dev);
- arcnetA_continue_tx(dev);
- if (!lp->sending)
- arcnetAS_go_tx(dev);
- }
- }
-
- /* if segnum==numsegs, the transmission is finished;
- * free the skb right away.
+ if (!lp->txready)
+ {
+ /* prepare a packet, launch it and prepare
+ * another.
*/
- if (out->segnum==out->numsegs)
+ arcnetA_continue_tx(dev);
+ if (arcnet_go_tx(dev,1))
{
- /* transmit completed */
- out->segnum++;
- if (out->skb)
- dev_kfree_skb(out->skb,FREE_WRITE);
- out->skb=NULL;
+ arcnetA_continue_tx(dev);
+ arcnet_go_tx(dev,1);
}
}
+
+ /* if segnum==numsegs, the transmission is finished;
+ * free the skb right away.
+ */
+ if (out->segnum==out->numsegs)
+ {
+ /* transmit completed */
+ out->segnum++;
+ if (out->skb)
+ dev_kfree_skb(out->skb,FREE_WRITE);
+ out->skb=NULL;
+ }
}
- lp->intx--;
- lp->stats.tx_packets++;
dev->trans_start=jiffies;
+ lp->intx--;
return 0;
}
-/* After an RFC1201 split packet has been set up, this function calls
- * arcnetAS_prepare_tx to load the next segment into the card. This function
- * does NOT automatically call arcnetAS_go_tx to allow for easier double-
- * buffering.
+
+/* Called by the kernel in order to transmit an ethernet-type packet.
*/
-static void arcnetA_continue_tx(struct device *dev)
+static int
+arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int maxsegsize=XMTU-4;
- struct Outgoing *out=&(lp->outgoing);
+ int bad;
+ union ArcPacket *arcpacket =
+ (union ArcPacket *)(dev->mem_start+512*(lp->txbuf^1));
+ u_char *arcsoft,daddr;
+ short offset,length=skb->len+1;
+
+ BUGMSG(D_DURING,"in arcnetE_send_packet (skb=%p)\n",skb);
+
+ lp->intx++;
- if (lp->txready)
+ bad=arcnet_send_packet_bad(skb,dev);
+ if (bad)
{
- printk("arcnet: continue_tx: called with packet in buffer!\n");
- return;
+ lp->intx--;
+ return bad;
}
- if (out->segnum>=out->numsegs)
+ TBUSY=1;
+
+ if (length>XMTU)
{
- printk("arcnet: continue_tx: building segment %d of %d!\n",
- out->segnum+1,out->numsegs);
- }
-
- if (!out->segnum) /* first packet */
- out->hdr->split_flag=((out->numsegs-2)<<1)+1;
- else
- out->hdr->split_flag=out->segnum<<1;
-
- out->seglen=maxsegsize;
- if (out->seglen>out->dataleft) out->seglen=out->dataleft;
-
- BUGLVL(D_TX) printk("arcnet: building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
- out->segnum+1,out->seglen,out->numsegs,
- out->length,out->hdr->split_flag);
+ printk("%6s: MTU must be <= 493 for ethernet encap (length=%d).\n",
+ dev->name,length);
+ printk("%6s: transmit aborted.\n",dev->name);
- arcnetAS_prepare_tx(dev,((char *)out->hdr)+EXTRA_CLIENTDATA,
- sizeof(struct ClientData)-EXTRA_CLIENTDATA,
- out->data,out->seglen,out->hdr->daddr,1);
+ dev_kfree_skb(skb,FREE_WRITE);
+ return 0;
+ }
- out->dataleft-=out->seglen;
- out->data+=out->seglen;
- out->segnum++;
-}
-
-
-/* Given an skb, copy a packet into the ARCnet buffers for later transmission
- * by arcnetAS_go_tx.
- */
-static void
-arcnetAS_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
- char *data,int length,int daddr,int exceptA)
-{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- struct ClientData *arcsoft;
- union ArcPacket *arcpacket =
- (union ArcPacket *)(dev->mem_start+512*(lp->txbuf^1));
- int offset;
-
- lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate between 2 and 3 */
-
- length+=hdrlen;
+ BUGMSG(D_DURING,"starting tx sequence...\n");
- BUGLVL(D_TX)
- printk("arcnet: arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
- hdr,length,data);
+ lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate btw 2 & 3 */
/* clean out the page to make debugging make more sense :) */
BUGLVL(D_DURING)
memset((void *)dev->mem_start+lp->txbuf*512,0x42,512);
- arcpacket->hardheader.destination=daddr;
+ /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
+ if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF)
+ daddr=arcpacket->hardheader.destination=0;
+ else
+ daddr=arcpacket->hardheader.destination=
+ ((struct ethhdr*)(skb->data))->h_dest[5];
/* load packet into shared memory */
- if (length<=MTU) /* Normal (256-byte) Packet */
- {
- arcpacket->hardheader.offset1=offset=256-length;
- arcsoft=(struct ClientData *)
- (&arcpacket->raw[offset]);
- }
- else if (length>=MinTU) /* Extended (512-byte) Packet */
- {
- arcpacket->hardheader.offset1=0;
- arcpacket->hardheader.offset2=offset=512-length;
-
- arcsoft=(struct ClientData *)
- (&arcpacket->raw[offset]);
- }
- else if (exceptA) /* RFC1201 Exception Packet */
+ offset=512-length;
+ if (length>MTU) /* long/exception packet */
{
+ if (length<MinTU) offset-=3;
arcpacket->hardheader.offset1=0;
- arcpacket->hardheader.offset2=offset=512-length-4;
- arcsoft=(struct ClientData *)
- (&arcpacket->raw[offset+4]);
-
- /* exception-specific stuff - these four bytes
- * make the packet long enough to fit in a 512-byte
- * frame.
- */
- arcpacket->raw[offset+0]=hdr[0];
- arcpacket->raw[offset+1]=0xFF; /* FF flag */
- arcpacket->raw[offset+2]=0xFF; /* FF padding */
- arcpacket->raw[offset+3]=0xFF; /* FF padding */
+ arcpacket->hardheader.offset2=offset;
}
- else /* "other" Exception packet */
+ else /* short packet */
{
- /* RFC1051 - set 4 trailing bytes to 0 */
- memset(&arcpacket->raw[508],0,4);
-
- /* now round up to MinTU */
- arcpacket->hardheader.offset1=0;
- arcpacket->hardheader.offset2=offset=512-MinTU;
- arcsoft=(struct ClientData *)(&arcpacket->raw[offset]);
+ arcpacket->hardheader.offset1=(offset-=256);
}
-
-
+
+ BUGMSG(D_DURING," length=%Xh, offset=%Xh, offset1=%Xh, offset2=%Xh\n",
+ length,offset,arcpacket->hardheader.offset1,
+ arcpacket->hardheader.offset2);
+
+ arcsoft=&arcpacket->raw[offset];
+ arcsoft[0]=ARC_P_ETHER;
+ arcsoft++;
+
/* copy the packet into ARCnet shmem
* - the first bytes of ClientData header are skipped
*/
- memcpy((u_char*)arcsoft,
- (u_char*)hdr,hdrlen);
- memcpy((u_char*)arcsoft+hdrlen,
- data,length-hdrlen);
+ BUGMSG(D_DURING,"ready to memcpy\n");
+
+ memcpy(arcsoft,skb->data,skb->len);
- BUGLVL(D_DURING) printk("arcnet: transmitting packet to station %02Xh (%d bytes)\n",
+ BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
daddr,length);
-
+
BUGLVL(D_TX)
{
int countx,county;
-
- printk("arcnet: packet dump [tx] follows:");
+
+ printk("%6s: packet dump [tx] follows:",dev->name);
- for (county=0; county<16+(length>MTU)*16; county++)
+ for (county=0; county<16+(length>=240)*16; county++)
{
printk("\n[%04X] ",county*16);
for (countx=0; countx<16; countx++)
@@ -1560,347 +1583,288 @@
lp->outgoing.lastload_dest=daddr;
#endif
lp->txready=lp->txbuf; /* packet is ready for sending */
-}
-/* Actually start transmitting a packet that was placed in the card's
- * buffer by arcnetAS_prepare_tx.
- */
-static void
-arcnetAS_go_tx(struct device *dev)
-{
- struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
- int ioaddr=dev->base_addr;
-
- BUGLVL(D_DURING)
- printk("arcnet: go_tx: status=%Xh\n",
- inb(STATUS));
-
- if (!(inb(STATUS)&TXFREEflag) || !lp->txready) return;
-
- /* start sending */
- outb(TXcmd|(lp->txready<<3),COMMAND);
+ dev_kfree_skb(skb,FREE_WRITE);
- outb(TXFREEflag|NORXflag|RECON_flag,INTMASK);
+ if (arcnet_go_tx(dev,1))
+ {
+ /* inform upper layers */
+ TBUSY=0;
+ mark_bh(NET_BH);
+ }
- dev->trans_start = jiffies;
- lp->txready=0;
- lp->sending++;
-#ifdef VERIFY_ACK
- lp->outgoing.lasttrans_dest=lp->outgoing.lastload_dest;
- lp->outgoing.lastload_dest=0;
-#endif
+ dev->trans_start=jiffies;
+ lp->intx--;
+ return 0;
}
-/* Called by the kernel in order to transmit an ethernet-type packet.
+/* Called by the kernel in order to transmit an RFC1051-type packet.
*/
static int
-arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
+arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ int ioaddr=dev->base_addr,bad,length;
+ struct S_ClientData *hdr=(struct S_ClientData *)skb->data;
+
+ lp->intx++;
- BUGLVL(D_DURING)
- printk("%s: in arcnetE_send_packet (skb=%p)\n",dev->name,skb);
+ BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
+ inb(STATUS),lp->intx);
- if (IF_TBUSY)
+ bad=arcnet_send_packet_bad(skb,dev);
+ if (bad)
{
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 10)
- return 1;
- printk("%s: transmit timed out\n",dev->name);
-
- /* Try to restart the adaptor. */
- TBUSY=0;
- /*dev->trans_start = jiffies;*/
- return 0;
+ lp->intx--;
+ return bad;
}
+
+ TBUSY=1;
- /* If some higher layer thinks we've missed an tx-done interrupt
- we are passed NULL. Caution: dev_tint() handles the cli()/sti()
- itself. */
- if (skb == NULL)
- {
- dev_tint(dev);
- return 0;
- }
+ length = 1 < skb->len ? skb->len : 1;
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else
+ BUGLVL(D_SKB)
{
- union ArcPacket *arcpacket =
- (union ArcPacket *)(dev->mem_start+512*(lp->txbuf^1));
- u_char *arcsoft,daddr;
- short offset,length=skb->len+1;
-
- TBUSY=1;
-
- if (length>XMTU)
+ short i;
+ for(i=0; i<skb->len; i++)
{
- printk("arcnet: MTU for %s and %s must be <= 493 for ethernet encap.\n",
- lp->adev->name,lp->edev->name);
- printk("arcnet: transmit aborted.\n");
-
- dev_kfree_skb(skb,FREE_WRITE);
- return 0;
+ if( i%16 == 0 ) printk("\n[%04hX] ",i);
+ printk("%02hX ",((unsigned char*)skb->data)[i]);
}
-
- BUGLVL(D_DURING)
- printk("arcnet: starting tx sequence...\n");
-
- lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate btw 2 & 3 */
+ printk("\n");
+ }
- /* clean out the page to make debugging make more sense :) */
- BUGLVL(D_DURING)
- memset((void *)dev->mem_start+lp->txbuf*512,0x42,512);
+ /*if (lp->txready && inb(STATUS)&TXFREEflag)
+ arcnet_go_tx(dev);*/
- /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
- if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF)
- daddr=arcpacket->hardheader.destination=0;
- else
- daddr=arcpacket->hardheader.destination=
- ((struct ethhdr*)(skb->data))->h_dest[5];
+ /* fits in one packet? */
+ if (length-S_EXTRA_CLIENTDATA<=XMTU)
+ {
+ arcnetAS_prepare_tx(dev,
+ skb->data+S_EXTRA_CLIENTDATA,
+ sizeof(struct S_ClientData)-S_EXTRA_CLIENTDATA,
+ skb->data+sizeof(struct S_ClientData),
+ length-sizeof(struct S_ClientData),
+ hdr->daddr,0);
- /* load packet into shared memory */
- offset=512-length;
- if (length>MTU) /* long/exception packet */
- {
- if (length<MinTU) offset-=3;
- arcpacket->hardheader.offset1=0;
- arcpacket->hardheader.offset2=offset;
- }
- else /* short packet */
- {
- arcpacket->hardheader.offset1=(offset-=256);
- }
-
- BUGLVL(D_DURING)
- printk("arcnet: length=%Xh, offset=%Xh, offset1=%Xh, offset2=%Xh\n",
- length,offset,arcpacket->hardheader.offset1,
- arcpacket->hardheader.offset2);
-
- arcsoft=&arcpacket->raw[offset];
- arcsoft[0]=ARC_P_ETHER;
- arcsoft++;
-
- /* copy the packet into ARCnet shmem
- * - the first bytes of ClientData header are skipped
- */
- BUGLVL(D_DURING) printk("arcnet: ready to memcpy\n");
-
- memcpy(arcsoft,skb->data,skb->len);
-
- BUGLVL(D_DURING)
- printk("arcnet: transmitting packet to station %02Xh (%d bytes)\n",
- daddr,length);
+ /* done right away */
+ dev_kfree_skb(skb,FREE_WRITE);
- BUGLVL(D_TX)
+ if (arcnet_go_tx(dev,1))
{
- int countx,county;
-
- printk("arcnet: packet dump [tx] follows:");
-
- for (county=0; county<16+(length>=240)*16; county++)
- {
- printk("\n[%04X] ",county*16);
- for (countx=0; countx<16; countx++)
- printk("%02X ",
- arcpacket->raw[county*16+countx]);
- }
-
- printk("\n");
+ /* inform upper layers */
+ TBUSY=0;
+ mark_bh(NET_BH);
}
-
- #ifdef VERIFY_ACK
- lp->outgoing.lastload_dest=daddr;
- #endif
- lp->txready=lp->txbuf; /* packet is ready for sending */
-
- arcnetAS_go_tx(dev);
- dev->trans_start = jiffies;
+ }
+ else /* too big for one - not accepted */
+ {
+ printk("arcnetS: packet too long (length=%d)\n",
+ length);
+ dev_kfree_skb(skb,FREE_WRITE);
+ lp->stats.tx_dropped++;
+ TBUSY=0;
+ mark_bh(NET_BH);
}
- dev_kfree_skb(skb,FREE_WRITE);
-
+ dev->trans_start=jiffies;
+ lp->intx--;
return 0;
}
-/* Called by the kernel in order to transmit an RFC1051-type packet.
+/* After an RFC1201 split packet has been set up, this function calls
+ * arcnetAS_prepare_tx to load the next segment into the card. This function
+ * does NOT automatically call arcnet_go_tx.
*/
-static int
-arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
+static void arcnetA_continue_tx(struct device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int ioaddr=dev->base_addr;
-
- lp->intx++;
+ int maxsegsize=XMTU-4;
+ struct Outgoing *out=&(lp->outgoing);
- BUGLVL(D_DURING)
- printk("arcnetS: transmit requested (status=%Xh, inTX=%d)\n",
- inb(STATUS),lp->intx);
-
- if (lp->in_txhandler)
+ if (lp->txready)
{
- printk("arcnetS: send_packet called while in txhandler!\n");
- lp->intx--;
- return 1;
+ printk("%6s: continue_tx: called with packet in buffer!\n",
+ dev->name);
+ return;
}
- if (IF_TBUSY)
+ if (out->segnum>=out->numsegs)
{
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- int recbuf=lp->recbuf;
- int status=inb(STATUS);
-
- if (tickssofar < 5)
- {
- BUGLVL(D_DURING)
- printk("arcnetS: premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
- status,tickssofar,lp->outgoing.skb,
- lp->outgoing.numsegs,
- lp->outgoing.segnum);
- lp->intx--;
- return 1;
- }
+ printk("%6s: continue_tx: building segment %d of %d!\n",
+ dev->name,out->segnum+1,out->numsegs);
+ }
- BUGLVL(D_EXTRA)
- printk("arcnetS: transmit timed out (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)\n",
- status,lp->intx,lp->in_txhandler,tickssofar);
-
- lp->stats.tx_errors++;
+ if (!out->segnum) /* first packet */
+ out->hdr->split_flag=((out->numsegs-2)<<1)+1;
+ else
+ out->hdr->split_flag=out->segnum<<1;
- /* Try to restart the adaptor. */
- /*arcnet_reset(dev);*/
+ out->seglen=maxsegsize;
+ if (out->seglen>out->dataleft) out->seglen=out->dataleft;
+
+ BUGMSG(D_TX,"building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
+ out->segnum+1,out->seglen,out->numsegs,
+ out->length,out->hdr->split_flag);
+
+ arcnetAS_prepare_tx(dev,((char *)out->hdr)+EXTRA_CLIENTDATA,
+ sizeof(struct ClientData)-EXTRA_CLIENTDATA,
+ out->data,out->seglen,out->hdr->daddr,1);
- outb(0,INTMASK);
- if (status&NORXflag) EnableReceiver();
- if (!(status&TXFREEflag)) outb(NOTXcmd,COMMAND);
- /*dev->trans_start = jiffies;*/
+ out->dataleft-=out->seglen;
+ out->data+=out->seglen;
+ out->segnum++;
+}
- if (lp->outgoing.skb)
- {
- dev_kfree_skb(lp->outgoing.skb,FREE_WRITE);
- lp->stats.tx_dropped++;
- }
- lp->outgoing.skb=NULL;
- TBUSY=0;
- lp->intx--;
- /*lp->intx=0;*/
- /*lp->in_txhandler=0;*/
- lp->txready=0;
- lp->sending=0;
- /*mark_bh(NET_BH);*/
+/* Given an skb, copy a packet into the ARCnet buffers for later transmission
+ * by arcnet_go_tx.
+ */
+static void
+arcnetAS_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
+ char *data,int length,int daddr,int exceptA)
+{
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ struct ClientData *arcsoft;
+ union ArcPacket *arcpacket =
+ (union ArcPacket *)(dev->mem_start+512*(lp->txbuf^1));
+ int offset;
+
+ lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate between 2 and 3 */
+
+ length+=hdrlen;
- outb(NORXflag|RECON_flag,INTMASK);
+ BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
+ hdr,length,data);
- return 1;
- }
+ /* clean out the page to make debugging make more sense :) */
+ BUGLVL(D_DURING)
+ memset((void *)dev->mem_start+lp->txbuf*512,0x42,512);
- /* If some higher layer thinks we've missed a tx-done interrupt
- we are passed NULL. Caution: dev_tint() handles the cli()/sti()
- itself. */
- if (skb == NULL) {
- printk("arcnetS: tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)\n",
- inb(STATUS),lp->intx,jiffies-dev->trans_start);
- dev_tint(dev);
- lp->intx--;
- return 0;
+ arcpacket->hardheader.destination=daddr;
+
+ /* load packet into shared memory */
+ if (length<=MTU) /* Normal (256-byte) Packet */
+ {
+ arcpacket->hardheader.offset1=offset=256-length;
+ arcsoft=(struct ClientData *)
+ (&arcpacket->raw[offset]);
}
-
- if (lp->txready) /* transmit already in progress! */
+ else if (length>=MinTU) /* Extended (512-byte) Packet */
{
- printk("arcnetS: trying to start new packet while busy! (status=%Xh)\n",
- inb(STATUS));
- /*printk("arcnetS: marking as not ready.\n");*/
- outb(0,INTMASK);
- outb(NOTXcmd,COMMAND); /* abort current send */
- arcnet_inthandler(dev); /* fake an interrupt */
- lp->stats.tx_errors++;
- lp->intx--;
- lp->txready=0; /* we definitely need this line! */
+ arcpacket->hardheader.offset1=0;
+ arcpacket->hardheader.offset2=offset=512-length;
- return 1;
+ arcsoft=(struct ClientData *)
+ (&arcpacket->raw[offset]);
}
-
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (set_bit(0, (void*)&dev->tbusy) != 0)
- {
- printk("arcnetS: transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
- inb(STATUS),lp->intx,jiffies-dev->trans_start);
- lp->intx--;
- return -EBUSY;
- }
- else {
- int length;
- struct S_ClientData *hdr=(struct S_ClientData *)skb->data;
+ else if (exceptA) /* RFC1201 Exception Packet */
+ {
+ arcpacket->hardheader.offset1=0;
+ arcpacket->hardheader.offset2=offset=512-length-4;
+ arcsoft=(struct ClientData *)
+ (&arcpacket->raw[offset+4]);
- TBUSY=1;
+ /* exception-specific stuff - these four bytes
+ * make the packet long enough to fit in a 512-byte
+ * frame.
+ */
+ arcpacket->raw[offset+0]=hdr[0];
+ arcpacket->raw[offset+1]=0xFF; /* FF flag */
+ arcpacket->raw[offset+2]=0xFF; /* FF padding */
+ arcpacket->raw[offset+3]=0xFF; /* FF padding */
+ }
+ else /* "other" Exception packet */
+ {
+ /* RFC1051 - set 4 trailing bytes to 0 */
+ memset(&arcpacket->raw[508],0,4);
+
+ /* now round up to MinTU */
+ arcpacket->hardheader.offset1=0;
+ arcpacket->hardheader.offset2=offset=512-MinTU;
+ arcsoft=(struct ClientData *)(&arcpacket->raw[offset]);
+ }
+
+
+ /* copy the packet into ARCnet shmem
+ * - the first bytes of ClientData header are skipped
+ */
+ memcpy((u_char*)arcsoft,
+ (u_char*)hdr,hdrlen);
+ memcpy((u_char*)arcsoft+hdrlen,
+ data,length-hdrlen);
- length = 1 < skb->len ? skb->len : 1;
+ BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
+ daddr,length);
+
+ BUGLVL(D_TX)
+ {
+ int countx,county;
- BUGLVL(D_SKB)
+ printk("%6s: packet dump [tx] follows:",dev->name);
+
+ for (county=0; county<16+(length>MTU)*16; county++)
{
- short i;
- for(i=0; i<skb->len; i++)
- {
- if( i%16 == 0 ) printk("\n[%04hX] ",i);
- printk("%02hX ",((unsigned char*)skb->data)[i]);
- }
- printk("\n");
+ printk("\n[%04X] ",county*16);
+ for (countx=0; countx<16; countx++)
+ printk("%02X ",
+ arcpacket->raw[county*16+countx]);
}
-
- if (lp->txready && inb(STATUS)&TXFREEflag)
- arcnetAS_go_tx(dev);
- /* fits in one packet? */
- if (length-S_EXTRA_CLIENTDATA<=XMTU)
- {
- arcnetAS_prepare_tx(dev,
- skb->data+S_EXTRA_CLIENTDATA,
- sizeof(struct S_ClientData)-S_EXTRA_CLIENTDATA,
- skb->data+sizeof(struct S_ClientData),
- length-sizeof(struct S_ClientData),
- hdr->daddr,0);
+ printk("\n");
+ }
- /* done right away */
- dev_kfree_skb(skb,FREE_WRITE);
-
- if (!lp->sending)
- {
- arcnetAS_go_tx(dev);
-
- /* inform upper layers */
- TBUSY=0;
- mark_bh(NET_BH);
- }
- }
- else /* too big for one - not accepted */
+#ifdef VERIFY_ACK
+ lp->outgoing.lastload_dest=daddr;
+#endif
+ lp->txready=lp->txbuf; /* packet is ready for sending */
+}
+
+/* Actually start transmitting a packet that was placed in the card's
+ * buffer by arcnetAS_prepare_tx. Returns 1 if a Tx is really started.
+ */
+static int
+arcnet_go_tx(struct device *dev,int enable_irq)
+{
+ struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
+ int ioaddr=dev->base_addr;
+
+ BUGMSG(D_DURING,"go_tx: status=%Xh\n",
+ inb(STATUS));
+
+ outb(0,INTMASK);
+
+ if (lp->sending || !lp->txready)
+ {
+ if (enable_irq)
{
- printk("arcnetS: packet too long (length=%d)\n",
- length);
- dev_kfree_skb(skb,FREE_WRITE);
- lp->stats.tx_dropped++;
- TBUSY=0;
- mark_bh(NET_BH);
+ if (lp->sending)
+ outb(TXFREEflag|NORXflag|RECON_flag,INTMASK);
+ else
+ outb(NORXflag|RECON_flag,INTMASK);
}
+ return 0;
}
- lp->intx--;
+ /* start sending */
+ outb(TXcmd|(lp->txready<<3),COMMAND);
+
lp->stats.tx_packets++;
- dev->trans_start=jiffies;
- return 0;
-}
+ lp->txready=0;
+ lp->sending++;
+
+#ifdef VERIFY_ACK
+ lp->outgoing.lasttrans_dest=lp->outgoing.lastload_dest;
+ lp->outgoing.lastload_dest=0;
+#endif
+ if (enable_irq)
+ outb(TXFREEflag|NORXflag|RECON_flag,INTMASK);
+ return 1;
+}
/****************************************************************************
@@ -1941,17 +1905,17 @@
{
struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;
-
+
if (IF_INTERRUPT)
{
- printk("arcnet: DRIVER PROBLEM! Nested arcnet interrupts!\n");
+ printk("%6s: DRIVER PROBLEM! Nested arcnet interrupts!\n",
+ dev->name);
return; /* don't even try. */
}
outb(0,INTMASK);
INTERRUPT = 1;
-
- BUGLVL(D_DURING)
- printk("arcnet: in net_interrupt (status=%Xh)\n",inb(STATUS));
+
+ BUGMSG(D_DURING,"in net_interrupt (status=%Xh)\n",inb(STATUS));
#if 1 /* Whatever you do, don't set this to 0. */
do
@@ -1959,17 +1923,22 @@
status = inb(STATUS);
didsomething=0;
+#if 0 /* no longer necessary - doing checking in arcnet_interrupt now */
if (!dev->start)
{
- BUGLVL(D_DURING)
- printk("arcnet: ARCnet not yet initialized. irq ignored. (status=%Xh)\n",
+ BUGMSG(D_DURING,"ARCnet not yet initialized. irq ignored. (status=%Xh)\n",
status);
if (!(status&NORXflag))
outb(NORXflag|RECON_flag,INTMASK);
+ /* using dev->interrupt here instead of INTERRUPT
+ * because if dev->start is 0, the other devices
+ * probably do not exist.
+ */
dev->interrupt=0;
return;
}
+#endif
/* RESET flag was enabled - card is resetting and if RX
* is disabled, it's NOT because we just got a packet.
@@ -1977,28 +1946,89 @@
if (status & RESETflag)
{
outb(CFLAGScmd|RESETclear,COMMAND);
- BUGLVL(D_INIT)
- printk("arcnet: reset irq (status=%Xh)\n",
+ BUGMSG(D_INIT,"reset irq (status=%Xh)\n",
status);
}
#ifdef DETECT_RECONFIGS
if (status & RECONflag)
{
outb(CFLAGScmd|CONFIGclear,COMMAND);
- BUGLVL(D_EXTRA)
- printk("arcnet: Network reconfiguration detected (status=%Xh)\n",
- status);
lp->stats.tx_carrier_errors++;
+
+ #ifdef SHOW_RECONFIGS
+ BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n",
+ status);
+ #endif /* SHOW_RECONFIGS */
+
+ #ifdef RECON_THRESHOLD
+ /* is the RECON info empty or old? */
+ if (!lp->first_recon || !lp->last_recon ||
+ jiffies-lp->last_recon > HZ*10)
+ {
+ if (lp->network_down)
+ printk("%6s: reconfiguration detected: cabling restored?\n",
+ dev->name);
+ lp->first_recon=lp->last_recon=jiffies;
+ lp->num_recons=lp->network_down=0;
+
+ BUGMSG(D_DURING,"recon: clearing counters.\n");
+ }
+ else /* add to current RECON counter */
+ {
+ lp->last_recon=jiffies;
+ lp->num_recons++;
+
+ BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
+ lp->num_recons,
+ (lp->last_recon-lp->first_recon)/HZ,
+ lp->network_down);
+
+ /* if network is marked up;
+ * and first_recon and last_recon are 60+ sec
+ * apart;
+ * and the average no. of recons counted is
+ * > RECON_THRESHOLD/min;
+ * then print a warning message.
+ */
+ if (!lp->network_down
+ && (lp->last_recon-lp->first_recon)<=HZ*60
+ && lp->num_recons >= RECON_THRESHOLD)
+ {
+ lp->network_down=1;
+ printk("%6s: many reconfigurations detected: cabling problem?\n",
+ dev->name);
+ }
+ else if (!lp->network_down
+ && lp->last_recon-lp->first_recon > HZ*60)
+ {
+ /* reset counters if we've gone for
+ * over a minute.
+ */
+ lp->first_recon=lp->last_recon;
+ lp->num_recons=1;
+ }
+ }
+ #endif
}
-#endif
+ #ifdef RECON_THRESHOLD
+ else if (lp->network_down && jiffies-lp->last_recon > HZ*10)
+ {
+ if (lp->network_down)
+ printk("%6s: cabling restored?\n",dev->name);
+ lp->first_recon=lp->last_recon=0;
+ lp->num_recons=lp->network_down=0;
+
+ BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
+ }
+ #endif
+#endif /* DETECT_RECONFIGS */
/* RX is inhibited - we must have received something. */
if (status & NORXflag)
{
int recbuf=lp->recbuf=!lp->recbuf;
- BUGLVL(D_DURING)
- printk("arcnet: receive irq (status=%Xh)\n",
+ BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
status);
/* enable receive of our next packet */
@@ -2017,8 +2047,7 @@
lp->in_txhandler++;
lp->sending--;
- BUGLVL(D_DURING)
- printk("arcnet: TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
+ BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
status,out->numsegs,out->segnum,out->skb);
#ifdef VERIFY_ACK
@@ -2026,27 +2055,23 @@
{
if (lp->outgoing.lasttrans_dest != 0)
{
- printk("arcnet: transmit was not acknowledged! (status=%Xh, dest=%d)\n",
- status,
+ printk("%6s: transmit was not acknowledged! (status=%Xh, dest=%d)\n",
+ dev->name,status,
lp->outgoing.lasttrans_dest);
lp->stats.tx_errors++;
+ lp->stats.tx_carrier_errors++;
}
else
{
- BUGLVL(D_DURING)
- printk("arcnet: broadcast was not acknowledged; that's normal (status=%Xh, dest=%d)\n",
+ BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%d)\n",
status,
lp->outgoing.lasttrans_dest);
}
}
#endif
-
/* send packet if there is one */
- if (lp->txready)
- {
- arcnetAS_go_tx(dev);
- didsomething++;
- }
+ arcnet_go_tx(dev,0);
+ didsomething++;
if (lp->intx)
{
@@ -2056,8 +2081,7 @@
if (!lp->outgoing.skb)
{
- BUGLVL(D_DURING)
- printk("arcnet: TX IRQ done: no split to continue.\n");
+ BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
/* inform upper layers */
if (!lp->txready && IF_TBUSY)
@@ -2070,15 +2094,12 @@
continue;
}
- /*lp->stats.tx_packets++;*/
-
/* if more than one segment, and not all segments
* are done, then continue xmit.
*/
if (out->segnum<out->numsegs)
arcnetA_continue_tx(dev);
- if (lp->txready && !lp->sending)
- arcnetAS_go_tx(dev);
+ arcnet_go_tx(dev,0);
/* if segnum==numsegs, the transmission is finished;
* free the skb.
@@ -2102,13 +2123,19 @@
lp->in_txhandler--;
}
+ else if (lp->txready && !lp->sending && !lp->intx)
+ {
+ BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n",
+ status);
+ arcnet_go_tx(dev,0);
+ didsomething++;
+ }
} while (--boguscount && didsomething);
- BUGLVL(D_DURING)
- printk("arcnet: net_interrupt complete (status=%Xh, count=%d)\n\n",
+ BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n\n",
inb(STATUS),boguscount);
- if (dev->start && lp->sending)
+ if (dev->start && (lp->sending || (lp->txready && !lp->intx)))
outb(NORXflag|TXFREEflag|RECON_flag,INTMASK);
else
outb(NORXflag|RECON_flag,INTMASK);
@@ -2145,6 +2172,8 @@
u_char *arcsoft;
short length,offset;
u_char daddr,saddr;
+
+ lp->stats.rx_packets++;
saddr=arcpacket->hardheader.source;
daddr=arcpacket->hardheader.destination;
@@ -2152,8 +2181,8 @@
/* if source is 0, it's a "used" packet! */
if (saddr==0)
{
- printk("arcnet: discarding old packet. (status=%Xh)\n",
- inb(STATUS));
+ printk("%6s: discarding old packet. (status=%Xh)\n",
+ dev->name,inb(STATUS));
lp->stats.rx_errors++;
return;
}
@@ -2173,8 +2202,7 @@
length=512-offset;
}
- BUGLVL(D_DURING)
- printk("arcnet: received packet from %02Xh to %02Xh (%d bytes)\n",
+ BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n",
saddr,daddr,length);
/* call the right receiver for the protocol */
@@ -2194,8 +2222,10 @@
arcnetS_rx(lp->sdev,arcsoft,length,saddr,daddr);
break;
default:
- printk("arcnet: received unknown protocol %d (%Xh)\n",
- arcsoft[0],arcsoft[0]);
+ printk("%6s: received unknown protocol %d (%Xh)\n",
+ dev->name,arcsoft[0],arcsoft[0]);
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
break;
}
@@ -2203,7 +2233,7 @@
{
int countx,county;
- printk("arcnet: packet dump [rx] follows:");
+ printk("%6s: packet dump [rx] follows:",dev->name);
for (county=0; county<16+(length>240)*16; county++)
{
@@ -2239,8 +2269,7 @@
struct sk_buff *skb;
struct ClientData *arcsoft,*soft;
- BUGLVL(D_DURING)
- printk("arcnet: it's an RFC1201 packet (length=%d)\n",
+ BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n",
length);
/* compensate for EXTRA_CLIENTDATA (which isn't actually in the
@@ -2251,8 +2280,7 @@
if (arcsoft->split_flag==0xFF) /* Exception Packet */
{
- BUGLVL(D_DURING)
- printk("arcnet: compensating for exception packet\n");
+ BUGMSG(D_DURING,"compensating for exception packet\n");
/* skip over 4-byte junkola */
arcsoft=(struct ClientData *)
@@ -2264,17 +2292,17 @@
{
struct Incoming *in=&lp->incoming[saddr];
- BUGLVL(D_RX) printk("arcnet: incoming is not split (splitflag=%d)\n",
+ BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n",
arcsoft->split_flag);
if (in->skb) /* already assembling one! */
{
- BUGLVL(D_EXTRA) printk("arcnet: aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
+ BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
in->sequence,arcsoft->split_flag,
arcsoft->sequence);
kfree_skb(in->skb,FREE_WRITE);
- lp->stats.tx_dropped++;
- lp->stats.rx_errors++;
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
in->skb=NULL;
}
@@ -2282,7 +2310,8 @@
skb = alloc_skb(length, GFP_ATOMIC);
if (skb == NULL) {
- printk("arcnet: Memory squeeze, dropping packet.\n");
+ printk("%6s: Memory squeeze, dropping packet.\n",
+ dev->name);
lp->stats.rx_dropped++;
return;
}
@@ -2314,22 +2343,23 @@
if (!*cptr) /* is saddr = 00? */
{
- BUGLVL(D_EXTRA)
- printk("arcnet: ARP source address was 00h, set to %02Xh.\n",
+ BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n",
saddr);
+ lp->stats.rx_crc_errors++;
*cptr=saddr;
}
- else BUGLVL(D_DURING)
+ else
{
- printk("arcnet: ARP source address (%Xh) is fine.\n",
+ BUGMSG(D_DURING,"ARP source address (%Xh) is fine.\n",
*cptr);
}
}
else
{
- printk("arcnet: funny-shaped ARP packet. (%Xh, %Xh)\n",
- arp->ar_hln,arp->ar_pln);
- lp->stats.rx_frame_errors++;
+ printk("%6s: funny-shaped ARP packet. (%Xh, %Xh)\n",
+ dev->name,arp->ar_hln,arp->ar_pln);
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
}
}
@@ -2349,7 +2379,6 @@
#endif
netif_rx(skb);
- lp->stats.rx_packets++;
}
else /* split packet */
{
@@ -2372,32 +2401,32 @@
struct Incoming *in=&lp->incoming[saddr];
- BUGLVL(D_RX) printk("arcnet: packet is split (splitflag=%d, seq=%d)\n",
+ BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n",
arcsoft->split_flag,in->sequence);
if (in->skb && in->sequence!=arcsoft->sequence)
{
- BUGLVL(D_EXTRA) printk("arcnet: wrong seq number, aborting assembly (expected=%d, seq=%d, splitflag=%d)\n",
+ BUGMSG(D_EXTRA,"wrong seq number, aborting assembly (expected=%d, seq=%d, splitflag=%d)\n",
in->sequence,arcsoft->sequence,
arcsoft->split_flag);
kfree_skb(in->skb,FREE_WRITE);
in->skb=NULL;
- lp->stats.tx_dropped++;
- lp->stats.rx_fifo_errors++;
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
in->lastpacket=in->numpackets=0;
}
if (arcsoft->split_flag & 1) /* first packet in split */
{
- BUGLVL(D_RX) printk("arcnet: brand new splitpacket (splitflag=%d)\n",
+ BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n",
arcsoft->split_flag);
if (in->skb) /* already assembling one! */
{
- BUGLVL(D_EXTRA) printk("arcnet: aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
+ BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
in->sequence,arcsoft->split_flag,
arcsoft->sequence);
- lp->stats.tx_dropped++;
- lp->stats.rx_over_errors++;
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
kfree_skb(in->skb,FREE_WRITE);
}
@@ -2407,9 +2436,10 @@
if (in->numpackets>16)
{
- BUGLVL(D_EXTRA) printk("arcnet: incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
+ BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
arcsoft->split_flag);
- lp->stats.rx_dropped++;
+ lp->stats.rx_errors++;
+ lp->stats.rx_length_errors++;
return;
}
@@ -2417,7 +2447,7 @@
+ sizeof(struct ClientData),
GFP_ATOMIC);
if (skb == NULL) {
- printk("%s: (split) memory squeeze, dropping packet.\n",
+ printk("%6s: (split) memory squeeze, dropping packet.\n",
dev->name);
lp->stats.rx_dropped++;
return;
@@ -2447,9 +2477,10 @@
*/
if (!in->skb)
{
- BUGLVL(D_EXTRA) printk("arcnet: can't continue split without starting first! (splitflag=%d, seq=%d)\n",
+ BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d)\n",
arcsoft->split_flag,arcsoft->sequence);
lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
return;
}
@@ -2459,19 +2490,21 @@
/* harmless duplicate? ignore. */
if (packetnum<=in->lastpacket-1)
{
- BUGLVL(D_EXTRA) printk("arcnet: duplicate splitpacket ignored! (splitflag=%d)\n",
+ BUGMSG(D_EXTRA,"duplicate splitpacket ignored! (splitflag=%d)\n",
arcsoft->split_flag);
+ lp->stats.rx_errors++;
+ lp->stats.rx_frame_errors++;
return;
}
/* "bad" duplicate, kill reassembly */
- BUGLVL(D_EXTRA) printk("arcnet: out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
+ BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
in->sequence,arcsoft->split_flag,
arcsoft->sequence);
kfree_skb(in->skb,FREE_WRITE);
in->skb=NULL;
- lp->stats.tx_dropped++;
- lp->stats.rx_fifo_errors++;
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
in->lastpacket=in->numpackets=0;
return;
}
@@ -2494,29 +2527,33 @@
if (in->lastpacket == in->numpackets)
{
if (!skb || !in->skb)
- printk("arcnet: ?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
- skb,in->skb);
- in->skb=NULL;
- in->lastpacket=in->numpackets=0;
+ {
+ printk("%6s: ?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
+ dev->name,skb,in->skb);
+ }
+ else
+ {
+ in->skb=NULL;
+ in->lastpacket=in->numpackets=0;
- BUGLVL(D_SKB)
- {
- short i;
- for(i=0; i<skb->len; i++)
- {
- if( i%16 == 0 ) printk("\n[%04hX] ",i);
- printk("%02hX ",((unsigned char*)skb->data)[i]);
- }
- printk("\n");
- }
+ BUGLVL(D_SKB)
+ {
+ short i;
+ for(i=0; i<skb->len; i++)
+ {
+ if( i%16 == 0 ) printk("\n[%04hX] ",i);
+ printk("%02hX ",((unsigned char*)skb->data)[i]);
+ }
+ printk("\n");
+ }
- #ifndef LINUX12
- skb->protocol=arcnetA_type_trans(skb,dev);
- #endif
+ #ifndef LINUX12
+ skb->protocol=arcnetA_type_trans(skb,dev);
+ #endif
- netif_rx(skb);
- lp->stats.rx_packets++;
+ netif_rx(skb);
+ }
}
}
}
@@ -2531,13 +2568,12 @@
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
struct sk_buff *skb;
- BUGLVL(D_DURING)
- printk("arcnet: it's an ethernet-encap packet (length=%d)\n",
+ BUGMSG(D_DURING,"it's an ethernet-encap packet (length=%d)\n",
length);
skb = alloc_skb(length, GFP_ATOMIC);
if (skb == NULL) {
- printk("arcnet: Memory squeeze, dropping packet.\n");
+ printk("%6s: Memory squeeze, dropping packet.\n",dev->name);
lp->stats.rx_dropped++;
return;
}
@@ -2550,7 +2586,7 @@
BUGLVL(D_SKB)
{
short i;
- printk("arcnet: rx skb dump follows:\n");
+ printk("%6s: rx skb dump follows:\n",dev->name);
for(i=0; i<skb->len; i++)
{
if (i%16==0)
@@ -2566,7 +2602,6 @@
#endif
netif_rx(skb);
- lp->stats.rx_packets++;
}
/* Packet receiver for RFC1051 packets;
@@ -2582,8 +2617,7 @@
arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA);
length+=S_EXTRA_CLIENTDATA;
- BUGLVL(D_DURING)
- printk("arcnetS: it's an RFC1051 packet (length=%d)\n",
+ BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n",
length);
@@ -2625,7 +2659,6 @@
#endif
netif_rx(skb);
- lp->stats.rx_packets++;
}
}
@@ -2659,7 +2692,7 @@
static void
set_multicast_list(struct device *dev, int num_addrs, void *addrs)
{
-#if 0 /* no promiscuous mode at all on most ARCnet models */
+#if 0 /* no promiscuous mode at all on most (all?) ARCnet models */
struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
short ioaddr = dev->base_addr;
@@ -2690,10 +2723,9 @@
#else
skb_push(skb,dev->hard_header_len);
#endif
-/* struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);*/
+ struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
- BUGLVL(D_DURING)
- printk("arcnetA: create header from %d to %d; protocol %d (%Xh); size %u.\n",
+ BUGMSG(D_DURING,"create header from %d to %d; protocol %d (%Xh); size %u.\n",
saddr ? *(u_char*)saddr : -1,
daddr ? *(u_char*)daddr : -1,
type,type,len);
@@ -2711,14 +2743,18 @@
head->protocol_id=ARC_P_RARP;
break;
case ETH_P_IPX:
+ case ETH_P_802_3:
+ case ETH_P_802_2:
head->protocol_id=ARC_P_IPX;
break;
case ETH_P_ATALK:
head->protocol_id=ARC_P_ATALK;
break;
default:
- printk("arcnet: I don't understand protocol %d (%Xh)\n",
- type,type);
+ printk("%6s: I don't understand protocol %d (%Xh)\n",
+ dev->name,type,type);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
return 0;
}
@@ -2771,24 +2807,24 @@
#else
skb_push(skb,dev->hard_header_len);
#endif
-/* struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);*/
+ struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
/* set the protocol ID according to RFC1051 */
switch(type)
{
case ETH_P_IP:
head->protocol_id=ARC_P_IP_RFC1051;
- BUGLVL(D_DURING)
- printk("arcnetS: S_header: IP_RFC1051 packet.\n");
+ BUGMSG(D_DURING,"S_header: IP_RFC1051 packet.\n");
break;
case ETH_P_ARP:
head->protocol_id=ARC_P_ARP_RFC1051;
- BUGLVL(D_DURING)
- printk("arcnetS: S_header: ARP_RFC1051 packet.\n");
+ BUGMSG(D_DURING,"S_header: ARP_RFC1051 packet.\n");
break;
default:
printk("arcnetS: I don't understand protocol %d (%Xh)\n",
type,type);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
return 0;
}
@@ -2827,6 +2863,7 @@
struct sk_buff *skb)
{
struct ClientData *head = (struct ClientData *)buff;
+ struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
int status;
/*
@@ -2835,8 +2872,10 @@
if(head->protocol_id != ARC_P_IP)
{
- printk("arcnet: I don't understand protocol type %d (%Xh) addresses!\n",
- head->protocol_id,head->protocol_id);
+ printk("%6s: I don't understand protocol type %d (%Xh) addresses!\n",
+ dev->name,head->protocol_id,head->protocol_id);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
head->daddr=0;
/*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
return 0;
@@ -2846,12 +2885,10 @@
* Try and get ARP to resolve the header.
*/
#ifdef CONFIG_INET
- BUGLVL(D_DURING)
- printk("arcnetA: rebuild header from %d to %d; protocol %Xh\n",
+ BUGMSG(D_DURING,"rebuild header from %d to %d; protocol %Xh\n",
head->saddr,head->daddr,head->protocol_id);
status=arp_find(&(head->daddr), dst, dev, dev->pa_addr, skb)? 1 : 0;
- BUGLVL(D_DURING)
- printk("arcnetA: rebuilt: from %d to %d; protocol %Xh\n",
+ BUGMSG(D_DURING," rebuilt: from %d to %d; protocol %Xh\n",
head->saddr,head->daddr,head->protocol_id);
return status;
#else
@@ -2864,6 +2901,7 @@
struct sk_buff *skb)
{
struct S_ClientData *head = (struct S_ClientData *)buff;
+ struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
/*
* Only ARP and IP are currently supported
@@ -2873,6 +2911,8 @@
{
printk("arcnetS: I don't understand protocol type %d (%Xh) addresses!\n",
head->protocol_id,head->protocol_id);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
head->daddr=0;
/*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
return 0;
@@ -2922,14 +2962,14 @@
case ARC_P_IP: return htons(ETH_P_IP);
case ARC_P_ARP: return htons(ETH_P_ARP);
case ARC_P_RARP: return htons(ETH_P_RARP);
- case ARC_P_IPX: return htons(ETH_P_IPX);
+ case ARC_P_IPX: return htons(ETH_P_802_3);
case ARC_P_ATALK: return htons(ETH_P_ATALK); /* untested appletalk */
case ARC_P_LANSOFT: /* don't understand. fall through. */
default:
- BUGLVL(D_EXTRA)
- printk("arcnet: received packet of unknown protocol id %d (%Xh)\n",
+ BUGMSG(D_EXTRA,"received packet of unknown protocol id %d (%Xh)\n",
head->protocol_id,head->protocol_id);
- lp->stats.rx_frame_errors++;
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
return 0;
}
@@ -2943,7 +2983,7 @@
struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
#ifdef LINUX12
- head=(struct ClientData *)skb->data;
+ head=(struct S_ClientData *)skb->data;
#else
/* Pull off the arcnet header. */
skb->mac.raw=skb->data;
@@ -2966,10 +3006,10 @@
case ARC_P_IP_RFC1051: return htons(ETH_P_IP);
case ARC_P_ARP_RFC1051: return htons(ETH_P_ARP);
default:
- BUGLVL(D_EXTRA)
- printk("arcnetS: received packet of unknown protocol id %d (%Xh)\n",
+ BUGMSG(D_EXTRA,"received packet of unknown protocol id %d (%Xh)\n",
head->protocol_id,head->protocol_id);
- lp->stats.rx_frame_errors++;
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this