Skip to contentSkip to conversation

fix 3c509.c for MCA drivers

PATCH In review James Bottomley 4 participants 10 messages Feb 3, 2003 – Feb 15, 2003

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fix 3c509.c for MCA drivers

The attached fixes the MCA version of the 3c509 and updates it to the new MCA API.

Someone who knows PNP-ISA should migrate it to a probing API for that too.

I've put the el3_probe back into Space.c for ISA only otherwise the driver won't work for ISA (could someone with an ISA card test this).

James

# 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.956   -> 1.957  
#	 drivers/net/3c509.c	1.29    -> 1.30   
#	 drivers/net/Space.c	1.15    -> 1.16   

#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/02 jejb@mulgrave.(none) 1.957
# 3c509 fixes: correct MCA probing, add back ISA probe to Space.c # --------------------------------------------
#

drivers/net/3c509.c +132 -110
diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c
@@ -103,6 +103,10 @@
 static int el3_debug = 2;
 #endif
 
+/* Used to do a global count of all the cards in the system.  Must be
+ * a global variable so that the mca/eisa probe routines can increment
+ * it */
+static int el3_cards = 0;
 
 /* To minimize the size of the driver source I only define operating
    constants if they are used several times.  You'll need the manual
@@ -167,16 +171,15 @@
 	/* skb send-queue */
 	int head, size;
 	struct sk_buff *queue[SKB_QUEUE_SIZE];
-	char mca_slot;
 #ifdef CONFIG_PM
 	struct pm_dev *pmdev;
 #endif
-#ifdef __ISAPNP__
-	struct pnp_dev *pnpdev;
-#endif
-#ifdef CONFIG_EISA
-	struct eisa_device *edev;
-#endif
+	enum {
+		EL3_MCA,
+		EL3_PNP,
+		EL3_EISA,
+	} type;						/* type of device */
+	struct device *dev;
 };
 static int id_port __initdata = 0x110;	/* Start with 0x110 to avoid new sound cards.*/
 static struct net_device *el3_root_dev;
@@ -200,6 +203,8 @@
 static int el3_resume(struct pm_dev *pdev);
 static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data);
 #endif
+/* generic device remove for all device types */
+static int el3_device_remove (struct device *device);
 
 #ifdef CONFIG_EISA
 struct eisa_device_id el3_eisa_ids[] = {
@@ -209,31 +214,46 @@
 };
 
 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)
+				.remove  = __devexit_p (el3_device_remove)
 		}
 };
 #endif
 
 #ifdef CONFIG_MCA
-struct el3_mca_adapters_struct {
-	char* name;
-	int id;
+static int el3_mca_probe(struct device *dev);
+
+static short el3_mca_adapter_ids[] __initdata = {
+		0x627c,
+		0x627d,
+		0x62db,
+		0x62f6,
+		0x62f7,
+		0x0000
+};
+
+static char *el3_mca_adapter_names[] __initdata = {
+		"3Com 3c529 EtherLink III (10base2)",
+		"3Com 3c529 EtherLink III (10baseT)",
+		"3Com 3c529 EtherLink III (test mode)",
+		"3Com 3c529 EtherLink III (TP or coax)",
+		"3Com 3c529 EtherLink III (TP)",
+		NULL
 };
 
-static struct el3_mca_adapters_struct el3_mca_adapters[] __initdata = {
-	{ "3Com 3c529 EtherLink III (10base2)", 0x627c },
-	{ "3Com 3c529 EtherLink III (10baseT)", 0x627d },
-	{ "3Com 3c529 EtherLink III (test mode)", 0x62db },
-	{ "3Com 3c529 EtherLink III (TP or coax)", 0x62f6 },
-	{ "3Com 3c529 EtherLink III (TP)", 0x62f7 },
-	{ NULL, 0 },
+static struct mca_driver el3_mca_driver = {
+		.id_table = el3_mca_adapter_ids,
+		.driver = {
+				.name = "3c529",
+				.bus = &mca_bus_type,
+				.probe = el3_mca_probe,
+				.remove = __devexit_p(el3_device_remove),
+		},
 };
 #endif /* CONFIG_MCA */
 
@@ -264,12 +284,12 @@
 };
 
 static u16 el3_isapnp_phys_addr[8][3];
-#endif /* __ISAPNP__ */
 static int nopnp;
+#endif /* __ISAPNP__ */
 
 /* 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
+ * - EISA devices probe/remove starts in el3_eisa_probe/el3_device_remove
  * - MCA/ISA still use el3_probe
  *
  * Both call el3_common_init/el3_common_remove. */
@@ -278,10 +298,9 @@
 {
 	struct el3_private *lp = dev->priv;
 	short i;
-  
-#ifdef CONFIG_EISA
-	if (!lp->edev)				/* EISA devices are not chained */
-#endif
+
+	el3_cards++;
+	if (!lp->dev)				/* probed devices are not chained */
 	{
 			lp->next_dev = el3_root_dev;
 			el3_root_dev = dev;
@@ -337,17 +356,13 @@
 		struct el3_private *lp = dev->priv;
 
 		(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
 #ifdef __ISAPNP__
-		if (lp->pnpdev)
-			pnp_device_detach(lp->pnpdev);
+		if (lp->type == EL3_PNP)
+			pnp_device_detach(to_pnp_dev(lp->dev));
 #endif
 
 		unregister_netdev (dev);
@@ -363,76 +378,11 @@
 	int ioaddr, irq, if_port;
 	u16 phys_addr[3];
 	static int current_tag;
-	int mca_slot = -1;
 #ifdef __ISAPNP__
 	static int pnp_cards;
 	struct pnp_dev *idev = NULL;
 #endif /* __ISAPNP__ */
 
-#ifdef CONFIG_MCA
-	/* Based on Erik Nygren's ([email protected]) 3c529 patch, heavily
-	 * modified by Chris Beauregard ([email protected])
-	 * to support standard MCA probing.
-	 *
-	 * redone for multi-card detection by ZP Gu ([email protected])
-	 * now works as a module
-	 */
-
-	if( MCA_bus ) {
-		int slot, j;
-		u_char pos4, pos5;
-
-		for( j = 0; el3_mca_adapters[j].name != NULL; j ++ ) {
-			slot = 0;
-			while( slot != MCA_NOTFOUND ) {
-				slot = mca_find_unused_adapter(
-					el3_mca_adapters[j].id, slot );
-				if( slot == MCA_NOTFOUND ) break;
-
-				/* if we get this far, an adapter has been
-				 * detected and is enabled
-				 */
-
-				pos4 = mca_read_stored_pos( slot, 4 );
-				pos5 = mca_read_stored_pos( slot, 5 );
-
-				ioaddr = ((short)((pos4&0xfc)|0x02)) << 8;
-				irq = pos5 & 0x0f;
-
-				/* probing for a card at a particular IO/IRQ */
-				if(dev && ((dev->irq >= 1 && dev->irq != irq) ||
-			   	(dev->base_addr >= 1 && dev->base_addr != ioaddr))) {
-					slot++;         /* probing next slot */
-					continue;
-				}
-
-				printk("3c509: found %s at slot %d\n",
-					el3_mca_adapters[j].name, slot + 1 );
-
-				/* claim the slot */
-				mca_set_adapter_name(slot, el3_mca_adapters[j].name);
-				mca_set_adapter_procfn(slot, NULL, NULL);
-				mca_mark_as_used(slot);
-
-				if_port = pos4 & 0x03;
-				if (el3_debug > 2) {
-					printk("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
-				}
-				EL3WINDOW(0);
-				for (i = 0; i < 3; i++) {
-					phys_addr[i] = htons(read_eeprom(ioaddr, i));
-				}
-				
-				mca_slot = slot;
-
-				goto found;
-			}
-		}
-		/* if we get here, we didn't find an MCA adapter */
-		return -ENODEV;
-	}
-#endif /* CONFIG_MCA */
-
 #ifdef __ISAPNP__
 	if (nopnp == 1)
 		goto no_pnp;
@@ -580,7 +530,7 @@
 
 	/* 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) {
 	    release_region(ioaddr, EL3_IO_EXTENT);
@@ -594,13 +544,80 @@
 	dev->if_port = if_port;
 	lp = dev->priv;
 #ifdef __ISAPNP__
-	lp->pnpdev = idev;
+	lp->dev = &idev->dev;
 #endif
-	lp->mca_slot = mca_slot;
 
 	return el3_common_init (dev);
 }
 
+#ifdef CONFIG_MCA
+static int __init el3_mca_probe(struct device *device) {
+		/* Based on Erik Nygren's ([email protected]) 3c529 patch,
+		 * heavily modified by Chris Beauregard
+		 * ([email protected]) to support standard MCA
+		 * probing.
+		 *
+		 * redone for multi-card detection by ZP Gu ([email protected])
+		 * now works as a module */
+
+		struct el3_private *lp;
+		short i;
+		int ioaddr, irq, if_port;
+		u16 phys_addr[3];
+		struct net_device *dev = NULL;
+		u_char pos4, pos5;
+		struct mca_device *mdev = to_mca_device(device);
+		int slot = mdev->slot;
+
+		pos4 = mca_device_read_stored_pos(mdev, 4);
+		pos5 = mca_device_read_stored_pos(mdev, 5);
+
+		ioaddr = ((short)((pos4&0xfc)|0x02)) << 8;
+		irq = pos5 & 0x0f;
+
+
+		printk("3c529: found %s at slot %d\n",
+			   el3_mca_adapter_names[mdev->index], slot + 1);
+
+		/* claim the slot */
+		strncpy(device->name, el3_mca_adapter_names[mdev->index],
+				sizeof(device->name));
+		mca_device_set_claim(mdev, 1);
+
+		if_port = pos4 & 0x03;
+
+		irq = mca_device_transform_irq(mdev, irq);
+		ioaddr = mca_device_transform_ioport(mdev, ioaddr); 
+		if (el3_debug > 2) {
+				printk("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
+		}
+		EL3WINDOW(0);
+		for (i = 0; i < 3; i++) {
+				phys_addr[i] = htons(read_eeprom(ioaddr, i));
+		}
+
+		dev = init_etherdev(NULL, sizeof(struct el3_private));
+		if (dev == NULL) {
+				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->dev = device;
+		lp->type = EL3_MCA;
+		device->driver_data = dev;
+
+		return el3_common_init (dev);
+}
+		
+#endif /* CONFIG_MCA */
+
 #ifdef CONFIG_EISA
 static int __init el3_eisa_probe (struct device *device)
 {
@@ -642,25 +659,26 @@
 	dev->irq = irq;
 	dev->if_port = if_port;
 	lp = dev->priv;
-	lp->mca_slot = -1;
-	lp->edev = edev;
+	lp->dev = device;
+	lp->type = EL3_EISA;
 	eisa_set_drvdata (edev, dev);
 
 	return el3_common_init (dev);
 }
+#endif
 
-static int __devexit el3_eisa_remove (struct device *device)
+/* This remove works for all device types.
+ *
+ * The net dev must be stored in the driver_data field */
+static int __devexit el3_device_remove (struct device *device)
 {
-		struct eisa_device *edev;
 		struct net_device *dev;
 
-		edev = to_eisa_device (device);
-		dev  = eisa_get_drvdata (edev);
+		dev  = device->driver_data;
 
 		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.
@@ -1080,7 +1098,7 @@
 	free_irq(dev->irq, dev);
 	/* Switching back to window 0 disables the IRQ. */
 	EL3WINDOW(0);
-	if (!lp->edev) {
+	if (lp->type != EL3_EISA) {
 	    /* 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... */
@@ -1530,7 +1548,7 @@
 
 static int __init el3_init_module(void)
 {
-	int el3_cards = 0;
+	el3_cards = 0;
 
 	if (debug >= 0)
 		el3_debug = debug;
@@ -1548,8 +1566,9 @@
 	if (eisa_driver_register (&el3_eisa_driver) < 0) {
 			eisa_driver_unregister (&el3_eisa_driver);
 	}
-	else
-			el3_cards++;				/* Found an eisa card */
+#endif
+#ifdef CONFIG_MCA
+	mca_register_driver(&el3_mca_driver);
 #endif
 	return el3_cards ? 0 : -ENODEV;
 }
@@ -1568,6 +1587,9 @@
 
 #ifdef CONFIG_EISA
 	eisa_driver_unregister (&el3_eisa_driver);
+#endif
+#ifdef CONFIG_MCA
+	mca_unregister_driver(&el3_mca_driver);
 #endif
 }
 
drivers/net/Space.c +3 -0
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
@@ -224,6 +224,9 @@
 #ifdef CONFIG_EL2 		/* 3c503 */
 	{el2_probe, 0},
 #endif
+#ifdef CONFIG_EL3
+	{el3_probe, 0},
+#endif
 #ifdef CONFIG_HPLAN
 	{hp_probe, 0},
 #endif
#1 lore raw
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"James" == James Bottomley <[email protected]> writes:

James> I've put the el3_probe back into Space.c for ISA only otherwise James> the driver won't work for ISA (could someone with an ISA card James> test this).

I've managed to finally get it to compile/work for ISA/ISA-PNP. I checked the stuff was working properly *without* el3_probe in Space.c. I also restored the 'ether=' functionality.

Anyway, this part of the code (ISA/ISA-PNP) is a real mess, and I wish somebody who knows what he's doing would clean it up.

        M.

===== drivers/net/3c509.c 1.25.1.5 vs 1.34 =====

drivers/net/3c509.c +37 -29
@@ -338,16 +338,6 @@
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->do_ioctl = netdev_ioctl;
 
-#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
-
 	return 0;
 }
 
@@ -417,6 +407,13 @@
 					phys_addr[j] =
 						htons(read_eeprom(ioaddr, j));
 			if_port = read_eeprom(ioaddr, 8) >> 14;
+			if (!(dev = init_etherdev(NULL, sizeof(struct el3_private)))) {
+					release_region(ioaddr, EL3_IO_EXTENT);
+					pnp_device_detach(idev);
+					return -ENOMEM;
+			}
+
+			SET_MODULE_OWNER(dev);
 			pnp_cards++;
 			goto found;
 		}
@@ -497,24 +494,29 @@
 	}
 	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)
+	if (!(dev = init_etherdev(NULL, sizeof(struct el3_private))))
+			return -ENOMEM;
+
+	SET_MODULE_OWNER(dev);
+	
+	/* Set passed-in IRQ or I/O Addr. */
+	if (dev->irq > 1  &&  dev->irq < 16)
 			irq = dev->irq;
 
-		if (dev->base_addr) {
+	if (dev->base_addr) {
 			if (dev->mem_end == 0x3c509 			/* Magic key */
 				&& dev->base_addr >= 0x200  &&  dev->base_addr <= 0x3e0)
-				ioaddr = dev->base_addr & 0x3f0;
-			else if (dev->base_addr != ioaddr)
-				return -ENODEV;
-		}
+					ioaddr = dev->base_addr & 0x3f0;
+			else if (dev->base_addr != ioaddr) {
+					unregister_netdev (dev);
+					return -ENODEV;
+			}
 	}
-#endif
 
-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
-		return -EBUSY;
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509")) {
+			unregister_netdev (dev);
+			return -EBUSY;
+	}
 
 	/* Set the adaptor tag so that the next card can be found. */
 	outb(0xd0 + ++current_tag, id_port);
@@ -524,19 +526,15 @@
 
 	EL3WINDOW(0);
 	if (inw(ioaddr) != 0x6d50) {
+		unregister_netdev (dev);
 		release_region(ioaddr, EL3_IO_EXTENT);
 		return -ENODEV;
 	}
 
 	/* Free the interrupt so that some other card can use it. */
 	outw(0x0f00, ioaddr + WN0_IRQ);
-
-	dev = init_etherdev(NULL, sizeof(struct el3_private));
-	if (dev == NULL) {
-	    release_region(ioaddr, EL3_IO_EXTENT);
-		return -ENOMEM;
-	}
-	SET_MODULE_OWNER(dev);
+	
+ found:							/* PNP jumps here... */
 
 	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
 	dev->base_addr = ioaddr;
@@ -545,6 +543,16 @@
 	lp = dev->priv;
 #ifdef __ISAPNP__
 	lp->dev = &idev->dev;
+#endif
+
+#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
 
 	return el3_common_init (dev);

===== drivers/net/Space.c 1.11.1.5 vs 1.19 =====

drivers/net/Space.c +0 -3
@@ -224,9 +224,6 @@
 #ifdef CONFIG_EL2 		/* 3c503 */
 	{el2_probe, 0},
 #endif
-#ifdef CONFIG_EL3
-	{el3_probe, 0},
-#endif
 #ifdef CONFIG_HPLAN
 	{hp_probe, 0},
 #endif
Signature · 2 lines
-- 
Places change, faces change. Life is so very strange.
#2 lore raw

PATCH 1/1 EISA/sysfs update

In reply to James Bottomley

James, LKML,

Here is the latest round of EISA/sysfs hacking.

Quoted 1 line

From the changelog :

# EISA/sysfs update.
#
# - Separate bus root code from generic code.
# - Add driver for i82375 PCI/EISA bridge.
# - Hacked parisc eisa driver so it can act as a root device. # - Add driver for so-called virtual root (for bridge-less systems). # - Allow multiple roots.

I tested it on alpha (AS1000-4/200 and Jensen) and parisc (C100). The parisc part really needs more work (I don't like the double probing at all), but at least it is now useable.

I'd be happy to read any comment about this code.

Thanks,

        M.

# 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.994 -> 1.995
# drivers/parisc/eisa.c 1.4 -> 1.5
# drivers/eisa/eisa-bus.c 1.2 -> 1.3
# drivers/eisa/Kconfig 1.1 -> 1.2
# drivers/eisa/Makefile 1.2 -> 1.3

#	include/linux/eisa.h	1.1     -> 1.2    
#	               (new)	        -> 1.2     drivers/eisa/i82375.c
#	               (new)	        -> 1.2     drivers/eisa/virtual_root.c

#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/14 [email protected] 1.995
# EISA/sysfs update.
#
# - Separate bus root code from generic code.
# - Add driver for i82375 PCI/EISA bridge.
# - Hacked parisc eisa driver so it can act as a root device. # - Add driver for so-called virtual root (for bridge-less systems). # - Allow multiple roots.
# --------------------------------------------
#

drivers/eisa/Kconfig +22 -1
diff -Nru a/drivers/eisa/Kconfig b/drivers/eisa/Kconfig
@@ -1,6 +1,27 @@
 #
-# PCI configuration
+# EISA configuration
 #
+config EISA_I82375
+	bool "Intel 82375 PCI/EISA bridge"
+	depends on PCI && EISA
+	default y
+	---help---
+	  Activate this option if your system contains an Intel 82375
+	  PCI to EISA bridge.
+
+	  When in doubt, say Y.
+
+config EISA_VIRTUAL_ROOT
+	bool "EISA virtual root device"
+	depends on EISA
+	default y
+	---help---
+	  Activate this option if your system only have EISA bus
+	  (no PCI slots). The Alpha Jensen is an example of such
+	  a system.
+
+	  When in doubt, say Y.
+
 config EISA_NAMES
 	bool "EISA device name database"
 	depends on EISA
drivers/eisa/Makefile +6 -1
diff -Nru a/drivers/eisa/Makefile b/drivers/eisa/Makefile
@@ -1,6 +1,11 @@
 # Makefile for the Linux device tree
 
-obj-$(CONFIG_EISA)	+= eisa-bus.o
+obj-$(CONFIG_EISA)	        += eisa-bus.o
+obj-${CONFIG_EISA_I82375}       += i82375.o
+
+# virtual_root.o should be the last EISA root device to initialize,
+# so leave it at the end of the list.
+obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o
 
 clean-files:= devlist.h
 
drivers/eisa/eisa-bus.c +43 -24

129 lines not on this page · raw message

drivers/eisa/i82375.c new file +61 -0

61 lines not on this page · raw message

drivers/eisa/virtual_root.c new file +49 -0

49 lines not on this page · raw message

drivers/parisc/eisa.c +16 -0
diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
@@ -35,6 +35,7 @@
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/eisa.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -61,6 +62,7 @@
 static struct eisa_ba {
 	struct pci_hba_data	hba;
 	unsigned long eeprom_addr;
+	struct eisa_root_device root;
 } eisa_dev;
 
 /* Port ops */
@@ -376,6 +378,20 @@
 	eisa_eeprom_init(eisa_dev.eeprom_addr);
 	eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
 	init_eisa_pic();
+
+	/* FIXME : Maybe we could get rid of io_space and only rely on
+	 * lmmio_space, since all operations are already going through
+	 * this region... Also get the number of slots from the
+	 * enumerator, not a hadcoded value.*/
+	eisa_dev.root.dev = &dev->dev;
+	dev->dev.driver_data = &eisa_dev.root;
+	eisa_dev.root.bus_base_addr = 0;
+	eisa_dev.root.res = &eisa_dev.hba.io_space;
+	eisa_dev.root.slots = EISA_MAX_SLOTS;
+	if (eisa_root_register (&eisa_dev.root)) {
+		printk(KERN_ERR "EISA: Failed to register EISA root\n");
+		return -1;
+	}
 	
 	return 0;
 }
include/linux/eisa.h +16 -1
diff -Nru a/include/linux/eisa.h b/include/linux/eisa.h
@@ -24,7 +24,8 @@
 };
 
 /* There is not much we can say about an EISA device, apart from
- * signature, slot number, and base address */
+ * signature, slot number, and base address. */
+
 struct eisa_device {
 	struct eisa_device_id id;
 	int                   slot;
@@ -56,5 +57,19 @@
 {
         edev->dev.driver_data = data;
 }
+
+/* The EISA root device. There's rumours about machines with multiple
+ * busses (PA-RISC ?), so we try to handle that. */
+
+struct eisa_root_device {
+	struct list_head node;
+	struct device   *dev;	 /* Pointer to bridge device */
+	struct resource *res;
+	unsigned long    bus_base_addr;
+	int		 slots;  /* Max slot number */
+	int              bus_nr; /* Set by eisa_root_register */
+};
+
+int eisa_root_register (struct eisa_root_device *root);
 
 #endif
Signature · 2 lines
-- 
Places change, faces change. Life is so very strange.
#3 lore raw

Re: [PATCH] EISA/sysfs update

Quoted 1 line · Marc Zyngier

# - Add driver for i82375 PCI/EISA bridge.

I believe this driver will work for any PCI/EISA bridge without any changes, not only for i82375. Probably we need to look for a class code rather than a device id.

Also, to get rid of that x86-ism I'd suggest something like

	i82375_root.dev		     = &pdev->dev;
	i82375_root.dev->driver_data = &i82375_root;
-	i82375_root.bus_base_addr    = 0; /* Warning, this is a x86-ism */
-	i82375_root.res		     = &ioport_resource;
+	i82375_root.res		     = pdev->bus->resource[0];
+	i82375_root.bus_base_addr    = pdev->bus->resource[0]->start;
	i82375_root.slots	     = EISA_MAX_SLOTS;

Without that you'll have resource conflicts on multi-hose alphas.

Otherwise, the patch looks good to me.

Ivan.

Applied
#4 lore raw

Re: [PATCH] EISA/sysfs update

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"Ivan" == Ivan Kokshaysky <[email protected]> writes:

Quoted 1 line · Marc Zyngier
Quoted 1 line

# - Add driver for i82375 PCI/EISA bridge.

Ivan> I believe this driver will work for any PCI/EISA bridge without Ivan> any changes, not only for i82375. Probably we need to look for a Ivan> class code rather than a device id.

Unfortunately, the i82375 appears to be unclassified :

00:07.0 Non-VGA unclassified device: Intel Corp. 82375EB (rev 03)

I'll had PCI_CLASS_BRIDGE_EISA anyway, just in case.

Ivan> Also, to get rid of that x86-ism I'd suggest something like

Ivan> - i82375_root.bus_base_addr = 0; /* Warning, this is a x86-ism */
Ivan> - i82375_root.res = &ioport_resource;
Ivan> + i82375_root.res = pdev->bus->resource[0];
Ivan> + i82375_root.bus_base_addr = pdev->bus->resource[0]->start;
Ivan> i82375_root.slots = EISA_MAX_SLOTS;

Ivan> Without that you'll have resource conflicts on multi-hose alphas.

Applied, thanks.

        M.
Signature · 1 line
Places change, faces change. Life is so very strange.
#5 lore raw

Re: [PATCH] EISA/sysfs update

Quoted 7 lines · Marc Zyngier

Ivan> I believe this driver will work for any PCI/EISA bridge without Ivan> any changes, not only for i82375. Probably we need to look for a Ivan> class code rather than a device id.

Unfortunately, the i82375 appears to be unclassified :

00:07.0 Non-VGA unclassified device: Intel Corp. 82375EB (rev 03)

We have this code in arch/alpha/kernel/pci.c for ages:

...
static void __init
quirk_eisa_bridge(struct pci_dev *dev)

{
	dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
...
struct pci_fixup pcibios_fixups[] __initdata = {
	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375,
	  quirk_eisa_bridge },

...

I think it belongs in drivers/pci/quirks.c.

Quoted 1 line

I'll had PCI_CLASS_BRIDGE_EISA anyway, just in case.

Actually I thought of replacing "i82375" with "pci_eisa" everywhere in your driver and

static struct pci_device_id pci_eisa_pci_tbl[] = {
	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
	  PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
	{ 0, }
};

Ivan.

#6 lore raw

Re: [PATCH] EISA/sysfs update

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"Ivan" == Ivan Kokshaysky <[email protected]> writes:

Ivan> We have this code in arch/alpha/kernel/pci.c for ages:

[...]

Ivan> I think it belongs in drivers/pci/quirks.c.

Indeed, this would be a good thing for x86 boxes.

Ivan> Actually I thought of replacing "i82375" with "pci_eisa" everywhere Ivan> in your driver and

[..]

Ok, I'll update the patch tonight, and will repost it.

Thanks,

        M.
Signature · 1 line
Places change, faces change. Life is so very strange.
#7 lore raw

Re: [PATCH] EISA/sysfs update, take #2

In reply to Ivan Kokshaysky

Folks,

Here is the updated EISA/sysfs patch, with the corrections discussed yesterday (using PCI_CLASS_BRIDGE_EISA, moving quirk_eisa_bridge from alpha to generic code, eisa_driver_register return value, as well as a 3C59x EISA probing fix).

        M.

# 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.994 -> 1.998
# drivers/net/3c59x.c 1.31 -> 1.32
# drivers/parisc/eisa.c 1.4 -> 1.6
# drivers/pci/quirks.c 1.22 -> 1.23
# arch/alpha/kernel/pci.c 1.22 -> 1.23
# drivers/eisa/eisa-bus.c 1.2 -> 1.4
# drivers/eisa/Kconfig 1.1 -> 1.3
# drivers/eisa/Makefile 1.2 -> 1.4

#	include/linux/eisa.h	1.1     -> 1.2    
#	               (new)	        -> 1.4     drivers/eisa/pci_eisa.c
#	               (new)	        -> 1.2     drivers/eisa/virtual_root.c

#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/14 [email protected] 1.995
# EISA/sysfs update.
#
# - Separate bus root code from generic code.
# - Add driver for i82375 PCI/EISA bridge.
# - Hacked parisc eisa driver so it can act as a root device.
# - Add driver for so-called virtual root (for bridge-less systems). # - Allow multiple roots.
# --------------------------------------------
# 03/02/15 [email protected] 1.996
# Moved quirk_eisa_bridge from alpha to generic code,
# since the EISA code needs it now.
# --------------------------------------------
# 03/02/15 [email protected] 1.997
# Use PCI_CLASS_BRIDGE_EISA instead of i82375 ID.
# A few fixes all over the map.
# --------------------------------------------
# 03/02/15 [email protected] 1.998
# 3c59x :
# Prevent driver from returning ENODEV in case it has registered with the EISA # framework, but no device has been found yet (it happends when the driver is

# built into the kernel, and the EISA bus root has not been discovered yet).
# --------------------------------------------
#
diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
--- a/arch/alpha/kernel/pci.c	Sat Feb 15 12:56:07 2003
+++ b/arch/alpha/kernel/pci.c	Sat Feb 15 12:56:07 2003
@@ -57,12 +57,6 @@
  */

static void __init
-quirk_eisa_bridge(struct pci_dev *dev)
-{
- dev->class = PCI_CLASS_BRIDGE_EISA << 8;
-}
-
-static void __init
quirk_isa_bridge(struct pci_dev *dev)
{
dev->class = PCI_CLASS_BRIDGE_ISA << 8;
@@ -125,8 +119,6 @@
}

struct pci_fixup pcibios_fixups[] __initdata = {
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375,
- quirk_eisa_bridge },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378,
quirk_isa_bridge },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229,

drivers/eisa/Kconfig +23 -1
diff -Nru a/drivers/eisa/Kconfig b/drivers/eisa/Kconfig
@@ -1,6 +1,28 @@
 #
-# PCI configuration
+# EISA configuration
 #
+config EISA_PCI_EISA
+	bool "Generic PCI/EISA bridge"
+	depends on PCI && EISA
+	default y
+	---help---
+	  Activate this option if your system contains a PCI to EISA
+	  bridge. If your system have both PCI and EISA slots, you
+	  certainly need this option.
+
+	  When in doubt, say Y.
+
+config EISA_VIRTUAL_ROOT
+	bool "EISA virtual root device"
+	depends on EISA
+	default y
+	---help---
+	  Activate this option if your system only have EISA bus
+	  (no PCI slots). The Alpha Jensen is an example of such
+	  a system.
+
+	  When in doubt, say Y.
+
 config EISA_NAMES
 	bool "EISA device name database"
 	depends on EISA
drivers/eisa/Makefile +6 -1
diff -Nru a/drivers/eisa/Makefile b/drivers/eisa/Makefile
@@ -1,6 +1,11 @@
 # Makefile for the Linux device tree
 
-obj-$(CONFIG_EISA)	+= eisa-bus.o
+obj-$(CONFIG_EISA)	        += eisa-bus.o
+obj-${CONFIG_EISA_PCI_EISA}     += pci_eisa.o
+
+# virtual_root.o should be the last EISA root device to initialize,
+# so leave it at the end of the list.
+obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o
 
 clean-files:= devlist.h
 
drivers/eisa/eisa-bus.c +44 -25

137 lines not on this page · raw message

drivers/eisa/pci_eisa.c new file +64 -0

64 lines not on this page · raw message

drivers/eisa/virtual_root.c new file +49 -0

49 lines not on this page · raw message

drivers/net/3c59x.c +10 -3
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
@@ -1007,6 +1007,7 @@
 /* returns count found (>= 0), or negative on error */
 static int __init vortex_eisa_init (void)
 {
+	int eisa_found = 0;
 	int orig_cards_found = vortex_cards_found;
 
 	/* Now check all slots of the EISA bus. */
@@ -1014,8 +1015,14 @@
 		return 0;
 
 #ifdef CONFIG_EISA
-	if (eisa_driver_register (&vortex_eisa_driver) < 0) {
-		eisa_driver_unregister (&vortex_eisa_driver);
+	if (eisa_driver_register (&vortex_eisa_driver) >= 0) {
+			/* Because of the way EISA bus is probed, we cannot assume
+			 * any device have been found when we exit from
+			 * eisa_driver_register (the bus root driver may not be
+			 * initialized yet). So we blindly assume something was
+			 * found, and let the sysfs magic happend... */
+			
+			eisa_found = 1;
 	}
 #endif
 	
@@ -1025,7 +1032,7 @@
 					  compaq_device_id, vortex_cards_found++);
 	}
 
-	return vortex_cards_found - orig_cards_found;
+	return vortex_cards_found - orig_cards_found + eisa_found;
 }
 
 /* returns count (>= 0), or negative on error */
drivers/parisc/eisa.c +14 -0
diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
@@ -35,6 +35,7 @@
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/eisa.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -61,6 +62,7 @@
 static struct eisa_ba {
 	struct pci_hba_data	hba;
 	unsigned long eeprom_addr;
+	struct eisa_root_device root;
 } eisa_dev;
 
 /* Port ops */
@@ -376,6 +378,18 @@
 	eisa_eeprom_init(eisa_dev.eeprom_addr);
 	eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
 	init_eisa_pic();
+
+	/* FIXME : Get the number of slots from the enumerator, not a
+	 * hadcoded value. Also don't enumerate the bus twice. */
+	eisa_dev.root.dev = &dev->dev;
+	dev->dev.driver_data = &eisa_dev.root;
+	eisa_dev.root.bus_base_addr = 0;
+	eisa_dev.root.res = &eisa_dev.hba.io_space;
+	eisa_dev.root.slots = EISA_MAX_SLOTS;
+	if (eisa_root_register (&eisa_dev.root)) {
+		printk(KERN_ERR "EISA: Failed to register EISA root\n");
+		return -1;
+	}
 	
 	return 0;
 }
drivers/pci/quirks.c +10 -0
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
@@ -535,6 +535,15 @@
 	}
 }
 
+/* This was originally an Alpha specific thing, but it really fits here.
+ * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
+ */
+
+static void __init quirk_eisa_bridge(struct pci_dev *dev)
+{
+	dev->class = PCI_CLASS_BRIDGE_EISA << 8;
+}
+
 /*
  *  The main table of quirks.
  */
@@ -604,6 +613,7 @@
 
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master },
 	
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge },
 
 	{ 0 }
 };
include/linux/eisa.h +16 -1
diff -Nru a/include/linux/eisa.h b/include/linux/eisa.h
@@ -24,7 +24,8 @@
 };
 
 /* There is not much we can say about an EISA device, apart from
- * signature, slot number, and base address */
+ * signature, slot number, and base address. */
+
 struct eisa_device {
 	struct eisa_device_id id;
 	int                   slot;
@@ -56,5 +57,19 @@
 {
         edev->dev.driver_data = data;
 }
+
+/* The EISA root device. There's rumours about machines with multiple
+ * busses (PA-RISC ?), so we try to handle that. */
+
+struct eisa_root_device {
+	struct list_head node;
+	struct device   *dev;	 /* Pointer to bridge device */
+	struct resource *res;
+	unsigned long    bus_base_addr;
+	int		 slots;  /* Max slot number */
+	int              bus_nr; /* Set by eisa_root_register */
+};
+
+int eisa_root_register (struct eisa_root_device *root);
 
 #endif
Signature · 2 lines
-- 
Places change, faces change. Life is so very strange.
#8 lore raw

Re: [PATCH] EISA/sysfs update

In reply to Marc Zyngier
Quoted 3 lines · Marc Zyngier

James, LKML,

Here is the latest round of EISA/sysfs hacking.

BTW, could you fix eisa_driver_register to properly return 0 on sucess instead of 1?

#9 lore raw

Re: [PATCH] EISA/sysfs update

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"Christoph" == Christoph Hellwig <[email protected]> writes:

Christoph> BTW, could you fix eisa_driver_register to properly return Christoph> 0 on sucess instead of 1?

Huhhh... Nice catch.

Thanks,

        M.
Signature · 1 line
Places change, faces change. Life is so very strange.