linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] fix 3c509.c for MCA drivers
@ 2003-02-03  3:09 James Bottomley
  2003-02-08 17:25 ` Marc Zyngier
  2003-02-14 10:16 ` [PATCH] EISA/sysfs update Marc Zyngier
  0 siblings, 2 replies; 10+ messages in thread
From: James Bottomley @ 2003-02-03  3:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: jgarzik, mzyngier

[-- Attachment #1: Type: text/plain, Size: 308 bytes --]



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


[-- Attachment #2: tmp.diff --]
[-- Type: text/plain, Size: 11584 bytes --]

# 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
# --------------------------------------------
#
diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c
--- a/drivers/net/3c509.c	Sun Feb  2 22:04:26 2003
+++ b/drivers/net/3c509.c	Sun Feb  2 22:04:26 2003
@@ -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 (nygren@mit.edu) 3c529 patch, heavily
-	 * modified by Chris Beauregard (cpbeaure@csclub.uwaterloo.ca)
-	 * to support standard MCA probing.
-	 *
-	 * redone for multi-card detection by ZP Gu (zpg@castle.net)
-	 * 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 (nygren@mit.edu) 3c529 patch,
+		 * heavily modified by Chris Beauregard
+		 * (cpbeaure@csclub.uwaterloo.ca) to support standard MCA
+		 * probing.
+		 *
+		 * redone for multi-card detection by ZP Gu (zpg@castle.net)
+		 * 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
 }
 
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	Sun Feb  2 22:04:26 2003
+++ b/drivers/net/Space.c	Sun Feb  2 22:04:26 2003
@@ -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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] fix 3c509.c for MCA drivers
  2003-02-03  3:09 [PATCH] fix 3c509.c for MCA drivers James Bottomley
@ 2003-02-08 17:25 ` Marc Zyngier
  2003-02-14 10:16 ` [PATCH] EISA/sysfs update Marc Zyngier
  1 sibling, 0 replies; 10+ messages in thread
From: Marc Zyngier @ 2003-02-08 17:25 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-kernel, jgarzik

[-- Attachment #1: Type: text/plain, Size: 553 bytes --]

>>>>> "James" == James Bottomley <James.Bottomley@steeleye.com> 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.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 3c509.patch --]
[-- Type: text/x-patch, Size: 3257 bytes --]

===== drivers/net/3c509.c 1.25.1.5 vs 1.34 =====
--- 1.25.1.5/drivers/net/3c509.c	Mon Feb  3 08:35:11 2003
+++ 1.34/drivers/net/3c509.c	Sat Feb  8 17:17:14 2003
@@ -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 =====
--- 1.11.1.5/drivers/net/Space.c	Mon Feb  3 08:35:11 2003
+++ 1.19/drivers/net/Space.c	Sat Feb  8 17:18:21 2003
@@ -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

[-- Attachment #3: Type: text/plain, Size: 59 bytes --]


-- 
Places change, faces change. Life is so very strange.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] EISA/sysfs update
  2003-02-03  3:09 [PATCH] fix 3c509.c for MCA drivers James Bottomley
  2003-02-08 17:25 ` Marc Zyngier
@ 2003-02-14 10:16 ` Marc Zyngier
  2003-02-14 14:32   ` Ivan Kokshaysky
  2003-02-14 18:12   ` [PATCH] EISA/sysfs update Christoph Hellwig
  1 sibling, 2 replies; 10+ messages in thread
From: Marc Zyngier @ 2003-02-14 10:16 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 609 bytes --]

James, LKML,

Here is the latest round of EISA/sysfs hacking.

>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.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: EISA/sysfs update --]
[-- Type: text/x-patch, Size: 11621 bytes --]

# 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	maz@hina.wild-wind.fr.eu.org	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.
# --------------------------------------------
#
diff -Nru a/drivers/eisa/Kconfig b/drivers/eisa/Kconfig
--- a/drivers/eisa/Kconfig	Fri Feb 14 11:14:39 2003
+++ b/drivers/eisa/Kconfig	Fri Feb 14 11:14:39 2003
@@ -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
diff -Nru a/drivers/eisa/Makefile b/drivers/eisa/Makefile
--- a/drivers/eisa/Makefile	Fri Feb 14 11:14:39 2003
+++ b/drivers/eisa/Makefile	Fri Feb 14 11:14:39 2003
@@ -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
 
diff -Nru a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
--- a/drivers/eisa/eisa-bus.c	Fri Feb 14 11:14:39 2003
+++ b/drivers/eisa/eisa-bus.c	Fri Feb 14 11:14:39 2003
@@ -15,6 +15,8 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 
+#define SLOT_ADDRESS(r,n) (r->bus_base_addr + (0x1000 * n))
+
 #define EISA_DEVINFO(i,s) { .id = { .sig = i }, .name = s }
 
 struct eisa_device_info {
@@ -95,12 +97,6 @@
 	.match = eisa_bus_match,
 };
 
-/* The default EISA device parent (virtual root device). */
-static struct device eisa_bus_root = {
-       .name           = "EISA Bridge",
-       .bus_id         = "eisa",
-};
-
 int eisa_driver_register (struct eisa_driver *edrv)
 {
 	int r;
@@ -125,7 +121,8 @@
 
 static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
 
-static void __init eisa_register_device (char *sig, int slot)
+static void __init eisa_register_device (struct eisa_root_device *root,
+					 char *sig, int slot)
 {
 	struct eisa_device *edev;
 
@@ -135,11 +132,11 @@
 	memset (edev, 0, sizeof (*edev));
 	memcpy (edev->id.sig, sig, 7);
 	edev->slot = slot;
-	edev->base_addr = 0x1000 * slot;
+	edev->base_addr = SLOT_ADDRESS (root, slot);
 	eisa_name_device (edev);
-	edev->dev.parent = &eisa_bus_root;
+	edev->dev.parent = root->dev;
 	edev->dev.bus = &eisa_bus_type;
-	sprintf (edev->dev.bus_id, "00:%02X", slot);
+	sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot);
 
 	/* Don't register resource for slot 0, since this will surely
 	 * fail... :-( */
@@ -150,7 +147,7 @@
 		edev->res.end   = edev->res.start + 0xfff;
 		edev->res.flags = IORESOURCE_IO;
 
-		if (request_resource (&ioport_resource, &edev->res)) {
+		if (request_resource (root->res, &edev->res)) {
 			printk (KERN_WARNING \
 				"Cannot allocate resource for EISA slot %d\n",
 				slot);
@@ -167,16 +164,18 @@
 	device_create_file (&edev->dev, &dev_attr_signature);
 }
 
-static int __init eisa_probe (void)
+static int __init eisa_probe (struct eisa_root_device *root)
 {
         int i, c;
         char *str;
-        unsigned long slot_addr;
+        unsigned long sig_addr;
 
-        printk (KERN_INFO "EISA: Probing bus...\n");
-        for (c = 0, i = 0; i <= EISA_MAX_SLOTS; i++) {
-                slot_addr = (0x1000 * i) + EISA_VENDOR_ID_OFFSET;
-                if ((str = decode_eisa_sig (slot_addr))) {
+        printk (KERN_INFO "EISA: Probing bus %d at %s\n",
+		root->bus_nr, root->dev->name);
+	
+        for (c = 0, i = 0; i <= root->slots; i++) {
+                sig_addr = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
+                if ((str = decode_eisa_sig (sig_addr))) {
 			if (!i)
 				printk (KERN_INFO "EISA: Motherboard %s detected\n",
 					str);
@@ -187,7 +186,7 @@
 				c++;
 			}
 
-			eisa_register_device (str, i);
+			eisa_register_device (root, str, i);
                 }
         }
         printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s");
@@ -195,20 +194,40 @@
 	return 0;
 }
 
+
+static LIST_HEAD (eisa_root_head);
+
+static int eisa_bus_count;
+
+int eisa_root_register (struct eisa_root_device *root)
+{
+	struct list_head *node;
+	struct eisa_root_device *tmp_root;
+
+	/* Check if this bus base address has been already
+	 * registered. This prevents the virtual root device from
+	 * registering after the real one has, for example... */
+	
+	list_for_each (node, &eisa_root_head) {
+		tmp_root = list_entry (node, struct eisa_root_device, node);
+		if (tmp_root->bus_base_addr == root->bus_base_addr)
+			return -1; /* Space already taken, buddy... */
+	}
+	
+	root->bus_nr = eisa_bus_count++;
+	list_add_tail (&root->node, &eisa_root_head);
+	return eisa_probe (root);
+}
+
 static int __init eisa_init (void)
 {
 	int r;
 	
 	if ((r = bus_register (&eisa_bus_type)))
 		return r;
-	
-	if ((r = device_register (&eisa_bus_root))) {
-		bus_unregister (&eisa_bus_type);
-		return r;
-	}
 
 	printk (KERN_INFO "EISA bus registered\n");
-	return eisa_probe ();
+	return 0;
 }
 
 postcore_initcall (eisa_init);
diff -Nru a/drivers/eisa/i82375.c b/drivers/eisa/i82375.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/eisa/i82375.c	Fri Feb 14 11:14:39 2003
@@ -0,0 +1,61 @@
+/*
+ * Minimalist driver for the Intel 82375 PCI-to-EISA bridge.
+ *
+ * (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
+ *
+ * This code is released under the GPL version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/eisa.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+/* There is only *one* i82375 device per machine, right ? */
+static struct eisa_root_device i82375_root;
+
+static int __devinit i82375_init (struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+{
+	int rc;
+
+	if ((rc = pci_enable_device (pdev))) {
+		printk (KERN_INFO "i82375 : Could not enable device %s\n",
+			pdev->slot_name);
+		return rc;
+	}
+
+	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.slots	     = EISA_MAX_SLOTS;
+
+	if (eisa_root_register (&i82375_root)) {
+		printk (KERN_INFO "i82375 : Could not register EISA root\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static struct pci_device_id i82375_pci_tbl[] = {
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, }
+};
+
+static struct pci_driver i82375_driver = {
+	.name		= "i82375",
+	.id_table	= i82375_pci_tbl,
+	.probe		= i82375_init,
+};
+
+static int __init i82375_init_module (void)
+{
+	return pci_module_init (&i82375_driver);
+}
+
+device_initcall(i82375_init_module);
diff -Nru a/drivers/eisa/virtual_root.c b/drivers/eisa/virtual_root.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/eisa/virtual_root.c	Fri Feb 14 11:14:39 2003
@@ -0,0 +1,49 @@
+/*
+ * Virtual EISA root driver.
+ * Acts as a placeholder if we don't have a proper EISA bridge.
+ *
+ * (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
+ *
+ * This code is released under the GPL version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/eisa.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+/* The default EISA device parent (virtual root device). */
+static struct device eisa_root_dev = {
+       .name        = "Virtual EISA Bridge",
+       .bus_id      = "eisa",
+};
+
+static struct eisa_root_device eisa_bus_root = {
+	.dev           = &eisa_root_dev,
+	.bus_base_addr = 0,
+	.res	       = &ioport_resource,
+	.slots	       = EISA_MAX_SLOTS,
+};
+
+static int virtual_eisa_root_init (void)
+{
+	int r;
+	
+        if ((r = device_register (&eisa_root_dev))) {
+                return r;
+        }
+
+	eisa_root_dev.driver_data = &eisa_bus_root;
+
+	if (eisa_root_register (&eisa_bus_root)) {
+		/* A real bridge may have been registered before
+		 * us. So quietly unregister. */
+		device_unregister (&eisa_root_dev);
+		return -1;
+	}
+
+	return 0;
+}
+
+device_initcall (virtual_eisa_root_init);
diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
--- a/drivers/parisc/eisa.c	Fri Feb 14 11:14:39 2003
+++ b/drivers/parisc/eisa.c	Fri Feb 14 11:14:39 2003
@@ -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;
 }
diff -Nru a/include/linux/eisa.h b/include/linux/eisa.h
--- a/include/linux/eisa.h	Fri Feb 14 11:14:39 2003
+++ b/include/linux/eisa.h	Fri Feb 14 11:14:39 2003
@@ -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

[-- Attachment #3: Type: text/plain, Size: 59 bytes --]


-- 
Places change, faces change. Life is so very strange.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] EISA/sysfs update
  2003-02-14 10:16 ` [PATCH] EISA/sysfs update Marc Zyngier
@ 2003-02-14 14:32   ` Ivan Kokshaysky
  2003-02-14 15:32     ` Marc Zyngier
  2003-02-14 18:12   ` [PATCH] EISA/sysfs update Christoph Hellwig
  1 sibling, 1 reply; 10+ messages in thread
From: Ivan Kokshaysky @ 2003-02-14 14:32 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: James Bottomley, linux-kernel

On Fri, Feb 14, 2003 at 11:16:24AM +0100, Marc Zyngier wrote:
> # - 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.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] EISA/sysfs update
  2003-02-14 14:32   ` Ivan Kokshaysky
@ 2003-02-14 15:32     ` Marc Zyngier
  2003-02-14 16:05       ` Ivan Kokshaysky
  0 siblings, 1 reply; 10+ messages in thread
From: Marc Zyngier @ 2003-02-14 15:32 UTC (permalink / raw)
  To: Ivan Kokshaysky; +Cc: James Bottomley, linux-kernel

>>>>> "Ivan" == Ivan Kokshaysky <ink@jurassic.park.msu.ru> writes:

Ivan> On Fri, Feb 14, 2003 at 11:16:24AM +0100, Marc Zyngier wrote:
>> # - 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.
-- 
Places change, faces change. Life is so very strange.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] EISA/sysfs update
  2003-02-14 15:32     ` Marc Zyngier
@ 2003-02-14 16:05       ` Ivan Kokshaysky
  2003-02-14 16:42         ` Marc Zyngier
  2003-02-15 12:20         ` [PATCH] EISA/sysfs update, take #2 Marc Zyngier
  0 siblings, 2 replies; 10+ messages in thread
From: Ivan Kokshaysky @ 2003-02-14 16:05 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: James Bottomley, linux-kernel

On Fri, Feb 14, 2003 at 04:32:50PM +0100, Marc Zyngier wrote:
> 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.

> 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.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] EISA/sysfs update
  2003-02-14 16:05       ` Ivan Kokshaysky
@ 2003-02-14 16:42         ` Marc Zyngier
  2003-02-15 12:20         ` [PATCH] EISA/sysfs update, take #2 Marc Zyngier
  1 sibling, 0 replies; 10+ messages in thread
From: Marc Zyngier @ 2003-02-14 16:42 UTC (permalink / raw)
  To: Ivan Kokshaysky; +Cc: James Bottomley, linux-kernel

>>>>> "Ivan" == Ivan Kokshaysky <ink@jurassic.park.msu.ru> 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.
-- 
Places change, faces change. Life is so very strange.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] EISA/sysfs update
  2003-02-14 10:16 ` [PATCH] EISA/sysfs update Marc Zyngier
  2003-02-14 14:32   ` Ivan Kokshaysky
@ 2003-02-14 18:12   ` Christoph Hellwig
  2003-02-14 19:37     ` Marc Zyngier
  1 sibling, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2003-02-14 18:12 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: James Bottomley, linux-kernel

On Fri, Feb 14, 2003 at 11:16:24AM +0100, Marc Zyngier wrote:
> 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?


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] EISA/sysfs update
  2003-02-14 18:12   ` [PATCH] EISA/sysfs update Christoph Hellwig
@ 2003-02-14 19:37     ` Marc Zyngier
  0 siblings, 0 replies; 10+ messages in thread
From: Marc Zyngier @ 2003-02-14 19:37 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: James Bottomley, linux-kernel

>>>>> "Christoph" == Christoph Hellwig <hch@infradead.org> writes:

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

Huhhh... Nice catch.

Thanks,

        M.
-- 
Places change, faces change. Life is so very strange.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] EISA/sysfs update, take #2
  2003-02-14 16:05       ` Ivan Kokshaysky
  2003-02-14 16:42         ` Marc Zyngier
@ 2003-02-15 12:20         ` Marc Zyngier
  1 sibling, 0 replies; 10+ messages in thread
From: Marc Zyngier @ 2003-02-15 12:20 UTC (permalink / raw)
  To: Ivan Kokshaysky; +Cc: James Bottomley, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 256 bytes --]

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.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: eisa-drivers.patch --]
[-- Type: text/x-patch, Size: 15388 bytes --]

# 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	maz@hina.wild-wind.fr.eu.org	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	maz@hina.wild-wind.fr.eu.org	1.996
#     Moved quirk_eisa_bridge from alpha to generic code, 
#     since the EISA code needs it now.
# --------------------------------------------
# 03/02/15	maz@hina.wild-wind.fr.eu.org	1.997
# Use PCI_CLASS_BRIDGE_EISA instead of i82375 ID.
# A few fixes all over the map.
# --------------------------------------------
# 03/02/15	maz@hina.wild-wind.fr.eu.org	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,
diff -Nru a/drivers/eisa/Kconfig b/drivers/eisa/Kconfig
--- a/drivers/eisa/Kconfig	Sat Feb 15 12:56:07 2003
+++ b/drivers/eisa/Kconfig	Sat Feb 15 12:56:07 2003
@@ -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
diff -Nru a/drivers/eisa/Makefile b/drivers/eisa/Makefile
--- a/drivers/eisa/Makefile	Sat Feb 15 12:56:07 2003
+++ b/drivers/eisa/Makefile	Sat Feb 15 12:56:07 2003
@@ -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
 
diff -Nru a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
--- a/drivers/eisa/eisa-bus.c	Sat Feb 15 12:56:07 2003
+++ b/drivers/eisa/eisa-bus.c	Sat Feb 15 12:56:07 2003
@@ -15,6 +15,8 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 
+#define SLOT_ADDRESS(r,n) (r->bus_base_addr + (0x1000 * n))
+
 #define EISA_DEVINFO(i,s) { .id = { .sig = i }, .name = s }
 
 struct eisa_device_info {
@@ -95,12 +97,6 @@
 	.match = eisa_bus_match,
 };
 
-/* The default EISA device parent (virtual root device). */
-static struct device eisa_bus_root = {
-       .name           = "EISA Bridge",
-       .bus_id         = "eisa",
-};
-
 int eisa_driver_register (struct eisa_driver *edrv)
 {
 	int r;
@@ -109,7 +105,7 @@
 	if ((r = driver_register (&edrv->driver)) < 0)
 		return r;
 
-	return 1;
+	return 0;
 }
 
 void eisa_driver_unregister (struct eisa_driver *edrv)
@@ -125,7 +121,8 @@
 
 static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
 
-static void __init eisa_register_device (char *sig, int slot)
+static void __init eisa_register_device (struct eisa_root_device *root,
+					 char *sig, int slot)
 {
 	struct eisa_device *edev;
 
@@ -135,11 +132,11 @@
 	memset (edev, 0, sizeof (*edev));
 	memcpy (edev->id.sig, sig, 7);
 	edev->slot = slot;
-	edev->base_addr = 0x1000 * slot;
+	edev->base_addr = SLOT_ADDRESS (root, slot);
 	eisa_name_device (edev);
-	edev->dev.parent = &eisa_bus_root;
+	edev->dev.parent = root->dev;
 	edev->dev.bus = &eisa_bus_type;
-	sprintf (edev->dev.bus_id, "00:%02X", slot);
+	sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot);
 
 	/* Don't register resource for slot 0, since this will surely
 	 * fail... :-( */
@@ -150,7 +147,7 @@
 		edev->res.end   = edev->res.start + 0xfff;
 		edev->res.flags = IORESOURCE_IO;
 
-		if (request_resource (&ioport_resource, &edev->res)) {
+		if (request_resource (root->res, &edev->res)) {
 			printk (KERN_WARNING \
 				"Cannot allocate resource for EISA slot %d\n",
 				slot);
@@ -167,16 +164,18 @@
 	device_create_file (&edev->dev, &dev_attr_signature);
 }
 
-static int __init eisa_probe (void)
+static int __init eisa_probe (struct eisa_root_device *root)
 {
         int i, c;
         char *str;
-        unsigned long slot_addr;
+        unsigned long sig_addr;
 
-        printk (KERN_INFO "EISA: Probing bus...\n");
-        for (c = 0, i = 0; i <= EISA_MAX_SLOTS; i++) {
-                slot_addr = (0x1000 * i) + EISA_VENDOR_ID_OFFSET;
-                if ((str = decode_eisa_sig (slot_addr))) {
+        printk (KERN_INFO "EISA: Probing bus %d at %s\n",
+		root->bus_nr, root->dev->name);
+	
+        for (c = 0, i = 0; i <= root->slots; i++) {
+                sig_addr = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
+                if ((str = decode_eisa_sig (sig_addr))) {
 			if (!i)
 				printk (KERN_INFO "EISA: Motherboard %s detected\n",
 					str);
@@ -187,7 +186,7 @@
 				c++;
 			}
 
-			eisa_register_device (str, i);
+			eisa_register_device (root, str, i);
                 }
         }
         printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s");
@@ -195,20 +194,40 @@
 	return 0;
 }
 
+
+static LIST_HEAD (eisa_root_head);
+
+static int eisa_bus_count;
+
+int eisa_root_register (struct eisa_root_device *root)
+{
+	struct list_head *node;
+	struct eisa_root_device *tmp_root;
+
+	/* Check if this bus base address has been already
+	 * registered. This prevents the virtual root device from
+	 * registering after the real one has, for example... */
+	
+	list_for_each (node, &eisa_root_head) {
+		tmp_root = list_entry (node, struct eisa_root_device, node);
+		if (tmp_root->bus_base_addr == root->bus_base_addr)
+			return -1; /* Space already taken, buddy... */
+	}
+	
+	root->bus_nr = eisa_bus_count++;
+	list_add_tail (&root->node, &eisa_root_head);
+	return eisa_probe (root);
+}
+
 static int __init eisa_init (void)
 {
 	int r;
 	
 	if ((r = bus_register (&eisa_bus_type)))
 		return r;
-	
-	if ((r = device_register (&eisa_bus_root))) {
-		bus_unregister (&eisa_bus_type);
-		return r;
-	}
 
 	printk (KERN_INFO "EISA bus registered\n");
-	return eisa_probe ();
+	return 0;
 }
 
 postcore_initcall (eisa_init);
diff -Nru a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/eisa/pci_eisa.c	Sat Feb 15 12:56:07 2003
@@ -0,0 +1,64 @@
+/*
+ * Minimalist driver for a generic PCI-to-EISA bridge.
+ *
+ * (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
+ *
+ * This code is released under the GPL version 2.
+ *
+ * Ivan Kokshaysky <ink@jurassic.park.msu.ru> :
+ * Generalisation from i82375 to PCI_CLASS_BRIDGE_EISA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/eisa.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+/* There is only *one* pci_eisa device per machine, right ? */
+static struct eisa_root_device pci_eisa_root;
+
+static int __devinit pci_eisa_init (struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+{
+	int rc;
+
+	if ((rc = pci_enable_device (pdev))) {
+		printk (KERN_ERR "pci_eisa : Could not enable device %s\n",
+			pdev->slot_name);
+		return rc;
+	}
+
+	pci_eisa_root.dev              = &pdev->dev;
+	pci_eisa_root.dev->driver_data = &pci_eisa_root;
+	pci_eisa_root.res	       = pdev->bus->resource[0];
+	pci_eisa_root.bus_base_addr    = pdev->bus->resource[0]->start;
+	pci_eisa_root.slots	       = EISA_MAX_SLOTS;
+
+	if (eisa_root_register (&pci_eisa_root)) {
+		printk (KERN_ERR "pci_eisa : Could not register EISA root\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+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, }
+};
+
+static struct pci_driver pci_eisa_driver = {
+	.name		= "pci_eisa",
+	.id_table	= pci_eisa_pci_tbl,
+	.probe		= pci_eisa_init,
+};
+
+static int __init pci_eisa_init_module (void)
+{
+	return pci_module_init (&pci_eisa_driver);
+}
+
+device_initcall(pci_eisa_init_module);
diff -Nru a/drivers/eisa/virtual_root.c b/drivers/eisa/virtual_root.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/eisa/virtual_root.c	Sat Feb 15 12:56:07 2003
@@ -0,0 +1,49 @@
+/*
+ * Virtual EISA root driver.
+ * Acts as a placeholder if we don't have a proper EISA bridge.
+ *
+ * (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
+ *
+ * This code is released under the GPL version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/eisa.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+/* The default EISA device parent (virtual root device). */
+static struct device eisa_root_dev = {
+       .name        = "Virtual EISA Bridge",
+       .bus_id      = "eisa",
+};
+
+static struct eisa_root_device eisa_bus_root = {
+	.dev           = &eisa_root_dev,
+	.bus_base_addr = 0,
+	.res	       = &ioport_resource,
+	.slots	       = EISA_MAX_SLOTS,
+};
+
+static int virtual_eisa_root_init (void)
+{
+	int r;
+	
+        if ((r = device_register (&eisa_root_dev))) {
+                return r;
+        }
+
+	eisa_root_dev.driver_data = &eisa_bus_root;
+
+	if (eisa_root_register (&eisa_bus_root)) {
+		/* A real bridge may have been registered before
+		 * us. So quietly unregister. */
+		device_unregister (&eisa_root_dev);
+		return -1;
+	}
+
+	return 0;
+}
+
+device_initcall (virtual_eisa_root_init);
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	Sat Feb 15 12:56:07 2003
+++ b/drivers/net/3c59x.c	Sat Feb 15 12:56:07 2003
@@ -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 */
diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
--- a/drivers/parisc/eisa.c	Sat Feb 15 12:56:07 2003
+++ b/drivers/parisc/eisa.c	Sat Feb 15 12:56:07 2003
@@ -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;
 }
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	Sat Feb 15 12:56:07 2003
+++ b/drivers/pci/quirks.c	Sat Feb 15 12:56:07 2003
@@ -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 }
 };
diff -Nru a/include/linux/eisa.h b/include/linux/eisa.h
--- a/include/linux/eisa.h	Sat Feb 15 12:56:07 2003
+++ b/include/linux/eisa.h	Sat Feb 15 12:56:07 2003
@@ -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

[-- Attachment #3: Type: text/plain, Size: 59 bytes --]


-- 
Places change, faces change. Life is so very strange.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2003-02-15 12:12 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-03  3:09 [PATCH] fix 3c509.c for MCA drivers James Bottomley
2003-02-08 17:25 ` Marc Zyngier
2003-02-14 10:16 ` [PATCH] EISA/sysfs update Marc Zyngier
2003-02-14 14:32   ` Ivan Kokshaysky
2003-02-14 15:32     ` Marc Zyngier
2003-02-14 16:05       ` Ivan Kokshaysky
2003-02-14 16:42         ` Marc Zyngier
2003-02-15 12:20         ` [PATCH] EISA/sysfs update, take #2 Marc Zyngier
2003-02-14 18:12   ` [PATCH] EISA/sysfs update Christoph Hellwig
2003-02-14 19:37     ` Marc Zyngier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).