summaryrefslogtreecommitdiffstats
path: root/drivers/net/3c523.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/3c523.c')
-rw-r--r--drivers/net/3c523.c142
1 files changed, 88 insertions, 54 deletions
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index d907fe7f3..25daedb2d 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -62,8 +62,8 @@
search the MCA slots until it finds a 3c523 with the specified
parameters.
- This driver should support multiple ethernet cards, but I can't test
- that. If someone would I'd greatly appreciate it.
+ This driver does support multiple ethernet cards when used as a module
+ (up to MAX_3C523_CARDS, the default being 4)
This has been tested with both BNC and TP versions, internal and
external transceivers. Haven't tested with the 64K version (that I
@@ -76,7 +76,12 @@
update to 1.3.59, incorporated multicast diffs from ni52.c
Feb 15th, 1996
added shared irq support
-
+ Apr 1999
+ added support for multiple cards when used as a module
+ added option to disable multicast as is causes problems
+ Ganesh Sittampalam <ganesh.sittampalam@magdalen.oxford.ac.uk>
+ Stuart Adamson <stuart.adamson@compsoc.net>
+
$Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $
*/
@@ -107,6 +112,7 @@
/*************************************************************************/
#define DEBUG /* debug on */
#define SYSBUSVAL 0 /* 1 = 8 Bit, 0 = 16 bit - 3c523 only does 16 bit */
+#undef ELMC_MULTICAST /* Disable multicast support as it is somewhat seriously broken at the moment */
#define make32(ptr16) (p->memtop + (short) (ptr16) )
#define make24(ptr32) ((char *) (ptr32) - p->base)
@@ -180,7 +186,9 @@ static int elmc_open(struct device *dev);
static int elmc_close(struct device *dev);
static int elmc_send_packet(struct sk_buff *, struct device *);
static struct net_device_stats *elmc_get_stats(struct device *dev);
+#ifdef ELMC_MULTICAST
static void set_multicast_list(struct device *dev);
+#endif
/* helper-functions */
static int init586(struct device *dev);
@@ -432,21 +440,19 @@ __initfunc(int elmc_probe(struct device *dev))
while (slot != -1) {
status = mca_read_stored_pos(slot, 2);
+ dev->irq=irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6];
+ dev->base_addr=csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1];
+
/*
If we're trying to match a specified irq or IO address,
we'll reject a match unless it's what we're looking for.
+ Also reject it if the card is already in use.
*/
- if (base_addr || irq) {
- /* we're looking for a card at a particular place */
- if (irq && irq != irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6]) {
- slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
- continue;
- }
- if (base_addr && base_addr != csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1]) {
- slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
- continue;
- }
+ if((irq && irq != dev->irq) || (base_addr && base_addr != dev->base_addr)
+ || check_region(dev->base_addr,ELMC_IO_EXTENT)) {
+ slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
+ continue;
}
/* found what we're looking for... */
break;
@@ -476,9 +482,6 @@ __initfunc(int elmc_probe(struct device *dev))
/* revision is stored in the first 4 bits of the revision register */
revision = inb(dev->base_addr + ELMC_REVISION) & 0xf;
- /* figure out our irq */
- dev->irq = irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6];
-
/* according to docs, we read the interrupt and write it back to
the IRQ select register, since the POST might not configure the IRQ
properly. */
@@ -497,9 +500,6 @@ __initfunc(int elmc_probe(struct device *dev))
break;
}
- /* Our IO address? */
- dev->base_addr = csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1];
-
request_region(dev->base_addr, ELMC_IO_EXTENT, "3c523");
dev->priv = (void *) kmalloc(sizeof(struct priv), GFP_KERNEL);
@@ -565,7 +565,11 @@ __initfunc(int elmc_probe(struct device *dev))
dev->stop = &elmc_close;
dev->get_stats = &elmc_get_stats;
dev->hard_start_xmit = &elmc_send_packet;
+#ifdef ELMC_MULTICAST
dev->set_multicast_list = &set_multicast_list;
+#else
+ dev->set_multicast_list = NULL;
+#endif
ether_setup(dev);
@@ -577,6 +581,10 @@ __initfunc(int elmc_probe(struct device *dev))
That gets done in elmc_open(). I'm not sure that's such a good idea,
but it works, so I'll go with it. */
+#ifndef ELMC_MULTICAST
+ dev->flags&=~IFF_MULTICAST; /* Multicast doesn't work */
+#endif
+
return 0;
}
@@ -1210,6 +1218,7 @@ static struct net_device_stats *elmc_get_stats(struct device *dev)
* Set MC list ..
*/
+#ifdef ELMC_MULTICAST
static void set_multicast_list(struct device *dev)
{
if (!dev->start) {
@@ -1222,60 +1231,85 @@ static void set_multicast_list(struct device *dev)
startrecv586(dev);
dev->start = 1;
}
+#endif
/*************************************************************************/
#ifdef MODULE
-static char devicename[9] = {0,};
+/* Increase if needed ;) */
+#define MAX_3C523_CARDS 4
+/* I'm not sure where this magic 9 comes from */
+#define NAMELEN 9
-static struct device dev_elmc =
-{
- devicename /*"3c523" */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, elmc_probe
+static char devicenames[NAMELEN * MAX_3C523_CARDS] = {0,};
+
+static struct device dev_elmc[MAX_3C523_CARDS] =
+{
+ {
+ NULL /*"3c523" */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL
+ },
};
-static int irq = 0;
-static int io = 0;
-MODULE_PARM(irq, "i");
-MODULE_PARM(io, "i");
+static int irq[MAX_3C523_CARDS] = {0,};
+static int io[MAX_3C523_CARDS] = {0,};
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i");
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i");
int init_module(void)
{
- struct device *dev = &dev_elmc;
-
- dev->base_addr = io;
- dev->irq = irq;
- if (register_netdev(dev) != 0) {
- return -EIO;
+ int this_dev,found = 0;
+
+ /* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */
+ for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++)
+ {
+ struct device *dev = &dev_elmc[this_dev];
+ dev->name=devicenames+(NAMELEN*this_dev);
+ dev->irq=irq[this_dev];
+ dev->base_addr=io[this_dev];
+ dev->init=elmc_probe;
+ if(register_netdev(dev)!=0) {
+ if(io[this_dev]==0) break;
+ printk(KERN_WARNING "3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]);
+ } else found++;
}
- return 0;
+
+ if(found==0) {
+ if(io[0]==0) printk(KERN_NOTICE "3c523.c: No 3c523 cards found\n");
+ return -ENXIO;
+ } else return 0;
}
void cleanup_module(void)
{
- struct device *dev = &dev_elmc;
-
- /* shutdown interrupts on the card */
- elmc_id_reset586();
- if (dev->irq != 0) {
- /* this should be done by close, but if we failed to
- initialize properly something may have gotten hosed. */
- free_irq(dev->irq, dev);
- dev->irq = 0;
- }
- if (dev->base_addr != 0) {
- release_region(dev->base_addr, ELMC_IO_EXTENT);
- dev->base_addr = 0;
- }
- irq = 0;
- io = 0;
- unregister_netdev(dev);
+ int this_dev;
+ for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {
+
+ struct device *dev = &dev_elmc[this_dev];
+ if(dev->priv) {
+ /* shutdown interrupts on the card */
+ elmc_id_reset586();
+ if (dev->irq != 0) {
+ /* this should be done by close, but if we failed to
+ initialize properly something may have gotten hosed. */
+ free_irq(dev->irq, dev);
+ dev->irq = 0;
+ }
+ if (dev->base_addr != 0) {
+ release_region(dev->base_addr, ELMC_IO_EXTENT);
+ dev->base_addr = 0;
+ }
+ irq[this_dev] = 0;
+ io[this_dev] = 0;
+ unregister_netdev(dev);
- mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot,
+ mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot,
NULL, NULL);
- kfree_s(dev->priv, sizeof(struct priv));
- dev->priv = NULL;
+ kfree_s(dev->priv, sizeof(struct priv));
+ dev->priv = NULL;
+ }
+ }
}
#endif /* MODULE */