diff -uNr linux-2.2.18-pristine+ide/arch/ppc/kernel/pci.c linux-2.2.18/arch/ppc/kernel/pci.c
--- linux-2.2.18-pristine+ide/arch/ppc/kernel/pci.c	Sun Feb 11 09:33:47 2001
+++ linux-2.2.18/arch/ppc/kernel/pci.c	Sun Feb 11 10:51:37 2001
@@ -27,6 +27,14 @@
 
 #include "pci.h"
 
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
 unsigned long isa_io_base     = 0;
 unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
@@ -104,8 +112,11 @@
 		if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn)
 			continue;
 		/* this is the node, see if it has interrupts */
-		if (node->n_intrs > 0) 
+		if (node->n_intrs > 0) { 
 			dev->irq = node->intrs[0].line;
+			DBG("PCI: setting IRQ %d on device %02x:%02x.\n",
+				dev->irq, dev->bus->number, dev->devfn);
+		}
 		break;
 	}
 }
diff -uNr linux-2.2.18-pristine+ide/arch/ppc/kernel/pmac_pci.c linux-2.2.18/arch/ppc/kernel/pmac_pci.c
--- linux-2.2.18-pristine+ide/arch/ppc/kernel/pmac_pci.c	Sun Feb 11 09:33:47 2001
+++ linux-2.2.18/arch/ppc/kernel/pmac_pci.c	Sun Feb 11 11:10:13 2001
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/malloc.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
@@ -25,6 +26,15 @@
 
 #include "pci.h"
 
+#undef DEBUG
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
 struct bridge_data **bridges, *bridge_list;
 static int max_bus;
 
@@ -43,9 +53,14 @@
 
 
 static void add_bridges(struct device_node *dev, unsigned long *mem_ptr);
+void fix_chaos (struct bridge_data *);
+void fix_planb (struct pci_dev *);
+
+extern void pci_read_bases(struct pci_dev *, unsigned int);
 
 /*
  * Magic constants for enabling cache coherency in the bandit/PSX bridge.
+ * and for fixing control and planb.
  */
 #define APPLE_VENDID	0x106b
 #define BANDIT_DEVID	1
@@ -56,6 +71,10 @@
 #define BANDIT_MAGIC	0x50
 #define BANDIT_COHERENT	0x40
 
+#define CONTROL_DEVID	3
+#define PLANB_DEVID	4
+#define PLANB_BASE	0xf1000000
+
 __pmac
 void *pci_io_base(unsigned int bus)
 {
@@ -748,7 +767,7 @@
 				ioremap(addr->address + 0x800000, 0x1000);
 			bp->cfg_data = (volatile unsigned char *)
 				ioremap(addr->address + 0xc00000, 0x1000);
-			bp->io_base = (void *) ioremap(addr->address, 0x10000);
+			bp->io_base = (void *) ioremap(addr->address, 0x800000);
 			bp->io_base_phys = (void *)addr->address;
 		}
 		if (isa_io_base == 0)
@@ -771,35 +790,272 @@
 pmac_pcibios_fixup(void))
 {
 	struct pci_dev *dev;
-	
+	int i, has_io, has_mem;
+	unsigned short cmd;
+	struct bridge_data *bp;
+
 	/*
-	 * FIXME: This is broken: We should not assign IRQ's to IRQless
-	 *	  devices (look at PCI_INTERRUPT_PIN) and we also should
-	 *	  honor the existence of multi-function devices where
-	 *	  different functions have different interrupt pins. [mj]
+	 * The generic PCI code scans only bus 0 for devices and P2P
+	 * bridges. We fix this here based on the array of host
+	 * bridges.
+	 *
+	 * However, we need to treat the bus behind chaos with special
+	 * care. chaos doesn't like being poked at while scanning that
+	 * bus...
+	 *
+	 * Comments on everything below to mlan@cpu.lu...
 	 */
+	for (bp = bridge_list; bp != NULL; bp = bp->next) {
+		if (bp->bus_number == 0) continue;
+		if (strcmp(bp->node->name, "chaos") == 0)
+			fix_chaos(bp);
+		else
+			pci_scan_peer_bridge (bp->bus_number);
+	}
+
 	for(dev=pci_devices; dev; dev=dev->next)
 	{
-		/*
-		 * Open Firmware often doesn't initialize the,
-		 * PCI_INTERRUPT_LINE config register properly, so we
-		 * should find the device node and se if it has an
-		 * AAPL,interrupts property.
-		 */
 		struct bridge_data *bp = bridges[dev->bus->number];
 		unsigned char pin;
 			
-		if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||
-		    !pin)
-			continue; /* No interrupt generated -> no fixup */
-		/* We iterate all instances of uninorth for now */	
-		if (uninorth_count && dev->bus->number == 0) {
-			int i;
-			for (i=0;i<uninorth_count;i++)
-				fix_intr(uninorth_bridges[i].node->child, dev);
-		} else
-                	fix_intr(bp->node->child, dev);
+		DBG("PCI: Fixing device %02x:%02x (%04x:%04x)\n",
+			dev->bus->number, dev->devfn,
+			dev->vendor, dev->device);
+		/* SPECIAL DEVICES
+		 * ---------------
+		 * control was fixed in fix_chaos().
+		 */
+		if (dev->vendor == APPLE_VENDID &&
+		    dev->device == CONTROL_DEVID) {
+			continue;
+		}
+		/* planb needs special care.
+		 */
+		if (dev->vendor == APPLE_VENDID &&
+		    dev->device == PLANB_DEVID) {
+			fix_planb (dev);
+			continue;
+		}
+		/* INTERRUPT FIXING
+		 * ----------------
+		 * Open Firmware doesn't initialize the PCI_INTERRUPT_LINE
+		 * config register, so we need to find the device node and
+		 * see if it has an AAPL,interrupts property.
+		 *
+		 * Note that INTA# - INTD# are OR'ed together per slot,
+		 * so no need to worry about multifunction cards.
+		 */
+		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+		if (pin) {
+			/* We iterate all instances of uninorth for now */	
+			if (uninorth_count && dev->bus->number == 0) {
+				int i;
+				for (i=0;i<uninorth_count;i++)
+					fix_intr(uninorth_bridges[i].node->child, dev);
+			} else
+				fix_intr(bp->node->child, dev);
+		}
+		/* IO / MEMORY SPACE FIXING
+		 * ------------------------
+		 * Open Firmware does not enable I/O and memory space
+		 * response on PCI devices. We try to fix this, but we need
+		 * to be sure that OF didn't forget to assign an address
+		 * to the device. [mj]
+		 *
+		 * FIXME: How can we know? We should use OF properties....
+		 *
+		 * In addition, we correct any I/O space address by adding
+		 * the offset provided by the corresponding host bridge.
+		 */
+		has_io = has_mem = 0;
+		for(i=0; i<6; i++) {
+			unsigned long base;
+			unsigned long a = dev->base_address[i];
+			if (a == 0) continue;
+			if (a & PCI_BASE_ADDRESS_SPACE_IO) {
+				has_io = 1;
+				base = (unsigned long)
+					pci_io_base(dev->bus->number);
+				if (a < base) a += base;
+				if (a > base) {
+					dev->base_address[i] = a;
+					DBG("PCI: Correcting IO address %d on "
+					    "device %02x:%02x, now %08lx.\n",
+					    i, dev->bus->number,dev->devfn,a);
+				}
+			} else if (a & PCI_BASE_ADDRESS_MEM_MASK)
+				has_mem = 1;
+		}
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		if (has_io && !(cmd & PCI_COMMAND_IO)) {
+			DBG("PCI: Enabling I/O for device %02x:"
+			    "%02x\n", dev->bus->number, dev->devfn);
+			cmd |= PCI_COMMAND_IO;
+			pci_write_config_word(dev, PCI_COMMAND, cmd);
+		}
+		if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
+			DBG("PCI: Enabling memory for device %02x:"
+			    "%02x\n", dev->bus->number, dev->devfn);
+			cmd |= PCI_COMMAND_MEMORY;
+			pci_write_config_word(dev, PCI_COMMAND, cmd);
+		}
+	}
+}
+
+/*
+ * The chaos hostbridge, controlling the separate video bus
+ * on the 7x00/8x00 PowerMacs, doesn't like being probed for
+ * attached devices. Therefore, we rely on OF to discover those.
+ */
+__initfunc(
+void
+fix_chaos (struct bridge_data *bp))
+{
+	struct pci_bus *b;
+	struct pci_dev *dev, **bus_last;
+	struct device_node *nd;
+	unsigned char c, hdr_type;
+	unsigned int l;
+	extern struct pci_dev **pci_last_dev_p;
+	extern int pci_reverse;
+
+	if ((b = kmalloc(sizeof(*b), GFP_KERNEL)) == NULL) {
+		printk(KERN_ERR "PCI: Out of memory initializing chaos!\n");
+		return;
 	}
+	memset(b, 0, sizeof(*b));
+	b->next = pci_root.next;
+	pci_root.next = b;
+	b->number = b->secondary = b->subordinate = bp->bus_number;
+	bus_last = &b->devices;
+
+	/*
+	 * Walk OF's list of devices on this bus.
+	 */
+	for (nd = bp->node->child; nd; nd = nd->sibling) {
+		/*
+		 * We need at least one address entry to get the PCI
+		 * device / function values.
+		 */
+		if (nd->n_addrs == 0) {
+			printk(KERN_ERR "PCI: %s: not a PCI device!\n",
+				nd->name);
+			continue;
+		}
+		if ((dev = kmalloc(sizeof(*dev), GFP_ATOMIC)) == NULL) {
+			printk(KERN_ERR "PCI: Out of memory scanning chaos!\n");
+			return;
+		}
+		memset(dev, 0, sizeof(*dev));
+		dev->bus = b;
+		dev->devfn = (nd->addrs[0].space >> 8) & 0xff;
+		if (nd->n_intrs != 0)
+			dev->irq = nd->intrs[0].line;
+		pcibios_read_config_dword(b->number, dev->devfn,
+			PCI_VENDOR_ID, &l);
+		dev->vendor = l & 0xffff;
+		dev->device = (l >> 16) & 0xffff;
+		pcibios_read_config_dword(b->number, dev->devfn,
+			PCI_CLASS_REVISION, &l);
+		l >>= 8;
+		dev->class = l;
+		pcibios_read_config_byte(b->number, dev->devfn, PCI_HEADER_TYPE,
+			&hdr_type);
+		dev->hdr_type = hdr_type;
+		/*
+		 * We ignore any bridges on this bus, and don't care for
+		 * ROM (as far as I know, none ever appears here).
+		 */
+		pci_read_bases(dev, 6);
+		dev->rom_address = 0;
+		/*
+		 * OF sets PCI_COMMAND_MASTER if possible; therefore we
+		 * only need to read it's status.
+		 */
+		pcibios_read_config_byte(b->number, dev->devfn,PCI_COMMAND, &c);
+		dev->master = ((c & PCI_COMMAND_MASTER) != 0);
+
+		DBG("PCI: %02x:%02x [%04x/%04x]\n", b->number, dev->devfn,
+			dev->vendor, dev->device);
+		/*
+		 * Put it into the global PCI device chain.
+		 */
+		if (!pci_reverse) {
+			*pci_last_dev_p = dev;
+			pci_last_dev_p = &dev->next;
+		} else {
+			dev->next = pci_devices;
+			pci_devices = dev;
+		}
+		/*
+		 * Now insert it into the list of devices held
+		 * by the parent bus.
+		 */
+		*bus_last = dev;
+		bus_last = &dev->sibling;
+	}
+}
+
+__initfunc(
+void
+fix_planb (struct pci_dev *pcidev))
+{
+	/* There is a bug with the way OF assigns addresses
+	 * to the devices behind the chaos bridge.
+	 * control needs only 0x1000 of space, yet decodes only
+	 * the upper 16 bits. It therefore occupies a full 64K.
+	 * OF assigns the planb controller memory within this space;
+	 * so we need to change that here in order to access planb.
+	 * Note that the new address (0xf1000000) is within chaos'
+	 * address space, so it should never get assigned to other
+	 * devices by OF.
+	 * planb also gets its interrupt set.
+	 */
+	struct device_node *planb_device;
+	unsigned char bus, devfn, confreg;
+	unsigned short cmd;
+	unsigned int i, reg;
+
+	planb_device = find_devices("planb");
+	if (planb_device == 0) {
+		printk(KERN_WARNING "PCI: Error fixing planb: no OF device.\n");
+		return;
+	}
+	if (planb_device->next != NULL)
+		printk(KERN_WARNING "PCI: Only fixing first planb device.\n");
+	if (planb_device->n_addrs != 1) {
+		printk(KERN_WARNING "PCI: Error fixing planb: expected 1 "
+			"address, got %d.\n", planb_device->n_addrs);
+		return;
+	}
+	if (planb_device->n_intrs == 0) {
+		printk(KERN_WARNING "PCI: Error fixing planb: no IRQ.\n");
+		return;
+	}
+	bus = (planb_device->addrs[0].space >> 16) & 0xff;
+	devfn = (planb_device->addrs[0].space >> 8) & 0xff;
+	if ((bus != pcidev->bus->number) || (devfn != pcidev->devfn)) {
+		printk(KERN_WARNING "PCI: Error fixing planb: OF and PCI "
+			"device don't match!\n");
+		return;
+	}
+	pcidev->irq = planb_device->intrs[0].line;
+	confreg = planb_device->addrs[0].space & 0xff;
+	reg = (confreg - PCI_BASE_ADDRESS_0) >> 2;
+	/* Set the new base address */
+	pcibios_write_config_dword (bus, devfn, confreg, PLANB_BASE);
+	for (i=0; i<6; i++)
+		pcidev->base_address[i] = 0;
+	pcidev->base_address[reg] = PLANB_BASE;
+	/* Enable memory space, once the new base is set */
+	pcibios_read_config_dword (bus, devfn, confreg, &i);
+	pcibios_read_config_word (bus, devfn, PCI_COMMAND, &cmd);
+	cmd |= PCI_COMMAND_MEMORY;
+	pcibios_write_config_word (bus, devfn, PCI_COMMAND, cmd);
+
+	DBG("PCI: Fixing planb base address %d, now 0x%08x.\n",reg,PLANB_BASE);
+
+	return;
 }
 
 __initfunc(
diff -uNr linux-2.2.18-pristine+ide/arch/ppc/kernel/pmac_setup.c linux-2.2.18/arch/ppc/kernel/pmac_setup.c
--- linux-2.2.18-pristine+ide/arch/ppc/kernel/pmac_setup.c	Sun Feb 11 09:41:39 2001
+++ linux-2.2.18/arch/ppc/kernel/pmac_setup.c	Sun Feb 11 11:10:21 2001
@@ -705,8 +705,9 @@
         ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
 
 	/* _IO_BASE isn't set yet, so it's just as well that
-	   ppc_ide_md.io_base isn't used any more. :-) */
-        ppc_ide_md.io_base = _IO_BASE;
+	   ppc_ide_md.io_base isn't used any more. :-)
+        ppc_ide_md.io_base = _IO_BASE;	*/
+	ppc_ide_md.io_base = 0;
 #endif		
 }
 
