patch-2.1.54 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: 1479
- Date:
Sat Sep 6 10:05:42 1997
- Orig file:
v2.1.53/linux/drivers/net/arcnet.c
- Orig date:
Thu Sep 4 17:07:30 1997
diff -u --recursive --new-file v2.1.53/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
@@ -1,8 +1,9 @@
-/* arcnet.c:
+/* $Id: arcnet.c,v 1.30 1997/09/05 08:57:46 mj Exp $
+
Written 1994-1996 by Avery Pennarun,
derived from skeleton.c by Donald Becker.
- Contact Avery at: apenwarr@foxnet.net or
+ Contact Avery at: apenwarr@bond.net or
RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
**********************
@@ -17,6 +18,12 @@
**********************
+ v2.92 ALPHA (97/02/09)
+ - Code cleanup [Martin Mares <mj@atrey.karlin.mff.cuni.cz>]
+ - Better probing for the COM90xx chipset, although only as
+ a temporary solution until we implement adding of all found
+ devices at once. [mj]
+
v2.91 ALPHA (97/19/08)
- Add counting of octets in/out.
@@ -122,12 +129,13 @@
- Smarter recovery from RECON-during-transmit conditions. (ie.
retransmit immediately)
- 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.
+ - Replace setting of debug level with the "metric" flag hack by
+ something better. SIOCDEVPRIVATE is a good candidate, but it would
+ require an extra user-level utility.
- 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?
+ 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
@@ -154,9 +162,7 @@
*/
static const char *version =
- "arcnet.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
-
-
+ "arcnet.c: v2.92 97/09/02 Avery Pennarun <apenwarr@bond.net> et al.\n";
#include <linux/module.h>
#include <linux/config.h>
@@ -200,16 +206,14 @@
/**************************************************************************/
-/* These are now provided by the chipset driver. There's a performance
+/* These are now provided by the chipset driver. There's a performance
* overhead in using them.
*/
-
#define AINTMASK(x) ((*lp->asetmask)(dev, x))
#define ARCSTATUS ((*lp->astatus)(dev))
#define ACOMMAND(x) ((*lp->acommand)(dev, x))
-
int arcnet_debug=ARCNET_DEBUG;
/* Exported function prototypes */
@@ -235,7 +239,6 @@
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);
@@ -302,10 +305,6 @@
#endif
-
-
-
-
/****************************************************************************
* *
* Packet dumps for debugging *
@@ -334,6 +333,7 @@
}
#endif
+
/* Dump the contents of an ARCnet buffer
*/
#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
@@ -357,8 +357,6 @@
#endif
-
-
/* Setup a struct device for ARCnet. This should really be in net_init.c
* but since there are three different ARCnet devices ANYWAY... <gargle>
*
@@ -385,8 +383,7 @@
dev->pa_mask = 0;
dev->pa_alen = 4;
-
- /* Put in this stuff here, so we don't have to export the symbols
+ /* Put in this stuff here, so we don't have to export the symbols
* to the chipset drivers.
*/
@@ -405,7 +402,6 @@
* *
****************************************************************************/
-
/* Open/initialize the board. This is called sometime after booting when
* the 'ifconfig' program is run.
*
@@ -417,39 +413,33 @@
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);
@@ -467,7 +457,7 @@
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);
@@ -477,27 +467,27 @@
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;
}
@@ -508,7 +498,7 @@
arcnet_close(struct device *dev)
{
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");
@@ -522,36 +512,32 @@
lp->edev->start=0;
#endif
-
/* 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) */
+ SETMASK; /* no IRQ's (except RESET, of course) */
ACOMMAND(NOTXcmd); /* stop transmit */
ACOMMAND(NORXcmd); /* disable receive */
#endif
-
+
/* reset more flags */
- dev->interrupt=0;
+ dev->interrupt=0;
#ifdef CONFIG_ARCNET_ETH
- lp->edev->interrupt=0;
+ lp->edev->interrupt=0;
#endif
#ifdef CONFIG_ARCNET_1051
- lp->sdev->interrupt=0;
+ lp->sdev->interrupt=0;
#endif
-
-
-
/* 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;
@@ -561,7 +547,7 @@
kfree(lp->edev);
lp->edev=NULL;
#endif
-
+
#ifdef CONFIG_ARCNET_1051
/* free the RFC1051-encap protocol device */
lp->sdev->priv=NULL;
@@ -571,17 +557,16 @@
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;
}
-
/****************************************************************************
* *
* Transmitter routines *
@@ -594,24 +579,24 @@
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.
@@ -619,7 +604,7 @@
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",
@@ -628,10 +613,10 @@
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",
@@ -644,17 +629,17 @@
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;
-
+
#ifdef CONFIG_ARCNET_ETH
lp->edev->tbusy=0;
#endif
@@ -666,10 +651,10 @@
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",
@@ -681,10 +666,10 @@
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))
@@ -701,7 +686,7 @@
#ifdef CONFIG_ARCNET_ETH
lp->edev->tbusy=1;
#endif
-
+
return 0;
}
@@ -714,13 +699,13 @@
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)
{
@@ -729,20 +714,20 @@
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)
{
@@ -759,12 +744,12 @@
((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 */
@@ -774,19 +759,19 @@
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
@@ -799,7 +784,7 @@
arcnet_go_tx(dev,1);
}
}
-
+
/* if segnum==numsegs, the transmission is finished;
* free the skb right away.
*/
@@ -816,14 +801,14 @@
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;
}
@@ -837,38 +822,38 @@
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++;
@@ -936,30 +921,29 @@
{
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))
{
@@ -1000,7 +984,7 @@
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);
}
}
@@ -1012,7 +996,7 @@
* *
****************************************************************************/
-/*
+/*
* This is a generic packet receiver that calls arcnet??_rx depending on the
* protocol ID found.
*/
@@ -1020,10 +1004,10 @@
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])
{
@@ -1059,13 +1043,13 @@
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.
*/
-
-
+
+
}
@@ -1079,33 +1063,33 @@
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",
@@ -1117,9 +1101,9 @@
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");
@@ -1127,16 +1111,16 @@
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)
@@ -1146,12 +1130,12 @@
{
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",
@@ -1173,9 +1157,9 @@
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);
@@ -1198,12 +1182,12 @@
* 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",
@@ -1215,7 +1199,7 @@
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",
@@ -1229,11 +1213,11 @@
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",
@@ -1242,7 +1226,7 @@
lp->stats.rx_length_errors++;
return;
}
-
+
in->skb=skb=alloc_skb(508*in->numpackets
+ sizeof(struct ClientData),
GFP_ATOMIC);
@@ -1251,12 +1235,12 @@
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);
@@ -1265,7 +1249,7 @@
else /* not first packet */
{
int packetnum=((unsigned)arcsoft->split_flag>>1) + 1;
-
+
/* if we're not assembling, there's no point
* trying to continue.
*/
@@ -1280,7 +1264,7 @@
}
return;
}
-
+
in->lastpacket++;
if (packetnum!=in->lastpacket) /* not the right flag! */
{
@@ -1293,7 +1277,7 @@
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,
@@ -1306,20 +1290,20 @@
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)
{
@@ -1332,9 +1316,9 @@
{
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);
@@ -1344,15 +1328,12 @@
}
-
-
/****************************************************************************
* *
* Miscellaneous routines *
* *
****************************************************************************/
-
/* Get the current statistics. This may be called with the card open or
* closed.
*/
@@ -1360,7 +1341,7 @@
static struct net_device_stats *arcnet_get_stats(struct device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
+
return &lp->stats;
}
@@ -1376,12 +1357,12 @@
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)
{
@@ -1409,7 +1390,7 @@
lp->stats.tx_aborted_errors++;
return 0;
}
-
+
/*
* Set the source hardware address.
*
@@ -1422,10 +1403,10 @@
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)
{
@@ -1434,12 +1415,11 @@
}
else
head->daddr=0; /* better fill one in anyway */
-
+
return -dev->hard_header_len;
}
-
/* Rebuild the ARCnet ClientData header. This is called after an ARP
* (or in future other address resolution) has completed on this
* sk_buff. We now let ARP fill in the other fields.
@@ -1450,13 +1430,13 @@
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",
@@ -1467,7 +1447,7 @@
/*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
return 0;
}
-
+
/*
* Try to get ARP to resolve the header.
*/
@@ -1492,12 +1472,12 @@
{
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)
@@ -1506,14 +1486,14 @@
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);
@@ -1522,7 +1502,7 @@
lp->stats.rx_crc_errors++;
return 0;
}
-
+
return htons(ETH_P_IP);
}
@@ -1539,7 +1519,7 @@
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;
@@ -1547,7 +1527,7 @@
dev->open=arcnetE_open_close;
dev->stop=arcnetE_open_close;
dev->hard_start_xmit=arcnetE_send_packet;
-
+
return 0;
}
@@ -1571,13 +1551,13 @@
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)
{
@@ -1586,31 +1566,31 @@
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 */
@@ -1621,17 +1601,13 @@
{
offset-=256;
}
-
+
BUGMSG(D_DURING," length=%Xh, offset=%Xh\n",
length,offset);
-
-
- (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0,
+ (*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))
@@ -1639,7 +1615,7 @@
/* inform upper layers */
arcnet_tx_done(lp->adev, lp);
}
-
+
dev->trans_start=jiffies;
lp->intx--;
@@ -1697,9 +1673,9 @@
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);
@@ -1710,7 +1686,7 @@
dev->hard_start_xmit=arcnetS_send_packet;
dev->hard_header=arcnetS_header;
dev->rebuild_header=arcnetS_rebuild_header;
-
+
return 0;
}
@@ -1732,9 +1708,9 @@
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)
{
@@ -1743,11 +1719,11 @@
}
/* 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)
{
@@ -1757,10 +1733,10 @@
skb->data+sizeof(struct S_ClientData),
length-sizeof(struct S_ClientData),
hdr->daddr,0,0);
-
+
/* done right away */
dev_kfree_skb(skb,FREE_WRITE);
-
+
if (arcnet_go_tx(dev,1))
{
/* inform upper layers */
@@ -1775,14 +1751,14 @@
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;
}
@@ -1796,17 +1772,15 @@
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");
@@ -1823,9 +1797,9 @@
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);
@@ -1844,7 +1818,7 @@
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)
{
@@ -1863,7 +1837,7 @@
lp->stats.tx_aborted_errors++;
return 0;
}
-
+
/*
* Set the source hardware address.
*
@@ -1876,7 +1850,7 @@
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)
{
@@ -1885,7 +1859,7 @@
}
else
head->daddr=0; /* better fill one in anyway */
-
+
return -dev->hard_header_len;
}
@@ -1899,11 +1873,11 @@
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",
@@ -1914,7 +1888,7 @@
/*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
return 0;
}
-
+
/*
* Try to get ARP to resolve the header.
*/
@@ -1934,12 +1908,12 @@
{
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)
@@ -1948,7 +1922,7 @@
if (head->daddr != dev->dev_addr[0])
skb->pkt_type=PACKET_OTHERHOST;
}
-
+
/* now return the protocol number */
switch (head->protocol_id)
{
@@ -1960,20 +1934,19 @@
lp->stats.rx_crc_errors++;
return 0;
}
-
+
return htons(ETH_P_IP);
}
#endif /* CONFIG_ARCNET_1051 */
+
/****************************************************************************
* *
* Kernel Loadable Module Support *
* *
****************************************************************************/
-
-
#ifdef MODULE
void cleanup_module(void)
@@ -1982,7 +1955,7 @@
}
void arcnet_use_count(int open)
-{
+{
if (open)
MOD_INC_USE_COUNT;
else
@@ -1999,14 +1972,14 @@
int arcnet_num_devs=0;
char arcnet_dev_names[MAX_ARCNET_DEVS][10];
-void arcnet_init(void)
+__initfunc(void arcnet_init(void))
{
int c;
-
- (void) init_module();
+
+ init_module();
/* Don't register_netdev here. The chain hasn't been initialised. */
-
+
#ifdef CONFIG_ARCNET_COM90xx
if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS)
{
@@ -2020,7 +1993,7 @@
if (!arcnet_num_devs)
{
printk("Don't forget to load the chipset driver.\n");
- return;
+ return;
}
/* Link into the device chain */
@@ -2033,20 +2006,24 @@
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]);
-
}
-static
+
#endif /* MODULE */
-int init_module()
+
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(static int init_module(void))
+#endif
{
-
-#if 1
+#ifdef ALPHA_WARNING
BUGLVL(D_EXTRA)
{
printk("arcnet: ***\n");
@@ -2058,8 +2035,7 @@
}
#endif
- printk("%sGeneric arcnet support for Linux kernel.\n"
- "Available protocols: ARCnet RFC1201"
+ printk("%sAvailable protocols: ARCnet RFC1201"
#ifdef CONFIG_ARCNET_ETH
", Ethernet-Encap"
#endif
@@ -2074,50 +2050,20 @@
}
-
-
-
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
+ arcnum = 0;
+ for (;;)
{
- printk (KERN_INFO "arcnet: Can't find name for device\n");
- sprintf (device, "arc???");
+ sprintf(device, "arc%d", arcnum);
+ for (dev = dev_base; dev; dev=dev->next)
+ if (dev->name != device && !strcmp(dev->name, device))
+ break;
+ if (!dev)
+ return;
+ arcnum++;
}
}
-
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov