patch-2.1.54 linux/drivers/net/com90io.c
Next file: linux/drivers/net/com90xx.c
Previous file: linux/drivers/net/com20020.c
Back to the patch index
Back to the overall index
- Lines: 904
- Date:
Sat Sep 6 10:05:42 1997
- Orig file:
v2.1.53/linux/drivers/net/com90io.c
- Orig date:
Thu Sep 4 17:07:30 1997
diff -u --recursive --new-file v2.1.53/linux/drivers/net/com90io.c linux/drivers/net/com90io.c
@@ -1,11 +1,12 @@
-/* com90io.c:
+/* $Id: com90io.c,v 1.2 1997/09/05 08:57:52 mj Exp $
+
Written 1997 by David Woodhouse <dwmw2@cam.ac.uk>
Derived from the original arcnet.c,
Written 1994-1996 by Avery Pennarun,
which was in turn 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
**********************
@@ -59,36 +60,6 @@
#include <net/arp.h>
-
-
-
-/* External functions from arcnet.c */
-
-
-
-#if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
- char *desc);
-#else
-#define arcnet_dump_skb(dev,skb,desc) ;
-#endif
-
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
- char *desc);
-#else
-#define arcnet_dump_packet(dev,buffer,ext,desc) ;
-#endif
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
-extern void arcnet_makename(char *device);
-extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
-extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
-extern void arcnet_use_count(int open);
-
-
/* Internal function declarations */
static int arc90io_probe(struct device *dev);
@@ -127,13 +98,12 @@
#endif
-
/* Handy defines for ARCnet specific stuff */
-/* The number of low I/O ports used by the ethercard. */
+/* The number of low I/O ports used by the card. */
#define ARCNET_TOTAL_SIZE 16
- /* COM 9026 controller chip --> ARCnet register addresses */
+/* 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 (?) */
@@ -149,7 +119,6 @@
#define ARCRESET inb(_RESET)
-
#define SETCONF outb((lp->config),_CONFIG)
@@ -163,7 +132,7 @@
{
int ioaddr=dev->base_addr;
- outb(offset >> 8, _ADDR_HI);
+ outb(offset >> 8, _ADDR_HI);
outb(offset & 0xff, _ADDR_LO);
return inb(_MEMDATA);
@@ -173,7 +142,7 @@
{
int ioaddr=dev->base_addr;
- outb(offset >> 8, _ADDR_HI);
+ outb(offset >> 8, _ADDR_HI);
outb(offset & 0xff, _ADDR_LO);
outb(datum, _MEMDATA);
@@ -204,7 +173,7 @@
outb( (offset >> 8) | AUTOINCflag, _ADDR_HI);
outb( offset & 0xff, _ADDR_LO);
-
+
while (length--)
#ifdef ONE_AT_A_TIME_TX
put_buffer_byte(dev,offset++,*(dest++));
@@ -217,14 +186,13 @@
static const char *version =
"com90io.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
+
/****************************************************************************
* *
* Probe and initialization *
* *
****************************************************************************/
-
-
/* We cannot probe for an IO mapped card either, although we can check that
* it's where we were told it was, and even autoirq
*/
@@ -233,104 +201,100 @@
{
int ioaddr=dev->base_addr,status,delayval;
unsigned long airqmask;
-
+
BUGLVL(D_NORMAL) printk(version);
-
+
if (ioaddr<0x200)
{
BUGMSG(D_NORMAL,"No autoprobe for IO mapped cards; you "
"must specify the base address!\n");
return -ENODEV;
}
-
+
if (check_region(ioaddr, ARCNET_TOTAL_SIZE))
{
BUGMSG(D_INIT_REASONS,"IO check_region %x-%x failed.\n",
ioaddr,ioaddr+ARCNET_TOTAL_SIZE-1);
return -ENXIO;
}
-
+
if (ARCSTATUS == 0xFF)
{
BUGMSG(D_INIT_REASONS,"IO address %x empty\n",ioaddr);
return -ENODEV;
}
-
+
ARCRESET;
JIFFER(RESETtime);
-
+
status=ARCSTATUS;
-
+
if ((status & 0x9D)
!= (NORXflag|RECONflag|TXFREEflag|RESETflag))
{
BUGMSG(D_INIT_REASONS,"Status invalid (%Xh).\n",status);
return -ENODEV;
}
-
-
+
BUGMSG(D_INIT_REASONS,"Status after reset: %X\n",status);
-
-
+
ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
-
+
BUGMSG(D_INIT_REASONS,"Status after reset acknowledged: %X\n",status);
-
+
status=ARCSTATUS;
-
+
if (status & RESETflag)
{
BUGMSG(D_INIT_REASONS,"Eternal reset (status=%Xh)\n",status);
return -ENODEV;
}
-
+
outb((0x16 | IOMAPflag) &~ENABLE16flag, _CONFIG);
-
-
+
/* Read first loc'n of memory */
-
+
outb(AUTOINCflag ,_ADDR_HI);
outb(0,_ADDR_LO);
-
+
if ((status=inb(_MEMDATA)) != 0xd1)
{
BUGMSG(D_INIT_REASONS,"Signature byte not found"
" (%Xh instead).\n", status);
return -ENODEV;
}
-
+
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();
outb(NORXflag,_INTMASK);
udelay(1);
outb(0,_INTMASK);
dev->irq = probe_irq_off(airqmask);
-
+
if (dev->irq<=0)
{
BUGMSG(D_INIT_REASONS,"Autoprobe IRQ failed\n");
return -ENODEV;
}
}
-
+
return arc90io_found(dev,dev->base_addr,dev->irq);
}
-
/* Set up the struct device associated with this card. Called after
* probing succeeds.
*/
__initfunc(int arc90io_found(struct device *dev,int ioaddr,int airq))
{
struct arcnet_local *lp;
-
+
/* reserve the irq */
if (request_irq(airq,&arcnet_interrupt,0,"arcnet (COM90xx-IO)",NULL))
{
@@ -339,17 +303,15 @@
}
irq2dev_map[airq]=dev;
dev->irq=airq;
-
+
/* reserve the I/O region - guaranteed to work by check_region */
request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (COM90xx-IO)");
dev->base_addr=ioaddr;
-
-
+
dev->mem_start=dev->mem_end=dev->rmem_start=dev->rmem_end=(long)NULL;
-
-
+
/* Initialize the rest of the device structure. */
-
+
dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
if (dev->priv == NULL)
{
@@ -363,7 +325,7 @@
lp=(struct arcnet_local *)(dev->priv);
lp->card_type = ARC_90xx_IO;
lp->card_type_str = "COM 90xx (IO)";
-
+
lp->arcnet_reset=arc90io_reset;
lp->asetmask=arc90io_setmask;
lp->astatus=arc90io_status;
@@ -371,33 +333,30 @@
lp->openclose_device=arc90io_openclose;
lp->prepare_tx=arc90io_prepare_tx;
lp->inthandler=arc90io_inthandler;
-
-
-
/* 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);
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 archdr));
-
+
lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag;
SETCONF;
-
+
/* get and check the station ID from offset 1 in shmem */
lp->stationid = get_buffer_byte(dev,1);
-
+
if (!lp->stationid)
BUGMSG(D_NORMAL,"WARNING! Station address 00 is reserved "
"for broadcasts!\n");
@@ -405,19 +364,19 @@
BUGMSG(D_NORMAL,"WARNING! Station address FF may confuse "
"DOS networking programs!\n");
dev->dev_addr[0]=lp->stationid;
-
+
BUGMSG(D_NORMAL,"ARCnet COM90xx in IO-mapped mode: "
"station %02Xh found at %03lXh, IRQ %d.\n",
lp->stationid,
dev->base_addr,dev->irq);
-
+
return 0;
}
/****************************************************************************
* *
- * Utility routines for arcnet.c *
+ * Utility routines *
* *
****************************************************************************/
@@ -433,59 +392,59 @@
struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
short ioaddr=dev->base_addr;
int delayval,recbuf=lp->recbuf;
-
+
if (reset_delay==3)
{
ARCRESET;
return 0;
}
-
+
/* no IRQ's, please! */
lp->intmask=0;
SETMASK;
-
+
BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
dev->name,ARCSTATUS);
-
+
/* Set the thing to IO-mapped, 8-bit mode */
lp->config = (0x1C|IOMAPflag) & ~ENABLE16flag;
SETCONF;
-
+
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 (get_buffer_byte(dev,0) != 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);
-
+
/* 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;
}
@@ -500,11 +459,10 @@
}
-
static void arc90io_setmask(struct device *dev, u_char mask)
{
short ioaddr=dev->base_addr;
-
+
AINTMASK(mask);
}
@@ -530,22 +488,18 @@
arc90io_inthandler(struct device *dev)
{
struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
- int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;
+ int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;
-
-
-
AINTMASK(0);
-
+
BUGMSG(D_DURING,"in arc90io_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.
*/
@@ -554,56 +508,55 @@
BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
status);
arc90io_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;
int oldaddr=0;
-
+
BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
status);
-
+
/* enable receive of our next packet */
EnableReceiver();
-
+
if (lp->intx)
oldaddr=(inb(_ADDR_HI)<<8) | inb(_ADDR_LO);
-
-
+
+
/* Got a packet. */
arc90io_rx(dev,!recbuf);
-
-
+
+
if (lp->intx)
{
outb( (oldaddr >> 8), _ADDR_HI);
outb( oldaddr & 0xff, _ADDR_LO);
}
-
+
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)
@@ -620,11 +573,11 @@
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",
@@ -632,24 +585,24 @@
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) arcnet_tx_done(dev, lp);
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.
*/
@@ -663,12 +616,12 @@
dev_kfree_skb(out->skb,FREE_WRITE);
}
out->skb=NULL;
-
+
/* inform upper layers */
if (!lp->txready) arcnet_tx_done(dev, lp);
}
didsomething++;
-
+
lp->in_txhandler--;
}
else if (lp->txready && !lp->sending && !lp->intx)
@@ -678,21 +631,19 @@
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, config=%X)\n",
status,lp->config);
#endif /* SHOW_RECONFIGS */
-
+
#ifdef RECON_THRESHOLD
/* is the RECON info empty or old? */
if (!lp->first_recon || !lp->last_recon ||
@@ -702,19 +653,19 @@
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;
@@ -746,26 +697,24 @@
BUGMSG(D_NORMAL,"cabling restored?\n");
lp->first_recon=lp->last_recon=0;
lp->num_recons=lp->network_down=0;
-
+
BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
#endif
}
#endif /* DETECT_RECONFIGS */
} while (--boguscount && didsomething);
-
+
BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
ARCSTATUS,boguscount);
BUGMSG(D_DURING,"\n");
-
+
SETMASK; /* put back interrupt mask */
-
}
-
/* A packet has arrived; grab it from the buffers and pass it to the generic
* arcnet_rx routing to deal with it.
- */
+ */
static void
arc90io_rx(struct device *dev,int recbuf)
@@ -777,13 +726,13 @@
u_char *arcsoft;
short length,offset;
u_char daddr,saddr;
-
+
lp->stats.rx_packets++;
-
+
get_whole_buffer(dev,recbuf*512,4,(char *)arcpacket);
-
+
saddr=arcpacket->hardheader.source;
-
+
/* if source is 0, it's a "used" packet! */
if (saddr==0)
{
@@ -793,13 +742,13 @@
return;
}
/* Set source address to zero to mark it as old */
-
+
put_buffer_byte(dev,recbuf*512,0);
-
+
arcpacket->hardheader.source=0;
-
+
daddr=arcpacket->hardheader.destination;
-
+
if (arcpacket->hardheader.offset1) /* Normal Packet */
{
offset=arcpacket->hardheader.offset1;
@@ -812,16 +761,15 @@
arcsoft=&arcpacket->raw[offset];
length=512-offset;
}
-
+
get_whole_buffer(dev,recbuf*512+offset,length,(char *)arcpacket+offset);
-
+
arcnet_rx(lp, arcsoft, length, saddr, daddr);
-
+
BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
}
-
/* Given an skb, copy a packet into the ARCnet buffers for later transmission
* by arcnet_go_tx.
*/
@@ -830,20 +778,20 @@
char *data,int length,int daddr,int exceptA, int offset)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
+
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);
-
+
put_buffer_byte(dev, lp->txbuf*512+1, daddr);
/* load packet into shared memory */
if (length<=MTU) /* Normal (256-byte) Packet */
put_buffer_byte(dev, lp->txbuf*512+2, offset=offset?offset:256-length);
-
+
else if (length>=MinTU || offset) /* Extended (512-byte) Packet */
{
put_buffer_byte(dev, lp->txbuf*512+2, 0);
@@ -853,36 +801,36 @@
{
put_buffer_byte(dev, lp->txbuf*512+2, 0);
put_buffer_byte(dev, lp->txbuf*512+3, offset=512-length-4);
-
+
/* exception-specific stuff - these four bytes
* make the packet long enough to fit in a 512-byte
* frame.
*/
-
+
put_whole_buffer(dev, lp->txbuf*512+offset,4,"\0\0xff\0xff\0xff");
offset+=4;
}
else /* "other" Exception packet */
{
/* RFC1051 - set 4 trailing bytes to 0 */
-
+
put_whole_buffer(dev,lp->txbuf*512+508,4,"\0\0\0\0");
-
+
/* now round up to MinTU */
put_buffer_byte(dev, lp->txbuf*512+2, 0);
put_buffer_byte(dev, lp->txbuf*512+3, offset=512-MinTU);
}
-
+
/* copy the packet into ARCnet shmem
* - the first bytes of ClientData header are skipped
*/
-
+
put_whole_buffer(dev, 512*lp->txbuf+offset, hdrlen,(u_char *)hdr);
put_whole_buffer(dev, 512*lp->txbuf+offset+hdrlen,length-hdrlen,data);
-
+
BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
daddr,length);
-
+
lp->lastload_dest=daddr;
lp->txready=lp->txbuf; /* packet is ready for sending */
}
@@ -904,13 +852,13 @@
int init_module(void)
{
struct device *dev=cards[0];
-
+
cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);
if (!dev)
return -ENOMEM;
-
+
memset(dev, 0, sizeof(struct device));
-
+
dev->name=(char *)kmalloc(9, GFP_KERNEL);
if (!dev->name)
{
@@ -918,19 +866,19 @@
return -ENOMEM;
}
dev->init=arc90io_probe;
-
+
if (device)
strcpy(dev->name,device);
else arcnet_makename(dev->name);
dev->base_addr=io;
dev->irq=irq;
-
+
if (dev->irq==2) dev->irq=9;
-
+
if (register_netdev(dev) != 0)
return -EIO;
-
+
/* Increase use count of arcnet.o */
arcnet_use_count(1);
return 0;
@@ -940,9 +888,9 @@
{
struct device *dev=cards[0];
int ioaddr=dev->base_addr;
-
+
if (dev->start) (*dev->stop)(dev);
-
+
/* Flush TX and disable RX */
if (ioaddr)
{
@@ -954,23 +902,23 @@
driver is loaded later */
outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG);
}
-
+
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;
-
+
/* Decrease use count of arcnet.o */
arcnet_use_count(0);
}
-#else
+#else
__initfunc(void com90io_setup (char *str, int *ints))
{
@@ -982,9 +930,9 @@
MAX_ARCNET_DEVS);
return;
}
-
+
dev=&arcnet_devs[arcnet_num_devs];
-
+
if (ints[0] < 1)
{
printk("com90xx IO-MAP: You must give an IO address.\n");
@@ -1000,20 +948,17 @@
case 2: /* IRQ */
dev->irq=ints[2];
-
+
case 1: /* IO address */
dev->base_addr=ints[1];
}
dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
-
+
if (str)
strncpy(dev->name, str, 9);
-
+
arcnet_num_devs++;
}
#endif /* MODULE */
-
-
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov