Second patch is 3c509 driver ported to the sysfs EISA infrastructure :
--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=eisa-3c509.patch
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.803   -> 1.804  
#	 drivers/net/3c509.c	1.25    -> 1.26   
#	 drivers/net/Space.c	1.13    -> 1.14   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/11/10	maz@hina.wild-wind.fr.eu.org	1.804
# Ported to sysfs EISA framework.
# Added new style init/cleanup.
# --------------------------------------------
#
diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c
--- a/drivers/net/3c509.c	Sun Nov 10 22:49:20 2002
+++ b/drivers/net/3c509.c	Sun Nov 10 22:49:20 2002
@@ -53,11 +53,13 @@
 			- Additional ethtool features
 		v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
 			- Increase *read_eeprom udelay to workaround oops with 2 cards.
+		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
+		    - Introduce driver model for EISA cards.
 */
 
 #define DRV_NAME	"3c509"
-#define DRV_VERSION	"1.19a"
-#define DRV_RELDATE	"28Oct2002"
+#define DRV_VERSION	"1.19b"
+#define DRV_RELDATE	"08Nov2002"
 
 /* A few values that may be tweaked. */
 
@@ -85,6 +87,8 @@
 #include <linux/delay.h>	/* for udelay() */
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
+#include <linux/device.h>
+#include <linux/eisa.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -169,6 +173,9 @@
 #ifdef CONFIG_PM
 	struct pm_dev *pmdev;
 #endif
+#ifdef CONFIG_EISA
+	struct eisa_device *edev;
+#endif
 };
 static int id_port __initdata = 0x110;	/* Start with 0x110 to avoid new sound cards.*/
 static struct net_device *el3_root_dev;
@@ -193,6 +200,26 @@
 static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data);
 #endif
 
+#ifdef CONFIG_EISA
+struct eisa_device_id el3_eisa_ids[] = {
+		{ "TCM5092" },
+		{ "TCM5093" },
+		{ "" }
+};
+
+static int el3_eisa_probe (struct device *device);
+static int el3_eisa_remove (struct device *device);
+
+struct eisa_driver el3_eisa_driver = {
+		.id_table = el3_eisa_ids,
+		.driver   = {
+				.name    = "3c509",
+				.probe   = el3_eisa_probe,
+				.remove  = __devexit_p (el3_eisa_remove)
+		}
+};
+#endif
+
 #ifdef CONFIG_MCA
 struct el3_mca_adapters_struct {
 	char* name;
@@ -239,55 +266,102 @@
 #endif /* __ISAPNP__ */
 static int nopnp;
 
-int __init el3_probe(struct net_device *dev, int card_idx)
+/* With the driver model introduction for EISA devices, both init
+ * and cleanup have been split :
+ * - EISA devices probe/remove starts in el3_eisa_probe/el3_eisa_remove
+ * - MCA/ISA still use el3_probe
+ *
+ * Both call el3_common_init/el3_common_remove. */
+
+static int __init el3_common_init (struct net_device *dev)
 {
-	struct el3_private *lp;
-	short lrs_state = 0xff, i;
-	int ioaddr, irq, if_port;
-	u16 phys_addr[3];
-	static int current_tag;
-	int mca_slot = -1;
-#ifdef __ISAPNP__
-	static int pnp_cards;
-#endif /* __ISAPNP__ */
+    struct el3_private *lp = dev->priv;
+	short i;
+  
+#ifdef CONFIG_EISA
+	if (!lp->edev)				/* EISA devices are not chained */
+#endif
+	{
+			lp->next_dev = el3_root_dev;
+			el3_root_dev = dev;
+	}
+	spin_lock_init(&lp->lock);
 
-	if (dev) SET_MODULE_OWNER(dev);
+	if (dev->mem_start & 0x05) { /* xcvr codes 1/3/4/12 */
+		dev->if_port = (dev->mem_start & 0x0f);
+	} else { /* xcvr codes 0/8 */
+		/* use eeprom value, but save user's full-duplex selection */
+		dev->if_port |= (dev->mem_start & 0x08);
+	}
 
-	/* First check all slots of the EISA bus.  The next slot address to
-	   probe is kept in 'eisa_addr' to support multiple probe() calls. */
-	if (EISA_bus) {
-		static int eisa_addr = 0x1000;
-		while (eisa_addr < 0x9000) {
-			int device_id;
+	{
+		const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
+		printk("%s: 3c5x9 at %#3.3lx, %s port, address ",
+			dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)]);
+	}
 
-			ioaddr = eisa_addr;
-			eisa_addr += 0x1000;
+	/* Read in the station address. */
+	for (i = 0; i < 6; i++)
+		printk(" %2.2x", dev->dev_addr[i]);
+	printk(", IRQ %d.\n", dev->irq);
 
-			/* Check the standard EISA ID register for an encoded '3Com'. */
-			if (inw(ioaddr + 0xC80) != 0x6d50)
-				continue;
+	if (el3_debug > 0)
+		printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
 
-			/* Avoid conflict with 3c590, 3c592, 3c597, etc */
-			device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
-			if ((device_id & 0xFF00) == 0x5900) {
-				continue;
-			}
+	/* The EL3-specific entries in the device structure. */
+	dev->open = &el3_open;
+	dev->hard_start_xmit = &el3_start_xmit;
+	dev->stop = &el3_close;
+	dev->get_stats = &el3_get_stats;
+	dev->set_multicast_list = &set_multicast_list;
+	dev->tx_timeout = el3_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->do_ioctl = netdev_ioctl;
 
-			/* Change the register set to the configuration window 0. */
-			outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
+#ifdef CONFIG_PM
+	/* register power management */
+	lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback);
+	if (lp->pmdev) {
+		struct pm_dev *p;
+		p = lp->pmdev;
+		p->data = (struct net_device *)dev;
+	}
+#endif
 
-			irq = inw(ioaddr + WN0_IRQ) >> 12;
-			if_port = inw(ioaddr + 6)>>14;
-			for (i = 0; i < 3; i++)
-				phys_addr[i] = htons(read_eeprom(ioaddr, i));
+	return 0;
+}
 
-			/* Restore the "Product ID" to the EEPROM read register. */
-			read_eeprom(ioaddr, 3);
+static void el3_common_remove (struct net_device *dev)
+{
+		struct el3_private *lp = dev->priv;
 
-			/* Was the EISA code an add-on hack?  Nahhhhh... */
-			goto found;
-		}
-	}
+		(void) lp;				/* Keep gcc quiet... */
+#ifdef CONFIG_MCA		
+		if(lp->mca_slot!=-1)
+			mca_mark_as_unused(lp->mca_slot);
+#endif
+#ifdef CONFIG_PM
+		if (lp->pmdev)
+			pm_unregister(lp->pmdev);
+#endif
+
+		unregister_netdev (dev);
+		release_region(dev->base_addr, EL3_IO_EXTENT);
+		kfree (dev);
+}
+
+static int __init el3_probe(int card_idx)
+{
+    struct net_device *dev;
+	struct el3_private *lp;
+	short lrs_state = 0xff, i;
+	int ioaddr, irq, if_port;
+	u16 phys_addr[3];
+	static int current_tag;
+	int mca_slot = -1;
+#ifdef __ISAPNP__
+	static int pnp_cards;
+#endif /* __ISAPNP__ */
 
 #ifdef CONFIG_MCA
 	/* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, heavily
@@ -464,6 +538,8 @@
 	}
 	irq = id_read_eeprom(9) >> 12;
 
+#if 0							/* Huh ?
+								   Can someone explain what is this for ? */
 	if (dev) {					/* Set passed-in IRQ or I/O Addr. */
 		if (dev->irq > 1  &&  dev->irq < 16)
 			irq = dev->irq;
@@ -476,6 +552,7 @@
 				return -ENODEV;
 		}
 	}
+#endif
 
 	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
 		return -EBUSY;
@@ -495,76 +572,83 @@
 	/* Free the interrupt so that some other card can use it. */
 	outw(0x0f00, ioaddr + WN0_IRQ);
  found:
+	dev = init_etherdev(NULL, sizeof(struct el3_private));
 	if (dev == NULL) {
-		dev = init_etherdev(dev, sizeof(struct el3_private));
-		if (dev == NULL) {
-			release_region(ioaddr, EL3_IO_EXTENT);
-			return -ENOMEM;
-		}
-		SET_MODULE_OWNER(dev);
+	    release_region(ioaddr, EL3_IO_EXTENT);
+		return -ENOMEM;
 	}
+	SET_MODULE_OWNER(dev);
+
 	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
+	dev->if_port = if_port;
+	lp = dev->priv;
+	lp->mca_slot = mca_slot;
 
-	if (dev->mem_start & 0x05) { /* xcvr codes 1/3/4/12 */
-		dev->if_port = (dev->mem_start & 0x0f);
-	} else { /* xcvr codes 0/8 */
-		/* use eeprom value, but save user's full-duplex selection */
-		dev->if_port = (if_port | (dev->mem_start & 0x08) );
-	}
+	return el3_common_init (dev);
+}
 
-	{
-		const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
-		printk("%s: 3c5x9 at %#3.3lx, %s port, address ",
-			dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)]);
+#ifdef CONFIG_EISA
+static int __init el3_eisa_probe (struct device *device)
+{
+	struct el3_private *lp;
+	short i;
+	int ioaddr, irq, if_port;
+	u16 phys_addr[3];
+	struct net_device *dev = NULL;
+	struct eisa_device *edev;
+
+	/* Yeepee, The driver framework is calling us ! */
+	edev = to_eisa_device (device);
+	ioaddr = edev->base_addr;
+	
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
+		return -EBUSY;
+
+	/* Change the register set to the configuration window 0. */
+	outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
+
+	irq = inw(ioaddr + WN0_IRQ) >> 12;
+	if_port = inw(ioaddr + 6)>>14;
+	for (i = 0; i < 3; i++)
+			phys_addr[i] = htons(read_eeprom(ioaddr, i));
+
+	/* Restore the "Product ID" to the EEPROM read register. */
+	read_eeprom(ioaddr, 3);
+
+	dev = init_etherdev(NULL, sizeof(struct el3_private));
+	if (dev == NULL) {
+			release_region(ioaddr, EL3_IO_EXTENT);
+			return -ENOMEM;
 	}
 
-	/* Read in the station address. */
-	for (i = 0; i < 6; i++)
-		printk(" %2.2x", dev->dev_addr[i]);
-	printk(", IRQ %d.\n", dev->irq);
+	SET_MODULE_OWNER(dev);
 
-	/* Make up a EL3-specific-data structure. */
-	if (dev->priv == NULL)
-		dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
-	if (dev->priv == NULL)
-		return -ENOMEM;
-	memset(dev->priv, 0, sizeof(struct el3_private));
-	
+	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	dev->if_port = if_port;
 	lp = dev->priv;
-	lp->mca_slot = mca_slot;
-	lp->next_dev = el3_root_dev;
-	spin_lock_init(&lp->lock);
-	el3_root_dev = dev;
+	lp->mca_slot = -1;
+	lp->edev = edev;
+	edev->driver_data = dev;
 
-	if (el3_debug > 0)
-		printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
+	return el3_common_init (dev);
+}
 
-	/* The EL3-specific entries in the device structure. */
-	dev->open = &el3_open;
-	dev->hard_start_xmit = &el3_start_xmit;
-	dev->stop = &el3_close;
-	dev->get_stats = &el3_get_stats;
-	dev->set_multicast_list = &set_multicast_list;
-	dev->tx_timeout = el3_tx_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->do_ioctl = netdev_ioctl;
+static int __devexit el3_eisa_remove (struct device *device)
+{
+		struct eisa_device *edev;
+		struct net_device *dev;
 
-#ifdef CONFIG_PM
-	/* register power management */
-	lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback);
-	if (lp->pmdev) {
-		struct pm_dev *p;
-		p = lp->pmdev;
-		p->data = (struct net_device *)dev;
-	}
-#endif
+		edev = to_eisa_device (device);
+		dev  = edev->driver_data;
 
-	/* Fill in the generic fields of the device structure. */
-	ether_setup(dev);
-	return 0;
+		el3_common_remove (dev);
+		return 0;
 }
+#endif
 
 /* Read a word from the EEPROM using the regular EEPROM access register.
    Assume that we are in register window zero.
@@ -974,7 +1058,8 @@
 el3_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
-
+	struct el3_private *lp = (struct el3_private *)dev->priv;
+	
 	if (el3_debug > 2)
 		printk("%s: Shutting down ethercard.\n", dev->name);
 
@@ -983,8 +1068,12 @@
 	free_irq(dev->irq, dev);
 	/* Switching back to window 0 disables the IRQ. */
 	EL3WINDOW(0);
-	/* But we explicitly zero the IRQ line select anyway. */
-	outw(0x0f00, ioaddr + WN0_IRQ);
+	if (!lp->edev) {
+	    /* But we explicitly zero the IRQ line select anyway. Don't do
+	     * it on EISA cards, it prevents the module from getting an
+	     * IRQ after unload+reload... */
+	    outw(0x0f00, ioaddr + WN0_IRQ);
+	}
 
 	return 0;
 }
@@ -1406,7 +1495,6 @@
 
 #endif /* CONFIG_PM */
 
-#ifdef MODULE
 /* Parameters that may be passed into the module. */
 static int debug = -1;
 static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
@@ -1428,8 +1516,7 @@
 MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B) ISA/PnP ethernet driver");
 MODULE_LICENSE("GPL");
 
-int
-init_module(void)
+static int __init el3_init_module(void)
 {
 	int el3_cards = 0;
 
@@ -1437,7 +1524,7 @@
 		el3_debug = debug;
 
 	el3_root_dev = NULL;
-	while (el3_probe(0, el3_cards) == 0) {
+	while (el3_probe(el3_cards) == 0) {
 		if (irq[el3_cards] > 1)
 			el3_root_dev->irq = irq[el3_cards];
 		if (xcvr[el3_cards] >= 0)
@@ -1445,34 +1532,36 @@
 		el3_cards++;
 	}
 
+#ifdef CONFIG_EISA
+	if (eisa_driver_register (&el3_eisa_driver) < 0) {
+			eisa_driver_unregister (&el3_eisa_driver);
+	}
+	else
+			el3_cards++;				/* Found an eisa card */
+#endif
 	return el3_cards ? 0 : -ENODEV;
 }
 
-void
-cleanup_module(void)
+static void __exit el3_cleanup_module(void)
 {
 	struct net_device *next_dev;
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (el3_root_dev) {
 		struct el3_private *lp = (struct el3_private *)el3_root_dev->priv;
-#ifdef CONFIG_MCA		
-		if(lp->mca_slot!=-1)
-			mca_mark_as_unused(lp->mca_slot);
-#endif
 
-#ifdef CONFIG_PM
-		if (lp->pmdev)
-			pm_unregister(lp->pmdev);
-#endif
 		next_dev = lp->next_dev;
-		unregister_netdev(el3_root_dev);
-		release_region(el3_root_dev->base_addr, EL3_IO_EXTENT);
-		kfree(el3_root_dev);
+		el3_common_remove (el3_root_dev);
 		el3_root_dev = next_dev;
 	}
+
+#ifdef CONFIG_EISA
+	eisa_driver_unregister (&el3_eisa_driver);
+#endif
 }
-#endif /* MODULE */
+
+module_init (el3_init_module);
+module_exit (el3_cleanup_module);
 
 /*
  * Local variables:
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	Sun Nov 10 22:49:20 2002
+++ b/drivers/net/Space.c	Sun Nov 10 22:49:20 2002
@@ -56,7 +56,6 @@
 extern int hp_plus_probe(struct net_device *dev);
 extern int express_probe(struct net_device *);
 extern int eepro_probe(struct net_device *);
-extern int el3_probe(struct net_device *);
 extern int at1500_probe(struct net_device *);
 extern int at1700_probe(struct net_device *);
 extern int fmv18x_probe(struct net_device *);
@@ -215,9 +214,6 @@
  * look for EISA/PCI/MCA cards in addition to ISA cards).
  */
 static struct devprobe isa_probes[] __initdata = {
-#ifdef CONFIG_EL3		/* ISA, EISA, MCA 3c5x9 */
-	{el3_probe, 0},
-#endif
 #ifdef CONFIG_HP100 		/* ISA, EISA & PCI */
 	{hp100_probe, 0},
 #endif	
--=-=-=
-- Places change, faces change. Life is so very strange.--=-=-=-- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/