2003-05-01 16:41:38

by Jeff Muizelaar

[permalink] [raw]
Subject: [PATCH 0/4] NE2000 driver updates

The first two patches are retransmits of the original PnP api patches
updated to apply to a current tree.

The third patch is more of an RFC. It consolidates the creation/removal
of the driver between the PnP code and the plain ISA code. In doing so
it changes the net_device allocation from static to dynamic and allows
PnP support when the driver is compiled in. This is probably how things
will eventually have to be if there is ever driver model support for
plain ISA devices.

The forth patch gets rid of the use of dev->mem_end as a bad flag.

Caveats:
It appears that the patch will break any autoprobe ordering because it no
longer uses Space.c when compiled into the kernel.
Data size of object goes up about 100 bytes.

-Jeff


2003-05-01 16:46:26

by Jeff Muizelaar

[permalink] [raw]
Subject: [PATCH 1/4] NE2000 driver updates

--- linux-2.5.66/drivers/net/ne.c 2003-03-24 17:00:21.000000000 -0500
+++ linux-2.5.66-nepnp/drivers/net/ne.c 2003-03-29 21:39:17.000000000 -0500
@@ -29,21 +29,20 @@
last in cleanup_modue()
Richard Guenther : Added support for ISAPnP cards
Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead.
+ Jeff Muizelaar : moved over to generic PnP api

*/

/* Routines for the NatSemi-based designs (NE[12]000). */

-static const char version1[] =
-"ne.c:v1.10 9/23/94 Donald Becker ([email protected])\n";
-static const char version2[] =
-"Last modified Nov 1, 2000 by Paul Gortmaker\n";
+static const char version[] =
+"ne.c:v1.10a 1/26/03 Donald Becker ([email protected])\n";


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/isapnp.h>
+#include <linux/pnp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -76,20 +75,18 @@
};
#endif

-static struct isapnp_device_id isapnp_clone_list[] __initdata = {
- { ISAPNP_CARD_ID('A','X','E',0x2011),
- ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
- (long) "NetGear EA201" },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
- (long) "NN NE2000" },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
- (long) "Generic PNP" },
- { } /* terminate list */
+#ifdef CONFIG_PNP
+static const struct pnp_device_id ne_pnp_table[] = {
+ /* NetGear EA201 */
+ {.id = "AXE2011", .driver_data = 0},
+ /* NN NE2000 */
+ {.id = "EDI0216", .driver_data = 0},
+ /* NE2000 Compatible */
+ {.id = "PNP80d6", .driver_data = 0},
};

-MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
+MODULE_DEVICE_TABLE(pnp, ne_pnp_table);
+#endif

#ifdef SUPPORT_NE_BAD_CLONES
/* A list of bad clones that we none-the-less recognize. */
@@ -126,9 +123,20 @@
#define NESM_START_PG 0x40 /* First page of TX buffer */
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */

+#ifdef CONFIG_PNP
+static int ne_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id);
+static void ne_pnp_remove(struct pnp_dev *dev);
+
+static struct pnp_driver ne_pnp_driver = {
+ .name = "ne",
+ .id_table = ne_pnp_table,
+ .probe = ne_pnp_probe,
+ .remove = ne_pnp_remove,
+};
+#endif
+
int ne_probe(struct net_device *dev);
static int ne_probe1(struct net_device *dev, int ioaddr);
-static int ne_probe_isapnp(struct net_device *dev);

static int ne_open(struct net_device *dev);
static int ne_close(struct net_device *dev);
@@ -175,10 +183,6 @@
else if (base_addr != 0) /* Don't probe at all. */
return -ENXIO;

- /* Then look for any installed ISAPnP clones */
- if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
- return 0;
-
#ifndef MODULE
/* Last resort. The semi-risky ISA auto-probe. */
for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
@@ -191,50 +195,58 @@
return -ENODEV;
}

-static int __init ne_probe_isapnp(struct net_device *dev)
+#ifdef CONFIG_PNP
+static int ne_pnp_probe(struct pnp_dev *idev, const struct pnp_device_id *dev_id)
{
- int i;
-
- for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
- struct pnp_dev *idev = NULL;
+ struct net_device *dev;
+ int err;
+
+ if ( !(dev = alloc_etherdev(0)) ){
+ err = -ENOMEM;
+ goto alloc_fail;
+ }
+
+ dev->base_addr = pnp_port_start(idev, 0);
+ dev->irq = pnp_irq(idev, 0);
+ printk(KERN_INFO "ne.c: PnP reports %s at i/o %#lx, irq %d\n",
+ idev->dev.name, dev->base_addr, dev->irq);
+
+ SET_MODULE_OWNER(dev);
+
+ if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */
+ printk(KERN_ERR "ne.c: Probe of PnP card at %#lx failed\n", dev->base_addr);
+ err = -ENXIO;
+ goto probe_fail;
+ }
+
+ if ( (err = register_netdev(dev)) != 0)
+ goto register_fail;

- while ((idev = pnp_find_dev(NULL,
- isapnp_clone_list[i].vendor,
- isapnp_clone_list[i].function,
- idev))) {
- /* Avoid already found cards from previous calls */
- if (pnp_device_attach(idev) < 0)
- continue;
- if (pnp_activate_dev(idev) < 0) {
- pnp_device_detach(idev);
- continue;
- }
- /* if no io and irq, search for next */
- if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
- pnp_device_detach(idev);
- continue;
- }
- /* found it */
- dev->base_addr = pnp_port_start(idev, 0);
- dev->irq = pnp_irq(idev, 0);
- printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
- (char *) isapnp_clone_list[i].driver_data,
- dev->base_addr, dev->irq);
- if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */
- printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
- pnp_device_detach(idev);
- return -ENXIO;
- }
- ei_status.priv = (unsigned long)idev;
- break;
- }
- if (!idev)
- continue;
- return 0;
+ pnp_set_drvdata(idev, dev);
+
+ return 0;
+
+register_fail:
+ kfree(dev->priv);
+ release_region(dev->base_addr, NE_IO_EXTENT);
+probe_fail:
+ kfree(dev);
+alloc_fail:
+ return err;
+}
+
+static void ne_pnp_remove(struct pnp_dev *idev)
+{
+ struct net_device *dev = pnp_get_drvdata(idev);
+ if (dev) {
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, NE_IO_EXTENT);
+ kfree(dev->priv);
+ kfree(dev);
}
-
- return -ENODEV;
}
+#endif

static int __init ne_probe1(struct net_device *dev, int ioaddr)
{
@@ -273,7 +285,7 @@
}

if (ei_debug && version_printed++ == 0)
- printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
+ printk(KERN_INFO "%s", version);

printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);

@@ -757,6 +769,13 @@
{
int this_dev, found = 0;

+#ifdef CONFIG_PNP
+ found = pnp_register_driver(&ne_pnp_driver);
+ if (found < 0) {
+ return found;
+ }
+#endif
+
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
dev->irq = irq[this_dev];
@@ -774,6 +793,9 @@
printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
else
printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
+#ifdef CONFIG_PNP
+ pnp_unregister_driver(&ne_pnp_driver);
+#endif
return -ENXIO;
}
return 0;
@@ -783,17 +805,16 @@
{
int this_dev;

+#ifdef CONFIG_PNP
+ pnp_unregister_driver(&ne_pnp_driver);
+#endif
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
if (dev->priv != NULL) {
- void *priv = dev->priv;
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- if (idev)
- pnp_device_detach(idev);
+ unregister_netdev(dev);
free_irq(dev->irq, dev);
release_region(dev->base_addr, NE_IO_EXTENT);
- unregister_netdev(dev);
- kfree(priv);
+ kfree(dev->priv);
}
}
}


Attachments:
ne-pnp.patch (6.69 kB)

2003-05-01 16:47:55

by Jeff Muizelaar

[permalink] [raw]
Subject: [PATCH 3/4] NE2000 driver updates

