[parisc-linux-cvs] [PATCH] Fix the native bus walk code to search the device space between io_io_low, and io_io_high.

Ryan Bradetich rbradetich@uswest.net
10 Sep 2002 23:52:40 -0600


The following patch will find the devices on the E-Class systems.

the problem was that we only searched for devices at io_io_low ->
io_io_low + 2^18.  On the E-class systems, the devices were not located
in this range, instad they were located at: io_io_high - 2^18.

I have tested the patch on the E35, C200, and K460.

Thanks,

- Ryan


Index: arch/parisc/kernel/drivers.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/drivers.c,v
retrieving revision 1.47
diff -u -p -r1.47 drivers.c
--- arch/parisc/kernel/drivers.c	13 Apr 2002 22:12:27 -0000	1.47
+++ arch/parisc/kernel/drivers.c	11 Sep 2002 05:44:45 -0000
@@ -461,6 +461,7 @@ int register_parisc_device(struct parisc
 #define BC_PORT_MASK 0x8
 #define BC_LOWER_PORT 0x8
 
+
 #define BUS_CONVERTER(dev) \
         ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT))
 
@@ -473,14 +474,29 @@ int register_parisc_device(struct parisc
 	        __raw_readl((unsigned long)&((struct bc_module *)dev->hpa)->io_io_low) << 16 : \
 	        __raw_readl((unsigned long)&((struct bc_module *)dev->hpa)->io_io_low))
 
-static void walk_native_bus(unsigned long addr, struct parisc_device *parent);
+#define READ_IO_IO_HIGH(dev) \
+	(dev->id.hw_type == HPHW_IOA ? \
+	        __raw_readl((unsigned long)&((struct bc_module *)dev->hpa)->io_io_high) << 16 : \
+	        __raw_readl((unsigned long)&((struct bc_module *)dev->hpa)->io_io_high))
+
+
+static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, 
+			    struct parisc_device *parent);
+
+#define FLEX_MASK (unsigned long)0xfffffffffffc0000
+
+
 void walk_lower_bus(struct parisc_device *dev)
 {
+	unsigned long io_io_low, io_io_high;
 
 	if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev))
 		return;
 
-	walk_native_bus((unsigned long)(signed int)READ_IO_IO_LOW(dev), dev);
+	io_io_low = ((unsigned long)(signed int)READ_IO_IO_LOW(dev) + ~FLEX_MASK) & FLEX_MASK;
+	io_io_high = ((unsigned long)(signed int)READ_IO_IO_HIGH(dev) + ~FLEX_MASK) & FLEX_MASK;
+
+	walk_native_bus(io_io_low, io_io_high, dev);
 }
 
 #define MAX_NATIVE_DEVICES 64
@@ -488,7 +504,9 @@ void walk_lower_bus(struct parisc_device
 
 /**
  * walk_native_bus -- Probe a bus for devices
- * @addr: Base address of this bus.
+ * @io_io_low: Base address of this bus.
+ * @io_io_high: Last address of this bus.
+ * @parent: The parent bus device.
  * 
  * A native bus (eg Runway or GSC) may have up to 64 devices on it,
  * spaced at intervals of 0x1000 bytes.  PDC may not inform us of these
@@ -496,28 +514,32 @@ void walk_lower_bus(struct parisc_device
  * devices which are not physically connected (such as extra serial &
  * keyboard ports).  This problem is not yet solved.
  */
-static void walk_native_bus(unsigned long addr, struct parisc_device *parent)
+static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
+			    struct parisc_device *parent)
 {
-	int i;
+	int i, devices_found = 0;
+	unsigned long hpa = io_io_low;
 	struct hardware_path path;
 
 	get_node_path(parent, &path);
-	for (i = 0; i < MAX_NATIVE_DEVICES; i++) {
-		unsigned long hpa = (addr + i * NATIVE_DEVICE_OFFSET);
-		struct parisc_device *dev;
-
-		/* Was the device already added by Firmware? */
-		dev = find_device_by_addr(hpa);
-		if (!dev) {
-			path.mod = i;
-			dev = alloc_pa_dev(hpa, &path);
-			if (!dev)
-				continue;
-
-			register_parisc_device(dev);
+	do {
+		for (i = 0; i < MAX_NATIVE_DEVICES; i++, hpa += NATIVE_DEVICE_OFFSET) {
+			struct parisc_device *dev;
+
+			/* Was the device already added by Firmware? */
+			dev = find_device_by_addr(hpa);
+			if (!dev) {
+				path.mod = i;
+				dev = alloc_pa_dev(hpa, &path);
+				if (!dev)
+					continue;
+
+				register_parisc_device(dev);
+				devices_found++;
+			}
+			walk_lower_bus(dev);
 		}
-		walk_lower_bus(dev);
-	}
+	} while (!devices_found && hpa < io_io_high);
 }
 
 #define CENTRAL_BUS_ADDR (unsigned long) 0xfffffffffff80000
@@ -530,7 +552,9 @@ static void walk_native_bus(unsigned lon
  */
 void walk_central_bus(void)
 {
-	walk_native_bus(CENTRAL_BUS_ADDR, &root);
+	walk_native_bus(CENTRAL_BUS_ADDR, 
+			CENTRAL_BUS_ADDR + (MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET),
+			&root);
 }
 
 void fixup_child_irqs(struct parisc_device *parent, int base,