NE2000 driver updates
Subsystems (2)
cover 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
PATCH 1/4 NE2000 driver updates
drivers/net/ne.c +90 -69
@@ -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); } } }
PATCH 2/4 NE2000 driver updates
In reply to Jeff Muizelaardrivers/net/ne.c +8 -0
@@ -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);
PATCH 3/4 NE2000 driver updates
In reply to Jeff Muizelaardrivers/net/ne.c +101 -82
@@ -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);/*
Here is the correct patch, the previous one wasn't...
-Jeff
drivers/net/ne.c +101 -82
@@ -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);/*
drivers/net/Space.c +1 -1
@@ -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) */
PATCH 4/4 NE2000 driver updates
In reply to Jeff Muizelaardrivers/net/ne.c +9 -12
@@ -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");
Quoted 3 lines · Jeff Muizelaar
Caveats:
It appears that the patch will break any autoprobe ordering because it no longer usesSpace.cwhen 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
Quoted 9 lines · Alan Cox
The ne2000 ordering with the other ISA stuff in
space.cis 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.cfor 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
Quoted 2 lines · Jeff Muizelaar
Are we stuck with
Space.cforever? 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
Quoted 7 lines · Alan Cox
Quoted 1 line · Jeff Muizelaar
Are we stuck with
Space.cforever? 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 www.opencores.org, maybe we can convince hardware makers to use a better design. </plug>
Quoted 3 lines · Jeff Garzik
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.
Quoted 3 lines
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
Quoted 1 line
Did I mention that a GIGE ne2000 card exists?
I've got a 100Mbit one.
Alan
Hi Alan.
Quoted 9 lines
Quoted 2 lines
Are we stuck with
Space.cforever? 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
Quoted 8 lines
poke around for ISA device
Found one ?
Alloc ISA device
Fill in ports/range/IRQ
Fill in vendor/product with invented idents Announce itThen 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
Quoted 7 lines · Alan Cox
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
Quoted 11 lines
poke around for ISA device
Found one ?
Alloc isadevice
Fill in ports/range/irq
Fill in vendor/product with invented idents Announce itThen have ne2000 driver model code do the actual setup
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
drivers/isa/isa-bus.c +99 -0
@@ -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);
drivers/isa/Makefile +3 -0
@@ -0,0 +1,3 @@ +# Makefile for the Linux isa bus model + +obj-$(CONFIG_ISA) += isa-bus.o
drivers/Makefile +1 -0
@@ -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/
drivers/net/ne.c +213 -136
451 lines not on this page · raw message
include/linux/isa.h +45 -0
45 lines not on this page · raw message
Quoted 25 lines · Jeff Muizelaar
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 thebus_idbecause 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 bySpace.c) will autoprobe for ne2000 devices and then as it finds them it callsisa_register_device. It always returns-ENODEV. (eventually if all the net drivers get moved to this model, some of this stuff could be moved intoSpace.c) Later on, during module init the driver registers itself with with isa bus and thenne_isa_probeis called appropriately.
Quoted 8 lines
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. Eventuallyne2k_cbus.ccould 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
Quoted 10 lines · Adam Belay
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.
Quoted 2 lines
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.
Quoted 5 lines
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_idsat all.
Yeah, basically all we need is something that says "this is my device, give it to me later".
Quoted 7 lines
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