--- linux-2.5.66-nepnpid/drivers/net/ne.c 2003-03-29 21:39:29.000000000 -0500
+++ linux-2.5.66-nelist/drivers/net/ne.c 2003-05-01 11:05:56.000000000 -0400
@@ -30,13 +30,14 @@
Richard Guenther : Added support for ISAPnP cards
Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead.
Jeff Muizelaar : moved over to generic PnP api
+ Jeff Muizelaar : changed init code to act more probe like

*/

/* Routines for the NatSemi-based designs (NE[12]000). */

static const char version[] =
-"ne.c:v1.10a 1/26/03 Donald Becker ([email protected])\n";
+"ne.c:v1.10b 4/1/03 Donald Becker ([email protected])\n";


#include <linux/module.h>
@@ -134,7 +135,6 @@
#ifdef CONFIG_PNP
static int ne_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id);
static void ne_pnp_remove(struct pnp_dev *dev);
-
static struct pnp_driver ne_pnp_driver = {
.name = "ne",
.id_table = ne_pnp_table,
@@ -143,9 +143,14 @@
};
#endif

-int ne_probe(struct net_device *dev);
+static int ne_legacy_probe(unsigned long base_addr, unsigned long irq, unsigned long bad);
+
static int ne_probe1(struct net_device *dev, int ioaddr);

+static int ne_create(struct net_device **ndev, unsigned long base_addr,
+ unsigned long irq, unsigned long bad);
+static void ne_remove(struct net_device *dev);
+
static int ne_open(struct net_device *dev);
static int ne_close(struct net_device *dev);

@@ -179,73 +184,81 @@
E2010 starts at 0x100 and ends at 0x4000.
E2010-x starts at 0x100 and ends at 0xffff. */

-int __init ne_probe(struct net_device *dev)
+#ifdef CONFIG_PNP
+static int ne_pnp_probe(struct pnp_dev *idev, const struct pnp_device_id *dev_id)
{
- unsigned int base_addr = dev->base_addr;
-
- SET_MODULE_OWNER(dev);
-
- /* First check any supplied i/o locations. User knows best. <cough> */
- if (base_addr > 0x1ff) /* Check a single specified location. */
- return ne_probe1(dev, base_addr);
- else if (base_addr != 0) /* Don't probe at all. */
- return -ENXIO;
+ struct net_device *dev;
+ int err;
+ printk(KERN_INFO "ne.c: PnP reports %s at i/o %#lx, irq %ld\n",
+ idev->dev.name, pnp_port_start(idev, 0), pnp_irq(idev, 0));
+ err = ne_create(&dev, pnp_port_start(idev, 0), pnp_irq(idev, 0), 0);
+ if(dev)
+ pnp_set_drvdata(idev, dev);
+ return err;
+}

-#ifndef MODULE
- /* Last resort. The semi-risky ISA auto-probe. */
- for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
- int ioaddr = netcard_portlist[base_addr];
- if (ne_probe1(dev, ioaddr) == 0)
- return 0;
- }
+static void ne_pnp_remove(struct pnp_dev *idev)
+{
+ struct net_device *dev = pnp_get_drvdata(idev);
+ ne_remove(dev);
+}
#endif
+struct list_head ne_legacy_devs = LIST_HEAD_INIT(ne_legacy_devs);

- return -ENODEV;
+struct ne_legacy{
+ struct net_device *dev;
+ struct list_head list;
+};
+
+static int ne_legacy_probe(unsigned long base_addr, unsigned long irq, unsigned long bad)
+{
+ struct ne_legacy *ne_card;
+ int err;
+ ne_card = kmalloc(sizeof(struct ne_legacy), GFP_KERNEL);
+ err = ne_create(&ne_card->dev, base_addr, irq, bad);
+ if (!err)
+ list_add(&ne_card->list, &ne_legacy_devs);
+ else
+ kfree(ne_card);
+ return err;
}

-#ifdef CONFIG_PNP
-static int ne_pnp_probe(struct pnp_dev *idev, const struct pnp_device_id *dev_id)
+static int ne_create(struct net_device **ndev, unsigned long base_addr, unsigned long irq, unsigned long bad)
{
- struct net_device *dev;
int err;

- if ( !(dev = alloc_etherdev(0)) ){
+ if (!(*ndev = alloc_etherdev(0)) ){
err = -ENOMEM;
goto alloc_fail;
}

- dev->base_addr = pnp_port_start(idev, 0);
- dev->irq = pnp_irq(idev, 0);
- printk(KERN_INFO "ne.c: PnP reports %s at i/o %#lx, irq %d\n",
- idev->dev.name, dev->base_addr, dev->irq);
-
- SET_MODULE_OWNER(dev);
+ (*ndev)->base_addr = base_addr;
+ (*ndev)->irq = irq;
+ (*ndev)->mem_end = bad;
+ SET_MODULE_OWNER(*ndev);

- if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */
- printk(KERN_ERR "ne.c: Probe of PnP card at %#lx failed\n", dev->base_addr);
+ if (ne_probe1(*ndev, (*ndev)->base_addr) != 0) { /* Shouldn't happen. */
+ printk(KERN_ERR "ne.c: Probe at %#lx failed\n", (*ndev)->base_addr);
err = -ENXIO;
goto probe_fail;
}

- if ( (err = register_netdev(dev)) != 0)
+ if ( (err = register_netdev(*ndev)) != 0)
goto register_fail;
-
- pnp_set_drvdata(idev, dev);

return 0;

register_fail:
- kfree(dev->priv);
- release_region(dev->base_addr, NE_IO_EXTENT);
+ kfree((*ndev)->priv);
+ release_region((*ndev)->base_addr, NE_IO_EXTENT);
probe_fail:
- kfree(dev);
+ kfree(*ndev);
alloc_fail:
- return err;
+ return err;
}

-static void ne_pnp_remove(struct pnp_dev *idev)
+static void ne_remove(struct net_device *dev)
{
- struct net_device *dev = pnp_get_drvdata(idev);
if (dev) {
unregister_netdev(dev);
free_irq(dev->irq, dev);
@@ -254,7 +267,6 @@
kfree(dev);
}
}
-#endif

static int __init ne_probe1(struct net_device *dev, int ioaddr)
{
@@ -751,10 +763,7 @@
return;
}

-
-#ifdef MODULE
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
-static struct net_device dev_ne[MAX_NE_CARDS];
static int io[MAX_NE_CARDS];
static int irq[MAX_NE_CARDS];
static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
@@ -773,60 +782,70 @@
is at boot) and so the probe will get confused by any other 8390 cards.
ISA device autoprobes on a running machine are not recommended anyway. */

-int init_module(void)
-{
- int this_dev, found = 0;

+static int __init ne_init(void)
+{
+ int i, found = 0;
+ int err;
#ifdef CONFIG_PNP
found = pnp_register_driver(&ne_pnp_driver);
if (found < 0) {
- return found;
+ err = found;
+ goto pnp_fail;
}
#endif
+ /* First check any supplied i/o locations. User knows best. <cough> */
+ for (i = 0; i < MAX_NE_CARDS; i++) {
+ if (io[i] > 0x1ff) {
+ err = ne_legacy_probe(io[i], irq[i], bad[i]);
+ if (!err)
+ found++;
+ else
+ printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[i]);
+ }
+ }

- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = &dev_ne[this_dev];
- dev->irq = irq[this_dev];
- dev->mem_end = bad[this_dev];
- dev->base_addr = io[this_dev];
- dev->init = ne_probe;
- if (register_netdev(dev) == 0) {
+#ifndef MODULE
+ /* Last resort. The semi-risky ISA auto-probe. */
+ printk(KERN_INFO "ne.c: auto-probing...\m");
+ for (i = 0; netcard_portlist[i] != 0; i++) {
+ err = ne_legacy_probe(netcard_portlist[i], 0, 0);
+ if (!err) {
found++;
- continue;
- }
- if (found != 0) { /* Got at least one. */
- return 0;
- }
- if (io[this_dev] != 0)
- printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
- else
- printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
+ }
+ }
+#endif
+ if (found > 0) /* Got at least one. */
+ return 0;
+ else
+ printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
+
#ifdef CONFIG_PNP
- pnp_unregister_driver(&ne_pnp_driver);
+ pnp_unregister_driver(&ne_pnp_driver);
+pnp_fail:
#endif
- return -ENXIO;
- }
- return 0;
+ return -ENODEV;
}

