patch-2.1.53 linux/drivers/net/arcnet.c
Next file: linux/drivers/net/com20020.c
Previous file: linux/drivers/net/arc-rimi.c
Back to the patch index
Back to the overall index
- Lines: 4627
- Date:
Thu Sep 4 13:25:28 1997
- Orig file:
v2.1.52/linux/drivers/net/arcnet.c
- Orig date:
Mon Jun 16 16:35:55 1997
diff -u --recursive --new-file v2.1.52/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
@@ -17,6 +17,26 @@
**********************
+ v2.91 ALPHA (97/19/08)
+ - Add counting of octets in/out.
+
+ v2.90 ALPHA (97/08/08)
+ - Add support for kernel command line parsing so that chipset
+ drivers are usable when compiled in.
+
+ v2.80 ALPHA (97/08/01)
+ - Split source into multiple files; generic arcnet support and
+ individual chipset drivers. <dwmw2@cam.ac.uk>
+
+ v2.61 ALPHA (97/07/30) by David Woodhouse (dwmw2@cam.ac.uk) for
+ Nortel (Northern Telecom).
+ - Added support for IO-mapped modes and for SMC COM20020 chipset.
+ - Fixed (avoided) race condition in send_packet routines which was
+ discovered when the buffer copy routines got slow (?).
+ - Fixed support for device naming at load time.
+ - Added backplane, clock and timeout options for COM20020.
+ - Added support for promiscuous mode.
+
v2.60 ALPHA (96/11/23)
- Added patch from Vojtech Pavlik <vojtech@atrey.karlin.mff.cuni.cz>
and Martin Mares <mj@k332.feld.cvut.cz> to make the driver work
@@ -95,30 +115,26 @@
This is half-done in ARCnet 2.60, but still uses some
undocumented i386 stuff. (We shouldn't call phys_to_virt,
for example.)
+ - Allow use of RFC1051 or Ether devices without RFC1201.
+ - Keep separate stats for each device.
- Support "arpless" mode like NetBSD does, and as recommended
by the (obsoleted) RFC1051.
- - Some way to make RIM_I_MODE runtime switchable? Yuck...
- Smarter recovery from RECON-during-transmit conditions. (ie.
retransmit immediately)
- - Make arcnetE_send_packet use arcnet_prepare_tx for loading the
- packet into ARCnet memory.
- - Probe for multiple devices in one shot (trying to decide whether
- to do it the "ugly" way or not).
- Add support for the new 1.3.x IP header cache, and other features.
- Debug level should be changed with a system call, not a hack to
the "metric" flag.
+
- What about cards with shared memory that can be "turned off?"
(or that have none at all, like the SMC PC500longboard)
+ Does this work now, with IO_MAPPED_BUFFERS?
+
- Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
with temporarily.) Update: yes, the Pure Data config program
for DOS works fine, but the PDI508Plus I have doesn't! :)
- - Try to implement promiscuous (receive-all-packets) mode available
- on some newer cards with COM20020 and similar chips. I don't have
- one, but SMC sent me the specs.
- ATA protocol support??
- VINES TCP/IP encapsulation?? (info needed)
-
Sources:
- Crynwr arcnet.com/arcether.com packet drivers.
- arcnet.c v0.00 dated 1/1/94 and apparently by
@@ -128,6 +144,7 @@
- RFC's 1201 and 1051 - re: TCP/IP over ARCnet
- The official ARCnet COM9026 data sheets (!) thanks to Ken
Cornetet <kcornete@nyx10.cs.du.edu>
+ - The official ARCnet COM20020 data sheets.
- Information on some more obscure ARCnet controller chips, thanks
to the nice people at SMC.
- net/inet/eth.c (from kernel 1.1.50) for header-building info.
@@ -137,7 +154,7 @@
*/
static const char *version =
- "arcnet.c: v2.60 96/11/23 Avery Pennarun <apenwarr@foxnet.net>\n";
+ "arcnet.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
@@ -164,6 +181,9 @@
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/if_arcnet.h>
+#include <linux/arcdevice.h>
+
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
@@ -171,95 +191,6 @@
#include <net/arp.h>
-/**************************************************************************/
-
-/* Define this if you have a really ancient "RIM I" ARCnet card with no I/O
- * port at all and _only_ shared memory; this option MAY work for you. It's
- * untested, though, so good luck and write to me with any results!
- */
-#undef RIM_I_MODE
-
-/* Normally, the ARCnet device needs to be assigned a name (default arc0).
- * Ethernet devices have a function to automatically try eth0, eth1, etc
- * until a free name is found. To name the ARCnet device using an "eth?"
- * device name, define this option.
- */
-#undef CONFIG_ARCNET_ETHNAME
-
-/* On a fast computer, the buffer copy from memory to the ARCnet card during
- * a transmit can hog the bus just a little too long. SLOW_XMIT_COPY
- * replaces the fast memcpy() with a slower for() loop that seems to solve
- * my problems with ftape.
- *
- * Probably a better solution would be to use memcpy_toio (more portable
- * anyway) and modify that routine to support REALLY_SLOW_IO-style
- * defines; ARCnet probably is not the only driver that can screw up an
- * ftape DMA transfer.
- *
- * Turn this on if you have timing-sensitive DMA (ie. a tape drive) and
- * would like to sacrifice a little bit of network speed to reduce tape
- * write retries or some related problem.
- */
-#undef SLOW_XMIT_COPY
-
-/* 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.
- * Recons 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 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. The larger it is, though, the longer it will be between
- * necessary transmits - don't set this too large.
- */
-#define TX_TIMEOUT 20
-
-/* Define this to speed up the autoprobe by assuming if only one io port and
- * shmem are left in the list at Stage 5, they must correspond to each
- * other.
- *
- * This is undefined by default because it might not always be true, and the
- * extra check makes the autoprobe even more careful. Speed demons can turn
- * it on - I think it should be fine if you only have one ARCnet card
- * installed.
- *
- * If no ARCnet cards are installed, this delay never happens anyway and thus
- * the option has no effect.
- */
-#undef FAST_PROBE
-
-/* Define this to speed up "ifconfig up" by moving the card reset command
- * around. This is a new option in 2.41 ALPHA. If it causes problems,
- * undefine this to get the old behaviour; then send me email, because if
- * there are no problems, this option will go away very soon.
- */
-#define FAST_IFCONFIG
-
/* 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
@@ -269,353 +200,83 @@
/**************************************************************************/
-/* New debugging bitflags: each option can be enabled individually.
- *
- * 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.
- *
- * An ioctl() should be used for this instead, someday.
- *
- * Note: only debug flags included in the ARCNET_DEBUG_MAX define will
- * 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 /* important operational info */
-#define D_EXTRA 2 /* useful, but non-vital information */
-#define D_INIT 4 /* show init/probe messages */
-#define D_INIT_REASONS 8 /* show reasons for discarding probes */
-/* debug levels below give LOTS of output during normal operation! */
-#define D_DURING 16 /* trace operations (including irq's) */
-#define D_TX 32 /* show tx packets */
-#define D_RX 64 /* show rx packets */
-#define D_SKB 128 /* show skb's */
-
-#ifndef ARCNET_DEBUG_MAX
-#define ARCNET_DEBUG_MAX (~0) /* enable ALL debug messages */
-/*#define ARCNET_DEBUG_MAX (D_NORMAL|D_EXTRA|D_INIT|D_INIT_REASONS) */
-/*#define ARCNET_DEBUG_MAX 0 */ /* enable NO messages (bad idea) */
-#endif
-
-#ifndef ARCNET_DEBUG
-#define ARCNET_DEBUG (D_NORMAL|D_EXTRA)
-#endif
-int arcnet_debug = ARCNET_DEBUG;
-
-/* macros to simplify debug checking */
-#define BUGLVL(x) if ((ARCNET_DEBUG_MAX)&arcnet_debug&(x))
-#define BUGMSG2(x,msg,args...) BUGLVL(x) printk(msg, ## args)
-#define BUGMSG(x,msg,args...) BUGMSG2(x,"%s%6s: " msg, \
- x==D_NORMAL ? KERN_WARNING : \
- x<=D_INIT_REASONS ? KERN_INFO : KERN_DEBUG , \
- dev->name , ## args)
-
-/* Some useful multiprotocol macros. The idea here is that GCC will
- * optimize away multiple tests or assignments to lp->adev. Relying on this
- * results in the cleanest mess possible.
+/* These are now provided by the chipset driver. There's a performance
+ * overhead in using them.
*/
-#define ADEV lp->adev
-
-#ifdef CONFIG_ARCNET_ETH
- #define EDEV lp->edev
-#else
- #define EDEV lp->adev
-#endif
-
-#ifdef CONFIG_ARCNET_1051
- #define SDEV lp->sdev
-#else
- #define SDEV lp->adev
-#endif
-
-#define TBUSY ADEV->tbusy=EDEV->tbusy=SDEV->tbusy
-#define IF_TBUSY (ADEV->tbusy||EDEV->tbusy||SDEV->tbusy)
-#define INTERRUPT ADEV->interrupt=EDEV->interrupt=SDEV->interrupt
-#define IF_INTERRUPT (ADEV->interrupt||EDEV->interrupt||SDEV->interrupt)
-#define START ADEV->start=EDEV->start=SDEV->start
+#define AINTMASK(x) ((*lp->asetmask)(dev, x))
+#define ARCSTATUS ((*lp->astatus)(dev))
+#define ACOMMAND(x) ((*lp->acommand)(dev, x))
-/* The number of low I/O ports used by the ethercard. */
-#define ARCNET_TOTAL_SIZE 16
+int arcnet_debug=ARCNET_DEBUG;
-/* Handy defines for ARCnet specific stuff */
- /* COM 9026 controller chip --> ARCnet register addresses */
-#define _INTMASK (ioaddr+0) /* writable */
-#define _STATUS (ioaddr+0) /* readable */
-#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */
-#define _RESET (ioaddr+8) /* software reset (on read) */
+/* Exported function prototypes */
-/* RIM I (command/status is memory mapped) versus RIM III (standard I/O
- * mapped) macros. These make things a bit cleaner.
- */
-#ifdef RIM_I_MODE
- #define IOADDR (dev->mem_start+0x800)
- #define ARCSTATUS readb(_STATUS)
- #define ACOMMAND(cmd) writeb((cmd),_COMMAND)
- #define ARCRESET writeb(TESTvalue,ioaddr-0x800) /* fake reset */
- #define AINTMASK(msk) writeb((msk),_INTMASK)
- #define RELEASE_REGION(x,y) /* nothing */
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
#else
- #define IOADDR (dev->base_addr)
- #define ARCSTATUS inb(_STATUS)
- #define ACOMMAND(cmd) outb((cmd),_COMMAND)
- #define AINTMASK(msk) outb((msk),_INTMASK)
- #define ARCRESET inb(_RESET)
- #define RELEASE_REGION(x,y) release_region((x),(y))
-#endif
-
-#define SETMASK AINTMASK(lp->intmask)
-
- /* Time needed to reset the card - in jiffies. This works on my SMC
- * PC100. I can't find a reference that tells me just how long I
- * should wait.
- */
-#define RESETtime (HZ * 3 / 10) /* reset */
-
- /* these are the max/min lengths of packet data. (including
- * ClientData header)
- * note: packet sizes 250, 251, 252 are impossible (God knows why)
- * so exception packets become necessary.
- *
- * These numbers are compared with the length of the full packet,
- * including ClientData header.
- */
-#define MTU 253 /* normal packet max size */
-#define MinTU 257 /* extended packet min size */
-#define XMTU 508 /* extended packet max size */
-
- /* status/interrupt mask bit fields */
-#define TXFREEflag 0x01 /* transmitter available */
-#define TXACKflag 0x02 /* transmitted msg. ackd */
-#define RECONflag 0x04 /* system reconfigured */
-#define TESTflag 0x08 /* test flag */
-#define RESETflag 0x10 /* power-on-reset */
-#define RES1flag 0x20 /* reserved - usually set by jumper */
-#define RES2flag 0x40 /* reserved - usually set by jumper */
-#define NORXflag 0x80 /* receiver inhibited */
-
- /* in the command register, the following bits have these meanings:
- * 0-2 command
- * 3-4 page number (for enable rcv/xmt command)
- * 7 receive broadcasts
- */
-#define NOTXcmd 0x01 /* disable transmitter */
-#define NORXcmd 0x02 /* disable receiver */
-#define TXcmd 0x03 /* enable transmitter */
-#define RXcmd 0x04 /* enable receiver */
-#define CONFIGcmd 0x05 /* define configuration */
-#define CFLAGScmd 0x06 /* clear flags */
-#define TESTcmd 0x07 /* load test flags */
-
- /* flags for "clear flags" command */
-#define RESETclear 0x08 /* power-on-reset */
-#define CONFIGclear 0x10 /* system reconfigured */
-
- /* flags for "load test flags" command */
-#define TESTload 0x08 /* test flag (diagnostic) */
-
- /* byte deposited into first address of buffers on reset */
-#define TESTvalue 0321 /* that's octal for 0xD1 :) */
-
- /* for "enable receiver" command */
-#define RXbcasts 0x80 /* receive broadcasts */
-
- /* flags for "define configuration" command */
-#define NORMALconf 0x00 /* 1-249 byte packets */
-#define EXTconf 0x08 /* 250-504 byte packets */
-
- /* Starts receiving packets into recbuf.
- */
-#define EnableReceiver() ACOMMAND(RXcmd|(recbuf<<3)|RXbcasts)
-
- /* RFC1201 Protocol ID's */
-#define ARC_P_IP 212 /* 0xD4 */
-#define ARC_P_ARP 213 /* 0xD5 */
-#define ARC_P_RARP 214 /* 0xD6 */
-#define ARC_P_IPX 250 /* 0xFA */
-#define ARC_P_NOVELL_EC 236 /* 0xEC */
-
- /* Old RFC1051 Protocol ID's */
-#define ARC_P_IP_RFC1051 240 /* 0xF0 */
-#define ARC_P_ARP_RFC1051 241 /* 0xF1 */
-
- /* MS LanMan/WfWg protocol */
-#define ARC_P_ETHER 0xE8
-
- /* Unsupported/indirectly supported protocols */
-#define ARC_P_DATAPOINT_BOOT 0 /* very old Datapoint equipment */
-#define ARC_P_DATAPOINT_MOUNT 1
-#define ARC_P_POWERLAN_BEACON 8 /* Probably ATA-Netbios related */
-#define ARC_P_POWERLAN_BEACON2 243
-#define ARC_P_LANSOFT 251 /* 0xFB - what is this? */
-#define ARC_P_ATALK 0xDD
-
- /* the header required by the card itself */
-struct HardHeader
-{
- u_char source, /* source ARCnet - filled in automagically */
- destination, /* destination ARCnet - 0 for broadcast */
- offset1, /* offset of ClientData (256-byte packets) */
- offset2; /* offset of ClientData (512-byte packets) */
-};
-
- /* a complete ARCnet packet */
-union ArcPacket
-{
- struct HardHeader hardheader; /* the hardware header */
- u_char raw[512]; /* raw packet info, incl ClientData */
-};
-
- /* the "client data" header - RFC1201 information
- * notice that this screws up if it's not an even number of bytes
- * <sigh>
- */
-struct ClientData
-{
- /* data that's NOT part of real packet - we MUST get rid of it before
- * actually sending!!
- */
- u_char saddr, /* Source address - needed for IPX */
- daddr; /* Destination address */
-
- /* data that IS part of real packet */
- u_char protocol_id, /* ARC_P_IP, ARC_P_ARP, etc */
- split_flag; /* for use with split packets */
- u_short sequence; /* sequence number */
-};
-#define EXTRA_CLIENTDATA (sizeof(struct ClientData)-4)
-
-
- /* the "client data" header - RFC1051 information
- * this also screws up if it's not an even number of bytes
- * <sigh again>
- */
-struct S_ClientData
-{
- /* data that's NOT part of real packet - we MUST get rid of it before
- * actually sending!!
- */
- u_char saddr, /* Source address - needed for IPX */
- daddr, /* Destination address */
- junk; /* padding to make an even length */
-
- /* data that IS part of real packet */
- u_char protocol_id; /* ARC_P_IP, ARC_P_ARP, etc */
-};
-#define S_EXTRA_CLIENTDATA (sizeof(struct S_ClientData)-1)
-
-
-/* "Incoming" is information needed for each address that could be sending
- * to us. Mostly for partially-received split packets.
- */
-struct Incoming
-{
- struct sk_buff *skb; /* packet data buffer */
- unsigned char lastpacket, /* number of last packet (from 1) */
- numpackets; /* number of packets in split */
- u_short sequence; /* sequence number of assembly */
-};
-
-struct Outgoing
-{
- struct sk_buff *skb; /* buffer from upper levels */
- struct ClientData *hdr; /* clientdata of last packet */
- u_char *data; /* pointer to data in packet */
- short length, /* bytes total */
- dataleft, /* bytes left */
- segnum, /* segment being sent */
- numsegs, /* number of segments */
- seglen; /* length of segment */
-};
-
-
-/* Information that needs to be kept for each board. */
-struct arcnet_local {
- struct net_device_stats stats;
- u_short sequence; /* sequence number (incs with each packet) */
- u_char stationid, /* our 8-bit station address */
- recbuf, /* receive buffer # (0 or 1) */
- txbuf, /* transmit buffer # (2 or 3) */
- txready, /* buffer where a packet is ready to send */
- intmask; /* current value of INTMASK register */
- short intx, /* in TX routine? */
- in_txhandler, /* in TX_IRQ handler? */
- sending, /* transmit in progress? */
- lastload_dest, /* can last loaded packet be acked? */
- lasttrans_dest; /* can last TX'd packet be acked? */
-
-#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 */
- struct Outgoing outgoing; /* packet currently being sent */
-
- struct device *adev; /* RFC1201 protocol device */
-
-#ifdef CONFIG_ARCNET_ETH
- struct device *edev; /* Ethernet-Encap device */
+void arcnet_init(void);
+static int init_module(void);
+#ifdef CONFIG_ARCNET_COM90xx
+extern char com90xx_explicit;
+extern int arc90xx_probe(struct device *dev);
#endif
-
-#ifdef CONFIG_ARCNET_1051
- struct device *sdev; /* RFC1051 protocol device */
#endif
-};
-
-/* Index to functions, as function prototypes. */
+void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
+void arcnet_use_count (int open);
+void arcnet_setup(struct device *dev);
+void arcnet_makename(char *device);
+void arcnetA_continue_tx(struct device *dev);
+int arcnet_go_tx(struct device *dev,int enable_irq);
+void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
+void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
+
+
+EXPORT_SYMBOL(arcnet_debug);
+EXPORT_SYMBOL(arcnet_tx_done);
+EXPORT_SYMBOL(arcnet_use_count);
+EXPORT_SYMBOL(arcnet_setup);
+EXPORT_SYMBOL(arcnet_makename);
+EXPORT_SYMBOL(arcnetA_continue_tx);
+EXPORT_SYMBOL(arcnet_go_tx);
+EXPORT_SYMBOL(arcnet_interrupt);
+EXPORT_SYMBOL(arcnet_rx);
#if ARCNET_DEBUG_MAX & D_SKB
-static void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
+void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
char *desc);
+EXPORT_SYMBOL(arcnet_dump_skb);
#else
# define arcnet_dump_skb(dev,skb,desc) ;
#endif
#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-static void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
+void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
char *desc);
+EXPORT_SYMBOL(arcnet_dump_packet);
#else
# define arcnet_dump_packet(dev,buffer,ext,desc) ;
#endif
-extern int arcnet_probe(struct device *dev);
-static int arcnet_found(struct device *dev,int port,int airq,u_long shmem);
+/* Internal function prototypes */
-static void arcnet_setup(struct device *dev);
static int arcnet_open(struct device *dev);
static int arcnet_close(struct device *dev);
-static int arcnet_reset(struct device *dev,int reset_delay);
-
+static int arcnetA_header(struct sk_buff *skb,struct device *dev,
+ unsigned short type,void *daddr,void *saddr,unsigned len);
+static int arcnetA_rebuild_header(struct sk_buff *skb);
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 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 int arcnet_go_tx(struct device *dev,int enable_irq);
-
-static void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-static void arcnet_inthandler(struct device *dev);
-
-static void arcnet_rx(struct device *dev,int recbuf);
static void arcnetA_rx(struct device *dev,u_char *buf,
int length,u_char saddr, u_char daddr);
-
static struct net_device_stats *arcnet_get_stats(struct device *dev);
+static unsigned short arcnetA_type_trans(struct sk_buff *skb,
+ struct device *dev);
-int arcnetA_header(struct sk_buff *skb,struct device *dev,
- unsigned short type,void *daddr,void *saddr,unsigned len);
-int arcnetA_rebuild_header(struct sk_buff *skb);
-unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev);
#ifdef CONFIG_ARCNET_ETH
/* functions specific to Ethernet-Encap */
@@ -626,6 +287,7 @@
int length,u_char saddr, u_char daddr);
#endif
+
#ifdef CONFIG_ARCNET_1051
/* functions specific to RFC1051 */
static int arcnetS_init(struct device *dev);
@@ -633,20 +295,15 @@
static int arcnetS_send_packet(struct sk_buff *skb, struct device *dev);
static void arcnetS_rx(struct device *dev,u_char *buf,
int length,u_char saddr, u_char daddr);
-int arcnetS_header(struct sk_buff *skb,struct device *dev,
+static int arcnetS_header(struct sk_buff *skb,struct device *dev,
unsigned short type,void *daddr,void *saddr,unsigned len);
-int arcnetS_rebuild_header(struct sk_buff *skb);
-unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev);
+static int arcnetS_rebuild_header(struct sk_buff *skb);
+static unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev);
#endif
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-#endif
-#define tx_done(dev) 1
-#define JIFFER(time) for (delayval=jiffies+time; jiffies<delayval;) ;
+
/****************************************************************************
@@ -699,1209 +356,568 @@
}
#endif
-/****************************************************************************
- * *
- * Probe and initialization *
- * *
- ****************************************************************************/
-#ifdef RIM_I_MODE
-/* We cannot probe for a RIM I card; one reason is I don't know how to reset
- * them. In fact, we can't even get their node ID automatically. So, we
- * need to be passed a specific shmem address, IRQ, and node ID (stored in
- * dev->base_addr)
+
+/* Setup a struct device for ARCnet. This should really be in net_init.c
+ * but since there are three different ARCnet devices ANYWAY... <gargle>
+ *
+ * Actually, the whole idea of having all this kernel-dependent stuff (ie.
+ * "new-style flags") setup per-net-device is kind of weird anyway.
+ *
+ * Intelligent defaults?! Nah.
*/
-__initfunc(int arcnet_probe(struct device *dev))
+
+void arcnet_setup(struct device *dev)
{
- BUGLVL(D_NORMAL) printk(version);
- BUGMSG(D_NORMAL,"Compiled for ARCnet RIM I (autoprobe disabled)\n");
- BUGMSG(D_NORMAL,"Given: node %02lXh, shmem %lXh, irq %d\n",
- dev->base_addr,dev->mem_start,dev->irq);
+ dev_init_buffers(dev);
- if (dev->mem_start<=0 || dev->irq<=0)
- {
- BUGMSG(D_NORMAL,"No autoprobe for RIM I; you "
- "must specify the shmem and irq!\n");
- return -ENODEV;
- }
+ dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */
+ dev->addr_len = 1;
+ dev->type = ARPHRD_ARCNET;
+ dev->tx_queue_len = 30;
- if (dev->base_addr<=0 || dev->base_addr>255)
- {
- BUGMSG(D_NORMAL,"You need to specify your card's station "
- "ID!\n");
- return -ENODEV;
- }
+ /* New-style flags. */
+ dev->flags = IFF_BROADCAST;
+ dev->family = AF_INET;
+ dev->pa_addr = 0;
+ dev->pa_brdaddr = 0;
+ dev->pa_mask = 0;
+ dev->pa_alen = 4;
+
+
+ /* Put in this stuff here, so we don't have to export the symbols
+ * to the chipset drivers.
+ */
- return arcnet_found(dev,dev->base_addr,dev->irq,dev->mem_start);
+ dev->open=arcnet_open;
+ dev->stop=arcnet_close;
+ dev->hard_start_xmit=arcnetA_send_packet;
+ dev->get_stats=arcnet_get_stats;
+ dev->hard_header=arcnetA_header;
+ dev->rebuild_header=arcnetA_rebuild_header;
}
-#else /* not RIM_I_MODE, so use a real autoprobe */
-/* Check for an ARCnet network adaptor, and return '0' if one exists.
- * If dev->base_addr == 0, probe all likely locations.
- * If dev->base_addr == 1, always return failure.
- * If dev->base_addr == 2, allocate space for the device and return success
- * (detachable devices only).
- *
- * NOTE: the list of possible ports/shmems is static, so it is retained
- * across calls to arcnet_probe. So, if more than one ARCnet probe is made,
- * values that were discarded once will not even be tried again.
+/****************************************************************************
+ * *
+ * Open and close the driver *
+ * *
+ ****************************************************************************/
+
+
+/* Open/initialize the board. This is called sometime after booting when
+ * the 'ifconfig' program is run.
*
- * FIXME: grab all devices in one shot and eliminate the big static array.
+ * This routine should set everything up anew at each open, even
+ * registers that "should" only need to be set once at boot, so that
+ * there is non-reboot way to recover if something goes wrong.
*/
+static int
+arcnet_open(struct device *dev)
+{
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+
+ if (dev->metric>=1000)
+ {
+ arcnet_debug=dev->metric-1000;
+ printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug);
+ dev->metric=1;
+ }
+
+ BUGMSG(D_INIT,"arcnet_open: resetting card.\n");
+
+ /* try to put the card in a defined state - if it fails the first
+ * time, actually reset it.
+ */
+ if ((*lp->arcnet_reset)(dev,0) && (*lp->arcnet_reset)(dev,1))
+ return -ENODEV;
+#if 0
+ /* reset the card twice in case something goes wrong the first time.
+ */
+ if ((*(lp->arcnet_reset))(dev,1) && (*(lp->arcnet_reset))(dev,1))
+ return -ENODEV;
+#endif
+
+ dev->tbusy=0;
+ dev->interrupt=0;
+ lp->intx=0;
+ lp->in_txhandler=0;
+
+ /* The RFC1201 driver is the default - just store */
+ lp->adev=dev;
+
+ /* we're started */
+ dev->start=1;
+
+#ifdef CONFIG_ARCNET_ETH
+ /* Initialize the ethernet-encap protocol driver */
+ lp->edev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
+ if (lp->edev == NULL)
+ return -ENOMEM;
+ memcpy(lp->edev,dev,sizeof(struct device));
+ lp->edev->type=ARPHRD_ETHER;
+ lp->edev->name=(char *)kmalloc(10,GFP_KERNEL);
+ if (lp->edev->name == NULL) {
+ kfree(lp->edev);
+ lp->edev = NULL;
+ return -ENOMEM;
+ }
+ sprintf(lp->edev->name,"%se",dev->name);
+ lp->edev->init=arcnetE_init;
+ register_netdev(lp->edev);
+#endif
+
+#ifdef CONFIG_ARCNET_1051
+ /* Initialize the RFC1051-encap protocol driver */
+ lp->sdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
+ memcpy(lp->sdev,dev,sizeof(struct device));
+ lp->sdev->name=(char *)kmalloc(10,GFP_KERNEL);
+ sprintf(lp->sdev->name,"%ss",dev->name);
+ lp->sdev->init=arcnetS_init;
+ register_netdev(lp->sdev);
+#endif
+
+ /* Enable TX if we need to */
+ if (lp->en_dis_able_TX)
+ (*lp->en_dis_able_TX)(dev, 1);
+
+ /* make sure we're ready to receive IRQ's.
+ * arcnet_reset sets this for us, but if we receive one before
+ * START is set to 1, it could be ignored. So, we turn IRQ's
+ * off, then on again to clean out the IRQ controller.
+ */
+
+ AINTMASK(0);
+ udelay(1); /* give it time to set the mask before
+ * we reset it again. (may not even be
+ * necessary)
+ */
+ SETMASK;
+
+ /* Let it increase its use count */
+ (*lp->openclose_device)(1);
+
+ return 0;
+}
-static int ports[(0x3f0 - 0x200) / 16 + 1] __initdata = { 0 };
-static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata = { 0 };
-__initfunc(int arcnet_probe(struct device *dev))
+/* The inverse routine to arcnet_open - shuts down the card.
+ */
+static int
+arcnet_close(struct device *dev)
{
- static int init_once = 0;
- static int numports=sizeof(ports)/sizeof(ports[0]),
- numshmems=sizeof(shmems)/sizeof(shmems[0]);
-
- int count,status,delayval,ioaddr,numprint,airq,retval=-ENODEV,
- openparen=0;
- unsigned long airqmask;
- int *port;
- u_long *shmem;
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+
+ if (test_and_set_bit(0, (int *)&dev->tbusy))
+ BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n");
- if (!init_once)
- {
- for (count=0x200; count<=0x3f0; count+=16)
- ports[(count-0x200)/16] = count;
- for (count=0xA0000; count<=0xFF800; count+=2048)
- shmems[(count-0xA0000)/2048] = count;
- init_once=1;
- }
+ dev->start=0;
+#ifdef CONFIG_ARCNET_1051
+ lp->sdev->tbusy=1;
+ lp->sdev->start=0;
+#endif
+#ifdef CONFIG_ARCNET_ETH
+ lp->edev->tbusy=1;
+ lp->edev->start=0;
+#endif
- BUGLVL(D_NORMAL) printk(version);
+
+ /* Shut down the card */
+
+ /* Disable TX if we need to */
+ if (lp->en_dis_able_TX)
+ (*lp->en_dis_able_TX)(dev, 0);
+
+ (*lp->arcnet_reset)(dev, 3); /* reset IRQ won't run if START=0 */
+#if 0
+ lp->intmask=0;
+ SETMASK; /* no IRQ's (except RESET, of course) */
+ ACOMMAND(NOTXcmd); /* stop transmit */
+ ACOMMAND(NORXcmd); /* disable receive */
+#endif
+
+ /* reset more flags */
+ dev->interrupt=0;
+#ifdef CONFIG_ARCNET_ETH
+ lp->edev->interrupt=0;
+#endif
+#ifdef CONFIG_ARCNET_1051
+ lp->sdev->interrupt=0;
+#endif
- BUGMSG(D_DURING,"space used for probe buffers: %d+%d=%d bytes\n",
- sizeof(ports),sizeof(shmems),
- sizeof(ports)+sizeof(shmems));
-#if 1
- BUGLVL(D_EXTRA)
- {
- printk("arcnet: ***\n");
- printk("arcnet: * Read arcnet.txt for important release notes!\n");
- printk("arcnet: *\n");
- printk("arcnet: * This is an ALPHA version! (Last stable release: v2.56) E-mail me if\n");
- printk("arcnet: * you have any questions, comments, or bug reports.\n");
- printk("arcnet: ***\n");
- }
+
+ /* do NOT free lp->adev!! It's static! */
+ lp->adev=NULL;
+
+#ifdef CONFIG_ARCNET_ETH
+ /* free the ethernet-encap protocol device */
+ lp->edev->priv=NULL;
+ dev_close(lp->edev);
+ unregister_netdev(lp->edev);
+ kfree(lp->edev->name);
+ kfree(lp->edev);
+ lp->edev=NULL;
#endif
+
+#ifdef CONFIG_ARCNET_1051
+ /* free the RFC1051-encap protocol device */
+ lp->sdev->priv=NULL;
+ dev_close(lp->sdev);
+ unregister_netdev(lp->sdev);
+ kfree(lp->sdev->name);
+ kfree(lp->sdev);
+ lp->sdev=NULL;
+#endif
+
+ /* Update the statistics here. (not necessary in ARCnet) */
+
+ /* Decrease the use count */
+ (*lp->openclose_device)(0);
+
+ return 0;
+}
- BUGMSG(D_INIT,"given: base %lXh, IRQ %d, shmem %lXh\n",
- dev->base_addr,dev->irq,dev->mem_start);
- if (dev->base_addr > 0x1ff) /* Check a single specified port */
- {
- ports[0]=dev->base_addr;
- numports=1;
- }
- else if (dev->base_addr > 0) /* Don't probe at all. */
- return -ENXIO;
- if (dev->mem_start)
+/****************************************************************************
+ * *
+ * Transmitter routines *
+ * *
+ ****************************************************************************/
+
+/* Generic error checking routine for arcnet??_send_packet
+ */
+static int
+arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
+{
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+
+ BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
+ ARCSTATUS,lp->intx);
+
+ if (lp->in_txhandler)
+ {
+ 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;
+ }
+
+ if (test_bit(0, (int *)&dev->tbusy))
+ {
+ /* 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 status=ARCSTATUS;
+
+ if (tickssofar < TX_TIMEOUT)
+ {
+ 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);
+ return 1;
+ }
+
+ lp->intmask &= ~TXFREEflag;
+ SETMASK;
+
+ if (status&TXFREEflag) /* transmit _DID_ finish */
+ {
+ BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
+ status,tickssofar,lp->intmask,lp->lasttrans_dest);
+ lp->stats.tx_errors++;
+ }
+ else
+ {
+ BUGMSG(D_EXTRA,"tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n",
+ status,tickssofar,lp->intmask,lp->lasttrans_dest);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+
+ ACOMMAND(NOTXcmd);
+ }
+
+ if (lp->outgoing.skb)
{
- shmems[0]=dev->mem_start;
- numshmems=1;
+ dev_kfree_skb(lp->outgoing.skb,FREE_WRITE);
+ lp->stats.tx_dropped++;
}
+ lp->outgoing.skb=NULL;
+
+#ifdef CONFIG_ARCNET_ETH
+ lp->edev->tbusy=0;
+#endif
+#ifdef CONFIG_ARCNET_1051
+ lp->sdev->tbusy=0;
+#endif
+ if (!test_and_clear_bit(0,(int *)&dev->tbusy))
+ BUGMSG(D_EXTRA, "after timing out, tbusy was clear!\n");
+ lp->txready=0;
+ lp->sending=0;
+
+ return 1;
+ }
+
+ if (lp->txready) /* transmit already in progress! */
+ {
+ BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n",
+ ARCSTATUS);
+ lp->intmask &= ~TXFREEflag;
+ SETMASK;
+ ACOMMAND(NOTXcmd); /* abort current send */
+ (*lp->inthandler)(dev); /* fake an interrupt */
+ lp->stats.tx_errors++;
+ lp->stats.tx_fifo_errors++;
+ lp->txready=0; /* we definitely need this line! */
+
+ return 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 (test_and_set_bit(0, (int *)&lp->adev->tbusy))
+ {
+ BUGMSG(D_NORMAL,"transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
+ ARCSTATUS,lp->intx,jiffies-dev->trans_start);
+ lp->stats.tx_errors++;
+ lp->stats.tx_fifo_errors++;
+ return -EBUSY;
+ }
+#ifdef CONFIG_ARCNET_1051
+ lp->sdev->tbusy=1;
+#endif
+#ifdef CONFIG_ARCNET_ETH
+ lp->edev->tbusy=1;
+#endif
+
+ return 0;
+}
- /* Stage 1: abandon any reserved ports, or ones with status==0xFF
- * (empty), and reset any others by reading the reset port.
- */
- BUGMSG(D_INIT,"Stage 1: ");
- numprint=0;
- for (port = &ports[0]; port-ports<numports; port++)
- {
- numprint++;
- if (numprint>8)
- {
- BUGMSG2(D_INIT,"\n");
- BUGMSG(D_INIT,"Stage 1: ");
- numprint=1;
- }
- BUGMSG2(D_INIT,"%Xh ",*port);
-
- ioaddr=*port;
- if (check_region(*port, ARCNET_TOTAL_SIZE))
- {
- BUGMSG2(D_INIT_REASONS,"(check_region)\n");
- BUGMSG(D_INIT_REASONS,"Stage 1: ");
- BUGLVL(D_INIT_REASONS) numprint=0;
- *port=ports[numports-1];
- numports--;
- port--;
- continue;
- }
+/* 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 bad,oldmask=0;
+ struct Outgoing *out=&(lp->outgoing);
+
+ lp->intx++;
+
+ oldmask |= lp->intmask;
+ lp->intmask=0;
+ SETMASK;
+
+ bad=arcnet_send_packet_bad(skb,dev);
+ if (bad)
+ {
+ lp->intx--;
+ lp->intmask=oldmask;
+ SETMASK;
+ return bad;
+ }
+
+ /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
+
+ lp->intmask = oldmask & ~TXFREEflag;
+ SETMASK;
+
+ out->length = 1 < skb->len ? skb->len : 1;
+ out->hdr=(struct ClientData*)skb->data;
+ out->skb=skb;
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
+
+ out->hdr->sequence=(lp->sequence++);
+
+ /* 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);
+ if (out->hdr->split_flag)
+ BUGMSG(D_NORMAL,"short packet has split_flag set?! (split_flag=%d)\n",
+ out->hdr->split_flag);
+ out->numsegs=1;
+ out->segnum=1;
+ (*lp->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,0);
+
+ /* done right away */
+ lp->stats.tx_bytes += out->skb->len;
+ dev_kfree_skb(out->skb,FREE_WRITE);
+ out->skb=NULL;
+
+ if (arcnet_go_tx(dev,1))
+ {
+ /* inform upper layers */
+ arcnet_tx_done(dev, lp);
+ }
+ }
+ 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;
+
+ BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n",
+ out->length,out->numsegs);
+
+ /* 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 (arcnet_go_tx(dev,1))
+ {
+ 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)
+ {
+ lp->stats.tx_bytes += skb->len;
+ dev_kfree_skb(out->skb,FREE_WRITE);
+ }
+ out->skb=NULL;
+ }
+ }
+
+ dev->trans_start=jiffies;
+ lp->intx--;
+
+ /* make sure we didn't ignore a TX IRQ while we were in here */
+ lp->intmask |= TXFREEflag;
+ SETMASK;
+
+ return 0;
+}
- if (ARCSTATUS == 0xFF)
- {
- BUGMSG2(D_INIT_REASONS,"(empty)\n");
- BUGMSG(D_INIT_REASONS,"Stage 1: ");
- BUGLVL(D_INIT_REASONS) numprint=0;
- *port=ports[numports-1];
- numports--;
- port--;
- continue;
- }
- ARCRESET; /* begin resetting card */
+/* 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.
+ */
+void arcnetA_continue_tx(struct device *dev)
+{
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ int maxsegsize=XMTU-4;
+ struct Outgoing *out=&(lp->outgoing);
+
+ BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",
+ ARCSTATUS,lp->intx,lp->in_txhandler,lp->intmask);
+
+ if (lp->txready)
+ {
+ BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n");
+ return;
+ }
+
+ if (out->segnum>=out->numsegs)
+ {
+ BUGMSG(D_NORMAL,"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;
+
+ 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);
+
+ (*lp->prepare_tx)(dev,((char *)out->hdr)+EXTRA_CLIENTDATA,
+ sizeof(struct ClientData)-EXTRA_CLIENTDATA,
+ out->data,out->seglen,out->hdr->daddr,1,0);
+
+ out->dataleft-=out->seglen;
+ out->data+=out->seglen;
+ out->segnum++;
+}
- BUGMSG2(D_INIT_REASONS,"\n");
- BUGMSG(D_INIT_REASONS,"Stage 1: ");
- BUGLVL(D_INIT_REASONS) numprint=0;
- }
- BUGMSG2(D_INIT,"\n");
- if (!numports)
- {
- BUGMSG(D_NORMAL,"Stage 1: No ARCnet cards found.\n");
- return -ENODEV;
- }
+/* 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.
+ *
+ * This should probably always be called with the INTMASK register set to 0,
+ * so go_tx is not called recursively.
+ *
+ * The enable_irq flag determines whether to actually write INTMASK value
+ * to the card; TXFREEflag is always OR'ed into the memory variable either
+ * way.
+ */
+int arcnet_go_tx(struct device *dev,int enable_irq)
+{
+ struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
+ BUGMSG(D_DURING,"go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n",
+ ARCSTATUS,lp->intmask,lp->txready,lp->sending);
- /* Stage 2: we have now reset any possible ARCnet cards, so we can't
- * do anything until they finish. If D_INIT, print the list of
- * cards that are left.
- */
- BUGMSG(D_INIT,"Stage 2: ");
- numprint=0;
- for (port = &ports[0]; port-ports<numports; port++)
+ if (lp->sending || !lp->txready)
{
- numprint++;
- if (numprint>8)
+ if (enable_irq && lp->sending)
{
- BUGMSG2(D_INIT,"\n");
- BUGMSG(D_INIT,"Stage 2: ");
- numprint=1;
+ lp->intmask |= TXFREEflag;
+ SETMASK;
}
- BUGMSG2(D_INIT,"%Xh ",*port);
+ return 0;
}
- BUGMSG2(D_INIT,"\n");
- JIFFER(RESETtime);
-
- /* Stage 3: abandon any shmem addresses that don't have the signature
- * 0xD1 byte in the right place, or are read-only.
- */
- BUGMSG(D_INIT,"Stage 3: ");
- numprint=0;
- for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
- {
- u_long ptr;
+ /* start sending */
+ ACOMMAND(TXcmd|(lp->txready<<3));
- numprint++;
- if (numprint>8)
- {
- BUGMSG2(D_INIT,"\n");
- BUGMSG(D_INIT,"Stage 3: ");
- numprint=1;
- }
- BUGMSG2(D_INIT,"%lXh ",*shmem);
+ lp->stats.tx_packets++;
+ lp->txready=0;
+ lp->sending++;
- ptr=(u_long)(*shmem);
+ lp->lasttrans_dest=lp->lastload_dest;
+ lp->lastload_dest=0;
- if (readb(ptr) != TESTvalue)
- {
- BUGMSG2(D_INIT_REASONS,"(mem=%02Xh, not %02Xh)\n",
- readb(ptr),TESTvalue);
- BUGMSG(D_INIT_REASONS,"Stage 3: ");
- BUGLVL(D_INIT_REASONS) numprint=0;
- *shmem=shmems[numshmems-1];
- numshmems--;
- shmem--;
- continue;
- }
+ lp->intmask |= TXFREEflag;
- /* By writing 0x42 to the TESTvalue location, we also make
- * sure no "mirror" shmem areas show up - if they occur
- * in another pass through this loop, they will be discarded
- * because *cptr != TESTvalue.
- */
- writeb(0x42,ptr);
- if (readb(ptr) != 0x42)
- {
- BUGMSG2(D_INIT_REASONS,"(read only)\n");
- BUGMSG(D_INIT_REASONS,"Stage 3: ");
- *shmem=shmems[numshmems-1];
- numshmems--;
- shmem--;
- continue;
- }
-
- BUGMSG2(D_INIT_REASONS,"\n");
- BUGMSG(D_INIT_REASONS,"Stage 3: ");
- BUGLVL(D_INIT_REASONS) numprint=0;
- }
- BUGMSG2(D_INIT,"\n");
-
- if (!numshmems)
- {
- BUGMSG(D_NORMAL,"Stage 3: No ARCnet cards found.\n");
- return -ENODEV;
- }
-
- /* Stage 4: something of a dummy, to report the shmems that are
- * still possible after stage 3.
- */
- BUGMSG(D_INIT,"Stage 4: ");
- numprint=0;
- for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
- {
- numprint++;
- if (numprint>8)
- {
- BUGMSG2(D_INIT,"\n");
- BUGMSG(D_INIT,"Stage 4: ");
- numprint=1;
- }
- BUGMSG2(D_INIT,"%lXh ",*shmem);
- }
- BUGMSG2(D_INIT,"\n");
-
-
- /* Stage 5: for any ports that have the correct status, can disable
- * the RESET flag, and (if no irq is given) generate an autoirq,
- * register an ARCnet device.
- *
- * Currently, we can only register one device per probe, so quit
- * after the first one is found.
- */
- BUGMSG(D_INIT,"Stage 5: ");
- numprint=0;
- for (port = &ports[0]; port-ports<numports; port++)
- {
- numprint++;
- if (numprint>8)
- {
- BUGMSG2(D_INIT,"\n");
- BUGMSG(D_INIT,"Stage 5: ");
- numprint=1;
- }
- BUGMSG2(D_INIT,"%Xh ",*port);
-
- ioaddr=*port;
- status=ARCSTATUS;
-
- if ((status & 0x9D)
- != (NORXflag|RECONflag|TXFREEflag|RESETflag))
- {
- BUGMSG2(D_INIT_REASONS,"(status=%Xh)\n",status);
- BUGMSG(D_INIT_REASONS,"Stage 5: ");
- BUGLVL(D_INIT_REASONS) numprint=0;
- *port=ports[numports-1];
- numports--;
- port--;
- continue;
- }
-
- ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
- status=ARCSTATUS;
- if (status & RESETflag)
- {
- BUGMSG2(D_INIT_REASONS," (eternal reset, status=%Xh)\n",
- status);
- BUGMSG(D_INIT_REASONS,"Stage 5: ");
- BUGLVL(D_INIT_REASONS) numprint=0;
- *port=ports[numports-1];
- numports--;
- port--;
- continue;
- }
-
- /* skip this completely if an IRQ was given, because maybe
- * we're on a machine that locks during autoirq!
- */
- if (!dev->irq)
- {
- /* if we do this, we're sure to get an IRQ since the
- * card has just reset and the NORXflag is on until
- * we tell it to start receiving.
- */
- airqmask = probe_irq_on();
- AINTMASK(NORXflag);
- udelay(1);
- AINTMASK(0);
- airq = probe_irq_off(airqmask);
-
- if (airq<=0)
- {
- BUGMSG2(D_INIT_REASONS,"(airq=%d)\n",airq);
- BUGMSG(D_INIT_REASONS,"Stage 5: ");
- BUGLVL(D_INIT_REASONS) numprint=0;
- *port=ports[numports-1];
- numports--;
- port--;
- continue;
- }
- }
- else
- {
- airq=dev->irq;
- }
-
- BUGMSG2(D_INIT,"(%d,", airq);
- openparen=1;
-
- /* Everything seems okay. But which shmem, if any, puts
- * back its signature byte when the card is reset?
- *
- * If there are multiple cards installed, there might be
- * multiple shmems still in the list.
- */
-#ifdef FAST_PROBE
- if (numports>1 || numshmems>1)
- {
- ARCRESET;
- JIFFER(RESETtime);
- }
- else
- {
- /* just one shmem and port, assume they match */
- writeb(TESTvalue,shmems[0]);
- }
-#else
- ARCRESET;
- JIFFER(RESETtime);
-#endif
-
-
- for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
- {
- u_long ptr;
- ptr=(u_long)(*shmem);
-
- if (readb(ptr) == TESTvalue) /* found one */
- {
- BUGMSG2(D_INIT,"%lXh)\n", *shmem);
- openparen=0;
-
- /* register the card */
- retval=arcnet_found(dev,*port,airq,*shmem);
- if (retval) openparen=0;
-
- /* remove shmem from the list */
- *shmem=shmems[numshmems-1];
- numshmems--;
-
- break;
- }
- else
- {
- BUGMSG2(D_INIT_REASONS,"%Xh-", readb(ptr));
- }
- }
-
- if (openparen)
- {
- BUGMSG2(D_INIT,"no matching shmem)\n");
- BUGMSG(D_INIT_REASONS,"Stage 5: ");
- BUGLVL(D_INIT_REASONS) numprint=0;
- }
-
- *port=ports[numports-1];
- numports--;
- port--;
-
- if (!retval) break;
- }
- BUGMSG(D_INIT_REASONS,"\n");
-
- /* Now put back TESTvalue on all leftover shmems.
- */
- for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
- writeb(TESTvalue,*shmem);
-
- if (retval) BUGMSG(D_NORMAL,"Stage 5: No ARCnet cards found.\n");
- return retval;
-}
-
-#endif /* !RIM_I_MODE */
-
-
-/* Set up the struct device associated with this card. Called after
- * probing succeeds.
- */
-__initfunc(int arcnet_found(struct device *dev,int port,int airq, u_long shmem))
-{
- u_long first_mirror,last_mirror;
- struct arcnet_local *lp;
- int mirror_size;
-
- /* reserve the irq */
- if (request_irq(airq,&arcnet_interrupt,0,"arcnet",NULL))
- {
- BUGMSG(D_NORMAL,"Can't get IRQ %d!\n",airq);
- return -ENODEV;
- }
- irq2dev_map[airq]=dev;
- dev->irq=airq;
-
-#ifdef RIM_I_MODE
- dev->base_addr=0;
- writeb(TESTvalue,shmem);
- writeb(port,shmem+1); /* actually the node ID */
-#else
- /* reserve the I/O region - guaranteed to work by check_region */
- request_region(port,ARCNET_TOTAL_SIZE,"arcnet");
- dev->base_addr=port;
-#endif
-
- /* find the real shared memory start/end points, including mirrors */
-
- #define BUFFER_SIZE (512)
- #define MIRROR_SIZE (BUFFER_SIZE*4)
-
- /* guess the actual size of one "memory mirror" - the number of
- * bytes between copies of the shared memory. On most cards, it's
- * 2k (or there are no mirrors at all) but on some, it's 4k.
- */
- mirror_size=MIRROR_SIZE;
- if (readb(shmem)==TESTvalue
- && readb(shmem-mirror_size)!=TESTvalue
- && readb(shmem-2*mirror_size)==TESTvalue)
- mirror_size*=2;
-
- first_mirror=last_mirror=shmem;
- while (readb(first_mirror)==TESTvalue) first_mirror-=mirror_size;
- first_mirror+=mirror_size;
-
- while (readb(last_mirror)==TESTvalue) last_mirror+=mirror_size;
- last_mirror-=mirror_size;
-
- dev->mem_start=first_mirror;
- dev->mem_end=last_mirror+MIRROR_SIZE-1;
- dev->rmem_start=dev->mem_start+BUFFER_SIZE*0;
- dev->rmem_end=dev->mem_start+BUFFER_SIZE*2-1;
-
- /* Initialize the rest of the device structure. */
-
- dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
- if (dev->priv == NULL)
- {
- irq2dev_map[airq] = NULL;
- free_irq(airq,NULL);
- RELEASE_REGION(port,ARCNET_TOTAL_SIZE);
- return -ENOMEM;
- }
- memset(dev->priv,0,sizeof(struct arcnet_local));
- lp=(struct arcnet_local *)(dev->priv);
-
- dev->open=arcnet_open;
- dev->stop=arcnet_close;
- dev->hard_start_xmit=arcnetA_send_packet;
- dev->get_stats=arcnet_get_stats;
- /*dev->set_multicast_list = &set_multicast_list;*/
-
- /* Fill in the fields of the device structure with generic
- * values.
- */
- arcnet_setup(dev);
-
- /* And now fill particular fields with arcnet values */
- dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
- dev->hard_header_len=sizeof(struct ClientData);
- dev->hard_header=arcnetA_header;
- dev->rebuild_header=arcnetA_rebuild_header;
- lp->sequence=1;
- lp->recbuf=0;
-
- BUGMSG(D_DURING,"ClientData header size is %d.\n",
- sizeof(struct ClientData));
- BUGMSG(D_DURING,"HardHeader size is %d.\n",
- sizeof(struct HardHeader));
-
- /* get and check the station ID from offset 1 in shmem */
- lp->stationid = readb(first_mirror+1);
- if (lp->stationid==0)
- BUGMSG(D_NORMAL,"WARNING! Station address 00 is reserved "
- "for broadcasts!\n");
- else if (lp->stationid==255)
- BUGMSG(D_NORMAL,"WARNING! Station address FF may confuse "
- "DOS networking programs!\n");
- dev->dev_addr[0]=lp->stationid;
-
- BUGMSG(D_NORMAL,"ARCnet station %02Xh found at %03lXh, IRQ %d, "
- "ShMem %lXh (%ld*%d bytes).\n",
- lp->stationid,
- dev->base_addr,dev->irq,dev->mem_start,
- (dev->mem_end-dev->mem_start+1)/mirror_size,mirror_size);
-
- return 0;
-}
-
-
-/* Do a hardware reset on the card, and set up necessary registers.
- *
- * This should be called as little as possible, because it disrupts the
- * token on the network (causes a RECON) and requires a significant delay.
- *
- * However, it does make sure the card is in a defined state.
- */
-int arcnet_reset(struct device *dev,int reset_delay)
-{
- struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
- short ioaddr=IOADDR;
- int delayval,recbuf=lp->recbuf;
-
- /* no IRQ's, please! */
- lp->intmask=0;
- SETMASK;
-
- BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
- dev->name,ARCSTATUS);
-
- if (reset_delay)
- {
- /* reset the card */
- ARCRESET;
- JIFFER(RESETtime);
- }
-
- ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
- ACOMMAND(CFLAGScmd|CONFIGclear);
-
- /* verify that the ARCnet signature byte is present */
- if (readb(dev->mem_start) != TESTvalue)
- {
- BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
- return 1;
- }
-
- /* clear out status variables */
- recbuf=lp->recbuf=0;
- lp->txbuf=2;
-
- /* enable extended (512-byte) packets */
- ACOMMAND(CONFIGcmd|EXTconf);
-
-#ifndef SLOW_XMIT_COPY
- /* clean out all the memory to make debugging make more sense :) */
- BUGLVL(D_DURING)
- memset_io(dev->mem_start,0x42,2048);
-#endif
-
- /* and enable receive of our first packet to the first buffer */
- EnableReceiver();
-
- /* re-enable interrupts */
- lp->intmask|=NORXflag;
-#ifdef DETECT_RECONFIGS
- lp->intmask|=RECONflag;
-#endif
- SETMASK;
-
- /* done! return success. */
- return 0;
-}
-
-
-/* Setup a struct device for ARCnet. This should really be in net_init.c
- * but since there are three different ARCnet devices ANYWAY... <gargle>
- *
- * Actually, the whole idea of having all this kernel-dependent stuff (ie.
- * "new-style flags") setup per-net-device is kind of weird anyway.
- *
- * Intelligent defaults?! Nah.
- */
-
-void arcnet_setup(struct device *dev)
-{
- dev_init_buffers(dev);
-
- dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */
- dev->addr_len = 1;
- dev->type = ARPHRD_ARCNET;
- dev->tx_queue_len = 30; /* fairly long queue - arcnet is
- * quite speedy.
- */
-
- /* New-style flags. */
- dev->flags = IFF_BROADCAST;
- dev->family = AF_INET;
- dev->pa_addr = 0;
- dev->pa_brdaddr = 0;
- dev->pa_mask = 0;
- dev->pa_alen = 4;
-}
-
-
-/****************************************************************************
- * *
- * Open and close the driver *
- * *
- ****************************************************************************/
-
-
-/* Open/initialize the board. This is called sometime after booting when
- * the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-static int
-arcnet_open(struct device *dev)
-{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int ioaddr=IOADDR;
-
- if (dev->metric>=1000)
- {
- arcnet_debug=dev->metric-1000;
- printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug);
- dev->metric=1;
- }
-
- BUGMSG(D_INIT,"arcnet_open: resetting card.\n");
-
-#ifdef FAST_IFCONFIG
- /* try to put the card in a defined state - if it fails the first
- * time, actually reset it.
- */
- if (arcnet_reset(dev,0) && arcnet_reset(dev,1))
- return -ENODEV;
-#else
- /* reset the card twice in case something goes wrong the first time.
- */
- if (arcnet_reset(dev,1) && arcnet_reset(dev,1))
- return -ENODEV;
-#endif
-
- dev->tbusy=0;
- dev->interrupt=0;
- lp->intx=0;
- lp->in_txhandler=0;
-
- /* The RFC1201 driver is the default - just store */
- lp->adev=dev;
- BUGMSG(D_NORMAL,"ARCnet RFC1201 protocol initialized.\n");
-
-#ifdef CONFIG_ARCNET_ETH
- /* Initialize the ethernet-encap protocol driver */
- lp->edev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
- if (lp->edev == NULL)
- return -ENOMEM;
- memcpy(lp->edev,dev,sizeof(struct device));
- lp->edev->name=(char *)kmalloc(10,GFP_KERNEL);
- if (lp->edev->name == NULL) {
- kfree(lp->edev);
- lp->edev = NULL;
- return -ENOMEM;
- }
- sprintf(lp->edev->name,"%se",dev->name);
- lp->edev->init=arcnetE_init;
- register_netdev(lp->edev);
-#else
- BUGMSG(D_NORMAL,"Ethernet-Encap protocol not available (disabled).\n");
-#endif
-
-#ifdef CONFIG_ARCNET_1051
- /* Initialize the RFC1051-encap protocol driver */
- lp->sdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
- memcpy(lp->sdev,dev,sizeof(struct device));
- lp->sdev->name=(char *)kmalloc(10,GFP_KERNEL);
- sprintf(lp->sdev->name,"%ss",dev->name);
- lp->sdev->init=arcnetS_init;
- register_netdev(lp->sdev);
-#else
- BUGMSG(D_NORMAL,"RFC1051 protocol not available (disabled).\n");
-#endif
-
- /* we're started */
- START=1;
-
- /* make sure we're ready to receive IRQ's.
- * arcnet_reset sets this for us, but if we receive one before
- * START is set to 1, it could be ignored. So, we turn IRQ's
- * off, then on again to clean out the IRQ controller.
- */
- AINTMASK(0);
- udelay(1); /* give it time to set the mask before
- * we reset it again. (may not even be
- * necessary)
- */
- SETMASK;
-
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-
-/* The inverse routine to arcnet_open - shuts down the card.
- */
-static int
-arcnet_close(struct device *dev)
-{
- int ioaddr=IOADDR;
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
- TBUSY=1;
- START=0;
-
- /* Shut down the card */
-#ifdef FAST_IFCONFIG
- ARCRESET; /* reset IRQ won't run if START=0 */
-#else
- lp->intmask=0;
- SETMASK; /* no IRQ's (except RESET, of course) */
- ACOMMAND(NOTXcmd); /* stop transmit */
- ACOMMAND(NORXcmd); /* disable receive */
-#endif
-
- /* reset more flags */
- INTERRUPT=0;
-
- /* do NOT free lp->adev!! It's static! */
- lp->adev=NULL;
-
-#ifdef CONFIG_ARCNET_ETH
- /* free the ethernet-encap protocol device */
- lp->edev->priv=NULL;
- dev_close(lp->edev);
- unregister_netdev(lp->edev);
- kfree(lp->edev->name);
- kfree(lp->edev);
- lp->edev=NULL;
-#endif
-
-#ifdef CONFIG_ARCNET_1051
- /* free the RFC1051-encap protocol device */
- lp->sdev->priv=NULL;
- dev_close(lp->sdev);
- unregister_netdev(lp->sdev);
- kfree(lp->sdev->name);
- kfree(lp->sdev);
- lp->sdev=NULL;
-#endif
-
- /* Update the statistics here. (not necessary in ARCnet) */
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
+ if (enable_irq) SETMASK;
-
-
-/****************************************************************************
- * *
- * Transmitter routines *
- * *
- ****************************************************************************/
-
-/* Generic error checking routine for arcnet??_send_packet
- */
-static int
-arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
-{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int ioaddr=IOADDR;
-
- BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
- ARCSTATUS,lp->intx);
-
- if (lp->in_txhandler)
- {
- 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;
- }
-
- if (IF_TBUSY)
- {
- /* 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=ARCSTATUS;
-
- if (tickssofar < TX_TIMEOUT)
- {
- 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);
- return 1;
- }
-
- lp->intmask &= ~TXFREEflag;
- SETMASK;
-
- if (status&TXFREEflag) /* transmit _DID_ finish */
- {
- BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
- status,tickssofar,lp->intmask,lp->lasttrans_dest);
- lp->stats.tx_errors++;
- }
- else
- {
- BUGMSG(D_EXTRA,"tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n",
- status,tickssofar,lp->intmask,lp->lasttrans_dest);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
-
- ACOMMAND(NOTXcmd);
- }
-
- if (lp->outgoing.skb)
- {
- dev_kfree_skb(lp->outgoing.skb,FREE_WRITE);
- lp->stats.tx_dropped++;
- }
- lp->outgoing.skb=NULL;
-
- TBUSY=0;
- lp->txready=0;
- lp->sending=0;
-
- return 1;
- }
-
- if (lp->txready) /* transmit already in progress! */
- {
- BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n",
- ARCSTATUS);
- lp->intmask &= ~TXFREEflag;
- SETMASK;
- ACOMMAND(NOTXcmd); /* abort current send */
- arcnet_inthandler(dev); /* fake an interrupt */
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- lp->txready=0; /* we definitely need this line! */
-
- return 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 (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- {
- BUGMSG(D_NORMAL,"transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
- ARCSTATUS,lp->intx,jiffies-dev->trans_start);
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- return -EBUSY;
- }
-
- 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=IOADDR,bad;
- struct Outgoing *out=&(lp->outgoing);
-
- 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;
-
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-
- out->hdr->sequence=(lp->sequence++);
-
- /* 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);
- if (out->hdr->split_flag)
- BUGMSG(D_NORMAL,"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);
-
- /* done right away */
- dev_kfree_skb(out->skb,FREE_WRITE);
- out->skb=NULL;
-
- if (arcnet_go_tx(dev,1))
- {
- /* 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;
-
- BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n",
- out->length,out->numsegs);
-
- /* 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 (arcnet_go_tx(dev,1))
- {
- 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;
- }
- }
-
- dev->trans_start=jiffies;
- lp->intx--;
-
- /* make sure we didn't ignore a TX IRQ while we were in here */
- lp->intmask |= TXFREEflag;
- SETMASK;
-
- 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 arcnet_go_tx.
- */
-static void arcnetA_continue_tx(struct device *dev)
-{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int ioaddr=IOADDR,maxsegsize=XMTU-4;
- struct Outgoing *out=&(lp->outgoing);
-
- BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",
- ARCSTATUS,lp->intx,lp->in_txhandler,lp->intmask);
-
- if (lp->txready)
- {
- BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n");
- return;
- }
-
- if (out->segnum>=out->numsegs)
- {
- BUGMSG(D_NORMAL,"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;
-
- 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);
-
- out->dataleft-=out->seglen;
- out->data+=out->seglen;
- out->segnum++;
-}
-
-
-/* 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 *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1));
- int offset;
-
-#ifdef SLOW_XMIT_COPY
- char *iptr,*iend,*optr;
-#endif
-
- lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate between 2 and 3 */
-
- length+=hdrlen;
-
- BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
- hdr,length,data);
-
-#ifndef SLOW_XMIT_COPY
- /* clean out the page to make debugging make more sense :) */
- BUGLVL(D_DURING)
- memset_io(dev->mem_start+lp->txbuf*512,0x42,512);
-#endif
-
- arcpacket->hardheader.destination=daddr;
-
- /* load packet into shared memory */
- if (length<=MTU) /* Normal (256-byte) Packet */
- {
- arcpacket->hardheader.offset1=offset=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 */
- {
- 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 */
- }
- 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);
-#ifdef SLOW_XMIT_COPY
- for (iptr=data,iend=iptr+length-hdrlen,optr=(char *)arcsoft+hdrlen;
- iptr<iend; iptr++,optr++)
- {
- *optr=*iptr;
- /*udelay(5);*/
- }
-#else
- memcpy((u_char*)arcsoft+hdrlen,
- data,length-hdrlen);
-#endif
-
- BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
- daddr,length);
-
- BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>MTU,"tx");
- lp->lastload_dest=daddr;
- lp->txready=lp->txbuf; /* packet is ready for sending */
-}
-
-/* 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.
- *
- * This should probably always be called with the INTMASK register set to 0,
- * so go_tx is not called recursively.
- *
- * The enable_irq flag determines whether to actually write INTMASK value
- * to the card; TXFREEflag is always OR'ed into the memory variable either
- * way.
- */
-static int
-arcnet_go_tx(struct device *dev,int enable_irq)
-{
- struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
- int ioaddr=IOADDR;
-
- BUGMSG(D_DURING,"go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n",
- ARCSTATUS,lp->intmask,lp->txready,lp->sending);
-
- if (lp->sending || !lp->txready)
- {
- if (enable_irq && lp->sending)
- {
- lp->intmask |= TXFREEflag;
- SETMASK;
- }
- return 0;
- }
-
- /* start sending */
- ACOMMAND(TXcmd|(lp->txready<<3));
-
- lp->stats.tx_packets++;
- lp->txready=0;
- lp->sending++;
-
- lp->lasttrans_dest=lp->lastload_dest;
- lp->lastload_dest=0;
-
- lp->intmask |= TXFREEflag;
-
- if (enable_irq) SETMASK;
-
- return 1;
-}
+ return 1;
+}
/****************************************************************************
@@ -1911,274 +927,82 @@
****************************************************************************/
-/* The typical workload of the driver: Handle the network interface
- * interrupts. This doesn't do much right now except call arcnet_inthandler,
- * which takes different parameters but may be called from other places
- * as well.
- */
-static void
-arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs)
-{
- struct device *dev = (struct device *)(irq2dev_map[irq]);
- int ioaddr;
-
- if (dev==NULL)
- {
- BUGLVL(D_DURING)
- printk(KERN_DEBUG "arcnet: irq %d for unknown device.\n", irq);
- return;
- }
-
- BUGMSG(D_DURING,"in arcnet_interrupt\n");
-
- /* RESET flag was enabled - if !dev->start, we must clear it right
- * away (but nothing else) since inthandler() is never called.
- */
- ioaddr=IOADDR; /* can't do this before checking dev!=NULL */
- if (!dev->start)
- {
- if (ARCSTATUS & RESETflag)
- ACOMMAND(CFLAGScmd|RESETclear);
- return;
- }
-
- /* Call the "real" interrupt handler. */
- arcnet_inthandler(dev);
-}
-
-
-/* The actual interrupt handler routine - handle various IRQ's generated
- * by the card.
- */
-static void
-arcnet_inthandler(struct device *dev)
-{
- struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
- int ioaddr=IOADDR, status, boguscount = 3, didsomething;
-
- if (IF_INTERRUPT)
- {
- BUGMSG(D_NORMAL,"DRIVER PROBLEM! Nested arcnet interrupts!\n");
- return; /* don't even try. */
- }
-
- AINTMASK(0);
- INTERRUPT = 1;
-
- BUGMSG(D_DURING,"in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
- ARCSTATUS,lp->intmask);
-
- do
- {
- status = ARCSTATUS;
- didsomething=0;
-
-
- /* RESET flag was enabled - card is resetting and if RX
- * is disabled, it's NOT because we just got a packet.
- */
- if (status & RESETflag)
- {
- BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
- status);
- arcnet_reset(dev,0);
-
- /* all other flag values are just garbage */
- break;
- }
-
-
- /* RX is inhibited - we must have received something. */
- if (status & lp->intmask & NORXflag)
- {
- int recbuf=lp->recbuf=!lp->recbuf;
-
- BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
- status);
-
- /* enable receive of our next packet */
- EnableReceiver();
-
- /* Got a packet. */
- arcnet_rx(dev,!recbuf);
- didsomething++;
- }
-
- /* it can only be an xmit-done irq if we're xmitting :) */
- /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
- if (status & lp->intmask & TXFREEflag)
- {
- struct Outgoing *out=&(lp->outgoing);
- int was_sending=lp->sending;
-
- lp->intmask &= ~TXFREEflag;
-
- lp->in_txhandler++;
- if (was_sending) lp->sending--;
-
- BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
- status,out->numsegs,out->segnum,out->skb);
-
- if (was_sending && !(status&TXACKflag))
- {
- if (lp->lasttrans_dest != 0)
- {
- BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
- status,lp->lasttrans_dest);
- lp->stats.tx_errors++;
- lp->stats.tx_carrier_errors++;
- }
- else
- {
- BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
- status,
- lp->lasttrans_dest);
- }
- }
-
- /* send packet if there is one */
- arcnet_go_tx(dev,0);
- didsomething++;
-
- if (lp->intx)
- {
- BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
- ARCSTATUS,lp->intx);
- lp->in_txhandler--;
- continue;
- }
-
- if (!lp->outgoing.skb)
- {
- BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-
- /* inform upper layers */
- if (!lp->txready && IF_TBUSY)
- {
- TBUSY=0;
- mark_bh(NET_BH);
- }
- lp->in_txhandler--;
- continue;
- }
-
- /* if more than one segment, and not all segments
- * are done, then continue xmit.
- */
- if (out->segnum<out->numsegs)
- arcnetA_continue_tx(dev);
- arcnet_go_tx(dev,0);
-
- /* if segnum==numsegs, the transmission is finished;
- * free the skb.
- */
- if (out->segnum>=out->numsegs)
- {
- /* transmit completed */
- out->segnum++;
- if (out->skb)
- dev_kfree_skb(out->skb,FREE_WRITE);
- out->skb=NULL;
-
- /* inform upper layers */
- if (!lp->txready && IF_TBUSY)
- {
- TBUSY=0;
- mark_bh(NET_BH);
- }
- }
- didsomething++;
-
- lp->in_txhandler--;
- }
- else if (lp->txready && !lp->sending && !lp->intx)
- {
- BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n",
- status);
- arcnet_go_tx(dev,0);
- didsomething++;
- }
-
-#ifdef DETECT_RECONFIGS
- if (status & (lp->intmask) & RECONflag)
- {
- ACOMMAND(CFLAGScmd|CONFIGclear);
- lp->stats.tx_carrier_errors++;
-
- #ifdef SHOW_RECONFIGS
- BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n",
- status);
- #endif /* SHOW_RECONFIGS */
-
- #ifdef RECON_THRESHOLD
- /* is the RECON info empty or old? */
- if (!lp->first_recon || !lp->last_recon ||
- jiffies-lp->last_recon > HZ*10)
- {
- if (lp->network_down)
- BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
- lp->first_recon=lp->last_recon=jiffies;
- lp->num_recons=lp->network_down=0;
-
- BUGMSG(D_DURING,"recon: clearing counters.\n");
- }
- else /* add to current RECON counter */
- {
- lp->last_recon=jiffies;
- lp->num_recons++;
-
- BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
- lp->num_recons,
- (lp->last_recon-lp->first_recon)/HZ,
- lp->network_down);
-
- /* if network is marked up;
- * and first_recon and last_recon are 60+ sec
- * apart;
- * and the average no. of recons counted is
- * > RECON_THRESHOLD/min;
- * then print a warning message.
- */
- if (!lp->network_down
- && (lp->last_recon-lp->first_recon)<=HZ*60
- && lp->num_recons >= RECON_THRESHOLD)
- {
- lp->network_down=1;
- BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n");
- }
- else if (!lp->network_down
- && lp->last_recon-lp->first_recon > HZ*60)
- {
- /* reset counters if we've gone for
- * over a minute.
- */
- lp->first_recon=lp->last_recon;
- lp->num_recons=1;
- }
- }
- #endif
- }
- #ifdef RECON_THRESHOLD
- else if (lp->network_down && jiffies-lp->last_recon > HZ*10)
- {
- if (lp->network_down)
- BUGMSG(D_NORMAL,"cabling restored?\n");
- lp->first_recon=lp->last_recon=0;
- lp->num_recons=lp->network_down=0;
+/* The typical workload of the driver: Handle the network interface
+ * interrupts. Establish which device needs attention, and call the correct
+ * chipset interrupt handler.
+ */
+void
+arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs)
+{
+ struct device *dev = (struct device *)(irq2dev_map[irq]);
+ struct arcnet_local *lp;
+
+ if (dev==NULL)
+ {
+ BUGLVL(D_DURING)
+ printk(KERN_DEBUG "arcnet: irq %d for unknown device.\n", irq);
+ return;
+ }
+
+ BUGMSG(D_DURING,"in arcnet_interrupt\n");
+
+
+ lp=(struct arcnet_local *)dev->priv;
+
+ /* RESET flag was enabled - if !dev->start, we must clear it right
+ * away (but nothing else) since inthandler() is never called.
+ */
+
+ if (!dev->start)
+ {
+ if (ARCSTATUS & RESETflag)
+ ACOMMAND(CFLAGScmd|RESETclear);
+ return;
+ }
+
+
+ if (test_and_set_bit(0, (int *)&dev->interrupt))
+ {
+ BUGMSG(D_NORMAL,"DRIVER PROBLEM! Nested arcnet interrupts!\n");
+ return; /* don't even try. */
+ }
+#ifdef CONFIG_ARCNET_1051
+ lp->sdev->interrupt=1;
+#endif
+#ifdef CONFIG_ARCNET_ETH
+ lp->edev->interrupt=1;
+#endif
- BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
- }
- #endif
-#endif /* DETECT_RECONFIGS */
- } while (--boguscount && didsomething);
+ /* Call the "real" interrupt handler. */
+ (*lp->inthandler)(dev);
- BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
- ARCSTATUS,boguscount);
- BUGMSG(D_DURING,"\n");
+#ifdef CONFIG_ARCNET_ETH
+ lp->edev->interrupt=0;
+#endif
+#ifdef CONFIG_ARCNET_1051
+ lp->sdev->interrupt=0;
+#endif
+ if (!test_and_clear_bit(0, (int *)&dev->interrupt))
+ BUGMSG(D_NORMAL, "Someone cleared our dev->interrupt flag!\n");
- SETMASK; /* put back interrupt mask */
+}
- INTERRUPT=0;
+void arcnet_tx_done(struct device *dev, struct arcnet_local *lp)
+{
+ if (dev->tbusy)
+ {
+#ifdef CONFIG_ARCNET_ETH
+ lp->edev->tbusy=0;
+#endif
+#ifdef CONFIG_ARCNET_1051
+ lp->sdev->tbusy=0;
+#endif
+ if (!test_and_clear_bit(0, (int *)&dev->tbusy))
+ BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy"
+ " flag!\n");
+
+ mark_bh(NET_BH);
+ }
}
@@ -2188,374 +1012,335 @@
* *
****************************************************************************/
-
-/* A packet has arrived; grab it from the buffers and possibly unsplit it.
+/*
* This is a generic packet receiver that calls arcnet??_rx depending on the
* protocol ID found.
*/
-static void
-arcnet_rx(struct device *dev,int recbuf)
-{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int ioaddr=IOADDR;
- union ArcPacket *arcpacket=
- (union ArcPacket *)phys_to_virt(dev->mem_start+recbuf*512);
- u_char *arcsoft;
- short length,offset;
- u_char daddr,saddr;
- lp->stats.rx_packets++;
-
- saddr=arcpacket->hardheader.source;
- daddr=arcpacket->hardheader.destination;
-
- /* if source is 0, it's a "used" packet! */
- if (saddr==0)
- {
- BUGMSG(D_NORMAL,"discarding old packet. (status=%Xh)\n",
- ARCSTATUS);
- lp->stats.rx_errors++;
- return;
- }
- arcpacket->hardheader.source=0;
-
- if (arcpacket->hardheader.offset1) /* Normal Packet */
- {
- offset=arcpacket->hardheader.offset1;
- arcsoft=&arcpacket->raw[offset];
- length=256-offset;
- }
- else /* ExtendedPacket or ExceptionPacket */
- {
- offset=arcpacket->hardheader.offset2;
- arcsoft=&arcpacket->raw[offset];
-
- length=512-offset;
- }
-
- BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n",
- saddr,daddr,length);
-
- /* call the right receiver for the protocol */
- switch (arcsoft[0])
- {
- case ARC_P_IP:
- case ARC_P_ARP:
- case ARC_P_RARP:
- case ARC_P_IPX:
- case ARC_P_NOVELL_EC:
- arcnetA_rx(lp->adev,arcsoft,length,saddr,daddr);
- break;
+void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr)
+{
+ struct device *dev=lp->adev;
+
+ BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n",
+ saddr,daddr,length);
+
+ /* call the right receiver for the protocol */
+ switch (arcsoft[0])
+ {
+ case ARC_P_IP:
+ case ARC_P_ARP:
+ case ARC_P_RARP:
+ case ARC_P_IPX:
+ case ARC_P_NOVELL_EC:
+ arcnetA_rx(lp->adev,arcsoft,length,saddr,daddr);
+ break;
#ifdef CONFIG_ARCNET_ETH
- case ARC_P_ETHER:
- arcnetE_rx(lp->edev,arcsoft,length,saddr,daddr);
- break;
+ case ARC_P_ETHER:
+ arcnetE_rx(lp->edev,arcsoft,length,saddr,daddr);
+ break;
#endif
#ifdef CONFIG_ARCNET_1051
- case ARC_P_IP_RFC1051:
- case ARC_P_ARP_RFC1051:
- arcnetS_rx(lp->sdev,arcsoft,length,saddr,daddr);
- break;
-#endif
- case ARC_P_DATAPOINT_BOOT:
- case ARC_P_DATAPOINT_MOUNT:
- break;
- case ARC_P_POWERLAN_BEACON:
- case ARC_P_POWERLAN_BEACON2:
- break;
- case ARC_P_LANSOFT: /* don't understand. fall through. */
- default:
- BUGMSG(D_EXTRA,"received unknown protocol %d (%Xh) from station %d.\n",
- arcsoft[0],arcsoft[0],saddr);
- lp->stats.rx_errors++;
- lp->stats.rx_crc_errors++;
- break;
- }
-
- BUGLVL(D_RX) arcnet_dump_packet(dev,arcpacket->raw,length>240,"rx");
-
-
-#ifndef SLOW_XMIT_COPY
- /* clean out the page to make debugging make more sense :) */
- BUGLVL(D_DURING)
- memset((void *)arcpacket->raw,0x42,512);
-#endif
-
-
- /* If any worth-while packets have been received, a mark_bh(NET_BH)
- * has been done by netif_rx and Linux will handle them after we
- * return.
- */
+ case ARC_P_IP_RFC1051:
+ case ARC_P_ARP_RFC1051:
+ arcnetS_rx(lp->sdev,arcsoft,length,saddr,daddr);
+ break;
+#endif
+ case ARC_P_DATAPOINT_BOOT:
+ case ARC_P_DATAPOINT_MOUNT:
+ break;
+ case ARC_P_POWERLAN_BEACON:
+ case ARC_P_POWERLAN_BEACON2:
+ break;
+ case ARC_P_LANSOFT: /* don't understand. fall through. */
+ default:
+ BUGMSG(D_EXTRA,"received unknown protocol %d (%Xh) from station %d.\n",
+ arcsoft[0],arcsoft[0],saddr);
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
+ break;
+ }
+
+ /* If any worth-while packets have been received, a mark_bh(NET_BH)
+ * has been done by netif_rx and Linux will handle them after we
+ * return.
+ */
+
+
}
+
/* Packet receiver for "standard" RFC1201-style packets
*/
static void
arcnetA_rx(struct device *dev,u_char *buf,
- int length,u_char saddr, u_char daddr)
+ int length, u_char saddr, u_char daddr)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- struct sk_buff *skb;
- struct ClientData *arcsoft,*soft;
-
- BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n",
- length);
-
- /* compensate for EXTRA_CLIENTDATA (which isn't actually in the
- * packet)
- */
- arcsoft=(struct ClientData *)(buf-EXTRA_CLIENTDATA);
- length+=EXTRA_CLIENTDATA;
-
- if (arcsoft->split_flag==0xFF) /* Exception Packet */
- {
- BUGMSG(D_DURING,"compensating for exception packet\n");
-
- /* skip over 4-byte junkola */
- arcsoft=(struct ClientData *)
- ((u_char *)arcsoft + 4);
- length-=4;
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ struct sk_buff *skb;
+ struct ClientData *arcsoft,*soft;
+
+ BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n",
+ length);
+
+ /* compensate for EXTRA_CLIENTDATA (which isn't actually in the
+ * packet)
+ */
+ arcsoft=(struct ClientData *)(buf-EXTRA_CLIENTDATA);
+ length+=EXTRA_CLIENTDATA;
+
+ if (arcsoft->split_flag==0xFF) /* Exception Packet */
+ {
+ BUGMSG(D_DURING,"compensating for exception packet\n");
+
+ /* skip over 4-byte junkola */
+ arcsoft=(struct ClientData *)
+ ((u_char *)arcsoft + 4);
+ length-=4;
+ }
+
+ if (!arcsoft->split_flag) /* not split */
+ {
+ struct Incoming *in=&lp->incoming[saddr];
+
+ BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n",
+ arcsoft->split_flag);
+
+ if (in->skb) /* already assembling one! */
+ {
+ BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
+ in->sequence,arcsoft->split_flag,
+ arcsoft->sequence);
+ lp->aborted_seq=arcsoft->sequence;
+ kfree_skb(in->skb,FREE_WRITE);
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ in->skb=NULL;
+ }
+
+ in->sequence=arcsoft->sequence;
+
+ skb = alloc_skb(length, GFP_ATOMIC);
+ if (skb == NULL) {
+ BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
+ lp->stats.rx_dropped++;
+ return;
+ }
+ soft=(struct ClientData *)skb->data;
+
+ skb_put(skb,length);
+ skb->dev = dev;
+
+ memcpy((u_char *)soft+EXTRA_CLIENTDATA,
+ (u_char *)arcsoft+EXTRA_CLIENTDATA,
+ length-EXTRA_CLIENTDATA);
+ soft->daddr=daddr;
+ soft->saddr=saddr;
+
+ /* ARP packets have problems when sent from DOS.
+ * source address is always 0 on some systems! So we take
+ * the hardware source addr (which is impossible to fumble)
+ * and insert it ourselves.
+ */
+ if (soft->protocol_id == ARC_P_ARP)
+ {
+ struct arphdr *arp=(struct arphdr *)
+ ((char *)soft+sizeof(struct ClientData));
+
+ /* make sure addresses are the right length */
+ if (arp->ar_hln==1 && arp->ar_pln==4)
+ {
+ char *cptr=(char *)(arp)+sizeof(struct arphdr);
+
+ if (!*cptr) /* is saddr = 00? */
+ {
+ BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n",
+ saddr);
+ lp->stats.rx_crc_errors++;
+ *cptr=saddr;
+ }
+ else
+ {
+ BUGMSG(D_DURING,"ARP source address (%Xh) is fine.\n",
+ *cptr);
+ }
+ }
+ else
+ {
+ BUGMSG(D_NORMAL,"funny-shaped ARP packet. (%Xh, %Xh)\n",
+ arp->ar_hln,arp->ar_pln);
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
+ }
+ }
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
+
+ lp->stats.rx_bytes += skb->len;
+ skb->protocol=arcnetA_type_trans(skb,dev);
+ netif_rx(skb);
+ }
+ else /* split packet */
+ {
+ /* NOTE: MSDOS ARP packet correction should only need to
+ * apply to unsplit packets, since ARP packets are so short.
+ *
+ * My interpretation of the RFC1201 (ARCnet) document is that
+ * if a packet is received out of order, the entire assembly
+ * process should be aborted.
+ *
+ * The RFC also mentions "it is possible for successfully
+ * received packets to be retransmitted." As of 0.40 all
+ * previously received packets are allowed, not just the
+ * most recent one.
+ *
+ * We allow multiple assembly processes, one for each
+ * ARCnet card possible on the network. Seems rather like
+ * a waste of memory. Necessary?
+ */
+
+ struct Incoming *in=&lp->incoming[saddr];
+
+ BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n",
+ arcsoft->split_flag,in->sequence);
+
+ if (in->skb && in->sequence!=arcsoft->sequence)
+ {
+ BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
+ saddr,in->sequence,arcsoft->sequence,
+ arcsoft->split_flag);
+ kfree_skb(in->skb,FREE_WRITE);
+ in->skb=NULL;
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ in->lastpacket=in->numpackets=0;
+ }
+
+ if (arcsoft->split_flag & 1) /* first packet in split */
+ {
+ BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n",
+ arcsoft->split_flag);
+ if (in->skb) /* already assembling one! */
+ {
+ BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
+ in->sequence,arcsoft->split_flag,
+ arcsoft->sequence);
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ kfree_skb(in->skb,FREE_WRITE);
+ }
+
+ in->sequence=arcsoft->sequence;
+ in->numpackets=((unsigned)arcsoft->split_flag>>1)+2;
+ in->lastpacket=1;
+
+ if (in->numpackets>16)
+ {
+ BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
+ arcsoft->split_flag);
+ lp->stats.rx_errors++;
+ lp->stats.rx_length_errors++;
+ return;
+ }
+
+ in->skb=skb=alloc_skb(508*in->numpackets
+ + sizeof(struct ClientData),
+ GFP_ATOMIC);
+ if (skb == NULL) {
+ BUGMSG(D_NORMAL,"(split) memory squeeze, dropping packet.\n");
+ lp->stats.rx_dropped++;
+ return;
+ }
+
+ soft=(struct ClientData *)skb->data;
+
+ skb_put(skb,sizeof(struct ClientData));
+ skb->dev=dev;
+
+ memcpy((u_char *)soft+EXTRA_CLIENTDATA,
+ (u_char *)arcsoft+EXTRA_CLIENTDATA,
+ sizeof(struct ClientData)-EXTRA_CLIENTDATA);
+ soft->split_flag=0; /* final packet won't be split */
+ }
+ else /* not first packet */
+ {
+ int packetnum=((unsigned)arcsoft->split_flag>>1) + 1;
+
+ /* if we're not assembling, there's no point
+ * trying to continue.
+ */
+ if (!in->skb)
+ {
+ if (lp->aborted_seq != arcsoft->sequence)
+ {
+ BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n",
+ arcsoft->split_flag,arcsoft->sequence, lp->aborted_seq);
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ }
+ return;
+ }
+
+ in->lastpacket++;
+ if (packetnum!=in->lastpacket) /* not the right flag! */
+ {
+ /* harmless duplicate? ignore. */
+ if (packetnum<=in->lastpacket-1)
+ {
+ 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 */
+ BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
+ in->sequence,arcsoft->split_flag,
+ arcsoft->sequence);
+ lp->aborted_seq=arcsoft->sequence;
+ kfree_skb(in->skb,FREE_WRITE);
+ in->skb=NULL;
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ in->lastpacket=in->numpackets=0;
+ return;
+ }
+
+ soft=(struct ClientData *)in->skb->data;
+ }
+
+ skb=in->skb;
+
+ memcpy(skb->data+skb->len,
+ (u_char *)arcsoft+sizeof(struct ClientData),
+ length-sizeof(struct ClientData));
+ skb_put(skb,length-sizeof(struct ClientData));
+
+ soft->daddr=daddr;
+ soft->saddr=saddr;
+
+ /* are we done? */
+ if (in->lastpacket == in->numpackets)
+ {
+ if (!skb || !in->skb)
+ {
+ BUGMSG(D_NORMAL,"?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
+ skb,in->skb);
+ }
+ else
+ {
+ in->skb=NULL;
+ in->lastpacket=in->numpackets=0;
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
+
+ lp->stats.rx_bytes += skb->len;
+ skb->protocol=arcnetA_type_trans(skb,dev);
+ netif_rx(skb);
+ }
}
-
- if (!arcsoft->split_flag) /* not split */
- {
- struct Incoming *in=&lp->incoming[saddr];
-
- BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n",
- arcsoft->split_flag);
-
- if (in->skb) /* already assembling one! */
- {
- 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.rx_errors++;
- lp->stats.rx_missed_errors++;
- in->skb=NULL;
- }
-
- in->sequence=arcsoft->sequence;
-
- skb = alloc_skb(length, GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
- lp->stats.rx_dropped++;
- return;
- }
- soft=(struct ClientData *)skb->data;
-
- skb->len = length;
- skb->dev = dev;
-
- memcpy((u_char *)soft+EXTRA_CLIENTDATA,
- (u_char *)arcsoft+EXTRA_CLIENTDATA,
- length-EXTRA_CLIENTDATA);
- soft->daddr=daddr;
- soft->saddr=saddr;
-
- /* ARP packets have problems when sent from DOS.
- * source address is always 0 on some systems! So we take
- * the hardware source addr (which is impossible to fumble)
- * and insert it ourselves.
- */
- if (soft->protocol_id == ARC_P_ARP)
- {
- struct arphdr *arp=(struct arphdr *)
- ((char *)soft+sizeof(struct ClientData));
-
- /* make sure addresses are the right length */
- if (arp->ar_hln==1 && arp->ar_pln==4)
- {
- char *cptr=(char *)(arp)+sizeof(struct arphdr);
-
- if (!*cptr) /* is saddr = 00? */
- {
- BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n",
- saddr);
- lp->stats.rx_crc_errors++;
- *cptr=saddr;
- }
- else
- {
- BUGMSG(D_DURING,"ARP source address (%Xh) is fine.\n",
- *cptr);
- }
- }
- else
- {
- BUGMSG(D_NORMAL,"funny-shaped ARP packet. (%Xh, %Xh)\n",
- arp->ar_hln,arp->ar_pln);
- lp->stats.rx_errors++;
- lp->stats.rx_crc_errors++;
- }
- }
-
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-
- skb->protocol=arcnetA_type_trans(skb,dev);
-
- netif_rx(skb);
- }
- else /* split packet */
- {
- /* NOTE: MSDOS ARP packet correction should only need to
- * apply to unsplit packets, since ARP packets are so short.
- *
- * My interpretation of the RFC1201 (ARCnet) document is that
- * if a packet is received out of order, the entire assembly
- * process should be aborted.
- *
- * The RFC also mentions "it is possible for successfully
- * received packets to be retransmitted." As of 0.40 all
- * previously received packets are allowed, not just the
- * most recent one.
- *
- * We allow multiple assembly processes, one for each
- * ARCnet card possible on the network. Seems rather like
- * a waste of memory. Necessary?
- */
-
- struct Incoming *in=&lp->incoming[saddr];
-
- BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n",
- arcsoft->split_flag,in->sequence);
-
- if (in->skb && in->sequence!=arcsoft->sequence)
- {
- BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
- saddr,in->sequence,arcsoft->sequence,
- arcsoft->split_flag);
- kfree_skb(in->skb,FREE_WRITE);
- in->skb=NULL;
- lp->stats.rx_errors++;
- lp->stats.rx_missed_errors++;
- in->lastpacket=in->numpackets=0;
- }
-
- if (arcsoft->split_flag & 1) /* first packet in split */
- {
- BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n",
- arcsoft->split_flag);
- if (in->skb) /* already assembling one! */
- {
- BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
- in->sequence,arcsoft->split_flag,
- arcsoft->sequence);
- lp->stats.rx_errors++;
- lp->stats.rx_missed_errors++;
- kfree_skb(in->skb,FREE_WRITE);
- }
-
- in->sequence=arcsoft->sequence;
- in->numpackets=((unsigned)arcsoft->split_flag>>1)+2;
- in->lastpacket=1;
-
- if (in->numpackets>16)
- {
- BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
- arcsoft->split_flag);
- lp->stats.rx_errors++;
- lp->stats.rx_length_errors++;
- return;
- }
-
- in->skb=skb=alloc_skb(508*in->numpackets
- + sizeof(struct ClientData),
- GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL,"(split) memory squeeze, dropping packet.\n");
- lp->stats.rx_dropped++;
- return;
- }
-
- soft=(struct ClientData *)skb->data;
-
- skb->len=sizeof(struct ClientData);
- skb->dev=dev;
-
- memcpy((u_char *)soft+EXTRA_CLIENTDATA,
- (u_char *)arcsoft+EXTRA_CLIENTDATA,
- sizeof(struct ClientData)-EXTRA_CLIENTDATA);
- soft->split_flag=0; /* final packet won't be split */
- }
- else /* not first packet */
- {
- int packetnum=((unsigned)arcsoft->split_flag>>1) + 1;
-
- /* if we're not assembling, there's no point
- * trying to continue.
- */
- if (!in->skb)
- {
- 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;
- }
-
- in->lastpacket++;
- if (packetnum!=in->lastpacket) /* not the right flag! */
- {
- /* harmless duplicate? ignore. */
- if (packetnum<=in->lastpacket-1)
- {
- 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 */
- 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.rx_errors++;
- lp->stats.rx_missed_errors++;
- in->lastpacket=in->numpackets=0;
- return;
- }
-
- soft=(struct ClientData *)in->skb->data;
- }
-
- skb=in->skb;
-
- memcpy(skb->data+skb->len,
- (u_char *)arcsoft+sizeof(struct ClientData),
- length-sizeof(struct ClientData));
-
- skb->len+=length-sizeof(struct ClientData);
-
- soft->daddr=daddr;
- soft->saddr=saddr;
-
- /* are we done? */
- if (in->lastpacket == in->numpackets)
- {
- if (!skb || !in->skb)
- {
- BUGMSG(D_NORMAL,"?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
- skb,in->skb);
- }
- else
- {
- in->skb=NULL;
- in->lastpacket=in->numpackets=0;
-
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-
- skb->protocol=arcnetA_type_trans(skb,dev);
-
- netif_rx(skb);
- }
- }
- }
+ }
}
@@ -2574,99 +1359,83 @@
static struct net_device_stats *arcnet_get_stats(struct device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
- return &lp->stats;
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+
+ return &lp->stats;
}
-#if 0 /* standard ARCnet cards have no promiscuous mode */
-/* Set or clear the multicast filter for this adaptor.
- * num_addrs == -1 Promiscuous mode, receive all packets
- * num_addrs == 0 Normal mode, clear multicast list
- * num_addrs > 0 Multicast mode, receive normal and MC packets, and do
- * best-effort filtering.
- */
-static void
-set_multicast_list(struct device *dev)
-{
- if (num_addrs) {
- /* Enable promiscuous mode */
- } else
- /* Disable promiscuous mode, use normal mode */
-}
-#endif
/* Create the ARCnet ClientData header for an arbitrary protocol layer
*
* saddr=NULL means use device source address (always will anyway)
* daddr=NULL means leave destination address (eg unresolved arp)
*/
-int arcnetA_header(struct sk_buff *skb,struct device *dev,
- unsigned short type,void *daddr,void *saddr,unsigned len)
+static int arcnetA_header(struct sk_buff *skb,struct device *dev,
+ unsigned short type,void *daddr,void *saddr,unsigned len)
{
- struct ClientData *head = (struct ClientData *)
- skb_push(skb,dev->hard_header_len);
- struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-
- 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);
-
- /* set the protocol ID according to RFC1201 */
- switch(type)
- {
- case ETH_P_IP:
- head->protocol_id=ARC_P_IP;
- break;
- case ETH_P_ARP:
- head->protocol_id=ARC_P_ARP;
- break;
- case ETH_P_RARP:
- 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:
- BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
- type,type);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
- return 0;
- }
-
- /*
- * Set the source hardware address.
- *
- * This is pretty pointless for most purposes, but it can help
- * in debugging. saddr is stored in the ClientData header and
- * removed before sending the packet (since ARCnet does not allow
- * us to change the source address in the actual packet sent)
- */
- if(saddr)
- head->saddr=((u_char*)saddr)[0];
- else
- head->saddr=((u_char*)(dev->dev_addr))[0];
-
- head->split_flag=0; /* split packets are done elsewhere */
- head->sequence=0; /* so are sequence numbers */
-
- /* supposedly if daddr is NULL, we should ignore it... */
- if(daddr)
- {
- head->daddr=((u_char*)daddr)[0];
- return dev->hard_header_len;
- }
- else
- head->daddr=0; /* better fill one in anyway */
-
- return -dev->hard_header_len;
+ struct ClientData *head = (struct ClientData *)
+ skb_push(skb,dev->hard_header_len);
+ struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
+
+ 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);
+
+ /* set the protocol ID according to RFC1201 */
+ switch(type)
+ {
+ case ETH_P_IP:
+ head->protocol_id=ARC_P_IP;
+ break;
+ case ETH_P_ARP:
+ head->protocol_id=ARC_P_ARP;
+ break;
+ case ETH_P_RARP:
+ 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:
+ BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
+ type,type);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+ return 0;
+ }
+
+ /*
+ * Set the source hardware address.
+ *
+ * This is pretty pointless for most purposes, but it can help
+ * in debugging. saddr is stored in the ClientData header and
+ * removed before sending the packet (since ARCnet does not allow
+ * us to change the source address in the actual packet sent)
+ */
+ if(saddr)
+ head->saddr=((u_char*)saddr)[0];
+ else
+ head->saddr=((u_char*)(dev->dev_addr))[0];
+
+ head->split_flag=0; /* split packets are done elsewhere */
+ head->sequence=0; /* so are sequence numbers */
+
+ /* supposedly if daddr is NULL, we should ignore it... */
+ if(daddr)
+ {
+ head->daddr=((u_char*)daddr)[0];
+ return dev->hard_header_len;
+ }
+ else
+ head->daddr=0; /* better fill one in anyway */
+
+ return -dev->hard_header_len;
}
@@ -2675,42 +1444,42 @@
* (or in future other address resolution) has completed on this
* sk_buff. We now let ARP fill in the other fields.
*/
-int arcnetA_rebuild_header(struct sk_buff *skb)
+static int arcnetA_rebuild_header(struct sk_buff *skb)
{
- struct ClientData *head = (struct ClientData *)skb->data;
- struct device *dev=skb->dev;
- struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
- int status;
-
- /*
- * Only ARP and IP are currently supported
- *
- * FIXME: Anyone want to spec IPv6 over ARCnet ?
- */
-
- if(head->protocol_id != ARC_P_IP)
- {
- BUGMSG(D_NORMAL,"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;
- }
-
- /*
- * Try to get ARP to resolve the header.
- */
+ struct ClientData *head = (struct ClientData *)skb->data;
+ struct device *dev=skb->dev;
+ struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
+ int status;
+
+ /*
+ * Only ARP and IP are currently supported
+ *
+ * FIXME: Anyone want to spec IPv6 over ARCnet ?
+ */
+
+ if(head->protocol_id != ARC_P_IP)
+ {
+ BUGMSG(D_NORMAL,"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;
+ }
+
+ /*
+ * Try to get ARP to resolve the header.
+ */
#ifdef CONFIG_INET
- BUGMSG(D_DURING,"rebuild header from %d to %d; protocol %Xh\n",
- head->saddr,head->daddr,head->protocol_id);
- status=arp_find(&(head->daddr),skb)? 1 : 0;
- BUGMSG(D_DURING," rebuilt: from %d to %d; protocol %Xh\n",
- head->saddr,head->daddr,head->protocol_id);
- return status;
+ BUGMSG(D_DURING,"rebuild header from %d to %d; protocol %Xh\n",
+ head->saddr,head->daddr,head->protocol_id);
+ status=arp_find(&(head->daddr),skb)? 1 : 0;
+ BUGMSG(D_DURING," rebuilt: from %d to %d; protocol %Xh\n",
+ head->saddr,head->daddr,head->protocol_id);
+ return status;
#else
- return 0;
+ return 0;
#endif
}
@@ -2719,42 +1488,42 @@
*
* With ARCnet we have to convert everything to Ethernet-style stuff.
*/
-unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
+static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
{
- struct ClientData *head;
- struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
-
- /* Pull off the arcnet header. */
- skb->mac.raw=skb->data;
- skb_pull(skb,dev->hard_header_len);
- head=(struct ClientData *)skb->mac.raw;
-
- if (head->daddr==0)
- skb->pkt_type=PACKET_BROADCAST;
- else if (dev->flags&IFF_PROMISC)
- {
- /* if we're not sending to ourselves :) */
- if (head->daddr != dev->dev_addr[0])
- skb->pkt_type=PACKET_OTHERHOST;
- }
-
- /* now return the protocol number */
- switch (head->protocol_id)
- {
- 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:
- case ARC_P_NOVELL_EC:
- return htons(ETH_P_802_3);
- default:
- lp->stats.rx_errors++;
- lp->stats.rx_crc_errors++;
- return 0;
- }
-
- return htons(ETH_P_IP);
+ struct ClientData *head;
+ struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
+
+ /* Pull off the arcnet header. */
+ skb->mac.raw=skb->data;
+ skb_pull(skb,dev->hard_header_len);
+ head=(struct ClientData *)skb->mac.raw;
+
+ if (head->daddr==0)
+ skb->pkt_type=PACKET_BROADCAST;
+ else if (dev->flags&IFF_PROMISC)
+ {
+ /* if we're not sending to ourselves :) */
+ if (head->daddr != dev->dev_addr[0])
+ skb->pkt_type=PACKET_OTHERHOST;
+ }
+
+ /* now return the protocol number */
+ switch (head->protocol_id)
+ {
+ 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:
+ case ARC_P_NOVELL_EC:
+ return htons(ETH_P_802_3);
+ default:
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
+ return 0;
+ }
+
+ return htons(ETH_P_IP);
}
@@ -2769,19 +1538,17 @@
*/
static int arcnetE_init(struct device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
- ether_setup(dev); /* we're emulating ether here, not ARCnet */
- dev->dev_addr[0]=0;
- dev->dev_addr[5]=lp->stationid;
- dev->mtu=512-sizeof(struct HardHeader)-dev->hard_header_len-1;
- dev->open=arcnetE_open_close;
- dev->stop=arcnetE_open_close;
- dev->hard_start_xmit=arcnetE_send_packet;
-
- BUGMSG(D_NORMAL,"ARCnet Ethernet-Encap protocol initialized.\n");
-
- return 0;
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+
+ ether_setup(dev); /* we're emulating ether here, not ARCnet */
+ dev->dev_addr[0]=0;
+ dev->dev_addr[5]=lp->stationid;
+ dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len-1;
+ dev->open=arcnetE_open_close;
+ dev->stop=arcnetE_open_close;
+ dev->hard_start_xmit=arcnetE_send_packet;
+
+ return 0;
}
@@ -2790,7 +1557,7 @@
*/
static int arcnetE_open_close(struct device *dev)
{
- return 0;
+ return 0;
}
@@ -2799,97 +1566,80 @@
static int
arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int ioaddr=IOADDR,bad;
- union ArcPacket *arcpacket =
- (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1));
- u_char *arcsoft,daddr;
- short offset,length=skb->len+1;
-
- lp->intx++;
-
- bad=arcnet_send_packet_bad(skb,dev);
- if (bad)
- {
- lp->intx--;
- return bad;
- }
-
- TBUSY=1;
-
- if (length>XMTU)
- {
- BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n",
- length);
- BUGMSG(D_NORMAL,"transmit aborted.\n");
-
- dev_kfree_skb(skb,FREE_WRITE);
- lp->intx--;
- return 0;
- }
-
- BUGMSG(D_DURING,"starting tx sequence...\n");
-
- lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate btw 2 & 3 */
-
-#ifndef SLOW_XMIT_COPY
- /* clean out the page to make debugging make more sense :) */
- BUGLVL(D_DURING)
- memset_io(dev->mem_start+lp->txbuf*512,0x42,512);
-#endif
-
- /* 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 */
- 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);
- }
-
- 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
- */
- BUGMSG(D_DURING,"ready to memcpy\n");
-
- memcpy(arcsoft,skb->data,skb->len);
-
- BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
- daddr,length);
-
- BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>=240,"tx");
-
- lp->lastload_dest=daddr;
- lp->txready=lp->txbuf; /* packet is ready for sending */
-
- dev_kfree_skb(skb,FREE_WRITE);
-
- if (arcnet_go_tx(dev,1))
- {
- /* inform upper layers */
- TBUSY=0;
- mark_bh(NET_BH);
- }
-
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ int bad,oldmask=0;
+ u_char daddr;
+ short offset,length=skb->len+1;
+ u_char proto=ARC_P_ETHER;
+
+ lp->intx++;
+
+ oldmask |= lp->intmask;
+ lp->intmask=0;
+ SETMASK;
+
+ bad=arcnet_send_packet_bad(skb,dev);
+ if (bad)
+ {
+ lp->intx--;
+ lp->intmask=oldmask;
+ SETMASK;
+ return bad;
+ }
+
+ /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
+
+ lp->intmask=oldmask;
+ SETMASK;
+
+ if (length>XMTU)
+ {
+ BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n",
+ length);
+ BUGMSG(D_NORMAL,"transmit aborted.\n");
+
+ dev_kfree_skb(skb,FREE_WRITE);
+ lp->intx--;
+ return 0;
+ }
+
+ BUGMSG(D_DURING,"starting tx sequence...\n");
+
+ /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
+ if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF)
+ daddr=0;
+ else
+ daddr=((struct ethhdr*)(skb->data))->h_dest[5];
+
+ /* load packet into shared memory */
+ offset=512-length;
+ if (length>MTU) /* long/exception packet */
+ {
+ if (length<MinTU) offset-=3;
+ }
+ else /* short packet */
+ {
+ offset-=256;
+ }
+
+ BUGMSG(D_DURING," length=%Xh, offset=%Xh\n",
+ length,offset);
+
+
+
+ (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0,
+ offset);
+
+
+
+ dev_kfree_skb(skb,FREE_WRITE);
+
+ if (arcnet_go_tx(dev,1))
+ {
+ /* inform upper layers */
+ arcnet_tx_done(lp->adev, lp);
+ }
+
dev->trans_start=jiffies;
lp->intx--;
@@ -2920,15 +1670,16 @@
return;
}
- skb->len = length;
+ skb_put(skb,length);
+
skb->dev = dev;
memcpy(skb->data,(u_char *)arcsoft+1,length-1);
BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
+ lp->stats.rx_bytes += skb->len;
skb->protocol=eth_type_trans(skb,dev);
-
netif_rx(skb);
}
@@ -2945,23 +1696,22 @@
*/
static int arcnetS_init(struct device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
- arcnet_setup(dev);
-
- /* And now fill particular fields with arcnet values */
- dev->dev_addr[0]=lp->stationid;
- dev->hard_header_len=sizeof(struct S_ClientData);
- dev->mtu=512-sizeof(struct HardHeader)-dev->hard_header_len
- + S_EXTRA_CLIENTDATA;
- dev->open=arcnetS_open_close;
- dev->stop=arcnetS_open_close;
- dev->hard_start_xmit=arcnetS_send_packet;
- dev->hard_header=arcnetS_header;
- dev->rebuild_header=arcnetS_rebuild_header;
- BUGMSG(D_NORMAL,"ARCnet RFC1051 (NetBSD, AmiTCP) protocol initialized.\n");
-
- return 0;
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+
+ arcnet_setup(dev);
+
+ /* And now fill particular fields with arcnet values */
+ dev->dev_addr[0]=lp->stationid;
+ dev->hard_header_len=sizeof(struct S_ClientData);
+ dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len
+ + S_EXTRA_CLIENTDATA;
+ dev->open=arcnetS_open_close;
+ dev->stop=arcnetS_open_close;
+ dev->hard_start_xmit=arcnetS_send_packet;
+ dev->hard_header=arcnetS_header;
+ dev->rebuild_header=arcnetS_rebuild_header;
+
+ return 0;
}
@@ -2970,7 +1720,7 @@
*/
static int arcnetS_open_close(struct device *dev)
{
- return 0;
+ return 0;
}
@@ -2979,63 +1729,61 @@
static int
arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int ioaddr=IOADDR,bad,length;
- struct S_ClientData *hdr=(struct S_ClientData *)skb->data;
-
- lp->intx++;
-
- bad=arcnet_send_packet_bad(skb,dev);
- if (bad)
- {
- lp->intx--;
- return bad;
- }
-
- TBUSY=1;
-
- length = 1 < skb->len ? skb->len : 1;
-
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-
- /* fits in one packet? */
- if (length-S_EXTRA_CLIENTDATA<=XMTU)
- {
- arcnetAS_prepare_tx(dev,
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ int bad,length;
+ struct S_ClientData *hdr=(struct S_ClientData *)skb->data;
+
+ lp->intx++;
+
+ bad=arcnet_send_packet_bad(skb,dev);
+ if (bad)
+ {
+ lp->intx--;
+ return bad;
+ }
+
+ /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
+
+ length = 1 < skb->len ? skb->len : 1;
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
+
+ /* fits in one packet? */
+ if (length-S_EXTRA_CLIENTDATA<=XMTU)
+ {
+ (*lp->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);
-
- /* done right away */
- dev_kfree_skb(skb,FREE_WRITE);
-
- if (arcnet_go_tx(dev,1))
- {
- /* inform upper layers */
- TBUSY=0;
- mark_bh(NET_BH);
- }
- }
- else /* too big for one - not accepted */
- {
- BUGMSG(D_NORMAL,"packet too long (length=%d)\n",
- length);
- dev_kfree_skb(skb,FREE_WRITE);
- lp->stats.tx_dropped++;
- TBUSY=0;
- mark_bh(NET_BH);
- }
-
- dev->trans_start=jiffies;
- lp->intx--;
-
- /* make sure we didn't ignore a TX IRQ while we were in here */
- lp->intmask |= TXFREEflag;
- SETMASK;
-
- return 0;
+ hdr->daddr,0,0);
+
+ /* done right away */
+ dev_kfree_skb(skb,FREE_WRITE);
+
+ if (arcnet_go_tx(dev,1))
+ {
+ /* inform upper layers */
+ arcnet_tx_done(lp->adev, lp);
+ }
+ }
+ else /* too big for one - not accepted */
+ {
+ BUGMSG(D_NORMAL,"packet too long (length=%d)\n",
+ length);
+ dev_kfree_skb(skb,FREE_WRITE);
+ lp->stats.tx_dropped++;
+ arcnet_tx_done(lp->adev, lp);
+ }
+
+ dev->trans_start=jiffies;
+ lp->intx--;
+
+ /* make sure we didn't ignore a TX IRQ while we were in here */
+ lp->intmask |= TXFREEflag;
+ SETMASK;
+
+ return 0;
}
@@ -3043,47 +1791,45 @@
*/
static void
arcnetS_rx(struct device *dev,u_char *buf,
- int length,u_char saddr, u_char daddr)
+ int length,u_char saddr, u_char daddr)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- struct sk_buff *skb;
- struct S_ClientData *arcsoft,*soft;
-
- arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA);
- length+=S_EXTRA_CLIENTDATA;
-
- BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n",
- length);
-
-
-
- { /* was "if not split" in A protocol, S is never split */
-
- skb = alloc_skb(length, GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
- lp->stats.rx_dropped++;
- return;
- }
- soft=(struct S_ClientData *)skb->data;
- skb->len = length;
- memcpy((u_char *)soft + sizeof(struct S_ClientData)
- - S_EXTRA_CLIENTDATA,
- (u_char *)arcsoft + sizeof(struct S_ClientData)
- - S_EXTRA_CLIENTDATA,
- length - sizeof(struct S_ClientData)
- + S_EXTRA_CLIENTDATA);
- soft->protocol_id=arcsoft->protocol_id;
- soft->daddr=daddr;
- soft->saddr=saddr;
- skb->dev = dev; /* is already lp->sdev */
-
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-
- skb->protocol=arcnetS_type_trans(skb,dev);
-
- netif_rx(skb);
- }
+ struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ struct sk_buff *skb;
+ struct S_ClientData *arcsoft,*soft;
+
+ arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA);
+ length+=S_EXTRA_CLIENTDATA;
+
+ BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n",
+ length);
+
+
+
+ { /* was "if not split" in A protocol, S is never split */
+
+ skb = alloc_skb(length, GFP_ATOMIC);
+ if (skb == NULL) {
+ BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
+ lp->stats.rx_dropped++;
+ return;
+ }
+ soft=(struct S_ClientData *)skb->data;
+ skb_put(skb,length);
+
+ memcpy((u_char *)soft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA,
+ (u_char *)arcsoft + sizeof(struct S_ClientData) -S_EXTRA_CLIENTDATA,
+ length - sizeof(struct S_ClientData) + S_EXTRA_CLIENTDATA);
+ soft->protocol_id=arcsoft->protocol_id;
+ soft->daddr=daddr;
+ soft->saddr=saddr;
+ skb->dev = dev; /* is already lp->sdev */
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
+
+ lp->stats.rx_bytes += skb->len;
+ skb->protocol=arcnetS_type_trans(skb,dev);
+ netif_rx(skb);
+ }
}
@@ -3092,55 +1838,55 @@
* saddr=NULL means use device source address (always will anyway)
* daddr=NULL means leave destination address (eg unresolved arp)
*/
-int arcnetS_header(struct sk_buff *skb,struct device *dev,
- unsigned short type,void *daddr,void *saddr,unsigned len)
+static int arcnetS_header(struct sk_buff *skb,struct device *dev,
+ unsigned short type,void *daddr,void *saddr,unsigned len)
{
- struct S_ClientData *head = (struct S_ClientData *)
- skb_push(skb,dev->hard_header_len);
- 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;
- BUGMSG(D_DURING,"S_header: IP_RFC1051 packet.\n");
- break;
- case ETH_P_ARP:
- head->protocol_id=ARC_P_ARP_RFC1051;
- BUGMSG(D_DURING,"S_header: ARP_RFC1051 packet.\n");
- break;
- default:
- BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
- type,type);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
- return 0;
- }
-
- /*
- * Set the source hardware address.
- *
- * This is pretty pointless for most purposes, but it can help
- * in debugging. saddr is stored in the ClientData header and
- * removed before sending the packet (since ARCnet does not allow
- * us to change the source address in the actual packet sent)
- */
- if(saddr)
- head->saddr=((u_char*)saddr)[0];
- else
- head->saddr=((u_char*)(dev->dev_addr))[0];
-
- /* supposedly if daddr is NULL, we should ignore it... */
- if(daddr)
- {
+ struct S_ClientData *head = (struct S_ClientData *)
+ skb_push(skb,dev->hard_header_len);
+ 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;
+ BUGMSG(D_DURING,"S_header: IP_RFC1051 packet.\n");
+ break;
+ case ETH_P_ARP:
+ head->protocol_id=ARC_P_ARP_RFC1051;
+ BUGMSG(D_DURING,"S_header: ARP_RFC1051 packet.\n");
+ break;
+ default:
+ BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
+ type,type);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+ return 0;
+ }
+
+ /*
+ * Set the source hardware address.
+ *
+ * This is pretty pointless for most purposes, but it can help
+ * in debugging. saddr is stored in the ClientData header and
+ * removed before sending the packet (since ARCnet does not allow
+ * us to change the source address in the actual packet sent)
+ */
+ if(saddr)
+ head->saddr=((u_char*)saddr)[0];
+ else
+ head->saddr=((u_char*)(dev->dev_addr))[0];
+
+ /* supposedly if daddr is NULL, we should ignore it... */
+ if(daddr)
+ {
head->daddr=((u_char*)daddr)[0];
return dev->hard_header_len;
- }
- else
- head->daddr=0; /* better fill one in anyway */
-
- return -dev->hard_header_len;
+ }
+ else
+ head->daddr=0; /* better fill one in anyway */
+
+ return -dev->hard_header_len;
}
@@ -3148,34 +1894,34 @@
* (or in future other address resolution) has completed on this
* sk_buff. We now let ARP fill in the other fields.
*/
-int arcnetS_rebuild_header(struct sk_buff *skb)
+static int arcnetS_rebuild_header(struct sk_buff *skb)
{
- struct device *dev=skb->dev;
- struct S_ClientData *head = (struct S_ClientData *)skb->data;
- struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-
- /*
- * Only ARP and IP are currently supported
- */
-
- if(head->protocol_id != ARC_P_IP_RFC1051)
- {
- BUGMSG(D_NORMAL,"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;
- }
-
- /*
- * Try to get ARP to resolve the header.
- */
+ struct device *dev=skb->dev;
+ struct S_ClientData *head = (struct S_ClientData *)skb->data;
+ struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
+
+ /*
+ * Only ARP and IP are currently supported
+ */
+
+ if(head->protocol_id != ARC_P_IP_RFC1051)
+ {
+ BUGMSG(D_NORMAL,"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;
+ }
+
+ /*
+ * Try to get ARP to resolve the header.
+ */
#ifdef CONFIG_INET
- return arp_find(&(head->daddr),skb)? 1 : 0;
+ return arp_find(&(head->daddr),skb)? 1 : 0;
#else
- return 0;
+ return 0;
#endif
}
@@ -3186,36 +1932,36 @@
*/
unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev)
{
- struct S_ClientData *head;
- struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
-
- /* Pull off the arcnet header. */
- skb->mac.raw=skb->data;
- skb_pull(skb,dev->hard_header_len);
- head=(struct S_ClientData *)skb->mac.raw;
-
- if (head->daddr==0)
- skb->pkt_type=PACKET_BROADCAST;
- else if (dev->flags&IFF_PROMISC)
- {
- /* if we're not sending to ourselves :) */
- if (head->daddr != dev->dev_addr[0])
- skb->pkt_type=PACKET_OTHERHOST;
- }
-
- /* now return the protocol number */
- switch (head->protocol_id)
- {
- case ARC_P_IP_RFC1051: return htons(ETH_P_IP);
- case ARC_P_ARP_RFC1051: return htons(ETH_P_ARP);
- case ARC_P_ATALK: return htons(ETH_P_ATALK); /* untested appletalk */
- default:
- lp->stats.rx_errors++;
- lp->stats.rx_crc_errors++;
- return 0;
- }
-
- return htons(ETH_P_IP);
+ struct S_ClientData *head;
+ struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
+
+ /* Pull off the arcnet header. */
+ skb->mac.raw=skb->data;
+ skb_pull(skb,dev->hard_header_len);
+ head=(struct S_ClientData *)skb->mac.raw;
+
+ if (head->daddr==0)
+ skb->pkt_type=PACKET_BROADCAST;
+ else if (dev->flags&IFF_PROMISC)
+ {
+ /* if we're not sending to ourselves :) */
+ if (head->daddr != dev->dev_addr[0])
+ skb->pkt_type=PACKET_OTHERHOST;
+ }
+
+ /* now return the protocol number */
+ switch (head->protocol_id)
+ {
+ case ARC_P_IP_RFC1051: return htons(ETH_P_IP);
+ case ARC_P_ARP_RFC1051: return htons(ETH_P_ARP);
+ case ARC_P_ATALK: return htons(ETH_P_ATALK); /* untested appletalk */
+ default:
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
+ return 0;
+ }
+
+ return htons(ETH_P_IP);
}
#endif /* CONFIG_ARCNET_1051 */
@@ -3227,88 +1973,151 @@
****************************************************************************/
+
#ifdef MODULE
-static char devicename[9] = "";
-static struct device thiscard = {
- devicename, /* device name is inserted by linux/drivers/net/net_init.c */
- 0, 0, 0, 0,
- 0, 0, /* I/O address, IRQ */
- 0, 0, 0, NULL, arcnet_probe
-};
+void cleanup_module(void)
+{
+ printk("Generic arcnet support removed.\n");
+}
+
+void arcnet_use_count(int open)
+{
+ if (open)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
+}
+
+#else
+void arcnet_use_count(int open)
+{
+}
-static int io=0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
-static int irqnum=0; /* or use the insmod io= irq= shmem= options */
-static int irq=0;
-static int shmem=0;
-static char *device = NULL; /* use eg. device="arc1" to change name */
+struct device arcnet_devs[MAX_ARCNET_DEVS];
+int arcnet_num_devs=0;
+char arcnet_dev_names[MAX_ARCNET_DEVS][10];
-MODULE_PARM(io, "i");
-MODULE_PARM(irqnum, "i");
-MODULE_PARM(shmem, "i");
+void arcnet_init(void)
+{
+ int c;
+
+ (void) init_module();
-#ifdef RIM_I_MODE
- static int node=0; /* you must specify the node ID for RIM I cards */
+ /* Don't register_netdev here. The chain hasn't been initialised. */
+
+#ifdef CONFIG_ARCNET_COM90xx
+ if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS)
+ {
+ arcnet_devs[arcnet_num_devs].init=arc90xx_probe;
+ arcnet_devs[arcnet_num_devs].name=
+ (char *)&arcnet_dev_names[arcnet_num_devs];
+ arcnet_num_devs++;
+ }
#endif
-int init_module(void)
-{
- struct device *dev=&thiscard;
- if (device)
- strcpy(dev->name,device);
- #ifndef CONFIG_ARCNET_ETHNAME
- else if (!dev->name[0]) strcpy(dev->name,"arc0");
- #endif
+ if (!arcnet_num_devs)
+ {
+ printk("Don't forget to load the chipset driver.\n");
+ return;
+ }
- #ifdef RIM_I_MODE
- if (node) io=node;
- #endif
+ /* Link into the device chain */
- dev->base_addr=io;
+ /* Q: Should we put ourselves at the beginning or the end of the chain? */
+ /* Probably the end, because we're not so fast, but... */
- if (irq) irqnum=irq;
- dev->irq=irqnum;
- if (dev->irq==2) dev->irq=9;
+ for (c=0; c< (arcnet_num_devs-1); c++)
+ arcnet_devs[c].next=&arcnet_devs[c+1];
- if (shmem)
- {
- dev->mem_start=shmem;
- dev->mem_end=thiscard.mem_start+512*4-1;
- dev->rmem_start=thiscard.mem_start+512*0;
- dev->rmem_end=thiscard.mem_start+512*2-1;
- }
+ arcnet_devs[c].next=dev_base;
+ dev_base=&arcnet_devs[0];
+
+ /* Give names to those without them */
+
+ for (c=0; c< arcnet_num_devs; c++)
+ if (!arcnet_dev_names[c][0])
+ arcnet_makename((char *)&arcnet_dev_names[c]);
- if (register_netdev(dev) != 0)
- return -EIO;
- return 0;
}
-
-void cleanup_module(void)
+static
+#endif /* MODULE */
+int init_module()
{
- struct device *dev=&thiscard;
- int ioaddr=IOADDR;
+
+#if 1
+ BUGLVL(D_EXTRA)
+ {
+ printk("arcnet: ***\n");
+ printk("arcnet: * Read arcnet.txt for important release notes!\n");
+ printk("arcnet: *\n");
+ printk("arcnet: * This is an ALPHA version! (Last stable release: v2.56) E-mail me if\n");
+ printk("arcnet: * you have any questions, comments, or bug reports.\n");
+ printk("arcnet: ***\n");
+ }
+#endif
+
+ printk("%sGeneric arcnet support for Linux kernel.\n"
+ "Available protocols: ARCnet RFC1201"
+#ifdef CONFIG_ARCNET_ETH
+ ", Ethernet-Encap"
+#endif
+#ifdef CONFIG_ARCNET_1051
+ ", ARCnet RFC1051"
+#endif
+#ifdef MODULE
+ ".\nDon't forget to load the chipset driver"
+#endif
+ ".\n",version);
+ return 0;
+}
+
- if (dev->start) arcnet_close(dev);
- /* Flush TX and disable RX */
- if (ioaddr)
- {
- AINTMASK(0); /* disable IRQ's */
- ACOMMAND(NOTXcmd); /* stop transmit */
- ACOMMAND(NORXcmd); /* disable receive */
- }
- if (dev->irq)
- {
- irq2dev_map[dev->irq] = NULL;
- free_irq(dev->irq,NULL);
- }
- if (dev->base_addr) RELEASE_REGION(dev->base_addr,ARCNET_TOTAL_SIZE);
- unregister_netdev(dev);
- kfree(dev->priv);
- dev->priv = NULL;
+void arcnet_makename(char *device)
+{
+ __u32 arcmask=0;
+ struct device *dev;
+ char *c;
+ int arcnum;
+
+ for (dev = dev_base; dev; dev=dev->next)
+ {
+ arcnum=0;
+
+ if (!strncmp(dev->name, "arc", 3))
+ {
+ c = &dev->name[3];
+ while ((*c)>='0' && (*c)<='9')
+ {
+ arcnum *= 10;
+ arcnum += (*(c++)-'0');
+ }
+
+ if (arcnum<32)
+ arcmask |= ((__u32)1 << arcnum);
+ }
+
+
+ }
+
+ /* arcmask now holds a mask of the first 32 arcnet names available */
+
+ if ((__u32)~arcmask)
+ {
+ for (arcnum=0; arcmask&1; arcnum++, arcmask >>=1)
+ ;
+
+ sprintf (device, "arc%d",arcnum);
+ }
+ else
+ {
+ printk (KERN_INFO "arcnet: Can't find name for device\n");
+ sprintf (device, "arc???");
+ }
}
-#endif /* MODULE */
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov