patch-2.4.0-test2 linux/drivers/net/sk_mca.c
Next file: linux/drivers/net/sk_mca.h
Previous file: linux/drivers/net/sk_g16.c
Back to the patch index
Back to the overall index
- Lines: 874
- Date:
Mon Jun 19 13:42:38 2000
- Orig file:
v2.4.0-test1/linux/drivers/net/sk_mca.c
- Orig date:
Thu May 11 15:30:07 2000
diff -u --recursive --new-file v2.4.0-test1/linux/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c
@@ -62,14 +62,25 @@
implemented LANCE multicast filter
Jun 6th, 1999
additions for Linux 2.2
- Aug 2nd, 1999
- small fixes (David Weinehall)
+ Dec 25th, 1999
+ unfortunately there seem to be newer MC2+ boards that react
+ on IRQ 3/5/9/10 instead of 3/5/10/11, so we have to autoprobe
+ in questionable cases...
+ Dec 28th, 1999
+ integrated patches from David Weinehall & Bill Wendling for 2.3
+ kernels (isa_...functions). Things are defined in a way that
+ it still works with 2.0.x 8-)
+ Dec 30th, 1999
+ added handling of the remaining interrupt conditions. That
+ should cure the spurious hangs.
+ Jan 30th, 2000
+ newer kernels automatically probe more than one board, so the
+ 'startslot' as a variable is also needed here
+ June 1st, 2000
+ added changes for recent 2.3 kernels
*************************************************************************/
-#include <linux/module.h>
-#include <linux/version.h>
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
@@ -84,6 +95,11 @@
#include <asm/bitops.h>
#include <asm/io.h>
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif
+
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
@@ -96,11 +112,11 @@
* have to pack all state info into the device struct!
* ------------------------------------------------------------------------ */
-static char *MediaNames[Media_Count] = {
- "10Base2", "10BaseT", "10Base5", "Unknown" };
+static char *MediaNames[Media_Count] =
+ { "10Base2", "10BaseT", "10Base5", "Unknown" };
-static unsigned char poly[] = {
- 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0,
+static unsigned char poly[] =
+ { 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0
};
@@ -111,14 +127,14 @@
/* dump parts of shared memory - only needed during debugging */
#ifdef DEBUG
-static void dumpmem(struct net_device *dev, u32 start, u32 len)
+static void dumpmem(struct SKMCA_NETDEV *dev, u32 start, u32 len)
{
int z;
for (z = 0; z < len; z++) {
if ((z & 15) == 0)
printk("%04x:", z);
- printk(" %02x", readb(dev->mem_start + start + z));
+ printk(" %02x", SKMCA_READB(dev->mem_start + start + z));
if ((z & 15) == 15)
printk("\n");
}
@@ -133,7 +149,6 @@
do_gettimeofday(&tv);
printk("%9d:%06d: ", tv.tv_sec, tv.tv_usec);
}
-
#endif
/* deduce resources out of POS registers */
@@ -169,10 +184,10 @@
*irq = 5;
break;
case 8:
- *irq = 10;
+ *irq = -10;
break;
case 12:
- *irq = 11;
+ *irq = -11;
break;
}
*medium = (pos2 >> 6) & 3;
@@ -205,18 +220,37 @@
/* reset the whole board */
-static void ResetBoard(struct net_device *dev)
+static void ResetBoard(struct SKMCA_NETDEV *dev)
{
skmca_priv *priv = (skmca_priv *) dev->priv;
- writeb(CTRL_RESET_ON, priv->ctrladdr);
+ SKMCA_WRITEB(CTRL_RESET_ON, priv->ctrladdr);
udelay(10);
- writeb(CTRL_RESET_OFF, priv->ctrladdr);
+ SKMCA_WRITEB(CTRL_RESET_OFF, priv->ctrladdr);
+}
+
+/* wait for LANCE interface to become not busy */
+
+static int WaitLANCE(struct SKMCA_NETDEV *dev)
+{
+ skmca_priv *priv = (skmca_priv *) dev->priv;
+ int t = 0;
+
+ while ((SKMCA_READB(priv->ctrladdr) & STAT_IO_BUSY) ==
+ STAT_IO_BUSY) {
+ udelay(1);
+ if (++t > 1000) {
+ printk("%s: LANCE access timeout", dev->name);
+ return 0;
+ }
+ }
+
+ return 1;
}
/* set LANCE register - must be atomic */
-static void SetLANCE(struct net_device *dev, u16 addr, u16 value)
+static void SetLANCE(struct SKMCA_NETDEV *dev, u16 addr, u16 value)
{
skmca_priv *priv = (skmca_priv *) dev->priv;
unsigned long flags;
@@ -228,25 +262,25 @@
/* wait until no transfer is pending */
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ WaitLANCE(dev);
/* transfer register address to RAP */
- writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
- priv->ctrladdr);
- writew(addr, priv->ioregaddr);
- writeb(IOCMD_GO, priv->cmdaddr);
+ SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
+ priv->ctrladdr);
+ SKMCA_WRITEW(addr, priv->ioregaddr);
+ SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
udelay(1);
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ WaitLANCE(dev);
/* transfer data to register */
- writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA,
- priv->ctrladdr);
- writew(value, priv->ioregaddr);
- writeb(IOCMD_GO, priv->cmdaddr);
+ SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA,
+ priv->ctrladdr);
+ SKMCA_WRITEW(value, priv->ioregaddr);
+ SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
udelay(1);
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ WaitLANCE(dev);
/* reenable interrupts */
@@ -255,7 +289,7 @@
/* get LANCE register */
-static u16 GetLANCE(struct net_device *dev, u16 addr)
+static u16 GetLANCE(struct SKMCA_NETDEV *dev, u16 addr)
{
skmca_priv *priv = (skmca_priv *) dev->priv;
unsigned long flags;
@@ -268,25 +302,25 @@
/* wait until no transfer is pending */
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ WaitLANCE(dev);
/* transfer register address to RAP */
- writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
- priv->ctrladdr);
- writew(addr, priv->ioregaddr);
- writeb(IOCMD_GO, priv->cmdaddr);
+ SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
+ priv->ctrladdr);
+ SKMCA_WRITEW(addr, priv->ioregaddr);
+ SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
udelay(1);
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ WaitLANCE(dev);
/* transfer data from register */
- writeb(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA,
- priv->ctrladdr);
- writeb(IOCMD_GO, priv->cmdaddr);
+ SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA,
+ priv->ctrladdr);
+ SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
udelay(1);
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
- res = readw(priv->ioregaddr);
+ WaitLANCE(dev);
+ res = SKMCA_READW(priv->ioregaddr);
/* reenable interrupts */
@@ -297,7 +331,7 @@
/* build up descriptors in shared RAM */
-static void InitDscrs(struct net_device *dev)
+static void InitDscrs(struct SKMCA_NETDEV *dev)
{
u32 bufaddr;
@@ -314,11 +348,11 @@
descr.Flags = 0;
descr.Len = 0xf000;
descr.Status = 0;
- isa_memcpy_toio(dev->mem_start + RAM_TXBASE +
- (z * sizeof(LANCE_TxDescr)),
- &descr, sizeof(LANCE_TxDescr));
- memset_io(dev->mem_start + bufaddr, 0,
- RAM_BUFSIZE);
+ SKMCA_TOIO(dev->mem_start + RAM_TXBASE +
+ (z * sizeof(LANCE_TxDescr)), &descr,
+ sizeof(LANCE_TxDescr));
+ SKMCA_SETIO(dev->mem_start + bufaddr, 0,
+ RAM_BUFSIZE);
bufaddr += RAM_BUFSIZE;
}
}
@@ -334,11 +368,11 @@
descr.Flags = RXDSCR_FLAGS_OWN;
descr.MaxLen = -RAM_BUFSIZE;
descr.Len = 0;
- isa_memcpy_toio(dev->mem_start + RAM_RXBASE +
- (z * sizeof(LANCE_RxDescr)),
- &descr, sizeof(LANCE_RxDescr));
- isa_memset_io(dev->mem_start + bufaddr, 0,
- RAM_BUFSIZE);
+ SKMCA_TOIO(dev->mem_start + RAM_RXBASE +
+ (z * sizeof(LANCE_RxDescr)), &descr,
+ sizeof(LANCE_RxDescr));
+ SKMCA_SETIO(dev->mem_start + bufaddr, 0,
+ RAM_BUFSIZE);
bufaddr += RAM_BUFSIZE;
}
}
@@ -393,7 +427,7 @@
/* feed ready-built initialization block into LANCE */
-static void InitLANCE(struct net_device *dev)
+static void InitLANCE(struct SKMCA_NETDEV *dev)
{
skmca_priv *priv = (skmca_priv *) dev->priv;
@@ -423,8 +457,12 @@
/* we don't get ready until the LANCE has read the init block */
+#if (LINUX_VERSION_CODE >= 0x02032a)
netif_stop_queue(dev);
-
+#else
+ dev->tbusy = 1;
+#endif
+
/* let LANCE read the initialization block. LANCE is ready
when we receive the corresponding interrupt. */
@@ -433,12 +471,16 @@
/* stop the LANCE so we can reinitialize it */
-static void StopLANCE(struct net_device *dev)
+static void StopLANCE(struct SKMCA_NETDEV *dev)
{
/* can't take frames any more */
+#if (LINUX_VERSION_CODE >= 0x02032a)
netif_stop_queue(dev);
-
+#else
+ dev->tbusy = 1;
+#endif
+
/* disable interrupts, stop it */
SetLANCE(dev, LANCE_CSR0, CSR0_STOP);
@@ -446,7 +488,7 @@
/* initialize card and LANCE for proper operation */
-static void InitBoard(struct net_device *dev)
+static void InitBoard(struct SKMCA_NETDEV *dev)
{
LANCE_InitBlock block;
@@ -462,8 +504,7 @@
block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29);
block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29);
- isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block,
- sizeof(block));
+ SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
/* initialize LANCE. Implicitly sets up other structures in RAM. */
@@ -472,7 +513,7 @@
/* deinitialize card and LANCE */
-static void DeinitBoard(struct net_device *dev)
+static void DeinitBoard(struct SKMCA_NETDEV *dev)
{
/* stop LANCE */
@@ -483,44 +524,97 @@
ResetBoard(dev);
}
+/* probe for device's irq */
+
+static int ProbeIRQ(struct SKMCA_NETDEV *dev)
+{
+ unsigned long imaskval, njiffies, irq;
+ u16 csr0val;
+
+ /* enable all interrupts */
+
+ imaskval = probe_irq_on();
+
+ /* initialize the board. Wait for interrupt 'Initialization done'. */
+
+ ResetBoard(dev);
+ InitBoard(dev);
+
+ njiffies = jiffies + 100;
+ do {
+ csr0val = GetLANCE(dev, LANCE_CSR0);
+ }
+ while (((csr0val & CSR0_IDON) == 0) && (jiffies != njiffies));
+
+ /* turn of interrupts again */
+
+ irq = probe_irq_off(imaskval);
+
+ /* if we found something, ack the interrupt */
+
+ if (irq)
+ SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_IDON);
+
+ /* back to idle state */
+
+ DeinitBoard(dev);
+
+ return irq;
+}
+
/* ------------------------------------------------------------------------
* interrupt handler(s)
* ------------------------------------------------------------------------ */
-/* LANCE has read initializazion block -> start it */
+/* LANCE has read initialization block -> start it */
-static u16 irqstart_handler(struct net_device *dev, u16 oldcsr0)
+static u16 irqstart_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0)
{
/* now we're ready to transmit */
+#if (LINUX_VERSION_CODE >= 0x02032a)
netif_wake_queue(dev);
-
+#else
+ dev->tbusy = 0;
+#endif
+
/* reset IDON bit, start LANCE */
SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_IDON | CSR0_STRT);
return GetLANCE(dev, LANCE_CSR0);
}
+/* did we loose blocks due to a FIFO overrun ? */
+
+static u16 irqmiss_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0)
+{
+ skmca_priv *priv = (skmca_priv *) dev->priv;
+
+ /* update statistics */
+
+ priv->stat.rx_fifo_errors++;
+
+ /* reset MISS bit */
+
+ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_MISS);
+ return GetLANCE(dev, LANCE_CSR0);
+}
+
/* receive interrupt */
-static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0)
+static u16 irqrx_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0)
{
skmca_priv *priv = (skmca_priv *) dev->priv;
LANCE_RxDescr descr;
unsigned int descraddr;
- /* did we loose blocks due to a FIFO overrun ? */
-
- if (oldcsr0 & CSR0_MISS)
- priv->stat.rx_fifo_errors++;
-
/* run through queue until we reach a descriptor we do not own */
descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr));
while (1) {
/* read descriptor */
- isa_memcpy_fromio(&descr, dev->mem_start + descraddr,
- sizeof(LANCE_RxDescr));
+ SKMCA_FROMIO(&descr, dev->mem_start + descraddr,
+ sizeof(LANCE_RxDescr));
/* if we reach a descriptor we do not own, we're done */
if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0)
@@ -551,10 +645,9 @@
if (skb == NULL)
priv->stat.rx_dropped++;
else {
- isa_memcpy_fromio(skb_put(skb, descr.Len),
- dev->mem_start +
- descr.LowAddr,
- descr.Len);
+ SKMCA_FROMIO(skb_put(skb, descr.Len),
+ dev->mem_start +
+ descr.LowAddr, descr.Len);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_NONE;
@@ -571,8 +664,8 @@
descr.Flags |= RXDSCR_FLAGS_OWN;
/* update descriptor in shared RAM */
- isa_memcpy_toio(dev->mem_start + descraddr, &descr,
- sizeof(LANCE_RxDescr));
+ SKMCA_TOIO(dev->mem_start + descraddr, &descr,
+ sizeof(LANCE_RxDescr));
/* go to next descriptor */
priv->nextrx++;
@@ -591,7 +684,7 @@
/* transmit interrupt */
-static u16 irqtx_handler(struct net_device *dev, u16 oldcsr0)
+static u16 irqtx_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0)
{
skmca_priv *priv = (skmca_priv *) dev->priv;
LANCE_TxDescr descr;
@@ -603,8 +696,8 @@
RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr));
while (priv->txbusy > 0) {
/* read descriptor */
- isa_memcpy_fromio(&descr, dev->mem_start + descraddr,
- sizeof(LANCE_TxDescr));
+ SKMCA_FROMIO(&descr, dev->mem_start + descraddr,
+ sizeof(LANCE_TxDescr));
/* if the LANCE still owns this one, we've worked out all sent packets */
if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0)
@@ -653,9 +746,15 @@
/* at least one descriptor is freed. Therefore we can accept
a new one */
+ /* inform upper layers we're in business again */
+#if (LINUX_VERSION_CODE >= 0x02032a)
netif_wake_queue(dev);
-
+#else
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+#endif
+
return oldcsr0;
}
@@ -663,7 +762,7 @@
static void irq_handler(int irq, void *device, struct pt_regs *regs)
{
- struct net_device *dev = (struct net_device *) device;
+ struct SKMCA_NETDEV *dev = (struct SKMCA_NETDEV *) device;
u16 csr0val;
/* read CSR0 to get interrupt cause */
@@ -675,6 +774,14 @@
if ((csr0val & CSR0_INTR) == 0)
return;
+#if (LINUX_VERSION_CODE >= 0x02032a)
+#if 0
+ set_bit(LINK_STATE_RXSEM, &dev->state);
+#endif
+#else
+ dev->interrupt = 1;
+#endif
+
/* loop through the interrupt bits until everything is clear */
do {
@@ -682,10 +789,28 @@
csr0val = irqstart_handler(dev, csr0val);
if ((csr0val & CSR0_RINT) != 0)
csr0val = irqrx_handler(dev, csr0val);
+ if ((csr0val & CSR0_MISS) != 0)
+ csr0val = irqmiss_handler(dev, csr0val);
if ((csr0val & CSR0_TINT) != 0)
csr0val = irqtx_handler(dev, csr0val);
+ if ((csr0val & CSR0_MERR) != 0) {
+ SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_MERR);
+ csr0val = GetLANCE(dev, LANCE_CSR0);
+ }
+ if ((csr0val & CSR0_BABL) != 0) {
+ SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_BABL);
+ csr0val = GetLANCE(dev, LANCE_CSR0);
+ }
}
while ((csr0val & CSR0_INTR) != 0);
+
+#if (LINUX_VERSION_CODE >= 0x02032a)
+#if 0
+ clear_bit(LINK_STATE_RXSEM, &dev->state);
+#endif
+#else
+ dev->interrupt = 0;
+#endif
}
/* ------------------------------------------------------------------------
@@ -697,7 +822,7 @@
static int skmca_getinfo(char *buf, int slot, void *d)
{
int len = 0, i;
- struct net_device *dev = (struct net_device *) d;
+ struct SKMCA_NETDEV *dev = (struct SKMCA_NETDEV *) d;
skmca_priv *priv;
/* can't say anything about an uninitialized device... */
@@ -728,7 +853,7 @@
/* open driver. Means also initialization and start of LANCE */
-static int skmca_open(struct net_device *dev)
+static int skmca_open(struct SKMCA_NETDEV *dev)
{
int result;
skmca_priv *priv = (skmca_priv *) dev->priv;
@@ -745,8 +870,19 @@
dev->irq = priv->realirq;
/* set up the card and LANCE */
+
InitBoard(dev);
+ /* set up flags */
+
+#if (LINUX_VERSION_CODE >= 0x02032a)
+ netif_start_queue(dev);
+#else
+ dev->interrupt = 0;
+ dev->tbusy = 0;
+ dev->start = 0;
+#endif
+
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
@@ -756,7 +892,7 @@
/* close driver. Shut down board and free allocated resources */
-static int skmca_close(struct net_device *dev)
+static int skmca_close(struct SKMCA_NETDEV *dev)
{
/* turn off board */
DeinitBoard(dev);
@@ -775,7 +911,7 @@
/* transmit a block. */
-static int skmca_tx(struct sk_buff *skb, struct net_device *dev)
+static int skmca_tx(struct sk_buff *skb, struct SKMCA_NETDEV *dev)
{
skmca_priv *priv = (skmca_priv *) dev->priv;
LANCE_TxDescr descr;
@@ -783,8 +919,15 @@
int tmplen, retval = 0;
unsigned long flags;
- netif_stop_queue(dev);
-
+ /* if we get called with a NULL descriptor, the Ethernet layer thinks
+ our card is stuck an we should reset it. We'll do this completely: */
+
+ if (skb == NULL) {
+ DeinitBoard(dev);
+ InitBoard(dev);
+ return 0; /* don't try to free the block here ;-) */
+ }
+
/* is there space in the Tx queue ? If no, the upper layer gave us a
packet in spite of us not being ready and is really in trouble.
We'll do the dropping for him: */
@@ -796,8 +939,8 @@
/* get TX descriptor */
address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr));
- isa_memcpy_fromio(&descr, dev->mem_start + address,
- sizeof(LANCE_TxDescr));
+ SKMCA_FROMIO(&descr, dev->mem_start + address,
+ sizeof(LANCE_TxDescr));
/* enter packet length as 2s complement - assure minimum length */
tmplen = skb->len;
@@ -813,15 +956,14 @@
unsigned int destoffs = 0, l = strlen(fill);
while (destoffs < tmplen) {
- isa_memcpy_toio(dev->mem_start + descr.LowAddr +
- destoffs, fill, l);
+ SKMCA_TOIO(dev->mem_start + descr.LowAddr +
+ destoffs, fill, l);
destoffs += l;
}
}
/* do the real data copying */
- isa_memcpy_toio(dev->mem_start + descr.LowAddr, skb->data,
- skb->len);
+ SKMCA_TOIO(dev->mem_start + descr.LowAddr, skb->data, skb->len);
/* hand descriptor over to LANCE - this is the first and last chunk */
descr.Flags =
@@ -840,12 +982,19 @@
if (priv->nexttxput >= TXCOUNT)
priv->nexttxput = 0;
priv->txbusy++;
- if (priv->txbusy < TXCOUNT)
- netif_wake_queue(dev);
+
+ /* are we saturated ? */
+
+ if (priv->txbusy >= TXCOUNT)
+#if (LINUX_VERSION_CODE >= 0x02032a)
+ netif_stop_queue(dev);
+#else
+ dev->tbusy = 1;
+#endif
/* write descriptor back to RAM */
- isa_memcpy_toio(dev->mem_start + address, &descr,
- sizeof(LANCE_TxDescr));
+ SKMCA_TOIO(dev->mem_start + address, &descr,
+ sizeof(LANCE_TxDescr));
/* if no descriptors were active, give the LANCE a hint to read it
immediately */
@@ -855,24 +1004,31 @@
restore_flags(flags);
-tx_done:
+ tx_done:
+
/* When did that change exactly ? */
+
+#if LINUX_VERSION_CODE >= 0x020200
dev_kfree_skb(skb);
+#else
+ dev_kfree_skb(skb, FREE_WRITE);
+#endif
return retval;
}
/* return pointer to Ethernet statistics */
-static struct enet_statistics *skmca_stats(struct net_device *dev)
+static struct enet_statistics *skmca_stats(struct SKMCA_NETDEV *dev)
{
skmca_priv *priv = (skmca_priv *) dev->priv;
+
return &(priv->stat);
}
/* we don't support runtime reconfiguration, since an MCA card can
be unambigously identified by its POS registers. */
-static int skmca_config(struct net_device *dev, struct ifmap *map)
+static int skmca_config(struct SKMCA_NETDEV *dev, struct ifmap *map)
{
return 0;
}
@@ -880,7 +1036,7 @@
/* switch receiver mode. We use the LANCE's multicast filter to prefilter
multicast addresses. */
-static void skmca_set_multicast_list(struct net_device *dev)
+static void skmca_set_multicast_list(struct SKMCA_NETDEV *dev)
{
LANCE_InitBlock block;
@@ -888,8 +1044,7 @@
StopLANCE(dev);
/* ...then modify the initialization block... */
- isa_memcpy_fromio(&block, dev->mem_start + RAM_INITBASE,
- sizeof(block));
+ SKMCA_FROMIO(&block, dev->mem_start + RAM_INITBASE, sizeof(block));
if (dev->flags & IFF_PROMISC)
block.Mode |= LANCE_INIT_PROM;
else
@@ -909,8 +1064,7 @@
}
}
- isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block,
- sizeof(block));
+ SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
/* ...then reinit LANCE with the correct flags */
InitLANCE(dev);
@@ -920,13 +1074,9 @@
* hardware check
* ------------------------------------------------------------------------ */
-#ifdef MODULE
static int startslot; /* counts through slots when probing multiple devices */
-#else
-#define startslot 0 /* otherwise a dummy, since there is only eth0 in-kern */
-#endif
-int skmca_probe(struct net_device *dev)
+int skmca_probe(struct SKMCA_NETDEV *dev)
{
int force_detect = 0;
int junior, slot, i;
@@ -937,7 +1087,7 @@
/* can't work without an MCA bus ;-) */
if (MCA_bus == 0)
- return ENODEV;
+ return -ENODEV;
/* start address of 1 --> forced detection */
@@ -957,7 +1107,7 @@
getaddrs(slot, junior, &base, &irq, &medium);
-#if LINUX_VERSION_CODE >= 0x020200
+#if LINUX_VERSION_CODE >= 0x020300
/* slot already in use ? */
if (mca_is_adapter_used(slot)) {
@@ -1015,7 +1165,6 @@
priv->ioregaddr = base + 0x3ff0;
priv->ctrladdr = base + 0x3ff2;
priv->cmdaddr = base + 0x3ff3;
- priv->realirq = irq;
priv->medium = medium;
memset(&(priv->stat), 0, sizeof(struct enet_statistics));
@@ -1024,6 +1173,22 @@
dev->mem_start = base;
dev->mem_end = base + 0x4000;
+ /* autoprobe ? */
+ if (irq < 0) {
+ int nirq;
+
+ printk
+ ("%s: ambigous POS bit combination, must probe for IRQ...\n",
+ dev->name);
+ nirq = ProbeIRQ(dev);
+ if (nirq <= 0)
+ printk("%s: IRQ probe failed, assuming IRQ %d",
+ dev->name, priv->realirq = -irq);
+ else
+ priv->realirq = nirq;
+ } else
+ priv->realirq = irq;
+
/* set methods */
dev->open = skmca_open;
dev->stop = skmca_close;
@@ -1039,7 +1204,7 @@
/* copy out MAC address */
for (i = 0; i < 6; i++)
- dev->dev_addr[i] = readb(priv->macbase + (i << 1));
+ dev->dev_addr[i] = SKMCA_READB(priv->macbase + (i << 1));
/* print config */
printk("%s: IRQ %d, memory %#lx-%#lx, "
@@ -1053,9 +1218,7 @@
ResetBoard(dev);
-#ifdef MODULE
startslot = slot + 1;
-#endif
return 0;
}
@@ -1068,13 +1231,24 @@
#define DEVMAX 5
-static struct net_device moddevs[DEVMAX] =
- { {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
-{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
-{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
-{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
-{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}
+#if (LINUX_VERSION_CODE >= 0x020369)
+static struct SKMCA_NETDEV moddevs[DEVMAX] =
+ { {" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}
};
+#else
+static char NameSpace[8 * DEVMAX];
+static struct SKMCA_NETDEV moddevs[DEVMAX] =
+ { {NameSpace + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{NameSpace + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}
+};
+#endif
int irq = 0;
int io = 0;
@@ -1096,7 +1270,7 @@
void cleanup_module(void)
{
- struct net_device *dev;
+ struct SKMCA_NETDEV *dev;
skmca_priv *priv;
int z;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)