-void cleanup_module(void)
+static void __exit ne_cleanup(void)
{
- int this_dev;
-
+ struct list_head *entry;
+ struct list_head *tmp;
#ifdef CONFIG_PNP
pnp_unregister_driver(&ne_pnp_driver);
#endif
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = &dev_ne[this_dev];
- if (dev->priv != NULL) {
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
- kfree(dev->priv);
- }
+ /* Cleanup legacy devices */
+ list_for_each_safe(entry, tmp, &ne_legacy_devs) {
+ struct ne_legacy *card;
+ card = list_entry(entry, struct ne_legacy, list);
+ ne_remove(card->dev);
+ list_del(entry);
+ kfree(card);
}
}
-#endif /* MODULE */
+
+module_init(ne_init);
+module_exit(ne_cleanup);


/*


Attachments:
ne-legacy.patch (7.78 kB)

2003-05-01 16:46:55

by Jeff Muizelaar

[permalink] [raw]
Subject: [PATCH 2/4] NE2000 driver updates

--- linux-2.5.66-nepnp/drivers/net/ne.c 2003-03-29 21:39:17.000000000 -0500
+++ linux-2.5.66-nepnpid/drivers/net/ne.c 2003-03-29 21:39:29.000000000 -0500
@@ -81,8 +81,16 @@
{.id = "AXE2011", .driver_data = 0},
/* NN NE2000 */
{.id = "EDI0216", .driver_data = 0},
+ /* Novell/Anthem NE1000 */
+ {.id = "PNP80d3", .driver_data = 0},
+ /* Novell/Anthem NE2000 */
+ {.id = "PNP80d4", .driver_data = 0},
+ /* NE1000 Compatible */
+ {.id = "PNP80d5", .driver_data = 0},
/* NE2000 Compatible */
{.id = "PNP80d6", .driver_data = 0},
+ /* National Semiconductor AT/LANTIC EtherNODE 16-AT3 */
+ {.id = "PNP8160", .driver_data = 0},
};

MODULE_DEVICE_TABLE(pnp, ne_pnp_table);


Attachments:
ne-pnp-id.patch (679.00 B)

2003-05-01 16:56:33

by Jeff Muizelaar

[permalink] [raw]
Subject: Re: [PATCH 3/4] NE2000 driver updates

diff -u linux-2.5.66-nepnpid/drivers/net/ne.c linux-2.5.66-nelist/drivers/net/ne.c
--- linux-2.5.66-nepnpid/drivers/net/ne.c 2003-03-29 21:39:29.000000000 -0500
+++ linux-2.5.66-nelist/drivers/net/ne.c 2003-05-01 11:05:56.000000000 -0400
@@ -30,13 +30,14 @@
Richard Guenther : Added support for ISAPnP cards
Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead.
Jeff Muizelaar : moved over to generic PnP api
+ Jeff Muizelaar : changed init code to act more probe like

*/

/* Routines for the NatSemi-based designs (NE[12]000). */

static const char version[] =
-"ne.c:v1.10a 1/26/03 Donald Becker ([email protected])\n";
+"ne.c:v1.10b 4/1/03 Donald Becker ([email protected])\n";


#include <linux/module.h>
@@ -134,7 +135,6 @@
#ifdef CONFIG_PNP
static int ne_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id);
static void ne_pnp_remove(struct pnp_dev *dev);
-
static struct pnp_driver ne_pnp_driver = {
.name = "ne",
.id_table = ne_pnp_table,
@@ -143,9 +143,14 @@
};
#endif

-int ne_probe(struct net_device *dev);
+static int ne_legacy_probe(unsigned long base_addr, unsigned long irq, unsigned long bad);
+
static int ne_probe1(struct net_device *dev, int ioaddr);

+static int ne_create(struct net_device **ndev, unsigned long base_addr,
+ unsigned long irq, unsigned long bad);
+static void ne_remove(struct net_device *dev);
+
static int ne_open(struct net_device *dev);
static int ne_close(struct net_device *dev);

@@ -179,73 +184,81 @@
E2010 starts at 0x100 and ends at 0x4000.
E2010-x starts at 0x100 and ends at 0xffff. */

-int __init ne_probe(struct net_device *dev)
+#ifdef CONFIG_PNP
+static int ne_pnp_probe(struct pnp_dev *idev, const struct pnp_device_id *dev_id)
{
- unsigned int base_addr = dev->base_addr;
-
- SET_MODULE_OWNER(dev);
-
- /* First check any supplied i/o locations. User knows best. <cough> */
- if (base_addr > 0x1ff) /* Check a single specified location. */
- return ne_probe1(dev, base_addr);
- else if (base_addr != 0) /* Don't probe at all. */
- return -ENXIO;
+ struct net_device *dev;
+ int err;
+ printk(KERN_INFO "ne.c: PnP reports %s at i/o %#lx, irq %ld\n",
+ idev->dev.name, pnp_port_start(idev, 0), pnp_irq(idev, 0));
+ err = ne_create(&dev, pnp_port_start(idev, 0), pnp_irq(idev, 0), 0);
+ if(dev)
+ pnp_set_drvdata(idev, dev);
+ return err;
+}

-#ifndef MODULE
- /* Last resort. The semi-risky ISA auto-probe. */
- for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
- int ioaddr = netcard_portlist[base_addr];
- if (ne_probe1(dev, ioaddr) == 0)
- return 0;
- }
+static void ne_pnp_remove(struct pnp_dev *idev)
+{
+ struct net_device *dev = pnp_get_drvdata(idev);
+ ne_remove(dev);
+}
#endif
+struct list_head ne_legacy_devs = LIST_HEAD_INIT(ne_legacy_devs);

- return -ENODEV;
+struct ne_legacy{
+ struct net_device *dev;
+ struct list_head list;
+};
+
+static int ne_legacy_probe(unsigned long base_addr, unsigned long irq, unsigned long bad)
+{
+ struct ne_legacy *ne_card;
+ int err;
+ ne_card = kmalloc(sizeof(struct ne_legacy), GFP_KERNEL);
+ err = ne_create(&ne_card->dev, base_addr, irq, bad);
+ if (!err)
+ list_add(&ne_card->list, &ne_legacy_devs);
+ else
+ kfree(ne_card);
+ return err;
}

-#ifdef CONFIG_PNP
-static int ne_pnp_probe(struct pnp_dev *idev, const struct pnp_device_id *dev_id)
+static int ne_create(struct net_device **ndev, unsigned long base_addr, unsigned long irq, unsigned long bad)
{
- struct net_device *dev;
int err;

- if ( !(dev = alloc_etherdev(0)) ){
+ if (!(*ndev = alloc_etherdev(0)) ){
err = -ENOMEM;
goto alloc_fail;
}

- dev->base_addr = pnp_port_start(idev, 0);
- dev->irq = pnp_irq(idev, 0);
- printk(KERN_INFO "ne.c: PnP reports %s at i/o %#lx, irq %d\n",
- idev->dev.name, dev->base_addr, dev->irq);
-
- SET_MODULE_OWNER(dev);
+ (*ndev)->base_addr = base_addr;
+ (*ndev)->irq = irq;
+ (*ndev)->mem_end = bad;
+ SET_MODULE_OWNER(*ndev);

- if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */
- printk(KERN_ERR "ne.c: Probe of PnP card at %#lx failed\n", dev->base_addr);
+ if (ne_probe1(*ndev, (*ndev)->base_addr) != 0) { /* Shouldn't happen. */
+ printk(KERN_ERR "ne.c: Probe at %#lx failed\n", (*ndev)->base_addr);
err = -ENXIO;
goto probe_fail;
}

- if ( (err = register_netdev(dev)) != 0)
+ if ( (err = register_netdev(*ndev)) != 0)
goto register_fail;
-
- pnp_set_drvdata(idev, dev);

return 0;

register_fail:
- kfree(dev->priv);
- release_region(dev->base_addr, NE_IO_EXTENT);
+ kfree((*ndev)->priv);
+ release_region((*ndev)->base_addr, NE_IO_EXTENT);
probe_fail:
- kfree(dev);
+ kfree(*ndev);
alloc_fail:
- return err;
+ return err;
}

-static void ne_pnp_remove(struct pnp_dev *idev)
+static void ne_remove(struct net_device *dev)
{
- struct net_device *dev = pnp_get_drvdata(idev);
if (dev) {
unregister_netdev(dev);
free_irq(dev->irq, dev);
@@ -254,7 +267,6 @@
kfree(dev);
}
}
-#endif

static int __init ne_probe1(struct net_device *dev, int ioaddr)
{
@@ -751,10 +763,7 @@
return;
}

-
-#ifdef MODULE
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
-static struct net_device dev_ne[MAX_NE_CARDS];
static int io[MAX_NE_CARDS];
static int irq[MAX_NE_CARDS];
static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
@@ -773,60 +782,70 @@
is at boot) and so the probe will get confused by any other 8390 cards.
ISA device autoprobes on a running machine are not recommended anyway. */

-int init_module(void)
-{
- int this_dev, found = 0;

+static int __init ne_init(void)
+{
+ int i, found = 0;
+ int err;
#ifdef CONFIG_PNP
found = pnp_register_driver(&ne_pnp_driver);
if (found < 0) {
- return found;
+ err = found;
+ goto pnp_fail;
}
#endif
+ /* First check any supplied i/o locations. User knows best. <cough> */
+ for (i = 0; i < MAX_NE_CARDS; i++) {
+ if (io[i] > 0x1ff) {
+ err = ne_legacy_probe(io[i], irq[i], bad[i]);
+ if (!err)
+ found++;
+ else
+ printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[i]);
+ }
+ }

- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = &dev_ne[this_dev];
- dev->irq = irq[this_dev];
- dev->mem_end = bad[this_dev];
- dev->base_addr = io[this_dev];
- dev->init = ne_probe;
- if (register_netdev(dev) == 0) {
+#ifndef MODULE
+ /* Last resort. The semi-risky ISA auto-probe. */
+ printk(KERN_INFO "ne.c: auto-probing...\m");
+ for (i = 0; netcard_portlist[i] != 0; i++) {
+ err = ne_legacy_probe(netcard_portlist[i], 0, 0);
+ if (!err) {
found++;
- continue;
- }
- if (found != 0) { /* Got at least one. */
- return 0;
- }
- if (io[this_dev] != 0)
- printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
- else
- printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
+ }
+ }
+#endif
+ if (found > 0) /* Got at least one. */
+ return 0;
+ else
+ printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
+
#ifdef CONFIG_PNP
- pnp_unregister_driver(&ne_pnp_driver);
+ pnp_unregister_driver(&ne_pnp_driver);
+pnp_fail:
#endif
- return -ENXIO;
- }
- return 0;
+ return -ENODEV;
}

-void cleanup_module(void)
+static void __exit ne_cleanup(void)
{
- int this_dev;
-
+ struct list_head *entry;
+ struct list_head *tmp;
#ifdef CONFIG_PNP
pnp_unregister_driver(&ne_pnp_driver);
#endif
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = &dev_ne[this_dev];
- if (dev->priv != NULL) {
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
- kfree(dev->priv);
- }
+ /* Cleanup legacy devices */
+ list_for_each_safe(entry, tmp, &ne_legacy_devs) {
+ struct ne_legacy *card;
+ card = list_entry(entry, struct ne_legacy, list);
+ ne_remove(card->dev);
+ list_del(entry);
+ kfree(card);
}
}
-#endif /* MODULE */
+
+module_init(ne_init);
+module_exit(ne_cleanup);


/*
diff -u linux-2.5.66-nepnpid/drivers/net/Space.c linux-2.5.66-nelist/drivers/net/Space.c
--- linux-2.5.66-nepnpid/drivers/net/Space.c 2003-04-01 12:56:08.000000000 -0500
+++ linux-2.5.66-nelist/drivers/net/Space.c 2003-04-01 12:54:53.000000000 -0500
@@ -233,7 +233,7 @@
#ifdef CONFIG_E2100 /* Cabletron E21xx series. */
{e2100_probe, 0},
#endif
-#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */
+#ifdef CONFIG_NE2K_CBUS /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */
{ne_probe, 0},
#endif
#ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */


Attachments:
ne-legacy.patch (8.48 kB)

2003-05-01 17:35:25

by Jeff Muizelaar

[permalink] [raw]
Subject: [PATCH 4/4] NE2000 driver updates

--- linux-2.5.66-nelist/drivers/net/ne.c 2003-05-01 11:05:56.000000000 -0400
+++ linux-2.5.66-nebad/drivers/net/ne.c 2003-05-01 11:18:19.000000000 -0400
@@ -145,10 +145,10 @@

static int ne_legacy_probe(unsigned long base_addr, unsigned long irq, unsigned long bad);

-static int ne_probe1(struct net_device *dev, int ioaddr);
+static int ne_probe1(struct net_device *dev, int ioaddr, int bad);

static int ne_create(struct net_device **ndev, unsigned long base_addr,
- unsigned long irq, unsigned long bad);
+ unsigned long irq, int bad);
static void ne_remove(struct net_device *dev);

static int ne_open(struct net_device *dev);
@@ -223,7 +223,7 @@
return err;
}

-static int ne_create(struct net_device **ndev, unsigned long base_addr, unsigned long irq, unsigned long bad)
+static int ne_create(struct net_device **ndev, unsigned long base_addr, unsigned long irq, int bad)
{
int err;

@@ -237,7 +237,7 @@
(*ndev)->mem_end = bad;
SET_MODULE_OWNER(*ndev);

- if (ne_probe1(*ndev, (*ndev)->base_addr) != 0) { /* Shouldn't happen. */
+ if (ne_probe1(*ndev, (*ndev)->base_addr, bad) != 0) { /* Shouldn't happen. */
printk(KERN_ERR "ne.c: Probe at %#lx failed\n", (*ndev)->base_addr);
err = -ENXIO;
goto probe_fail;
@@ -268,14 +268,14 @@
}
}

-static int __init ne_probe1(struct net_device *dev, int ioaddr)
+static int __init ne_probe1(struct net_device *dev, int ioaddr, int bad_card)
{
int i;
unsigned char SA_prom[32];
int wordlength = 2;
const char *name = NULL;
int start_page, stop_page;
- int neX000, ctron, copam, bad_card;
+ int neX000, ctron, copam;
int reg0, ret;
static unsigned version_printed;

@@ -311,11 +311,8 @@

/* A user with a poor card that fails to ack the reset, or that
does not have a valid 0x57,0x57 signature can still use this
- without having to recompile. Specifying an i/o address along
- with an otherwise unused dev->mem_end value of "0xBAD" will
- cause the driver to skip these parts of the probe. */
-
- bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+ without having to recompile. Specifying a bad card will cause
+ the driver to skip these parts of the probe. */

/* Reset card. Who knows what dain-bramaged state it was left in. */

@@ -766,7 +763,7 @@
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
static int io[MAX_NE_CARDS];
static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
+static int bad[MAX_NE_CARDS]; /* bad sig or no reset ack */

MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");


Attachments:
ne-bad.patch (2.60 kB)

2003-05-01 20:10:40

by Alan

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

On Iau, 2003-05-01 at 17:53, Jeff Muizelaar wrote:
> Caveats:
> It appears that the patch will break any autoprobe ordering because it no
> longer uses Space.c when compiled into the kernel.

The ne2000 ordering with the other ISA stuff in space.c is really
sensitive for older systems. If you get ne2k too early it breaks some
other cards if it autoprobes, if you get it too late it lets other
stuff crash the box.

So you might want to keep to Space.c for non pnp stuff if non modular

2003-05-01 23:17:43

by Jeff Muizelaar

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

Alan Cox wrote:

>
>The ne2000 ordering with the other ISA stuff in space.c is really
>sensitive for older systems. If you get ne2k too early it breaks some
>other cards if it autoprobes, if you get it too late it lets other
>stuff crash the box.
>
>So you might want to keep to Space.c for non pnp stuff if non modular
>
>
Yeah, patches 1 and 2 do just this.

Are we stuck with Space.c forever? Anyone have any plans for replacing
it with something more driver-model friendly?

-Jeff

2003-05-02 16:17:09

by Riley Williams

[permalink] [raw]
Subject: RE: [PATCH 0/4] NE2000 driver updates

Hi Alan.

>> Are we stuck with Space.c forever? Anyone have any plans for
>> replacing it with something more driver-model friendly?
>
> Is it worth the effort. Why not just let the old ISA stuff live
> out its life in peace ? There is certainly no reason we couldn't
> make it more driver model like by splitting probe and activity
>
> i.e. ne2000 probing would do
>
> poke around for ISA device
> Found one ?
> Alloc ISA device
> Fill in ports/range/IRQ
> Fill in vendor/product with invented idents
> Announce it
>
> Then have ne2000 driver model code do the actual setup

Is the vendor ID 015A allocated to anything? If not, we could use
that to indicate ISA devices - it resembles ISA as a number, and
would thus be easier to identify. We could then use the product
number to identify the particular product. For example..

015A:2000 NE 2000 clone card.
015A:3509 3COM 3C509

...with other numbers allocated in a similar way. There may be some
duplication as the above allows 65,536 discrete ISA Bus products,
but that shouldn't matter providing we allocate unique product ID's
for each product actually installed on a particular system.

Alternatively, if it's free, we could use 15Ay:xxxx to allow for up
to 1,048,576 products, with ID's like the following...

15Ay:2000 NE 2000 clone card.
15Ay:3509 3COM 3C509

...with the 'y' digit used to allow up to 16 different products with
any given product ID, incremented by the kernel as required.

Best wishes from Riley.
---
* Nothing as pretty as a smile, nothing as ugly as a frown.

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.476 / Virus Database: 273 - Release Date: 24-Apr-2003

2003-05-02 14:47:33

by Alan

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

On Gwe, 2003-05-02 at 00:29, Jeff Muizelaar wrote:
> Are we stuck with Space.c forever? Anyone have any plans for replacing
> it with something more driver-model friendly?

Is it worth the effort. Why not just let the old isa stuff live out its
life in peace ? There is certainly no reason we couldnt make it more
driver model like by splitting probe and activity

ie ne2000 probing would do

poke around for ISA device
Found one ?
Alloc isadevice
Fill in ports/range/irq
Fill in vendor/product with invented idents
Announce it

Then have ne2000 driver model code do the actual setup


2003-05-02 15:45:15

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

Alan Cox wrote:
> On Gwe, 2003-05-02 at 00:29, Jeff Muizelaar wrote:
>
>>Are we stuck with Space.c forever? Anyone have any plans for replacing
>>it with something more driver-model friendly?
>
>
> Is it worth the effort. Why not just let the old isa stuff live out its
> life in peace ?


I'm glad you asked. :)

For the major families of ISA net drivers, I am craving massive
consolidation. People continue to use this stuff in embedded systems
and simulators, long past when the original cards disappear into the
ether, too. Considering that operations are inevitably IO bound, I am
even willing to spend a few (admittedly costly) extra cycles chasing
some additional function pointer de-refs, if we could massively shrink
the size and number of NE2000/lance/82596 drivers out there.

I guarantee these drivers are gonna be with us for many years to come,
and designers wanting to bang out a quick-and-easy MAC will create Yet
Another NE2000 Clone.[1]

Did I mention that a GIGE ne2000 card exists?

Jeff



[1] of course, with decent, free MAC and PHY cores at http://www.opencores.org,
maybe we can convince hardware makers to use a better design. </plug>

2003-05-02 16:10:51

by Alan

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

On Gwe, 2003-05-02 at 16:57, Jeff Garzik wrote:
> even willing to spend a few (admittedly costly) extra cycles chasing
> some additional function pointer de-refs, if we could massively shrink
> the size and number of NE2000/lance/82596 drivers out there.

Well the 8390 (ne2000 etc) has been abstracted cleanly for a very long
time indeed. 825xx is a pig because they chip variants are all subtly
and evilly different.

> I guarantee these drivers are gonna be with us for many years to come,
> and designers wanting to bang out a quick-and-easy MAC will create Yet
> Another NE2000 Clone.[1]

They seem to be cloning tulip nowdays

> Did I mention that a GIGE ne2000 card exists?

I've got a 100Mbit one.

Alan

2003-05-14 01:48:51

by Jeff Muizelaar

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

diff -urN linux-2.5.69/drivers/isa/isa-bus.c linux-2.5.69-isabus/drivers/isa/isa-bus.c
--- linux-2.5.69/drivers/isa/isa-bus.c 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.5.69-isabus/drivers/isa/isa-bus.c 2003-05-13 20:19:09.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * ISA bus support functions for sysfs.
+ *
+ * Derived from eisa bus support
+ *
+ * This code is released under the GPL version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/isa.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+
+
+static struct device isa_root_dev = {
+ .name = "isa bus",
+ .bus_id = "isa",
+};
+
+static int isa_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct isa_device *idev = to_isa_device(dev);
+ struct isa_driver *idrv = to_isa_driver(drv);
+ const struct isa_device_id *iids = idrv->id_table;
+ while (strlen (iids->id)) {
+ if (!strcmp(iids->id, idev->id.id)) {
+ return 1;
+ }
+ iids++;
+ }
+ return 0;
+}
+
+struct bus_type isa_bus_type = {
+ .name = "isa",
+ .match = isa_bus_match,
+};
+
+int isa_driver_register(struct isa_driver *idrv)
+{
+ int r;
+
+ idrv->driver.bus = &isa_bus_type;
+ if ((r = driver_register(&idrv->driver)) < 0)
+ return r;
+
+ return 0;
+}
+
+void isa_driver_unregister(struct isa_driver *idrv)
+{
+ driver_unregister(&idrv->driver);
+}
+
+int isa_device_register(unsigned long base_addr, unsigned long irq, struct isa_device_id *id)
+{
+ struct isa_device *idev;
+ if (!(idev = kmalloc(sizeof (*idev), GFP_KERNEL)))
+ return -ENOMEM;
+
+ memset(idev, 0, sizeof (*idev));
+
+ strncpy(idev->id.id, id->id, ISA_ID_LEN);
+ idev->id.driver_data = id->driver_data;
+
+ idev->base_addr = base_addr;
+ idev->irq = irq;
+ idev->dev.parent = &isa_root_dev;
+ idev->dev.bus = &isa_bus_type;
+ idev->dev.dma_mask = &idev->dma_mask;
+ sprintf(idev->dev.bus_id, "%lx", base_addr);
+
+ if (device_register(&idev->dev)){
+ return -1;
+ }
+ return 0;
+}
+
+static int __init isa_init(void)
+{
+ int r;
+ if ((r = device_register(&isa_root_dev)))
+ return r;
+ if ((r = bus_register(&isa_bus_type)))
+ return r;
+ printk(KERN_INFO "ISA bus registered\n");
+ return 0;
+}
+
+postcore_initcall (isa_init);
+
+EXPORT_SYMBOL (isa_bus_type);
+EXPORT_SYMBOL (isa_device_register);
+EXPORT_SYMBOL (isa_driver_register);
+EXPORT_SYMBOL (isa_driver_unregister);
diff -urN linux-2.5.69/drivers/isa/Makefile linux-2.5.69-isabus/drivers/isa/Makefile
--- linux-2.5.69/drivers/isa/Makefile 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.5.69-isabus/drivers/isa/Makefile 2003-05-13 20:12:24.000000000 -0400
@@ -0,0 +1,3 @@
+# Makefile for the Linux isa bus model
+
+obj-$(CONFIG_ISA) += isa-bus.o
diff -urN linux-2.5.69/drivers/Makefile linux-2.5.69-isabus/drivers/Makefile
--- linux-2.5.69/drivers/Makefile 2003-05-04 19:53:37.000000000 -0400
+++ linux-2.5.69-isabus/drivers/Makefile 2003-05-11 14:17:17.000000000 -0400
@@ -49,4 +49,5 @@
obj-$(CONFIG_ISDN_BOOL) += isdn/
obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
+obj-$(CONFIG_ISA) += isa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
diff -urN linux-2.5.69/drivers/net/ne.c linux-2.5.69-isabus/drivers/net/ne.c
--- linux-2.5.69/drivers/net/ne.c 2003-05-04 19:53:14.000000000 -0400
+++ linux-2.5.69-isabus/drivers/net/ne.c 2003-05-13 20:03:16.000000000 -0400
@@ -29,21 +29,21 @@
last in cleanup_modue()
Richard Guenther : Added support for ISAPnP cards
Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead.
+ Jeff Muizelaar : moved over to generic PnP api
+ Jeff Muizelaar : changed init code to act more probe like

*/

/* Routines for the NatSemi-based designs (NE[12]000). */

-static const char version1[] =
-"ne.c:v1.10 9/23/94 Donald Becker ([email protected])\n";
-static const char version2[] =
-"Last modified Nov 1, 2000 by Paul Gortmaker\n";
-
+static const char version[] =
+"ne.c:v1.10b 4/1/03 Donald Becker ([email protected])\n";

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/isapnp.h>
+#include <linux/pnp.h>
+#include <linux/isa.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -76,20 +76,30 @@
};
#endif

-static struct isapnp_device_id isapnp_clone_list[] __initdata = {
- { ISAPNP_CARD_ID('A','X','E',0x2011),
- ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
- (long) "NetGear EA201" },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
- (long) "NN NE2000" },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
- (long) "Generic PNP" },
- { } /* terminate list */
+#ifdef CONFIG_PNP
+static const struct pnp_device_id ne_pnp_table[] = {
+ /* NetGear EA201 */
+ {.id = "AXE2011", .driver_data = 0},
+ /* NN NE2000 */
+ {.id = "EDI0216", .driver_data = 0},
+ /* Novell/Anthem NE1000 */
+ {.id = "PNP80d3", .driver_data = 0},
+ /* Novell/Anthem NE2000 */
+ {.id = "PNP80d4", .driver_data = 0},
+ /* NE1000 Compatible */
+ {.id = "PNP80d5", .driver_data = 0},
+ /* NE2000 Compatible */
+ {.id = "PNP80d6", .driver_data = 0},
+ /* National Semiconductor AT/LANTIC EtherNODE 16-AT3 */
+ {.id = "PNP8160", .driver_data = 0},
};

-MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
+MODULE_DEVICE_TABLE(pnp, ne_pnp_table);
+#endif
+
+static const struct isa_device_id ne_isa_table[] = {
+ {.id = "ISA8711", .driver_data = 0},
+};

#ifdef SUPPORT_NE_BAD_CLONES
/* A list of bad clones that we none-the-less recognize. */
@@ -126,9 +136,34 @@
#define NESM_START_PG 0x40 /* First page of TX buffer */
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */

-int ne_probe(struct net_device *dev);
-static int ne_probe1(struct net_device *dev, int ioaddr);
-static int ne_probe_isapnp(struct net_device *dev);
+#ifdef CONFIG_PNP
+static int ne_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id);
+static void ne_pnp_remove(struct pnp_dev *dev);
+static struct pnp_driver ne_pnp_driver = {
+ .name = "ne",
+ .id_table = ne_pnp_table,
+ .probe = ne_pnp_probe,
+ .remove = ne_pnp_remove,
+};
+#endif
+
+static int ne_isa_probe(struct device *dev);
+static void ne_isa_remove(struct device *dev);
+static struct isa_driver ne_isa_driver = {
+ .id_table = ne_isa_table,
+ .driver = {
+ .name = "ne",
+ .probe = ne_isa_probe,
+ .remove = ne_isa_remove
+ }
+};
+
+static int ne_detect(int ioaddr, int irq, int bad);
+static int ne_probe1(struct net_device *dev, int ioaddr, int bad);
+
+static int ne_create(struct net_device **ndev, unsigned long base_addr,
+ unsigned long irq, int bad);
+static void ne_remove(struct net_device *dev);

static int ne_open(struct net_device *dev);
static int ne_close(struct net_device *dev);
@@ -165,89 +200,112 @@

int __init ne_probe(struct net_device *dev)
{
- unsigned int base_addr = dev->base_addr;
-
- SET_MODULE_OWNER(dev);
-
- /* First check any supplied i/o locations. User knows best. <cough> */
- if (base_addr > 0x1ff) /* Check a single specified location. */
- return ne_probe1(dev, base_addr);
- else if (base_addr != 0) /* Don't probe at all. */
- return -ENXIO;
-
- /* Then look for any installed ISAPnP clones */
- if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
- return 0;
-
#ifndef MODULE
- /* Last resort. The semi-risky ISA auto-probe. */
- for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
- int ioaddr = netcard_portlist[base_addr];
- if (ne_probe1(dev, ioaddr) == 0)
- return 0;
+ /* autoprobe */
+ int i;
+ for (i = 0; netcard_portlist[i] != 0; i++) {
+ if (ne_detect(netcard_portlist[i], 0, 0) == 0)
+ isa_device_register(netcard_portlist[i], 0, ne_isa_table);
}
#endif
-
return -ENODEV;
}

-static int __init ne_probe_isapnp(struct net_device *dev)
+#ifdef CONFIG_PNP
+static int ne_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
{
- int i;
+ struct net_device *ndev;
+ int err;
+ printk(KERN_INFO "ne.c: PnP reports %s at i/o %#lx, irq %ld\n",
+ pdev->dev.name, pnp_port_start(idev, 0), pnp_irq(pdev, 0));
+ err = ne_create(&ndev, pnp_port_start(pdev, 0), pnp_irq(pdev, 0), 0);
+ if(ndev)
+ pnp_set_drvdata(pdev, ndev);
+ return err;
+}

- for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
- struct pnp_dev *idev = NULL;
+static void ne_pnp_remove(struct pnp_dev *pdev)
+{
+ struct net_device *dev = pnp_get_drvdata(pdev);
+ ne_remove(dev);
+}
+#endif

- while ((idev = pnp_find_dev(NULL,
- isapnp_clone_list[i].vendor,
- isapnp_clone_list[i].function,
- idev))) {
- /* Avoid already found cards from previous calls */
- if (pnp_device_attach(idev) < 0)
- continue;
- if (pnp_activate_dev(idev) < 0) {
- pnp_device_detach(idev);
- continue;
- }
- /* if no io and irq, search for next */
- if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
- pnp_device_detach(idev);
- continue;
- }
- /* found it */
- dev->base_addr = pnp_port_start(idev, 0);
- dev->irq = pnp_irq(idev, 0);
- printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
- (char *) isapnp_clone_list[i].driver_data,
- dev->base_addr, dev->irq);
- if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */
- printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
- pnp_device_detach(idev);
- return -ENXIO;
- }
- ei_status.priv = (unsigned long)idev;
- break;
- }
- if (!idev)
- continue;
- return 0;
+static int ne_isa_probe(struct device *dev)
+{
+ struct isa_device *idev;
+ struct net_device *ndev;
+ int err;
+ idev = to_isa_device(dev);
+ err = ne_create(&ndev, idev->base_addr, idev->irq, idev->id.driver_data);
+ if(!err){
+ /* HACK to set device name */
+ strcpy(idev->dev.name, ((struct ei_device *)ndev->priv)->name);
+ isa_set_drvdata(idev, ndev);
}
+ return err;
+}

- return -ENODEV;
+static void ne_isa_remove(struct device *dev)
+{
+ struct isa_device *idev;
+ struct net_device *ndev;
+ idev = to_isa_device(dev);
+ ndev = isa_get_drvdata(idev);
+ ne_remove(ndev);
}

-static int __init ne_probe1(struct net_device *dev, int ioaddr)
+static int ne_create(struct net_device **ndev, unsigned long base_addr, unsigned long irq, int bad)
{
- int i;
- unsigned char SA_prom[32];
- int wordlength = 2;
- const char *name = NULL;
- int start_page, stop_page;
- int neX000, ctron, copam, bad_card;
- int reg0, ret;
+ int err;
+
+ if (!(*ndev = alloc_etherdev(0)) ){
+ err = -ENOMEM;
+ goto alloc_fail;
+ }
+
+ (*ndev)->base_addr = base_addr;
+ (*ndev)->irq = irq;
+ SET_MODULE_OWNER(*ndev);
+
+ if (ne_probe1(*ndev, (*ndev)->base_addr, bad) != 0) { /* Shouldn't happen. */
+ printk(KERN_ERR "ne.c: Probe at %#lx failed\n", (*ndev)->base_addr);
+ err = -ENXIO;
+ goto probe_fail;
+ }
+
+ if ( (err = register_netdev(*ndev)) != 0)
+ goto register_fail;
+
+ return 0;
+
+register_fail:
+ kfree((*ndev)->priv);
+ release_region((*ndev)->base_addr, NE_IO_EXTENT);
+probe_fail:
+ kfree(*ndev);
+alloc_fail:
+ return err;
+}
+
+static void ne_remove(struct net_device *dev)
+{
+ if (dev) {
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, NE_IO_EXTENT);
+ kfree(dev->priv);
+ kfree(dev);
+ }
+}
+
+
+static int __init ne_detect(int ioaddr, int irq, int bad_card)
+{
+ int reg0, ret=0;
static unsigned version_printed;

- if (!request_region(ioaddr, NE_IO_EXTENT, dev->name))
+ if (!request_region(ioaddr, NE_IO_EXTENT, "NE2000"))
return -EBUSY;

reg0 = inb_p(ioaddr);
@@ -273,17 +331,14 @@
}

if (ei_debug && version_printed++ == 0)
- printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
+ printk(KERN_INFO "%s", version);

printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);

/* A user with a poor card that fails to ack the reset, or that
does not have a valid 0x57,0x57 signature can still use this
- without having to recompile. Specifying an i/o address along
- with an otherwise unused dev->mem_end value of "0xBAD" will
- cause the driver to skip these parts of the probe. */
-
- bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+ without having to recompile. Specifying a bad card will cause
+ the driver to skip these parts of the probe. */

/* Reset card. Who knows what dain-bramaged state it was left in. */

@@ -296,18 +351,40 @@
while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
if (jiffies - reset_start_time > 2*HZ/100) {
if (bad_card) {
- printk(" (warning: no reset ack)");
+ printk(" (warning: no reset ack)\n");
break;
} else {
printk(" not found (no reset ack).\n");
ret = -ENODEV;
goto err_out;
}
+ } else {
+ printk("\n");
}
+

outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */
}

+
+err_out:
+ release_region(ioaddr, NE_IO_EXTENT);
+ return ret;
+}
+
+static int __init ne_probe1(struct net_device *dev, int ioaddr, int bad_card)
+{
+ int i;
+ unsigned char SA_prom[32];
+ int wordlength = 2;
+ const char *name = NULL;
+ int start_page, stop_page;
+ int neX000, ctron, copam;
+ int ret;
+ if(ne_detect(ioaddr, dev->irq, bad_card))
+ return -ENODEV;
+ if (!request_region(ioaddr, NE_IO_EXTENT, dev->name))
+ return -EBUSY;
/* Read the 16 bytes of station address PROM.
We must first initialize registers, similar to NS8390_init(eifdev, 0).
We can't reliably read the SAPROM address without this.
@@ -731,13 +808,10 @@
return;
}

-
-#ifdef MODULE
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
-static struct net_device dev_ne[MAX_NE_CARDS];
static int io[MAX_NE_CARDS];
static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
+static int bad[MAX_NE_CARDS]; /* bad sig or no reset ack */

MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
@@ -753,51 +827,54 @@
is at boot) and so the probe will get confused by any other 8390 cards.
ISA device autoprobes on a running machine are not recommended anyway. */

