summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2003-09-03 10:38:42 -0700
committerStephen Hemminger <shemminger@osdl.org>2003-09-03 10:38:42 -0700
commitfc9e07930b17eed12208b95411fd27aedf7d6327 (patch)
tree9cd7c9af25c292f58ada5ad31b9874035a1db05b
parent51845e3a3848fe875d1e074d1feaa6e64752fd22 (diff)
[NET]: Convert cops over to new initialization.
More from Al NE12-cops * switched cops to dynamic allocation * cops: embedded ->priv * cops: fixed ->irq clobbering on autoprobe Added * free_netdev
-rw-r--r--drivers/net/Space.c29
-rw-r--r--drivers/net/appletalk/cops.c132
2 files changed, 73 insertions, 88 deletions
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 2292798aa348..c13607036260 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -101,6 +101,9 @@ extern int mc32_probe(struct net_device *dev);
#ifdef CONFIG_SDLA
extern struct net_device *sdla_init(void);
#endif
+#ifdef CONFIG_COPS
+extern struct net_device *cops_probe(int unit);
+#endif
/* Detachable devices ("pocket adaptors") */
extern int de620_probe(struct net_device *);
@@ -388,6 +391,11 @@ static int __init ethif_probe(struct net_device *dev)
/* Statically configured drivers -- order matters here. */
void probe_old_netdevs(void)
{
+#ifdef CONFIG_COPS
+ cops_probe(0);
+ cops_probe(1);
+ cops_probe(2);
+#endif
#ifdef CONFIG_SDLA
sdla_init();
#endif
@@ -405,27 +413,6 @@ static struct net_device dev_ltpc = {
#define NEXT_DEV (&dev_ltpc)
#endif /* LTPC */
-#if defined(CONFIG_COPS)
-extern int cops_probe(struct net_device *);
-static struct net_device cops2_dev = {
- .name = "lt2",
- .next = NEXT_DEV,
- .init = cops_probe,
-};
-static struct net_device cops1_dev = {
- .name = "lt1",
- .next = &cops2_dev,
- .init = cops_probe,
-};
-static struct net_device cops0_dev = {
- .name = "lt0",
- .next = &cops1_dev,
- .init = cops_probe,
-};
-#undef NEXT_DEV
-#define NEXT_DEV (&cops0_dev)
-#endif /* COPS */
-
static struct net_device eth7_dev = {
.name = "eth%d",
.next = NEXT_DEV,
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index cb8dac24f286..579cf0d2ee5b 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -92,12 +92,8 @@ static int board_type = DAYNA; /* Module exported */
static int board_type = TANGENT;
#endif
-#ifdef MODULE
static int io = 0x240; /* Default IO for Dayna */
static int irq = 5; /* Default IRQ */
-#else
-static int io; /* Default IO for Dayna */
-#endif
/*
* COPS Autoprobe information.
@@ -146,7 +142,7 @@ static int io; /* Default IO for Dayna */
* Zero terminated list of IO ports to probe.
*/
-static unsigned int cops_portlist[] = {
+static unsigned int ports[] = {
0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260,
0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360,
0
@@ -184,7 +180,6 @@ struct cops_local
};
/* Index to functions, as function prototypes. */
-extern int cops_probe (struct net_device *dev);
static int cops_probe1 (struct net_device *dev, int ioaddr);
static int cops_irq (int ioaddr, int board);
@@ -208,6 +203,12 @@ static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static int cops_close (struct net_device *dev);
static struct net_device_stats *cops_get_stats (struct net_device *dev);
+static void cleanup_card(struct net_device *dev)
+{
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, COPS_IO_EXTENT);
+}
/*
* Check for a network adaptor of this type, and return '0' iff one exists.
@@ -215,31 +216,54 @@ static struct net_device_stats *cops_get_stats (struct net_device *dev);
* If dev->base_addr in [1..0x1ff], always return failure.
* otherwise go with what we pass in.
*/
-int __init cops_probe(struct net_device *dev)
+struct net_device * __init cops_probe(int unit)
{
- int i;
- int base_addr = dev->base_addr;
+ struct net_device *dev;
+ unsigned *port;
+ int base_addr;
+ int err = 0;
+
+ dev = alloc_netdev(sizeof(struct cops_local), "lt%d", ltalk_setup);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ if (unit >= 0) {
+ sprintf(dev->name, "lt%d", unit);
+ netdev_boot_setup_check(dev);
+ irq = dev->irq;
+ base_addr = dev->base_addr;
+ } else {
+ base_addr = dev->base_addr = io;
+ }
SET_MODULE_OWNER(dev);
- if(base_addr == 0 && io)
- base_addr=io;
-
- if(base_addr > 0x1ff) /* Check a single specified location. */
- return cops_probe1(dev, base_addr);
- else if(base_addr != 0) /* Don't probe at all. */
- return -ENXIO;
-
- /* FIXME Does this really work for cards which generate irq?
- * It's definitely N.G. for polled Tangent. sh
- * Dayna cards don't autoprobe well at all, but if your card is
- * at IRQ 5 & IO 0x240 we find it every time. ;) JS
- */
- for(i=0; cops_portlist[i]; i++)
- if(cops_probe1(dev, cops_portlist[i]) == 0)
- return 0;
-
- return -ENODEV;
+ if (base_addr > 0x1ff) { /* Check a single specified location. */
+ err = cops_probe1(dev, base_addr);
+ } else if (base_addr != 0) { /* Don't probe at all. */
+ err = -ENXIO;
+ } else {
+ /* FIXME Does this really work for cards which generate irq?
+ * It's definitely N.G. for polled Tangent. sh
+ * Dayna cards don't autoprobe well at all, but if your card is
+ * at IRQ 5 & IO 0x240 we find it every time. ;) JS
+ */
+ for (port = ports; *port && cops_probe1(dev, *port) < 0; port++)
+ ;
+ if (!*port)
+ err = -ENODEV;
+ }
+ if (err)
+ goto out;
+ err = register_netdev(dev);
+ if (err)
+ goto out1;
+ return dev;
+out1:
+ cleanup_card(dev);
+out:
+ kfree(dev);
+ return ERR_PTR(err);
}
/*
@@ -268,16 +292,15 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
* interrupts are typically not reported by the boards, and we must
* used AutoIRQ to find them.
*/
+ dev->irq = irq;
switch (dev->irq)
{
case 0:
/* COPS AutoIRQ routine */
dev->irq = cops_irq(ioaddr, board);
- if(!dev->irq) {
- retval = -EINVAL; /* No IRQ found on this port */
- goto err_out;
- }
-
+ if (dev->irq)
+ break;
+ /* No IRQ found on this port, fallthrough */
case 1:
retval = -EINVAL;
goto err_out;
@@ -302,22 +325,13 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
}
/* Reserve any actual interrupt. */
- if(dev->irq) {
+ if (dev->irq) {
retval = request_irq(dev->irq, &cops_interrupt, 0, dev->name, dev);
if (retval)
goto err_out;
}
- dev->base_addr = ioaddr;
-
- /* Initialize the private device structure. */
- dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL);
- if(dev->priv == NULL) {
- if (dev->irq)
- free_irq(dev->irq, dev);
- retval = -ENOMEM;
- goto err_out;
- }
+ dev->base_addr = ioaddr;
lp = (struct cops_local *)dev->priv;
memset(lp, 0, sizeof(struct cops_local));
@@ -326,9 +340,6 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
/* Copy local board variable to lp struct. */
lp->board = board;
- /* Fill in the fields of the device structure with LocalTalk values. */
- ltalk_setup(dev);
-
dev->hard_start_xmit = cops_send_packet;
dev->tx_timeout = cops_timeout;
dev->watchdog_timeo = HZ * 2;
@@ -1013,7 +1024,7 @@ static struct net_device_stats *cops_get_stats(struct net_device *dev)
}
#ifdef MODULE
-static struct net_device cops0_dev = { .init = cops_probe };
+static struct net_device *cops_dev;
MODULE_LICENSE("GPL");
MODULE_PARM(io, "i");
@@ -1022,33 +1033,20 @@ MODULE_PARM(board_type, "i");
int init_module(void)
{
- int result, err;
-
- if(io == 0)
+ if (io == 0)
printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
cardname);
-
- /* Copy the parameters from insmod into the device structure. */
- cops0_dev.base_addr = io;
- cops0_dev.irq = irq;
-
- err=dev_alloc_name(&cops0_dev, "lt%d");
- if(err < 0)
- return err;
-
- if((result = register_netdev(&cops0_dev)) != 0)
- return result;
-
+ cops_dev = cops_probe(-1);
+ if (IS_ERR(cops_dev))
+ return PTR_ERR(cops_dev);
return 0;
}
void cleanup_module(void)
{
- unregister_netdev(&cops0_dev);
- kfree(cops0_dev.priv);
- if(cops0_dev.irq)
- free_irq(cops0_dev.irq, &cops0_dev);
- release_region(cops0_dev.base_addr, COPS_IO_EXTENT);
+ unregister_netdev(cops_dev);
+ cleanup_card(cops_dev);
+ free_netdev(cops_dev);
}
#endif /* MODULE */