diff -uNr linux-2.2.18-pristine+ide/drivers/pci/pci.c linux-2.2.18/drivers/pci/pci.c
--- linux-2.2.18-pristine+ide/drivers/pci/pci.c	Sun Feb 11 09:32:38 2001
+++ linux-2.2.18/drivers/pci/pci.c	Sun Feb 11 11:10:26 2001
@@ -20,6 +20,7 @@
 #include <asm/page.h>
 
 #undef DEBUG
+#define DEBUG
 
 #ifdef DEBUG
 #define DBG(x...) printk(x)
@@ -29,8 +30,8 @@
 
 struct pci_bus pci_root;
 struct pci_dev *pci_devices = NULL;
-static struct pci_dev **pci_last_dev_p = &pci_devices;
-static int pci_reverse __initdata = 0;
+struct pci_dev **pci_last_dev_p = &pci_devices;
+int pci_reverse __initdata = 0;
 
 struct pci_dev *
 pci_find_slot(unsigned int bus, unsigned int devfn)
@@ -163,7 +164,7 @@
 	struct pci_dev *dev, **bus_last;
 	struct pci_bus *child;
 
-	DBG("pci_scan_bus for bus %d\n", bus->number);
+	DBG("PCI: pci_scan_bus for bus %d\n", bus->number);
 	bus_last = &bus->devices;
 	max = bus->secondary;
 	for (devfn = 0; devfn < 0xff; ++devfn) {
diff -uNr linux-2.2.18-pristine+ide/include/asm-ppc/io.h linux-2.2.18/include/asm-ppc/io.h
--- linux-2.2.18-pristine+ide/include/asm-ppc/io.h	Sun Feb 11 09:41:41 2001
+++ linux-2.2.18/include/asm-ppc/io.h	Sun Feb 11 11:10:30 2001
@@ -32,7 +32,9 @@
 extern unsigned long isa_io_base;
 extern unsigned long isa_mem_base;
 extern unsigned long pci_dram_offset;
-#define _IO_BASE	isa_io_base
+/* We're correcting io base addresses in pci fixup code */
+/* #define _IO_BASE	isa_io_base */
+#define _IO_BASE	0
 #define _ISA_MEM_BASE	isa_mem_base
 #define PCI_DRAM_OFFSET	pci_dram_offset
 #endif /* CONFIG_APUS */
diff -uNr linux-2.2.17-pristine/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c
--- linux-2.2.17-pristine/drivers/block/ide-pmac.c	Thu Sep  7 20:36:05 2000
+++ linux/drivers/block/ide-pmac.c	Thu Sep  7 22:52:51 2000
@@ -204,9 +203,9 @@
 		return;
 			
 	if (drive->select.all & 0x10)
-		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[1]);
+		out_le32((unsigned *)(IDE_DATA_REG + 0x200), pmac_ide[i].timings[1]);
 	else
-		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[0]);
+		out_le32((unsigned *)(IDE_DATA_REG + 0x200), pmac_ide[i].timings[0]);
 }
 
 /* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
@@ -355,7 +354,7 @@
 		if (i >= MAX_HWIFS)
 			break;
 
-		base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _IO_BASE;
+		base = (unsigned long) ioremap(np->addrs[0].address, 0x200);
 
 		/* XXX This is bogus. Should be fixed in the registry by checking
 		   the kind of host interrupt controller, a bit like gatwick