-int init_module(void)
-{
- int this_dev, found = 0;

- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = &dev_ne[this_dev];
- dev->irq = irq[this_dev];
- dev->mem_end = bad[this_dev];
- dev->base_addr = io[this_dev];
- dev->init = ne_probe;
- if (register_netdev(dev) == 0) {
- found++;
- continue;
- }
- if (found != 0) { /* Got at least one. */
- return 0;
+static int __init ne_init(void)
+{
+ int i;
+ int err;
+#ifdef CONFIG_PNP
+ err = pnp_register_driver(&ne_pnp_driver);
+ if (err < 0) {
+ goto pnp_fail;
+ }
+#endif
+ /* First check any supplied i/o locations. User knows best. <cough> */
+ for (i = 0; i < MAX_NE_CARDS; i++) {
+ if (io[i] > 0x1ff) {
+ err = ne_detect(io[i], irq[i], bad[i]);
+ if (!err)
+ isa_device_register(io[i], irq[i], ne_isa_table);
+ else
+ printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[i]);
+
}
- if (io[this_dev] != 0)
- printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
- else
- printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
- return -ENXIO;
}
+
+ err = isa_driver_register(&ne_isa_driver);
+ if (err < 0) {
+ goto isa_fail;
+ }
+
return 0;
+isa_fail:
+ printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
+#ifdef CONFIG_PNP
+ pnp_unregister_driver(&ne_pnp_driver);
+pnp_fail:
+#endif
+ return -ENODEV;
}

-void cleanup_module(void)
+static void __exit ne_cleanup(void)
{
- int this_dev;
-
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = &dev_ne[this_dev];
- if (dev->priv != NULL) {
- void *priv = dev->priv;
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- if (idev)
- pnp_device_detach(idev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
- unregister_netdev(dev);
- kfree(priv);
- }
- }
+#ifdef CONFIG_PNP
+ pnp_unregister_driver(&ne_pnp_driver);
+#endif
+ isa_driver_unregister(&ne_isa_driver);
}
-#endif /* MODULE */
+
+module_init(ne_init);
+module_exit(ne_cleanup);


/*
diff -urN linux-2.5.69/include/linux/isa.h linux-2.5.69-isabus/include/linux/isa.h
--- linux-2.5.69/include/linux/isa.h 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.5.69-isabus/include/linux/isa.h 2003-05-12 20:18:54.000000000 -0400
@@ -0,0 +1,45 @@
+#ifndef _LINUX_ISA_H
+#define _LINUX_ISA_H
+
+#define ISA_ID_LEN 9
+
+struct isa_device_id {
+ char id[ISA_ID_LEN];
+ unsigned long driver_data;
+};
+
+struct isa_device {
+ struct isa_device_id id;
+ unsigned long base_addr;
+ unsigned int irq;
+ u64 dma_mask;
+ struct device dev;
+};
+
+#define to_isa_device(n) container_of(n, struct isa_device, dev)
+
+struct isa_driver {
+ const struct isa_device_id *id_table;
+ struct device_driver driver;
+};
+
+
+#define to_isa_driver(drv) container_of(drv, struct isa_driver, driver)
+
+extern struct bus_type isa_bus_type;
+int isa_driver_register(struct isa_driver *idrv);
+void isa_driver_unregister(struct isa_driver *idrv);
+
+int isa_device_register(unsigned long base_addr, unsigned long irq, struct isa_device_id *id);
+
+static inline void *isa_get_drvdata(struct isa_device *idev)
+{
+ return idev->dev.driver_data;
+}
+
+static inline void isa_set_drvdata(struct isa_device *idev, void *data)
+{
+ idev->dev.driver_data = data;
+}
+
+#endif


Attachments:
isa-bus.patch (17.13 kB)

2003-05-14 11:47:44

by Alan

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

On Mer, 2003-05-14 at 08:29, Riley Williams wrote:

> If there's going to be any problems, it's with devices claiming the
> same IOaddr as each other - and certain addresses are far too common
> where that's concerned - especially 0x0300 through 0x031F which are
> almost universal in their use !!!!!!!

This is why you have to get the ordering right. Specifically you have to
deal with probe unsafe hardware (ie ne2000) early. Once you've checked
0x300 isnt an NE2000 its generally safe to probe there, before that its
a very bad idea. Space.c knows about this and a vast amount more.


2003-05-14 22:34:23

by Jeff Muizelaar

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

Riley Williams wrote:

>Hi Jeff.
>
> > Attached is the rough beginnings of a patch that does this.
> >
> > Basically it adds ISA bus support and uses it in ne.c.
> >
> > ISA Bus Support
> > --
> > The bus uses ioaddr as the bus_id because I don't think we have
> > anything else unique to use.
>
>If there's going to be any problems, it's with devices claiming the
>same IOaddr as each other - and certain addresses are far too common
>where that's concerned - especially 0x0300 through 0x031F which are
>almost universal in their use !!!!!!!
>
>
This is a problem that already exists, if two devices are at the same io
address there is not much we can do. Autoprobe will pick up one first
and the second is out of luck.
(or are you confusing bus_id with device_id?)

>
> > Drivers are responsible for adding devices to the bus, through
> > isa_device_register(). Once added, devices stay around forever,
> > even after driver unload. Right now I use the device id's stolen
> > from eisa, but I can't see any reason not to just make ids up as
> > necessary.
>
> > ne.c
> > ---
> > ne_probe (the function called by Space.c) autoprobes for ne2000
> > devices and then as it finds them it calls isa_register_device.
> > It always returns -ENODEV. (eventually if all the net drivers
> > get moved to this model, some of this stuff could be moved into
> > Space.c) Later on, during module init the driver registers itself
> > with ISA bus and then ne_isa_probe is called appropriately.
>
>According to what I've been told and have seen for myself in the
>past, having this autoprobe at address 0x0300 is VERY likely to lock
>the machine up solid because of the number of other devices using
>that range. However, autoprobing the other addresses that this card
>can be at is apparently far less dangerous.
>
Nothing is being changed as far as this concerned. If you compile ne.c
into your kernel you get autoprobe at 0x300.

-Jeff

2003-05-14 22:58:51

by Jeff Muizelaar

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

Alan Cox wrote:

>On Mer, 2003-05-14 at 08:29, Riley Williams wrote:
>
>
>
>>If there's going to be any problems, it's with devices claiming the
>>same IOaddr as each other - and certain addresses are far too common
>>where that's concerned - especially 0x0300 through 0x031F which are
>>almost universal in their use !!!!!!!
>>
>>
>
>This is why you have to get the ordering right. Specifically you have to
>deal with probe unsafe hardware (ie ne2000) early. Once you've checked
>0x300 isnt an NE2000 its generally safe to probe there, before that its
>a very bad idea. Space.c knows about this and a vast amount more.
>
>
With the patch none of the ordering gets changed, with the following
exceptions, afaik:

1. When request_region would prevent something from probing over top of
something else. This is a bug with my current patch, but a tough one to
avoid because we normally don't request_resource until the probe
function is called...

2. Any breakage that results from spliting probe1 into detect and setup:
device on 0x300.
driver x, and driver y.
old:
probe1 from driver x fails late in the routine. (after the place
where the detect/setup split would occur)
driver y probe1 succeds and it gets the device

new:
driver x detect succeceds.
all other driver detects at 0x300 thus fail.
driver x setup fails.
nobody gets the device.

This is a driver issue and as long as the split of probe1 to
detect/setup is done right there should be no problems.

Also ethX numbering could change because of the alloc/register_netdev is
happening at module init time and not at autoprobe time.

-Jeff

2003-05-15 01:43:00

by Adam Belay

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

On Tue, May 13, 2003 at 10:01:12PM -0400, Jeff Muizelaar wrote:
> Attached is the rough beginings of a patch that does this.
>
> Basically it adds isa bus support and uses it ne.c.
>
> ISA Bus Support
> --
> The bus uses ioaddr as the bus_id because I don't think we have anything
> else unique to use.
>
> Drivers are responsible for adding devices to the bus, through
> isa_device_register(). Once added, devices stay around forever, even
> after driver unload.
> Right now I use the device id's stolen from eisa, but I can't see any
> reason not to just make ids up as necessary.
>
>
> ne.c
> ---
> ne_probe (the function called by Space.c) will autoprobe for ne2000
> devices and then as it finds them it calls isa_register_device. It
> always returns -ENODEV. (eventually if all the net drivers get moved to
> this model, some of this stuff could be moved into Space.c)
> Later on, during module init the driver registers itself with with isa
> bus and then ne_isa_probe is called appropriately.
>
> Moving to doing things this way, should make it possible to merge pci
> support back in and get rid of ne2k-pci.c, because all buses will use
> the same model. Eventually ne2k_cbus.c could probably be added merged as
> well.
>
> Any comments or suggestions?
>
> -Jeff

Hi Jeff,

I agree that an isa interface with sysfs would be useful. This patch looks like
a great start. I'm considering the following aditional changes...

1.) Perhaps the contents of /drivers/eisa and /drivers/isa should be held in the
same directory. Comments?

2.) Some collaboration between isapnp, eisa, and isa would be nice. This is
because all three of these interfaces could potentially be detecting the same
devices, resulting in nasty conflicts.

3.) A sysfs interface that would export isa information would be useful.

4.) Perhaps the isa drivers could match against the name of the legacy probing
driver or maybe the system should be designed to not use device_ids at all.


Also a few things to consider...

Is isa limited to one dma, one irq, and one ioport? I haven't seen more then
this anywere but it would be nice to know for registration purposes.

What is the best action to take if a legacy probing technique detects an area
that conflicts with a previous legacy probe from another driver. At the very
least, it would be nice if isa was aware of such things.


Best Regards,
Adam

2003-05-15 02:49:13

by Jeff Muizelaar

[permalink] [raw]
Subject: Re: [PATCH 0/4] NE2000 driver updates

Adam Belay wrote:

>On Tue, May 13, 2003 at 10:01:12PM -0400, Jeff Muizelaar wrote:
>
>
>
>Hi Jeff,
>
>I agree that an isa interface with sysfs would be useful. This patch looks like
>a great start. I'm considering the following aditional changes...
>
>1.) Perhaps the contents of /drivers/eisa and /drivers/isa should be held in the
>same directory. Comments?
>
Maybe. Though, eisa is still a sane bus, where we get ids and slot
numbers etc. The isa code is pretty much a free for all.

>2.) Some collaboration between isapnp, eisa, and isa would be nice. This is
>because all three of these interfaces could potentially be detecting the same
>devices, resulting in nasty conflicts.
>
Yes, agreed. Probably the easiest way to this is something like an
isa_reserve_(region/resources) that checks if either eisa or pnp know
about anything at the place where we are going to probe. This keeps isa
autoprobe from blindly stealing everything it can get it's hands on, and
lets the higher level buses have priority over it.

This also brings up the question of whether something from eisa/pnp
should also be registered on the isa bus.

>3.) A sysfs interface that would export isa information would be useful.
>
>4.) Perhaps the isa drivers could match against the name of the legacy probing
>driver or maybe the system should be designed to not use device_ids at all.
>
>
Yeah, basically all we need is something that says "this is my device,
give it to me later".

>
>Also a few things to consider...
>
>Is isa limited to one dma, one irq, and one ioport? I haven't seen more then
>this anywere but it would be nice to know for registration purposes.
>
>What is the best action to take if a legacy probing technique detects an area
>that conflicts with a previous legacy probe from another driver. At the very
>least, it would be nice if isa was aware of such things.
>
Right now, it is basically first come, first serve. request_region keeps
people from stepping on each other toes. So, once a driver finds a
region it likes it keeps it and nobody else can touch it. I think it is
probably best to keep it this way.

-Jeff