diff -uNr linux-2.3.paul/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- linux-2.3.paul/arch/ppc/kernel/Makefile	Wed Mar  8 00:19:16 2000
+++ linux/arch/ppc/kernel/Makefile	Sun Mar 26 16:50:18 2000
@@ -38,7 +38,7 @@
 endif
 
 ifdef CONFIG_PCI
-O_OBJS += pci.o pci-dma.o
+O_OBJS += pci.o pci-dma.o pci_debug.o
 endif
 
 ifdef CONFIG_KGDB
diff -uNr linux-2.3.paul/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- linux-2.3.paul/arch/ppc/kernel/pci.c	Wed Mar  8 00:19:16 2000
+++ linux/arch/ppc/kernel/pci.c	Sun Mar 26 23:09:08 2000
@@ -22,6 +22,15 @@
 
 #include "pci.h"
 
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+
 static void __init pcibios_claim_resources(struct list_head *);
 
 unsigned long isa_io_base     = 0;
@@ -67,13 +76,272 @@
 	generic_pcibios_write_dword
 };
 
+
+
+#define PCI_PROBE_BIOS 1
+#define PCI_PROBE_CONF1 2
+#define PCI_PROBE_CONF2 4
+#define PCI_NO_SORT 0x100
+#define PCI_BIOS_SORT 0x200
+#define PCI_NO_CHECKS 0x400
+#define PCI_PEER_FIXUP 0x800
+#define PCI_ASSIGN_ROMS 0x1000
+#define PCI_BIOS_IRQ_SCAN 0x2000
+
+unsigned int pci_probe;
+
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			     struct resource *res, int resource)
+{
+	u32 new, check;
+	int reg;
+
+	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+	if (resource < 6) {
+		reg = PCI_BASE_ADDRESS_0 + 4*resource;
+	} else if (resource == PCI_ROM_RESOURCE) {
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+		reg = dev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
+
+	pci_write_config_dword(dev, reg, new);
+	pci_read_config_dword(dev, reg, &check);
+	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+		printk(KERN_ERR "PCI: Error while updating region "
+		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       new, check);
+	}
+}
+
+void
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+	struct pci_dev *dev = data;
+
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long start = res->start;
+
+		/* We need to avoid collisions with `mirrored' VGA ports
+		   and other strange ISA hardware, so we always want the
+		   addresses kilobyte aligned.  */
+		if (size > 0x100) {
+			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+			       " (%ld bytes)\n", dev->slot_name,
+			       dev->resource - res, size);
+		}
+
+		start = (start + 1024 - 1) & ~(1024 - 1);
+		res->start = start;
+	}
+}
+
+
+/*
+ *  Handle resources of PCI devices.  If the world were perfect, we could
+ *  just allocate all the resource regions and do nothing more.  It isn't.
+ *  On the other hand, we cannot just re-allocate all devices, as it would
+ *  require us to know lots of host bridge internals.  So we attempt to
+ *  keep as much of the original configuration as possible, but tweak it
+ *  when it's found to be wrong.
+ *
+ *  Known BIOS problems we have to work around:
+ *	- I/O or memory regions not configured
+ *	- regions configured, but not enabled in the command register
+ *	- bogus I/O addresses above 64K used
+ *	- expansion ROMs left enabled (this may sound harmless, but given
+ *	  the fact the PCI specs explicitly allow address decoders to be
+ *	  shared between expansion ROMs and other resource regions, it's
+ *	  at least dangerous)
+ *
+ *  Our solution:
+ *	(1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ *	    This gives us fixed barriers on where we can allocate.
+ *	(2) Allocate resources for all enabled devices.  If there is
+ *	    a collision, just mark the resource as unallocated. Also
+ *	    disable expansion ROMs during this step.
+ *	(3) Try to allocate resources for disabled devices.  If the
+ *	    resources were assigned correctly, everything goes well,
+ *	    if they weren't, they won't disturb allocation of other
+ *	    resources.
+ *	(4) Assign new addresses to resources which were either
+ *	    not configured at all or misconfigured.  If explicitly
+ *	    requested by the user, configure expansion ROM address
+ *	    as well.
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+	struct list_head *ln;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
+	int idx;
+	struct resource *r, *pr;
+
+	/* Depth-First Search on bus tree */
+	for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+		bus = pci_bus_b(ln);
+		if ((dev = bus->self)) {
+			for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+				r = &dev->resource[idx];
+				if (!r->start)
+					continue;
+				pr = pci_find_parent_resource(dev, r);
+				if (!pr || request_resource(pr, r) < 0)
+					printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
+			}
+		}
+		pcibios_allocate_bus_resources(&bus->children);
+	}
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+	struct pci_dev *dev;
+	int idx, disabled;
+	u16 command;
+	struct resource *r, *pr;
+
+	pci_for_each_dev(dev) {
+		pci_read_config_word(dev, PCI_COMMAND, &command);
+		for(idx = 0; idx < 6; idx++) {
+			r = &dev->resource[idx];
+			if (r->parent)		/* Already allocated */
+				continue;
+			if (!r->start)		/* Address not assigned at all */
+				continue;
+			if (r->end == 0xffffffff) {	/* Unassigned */
+				DBG("PCI: Resource %08lx-%08lx was unassigned\n", r->start, r->end);
+				r->end -= r->start;
+				r->start = 0;
+				continue;
+			}
+
+			if (r->flags & IORESOURCE_IO)
+				disabled = !(command & PCI_COMMAND_IO);
+			else
+				disabled = !(command & PCI_COMMAND_MEMORY);
+			if (pass == disabled) {
+				DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
+				    r->start, r->end, r->flags, disabled, pass);
+				pr = pci_find_parent_resource(dev, r);
+				if (!pr || request_resource(pr, r) < 0) {
+					printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name);
+					/* We'll assign a new address later */
+					r->end -= r->start;
+					r->start = 0;
+				}
+			}
+		}
+		if (!pass) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
+				/* Turn the ROM off, leave the resource region, but keep it unregistered. */
+				u32 reg;
+				DBG("PCI: Switching off ROM of %s\n", dev->slot_name);
+				r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
+				pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+				pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+			}
+		}
+	}
+}
+
+static void __init pcibios_assign_resources(void)
+{
+	struct pci_dev *dev;
+	int idx;
+	struct resource *r;
+
+	pci_for_each_dev(dev) {
+		int class = dev->class >> 8;
+
+		/* Don't touch classless devices and host bridges */
+		if (!class || class == PCI_CLASS_BRIDGE_HOST)
+			continue;
+
+		for(idx=0; idx<6; idx++) {
+			r = &dev->resource[idx];
+
+			/*
+			 *  Don't touch IDE controllers and I/O ports of video cards!
+			 */
+			if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
+			    (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
+				continue;
+
+			/*
+			 *  We shall assign a new address to this resource, either because
+			 *  the BIOS forgot to do so or because we have decided the old
+			 *  address was unusable for some reason.
+			 */
+			if (!r->start && r->end)
+				pci_assign_resource(dev, idx);
+		}
+
+		if (pci_probe & PCI_ASSIGN_ROMS) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			r->end -= r->start;
+			r->start = 0;
+			if (r->end)
+				pci_assign_resource(dev, PCI_ROM_RESOURCE);
+		}
+/*		pcibios_enable_resources(dev); */
+	}
+}
+
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for(idx=0; idx<6; idx++) {
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+
+
 void __init pcibios_init(void)
 {
+#if 0
 	printk("PCI: Probing PCI hardware\n");
 	pci_scan_bus(0, &generic_pci_ops, NULL);
 	if (ppc_md.pcibios_fixup)
 		ppc_md.pcibios_fixup();
 	pcibios_claim_resources(&pci_root_buses);
+#else
+	printk("PCI: Probing PCI hardware (semiautomatic)\n");
+	pci_scan_bus(0, &generic_pci_ops, NULL);
+	if (ppc_md.pcibios_fixup)
+		ppc_md.pcibios_fixup();
+
+	pcibios_allocate_bus_resources(&pci_root_buses);
+	pcibios_allocate_resources(0);
+	pcibios_allocate_resources(1);
+	pcibios_assign_resources();
+#endif
+debug_scan_pci();
 }
 
 void __init
@@ -131,31 +399,12 @@
 	return str;
 }
 
-/* the next two are stolen from the alpha port... */
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			struct resource *res, int resource)
-{
-        unsigned long where, size;
-        u32 reg;
-
-        where = PCI_BASE_ADDRESS_0 + (resource * 4);
-        size = res->end - res->start;
-        pci_read_config_dword(dev, where, &reg);
-        reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-        pci_write_config_dword(dev, where, reg);
-}
-
+/* the next one is stolen from the alpha port... */
 void __init
 pcibios_update_irq(struct pci_dev *dev, int irq)
 {
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 	/* XXX FIXME - update OF device tree node interrupt property */
-}
-
-void __init
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
-{
 }
 
 int pcibios_enable_device(struct pci_dev *dev)
diff -uNr linux-2.3.paul/arch/ppc/kernel/pci_debug.c linux/arch/ppc/kernel/pci_debug.c
--- linux-2.3.paul/arch/ppc/kernel/pci_debug.c	Thu Jan  1 01:00:00 1970
+++ linux/arch/ppc/kernel/pci_debug.c	Sun Mar 26 16:50:18 2000
@@ -0,0 +1,349 @@
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+static struct pci_dev *__pci_devices[100];
+static int num_pci_devices = 0;
+
+static struct pci_bus *__pci_buses[100];
+static int num_pci_buses = 0;
+
+static struct resource *__resources[1000];
+static int num_resources = 0;
+
+static void __add_pointer(const void *ptr, const void **table,
+			  int *num_entries, int max_entries)
+{
+    int i;
+
+    if (ptr == NULL)
+	return;
+
+    if (*num_entries == max_entries) {
+	printk("add_pointer: %p is full (%d entries)\n", table, *num_entries);
+	return;
+    }
+    for (i = 0; i < *num_entries; i++)
+	if ((unsigned long)table[i] == (unsigned long)ptr)
+	    return;
+    table[(*num_entries)++] = ptr;
+}
+
+static void __sort_table(const void **table, int num_entries)
+{
+    int i, j;
+
+    for (i = 0; i < num_entries-1; i++)
+	for (j = i+1; j < num_entries; j++)
+	    if ((unsigned long)table[j] < (unsigned long)table[i]) {
+		const void *t = table[i];
+		table[i] = table[j];
+		table[j] = t;
+	    }
+}
+
+static void add_pci_device(const struct pci_dev *dev)
+{
+    __add_pointer(dev, (const void **)__pci_devices, &num_pci_devices,
+		  sizeof(__pci_devices)/sizeof(void *));
+}
+
+static void add_pci_bus(const struct pci_bus *bus)
+{
+    __add_pointer(bus, (const void **)__pci_buses, &num_pci_buses,
+		  sizeof(__pci_buses)/sizeof(void *));
+}
+
+static void add_resource(const struct resource *res)
+{
+    __add_pointer(res, (const void **)__resources, &num_resources,
+		  sizeof(__resources)/sizeof(void *));
+}
+
+static void sort_pci_devices(void)
+{
+    __sort_table((const void **)__pci_devices, num_pci_devices);
+}
+
+static void sort_pci_buses(void)
+{
+    __sort_table((const void **)__pci_buses, num_pci_buses);
+}
+
+static void sort_resources(void)
+{
+    __sort_table((const void **)__resources, num_resources);
+}
+
+static void dump_resource_terse(int n, const struct resource *res)
+{
+    if (!res || !res->flags)
+	return;
+    printk("   %2d: %p [", n, res);
+    if (res->flags & IORESOURCE_IO)
+	printk(" I/O");
+    if (res->flags & IORESOURCE_MEM)
+	printk(" MEM");
+    if (res->flags & IORESOURCE_IRQ)
+	printk(" IRQ");
+    if (res->flags & IORESOURCE_DMA)
+	printk(" DMA");
+    if (res->flags & (IORESOURCE_IO|IORESOURCE_MEM))
+	printk(" %p-%p", (void *)res->start, (void *)res->end);
+    printk(" ]\n");
+}
+
+void dump_resource(const struct resource *res)
+{
+    printk("Resource %p %s\n", res, res->name);
+    if (!res->flags)
+	return;
+    printk("  range = %p-%p\n", (void *)res->start, (void *)res->end);
+    printk("  flags = 0x%08lx [", res->flags);
+    if (res->flags & IORESOURCE_IO)
+	printk(" IO");
+    if (res->flags & IORESOURCE_MEM)
+	printk(" MEM");
+    if (res->flags & IORESOURCE_IRQ)
+	printk(" IRQ");
+    if (res->flags & IORESOURCE_DMA)
+	printk(" DMA");
+
+    if (res->flags & IORESOURCE_PREFETCH)
+	printk(" PREFETCH");
+    if (res->flags & IORESOURCE_READONLY)
+	printk(" READONLY");
+    if (res->flags & IORESOURCE_CACHEABLE)
+	printk(" CACHEABLE");
+    if (res->flags & IORESOURCE_RANGELENGTH)
+	printk(" RANGELENGTH");
+    if (res->flags & IORESOURCE_SHADOWABLE)
+	printk(" SHADOWABLE");
+
+    if (res->flags & IORESOURCE_UNSET)
+	printk(" UNSET");
+    if (res->flags & IORESOURCE_AUTO)
+	printk(" AUTO");
+    if (res->flags & IORESOURCE_BUSY)
+	printk(" BUSY");
+
+    if (res->flags & IORESOURCE_IRQ) {
+	if (res->flags & IORESOURCE_IRQ_HIGHEDGE)
+	    printk(" IRQ_HIGHEDGE");
+	if (res->flags & IORESOURCE_IRQ_LOWEDGE)
+	    printk(" IRQ_LOWEDGE");
+	if (res->flags & IORESOURCE_IRQ_HIGHLEVEL)
+	    printk(" IRQ_HIGHLEVEL");
+	if (res->flags & IORESOURCE_IRQ_LOWLEVEL)
+	    printk(" IRQ_LOWLEVEL");
+    }
+
+    if (res->flags & IORESOURCE_DMA) {
+	switch (res->flags & IORESOURCE_DMA_TYPE_MASK) {
+	    case IORESOURCE_DMA_8BIT:
+		printk(" DMA_8BIT");
+		break;
+	    case IORESOURCE_DMA_8AND16BIT:
+		printk(" DMA_8AND16BIT");
+		break;
+	    case IORESOURCE_DMA_16BIT:
+		printk(" DMA_16BIT");
+		break;
+	}
+	if (res->flags & IORESOURCE_DMA_MASTER)
+	    printk(" DMA_MASTER");
+	if (res->flags & IORESOURCE_DMA_BYTE)
+	    printk(" DMA_BYTE");
+	if (res->flags & IORESOURCE_DMA_WORD)
+	    printk(" DMA_WORD");
+	switch (res->flags & IORESOURCE_DMA_SPEED_MASK) {
+	    case IORESOURCE_DMA_COMPATIBLE:
+		printk(" DMA_COMPATIBLE");
+		break;
+	    case IORESOURCE_DMA_TYPEA:
+		printk(" DMA_TYPEA");
+		break;
+	    case IORESOURCE_DMA_TYPEB:
+		printk(" DMA_TYPEB");
+		break;
+	    case IORESOURCE_DMA_TYPEF:
+		printk(" DMA_TYPEF");
+		break;
+	}
+    }
+
+    if (res->flags & IORESOURCE_MEM) {
+	if (res->flags & IORESOURCE_MEM_WRITEABLE)
+	    printk(" MEM_WRITEABLE");
+	if (res->flags & IORESOURCE_MEM_CACHEABLE)
+	    printk(" MEM_CACHEABLE");
+	if (res->flags & IORESOURCE_MEM_RANGELENGTH)
+	    printk(" MEM_RANGELENGTH");
+	switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
+	    case IORESOURCE_MEM_8BIT:
+		printk(" MEM_8BIT");
+		break;
+	    case IORESOURCE_MEM_16BIT:
+		printk(" MEM_16BIT");
+		break;
+	    case IORESOURCE_MEM_8AND16BIT:
+		printk(" MEM_8AND16BIT");
+		break;
+	}
+	if (res->flags & IORESOURCE_MEM_SHADOWABLE)
+	    printk(" MEM_SHADOWABLE");
+	if (res->flags & IORESOURCE_MEM_EXPANSIONROM)
+	    printk(" MEM_EXPANSIONROM");
+    }
+    printk(" ]\n");
+    printk("  parent = %p sibling = %p child = %p\n", res->parent,
+	   res->sibling, res->child);
+}
+
+void dump_pci_device(const struct pci_dev *dev)
+{
+    int i;
+
+    printk("PCI device %p %s %s\n", dev, dev->slot_name, dev->name);
+    printk("  global_list.prev = %p global_list.next = %p\n",
+	   dev->global_list.prev, dev->global_list.next);
+    printk("  bus_list.prev = %p bus_list.next = %p\n", dev->bus_list.prev,
+	   dev->bus_list.next);
+    printk("  bus = %p subordinate = %p\n", dev->bus, dev->subordinate);
+    printk("  sysdata = %p procent = %p devfn = 0x%08x\n", dev->sysdata,
+	   dev->procent, dev->devfn);
+    printk("  vendor/device = %04x:%04x subsystem = 0x%04x:%04x\n",
+	   dev->vendor, dev->device, dev->subsystem_vendor,
+	   dev->subsystem_device);
+    printk("  class = 0x%08x hdr_type = 0x%02x rom_base_reg = 0x%02x\n",
+	   dev->class, dev->hdr_type, dev->rom_base_reg);
+    printk("  driver = %p driver_data = %p\n", dev->driver, dev->driver_data);
+    printk("  dma_mask = %p\n", (void *)dev->dma_mask);
+    printk("  compatible[] = ");
+    for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++)
+	printk(" %04x:%04x", dev->vendor_compatible[i],
+	       dev->device_compatible[i]);
+    printk("\n");
+    printk("  irq = %d\n", dev->irq);
+    printk("  resource[] =\n");
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+	dump_resource_terse(i, &dev->resource[i]);
+    printk("  dma_resource[] =\n");
+    for (i = 0; i < DEVICE_COUNT_DMA; i++)
+	dump_resource_terse(i, &dev->dma_resource[i]);
+    printk("  irq_resource[] =\n");
+    for (i = 0; i < DEVICE_COUNT_IRQ; i++)
+	dump_resource_terse(i, &dev->irq_resource[i]);
+    printk("  active = %d ro = %d regs = 0x%04x\n", dev->active, dev->ro,
+	   dev->regs);
+    printk("  prepare = %p activate = %p deactivate = %p\n", dev->prepare,
+	   dev->activate, dev->deactivate);
+    printk("\n");
+}
+
+void dump_pci_bus(const struct pci_bus *bus)
+{
+    int i;
+
+    printk("PCI bus %p %s\n", bus, bus->name);
+    printk("  node.prev = %p node.next = %p\n", bus->node.prev,
+	   bus->node.next);
+    printk("  parent = %p\n", bus->parent);
+    printk("  children.prev = %p children.next = %p\n", bus->children.prev,
+	   bus->children.next);
+    printk("  devices.prev = %p devices.next = %p\n", bus->devices.prev,
+	   bus->devices.next);
+    printk("  self = %p\n", bus->self);
+    printk("  resource[] = [\n");
+    for (i = 0; i < 4; i++)
+	dump_resource_terse(i, bus->resource[i]);
+    printk("  ]\n");
+    printk("  ops = %p sysdata = %p procdir = %p\n", bus->ops, bus->sysdata,
+	   bus->procdir);
+    printk("  number = %d primary = %d secondary = %d subordinate = %d\n",
+	   bus->number, bus->primary, bus->secondary, bus->subordinate);
+    printk("  vendor/device = %04x:%04x\n", bus->vendor, bus->device);
+    printk("  serial = %d pnpver = %d productver = %d checksum = %d\n",
+	   bus->serial, bus->pnpver, bus->productver, bus->checksum);
+    printk("\n");
+}
+
+
+static void scan_pci_buses(void)
+{
+    struct pci_bus *bus;
+    int i;
+
+    for (bus = pci_bus_b(pci_root_buses.next);
+	 bus != pci_bus_b(&pci_root_buses);
+	 bus = pci_bus_b(bus->node.next)) {
+	add_pci_bus(bus);
+	for (i = 0; i < 4; i++)
+	    add_resource(bus->resource[i]);
+    }
+}
+
+static void scan_pci_devices(void)
+{
+    struct pci_dev *dev;
+    int i;
+
+    pci_for_each_dev(dev) {
+	add_pci_device(dev);
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+	    add_resource(&dev->resource[i]);
+	for (i = 0; i < DEVICE_COUNT_DMA; i++)
+	    add_resource(&dev->dma_resource[i]);
+	for (i = 0; i < DEVICE_COUNT_IRQ; i++)
+	    add_resource(&dev->irq_resource[i]);
+    }
+}
+
+void dump_pci_buses(void)
+{
+    int i;
+
+    printk(">>>>>>>>>>>>>>>>>>>> PCI Buses >>>>>>>>>>>>>>>>>>>>\n");
+    for (i = 0; i < num_pci_buses; i++)
+	dump_pci_bus(__pci_buses[i]);
+    printk("<<<<<<<<<<<<<<<<<<<< PCI Buses <<<<<<<<<<<<<<<<<<<<\n");
+}
+
+
+void dump_pci_devices(void)
+{
+    int i;
+
+    printk(">>>>>>>>>>>>>>>>>>>> PCI Devices >>>>>>>>>>>>>>>>>>>>\n");
+    for (i = 0; i < num_pci_devices; i++)
+	dump_pci_device(__pci_devices[i]);
+    printk("<<<<<<<<<<<<<<<<<<<< PCI Devices <<<<<<<<<<<<<<<<<<<<\n");
+}
+
+
+void dump_resources(void)
+{
+    int i;
+
+    printk(">>>>>>>>>>>>>>>>>>>> Resources >>>>>>>>>>>>>>>>>>>>\n");
+    for (i = 0; i < num_resources; i++)
+	dump_resource(__resources[i]);
+    printk("<<<<<<<<<<<<<<<<<<<< Resources <<<<<<<<<<<<<<<<<<<<\n");
+}
+
+void debug_scan_pci(void)
+{
+    scan_pci_buses();
+    scan_pci_devices();
+    sort_pci_buses();
+    sort_pci_devices();
+    sort_resources();
+}
+
+void debug_dump_pci(void)
+{
+    dump_pci_buses();
+    dump_pci_devices();
+    dump_resources();
+}
+
diff -uNr linux-2.3.paul/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- linux-2.3.paul/arch/ppc/kernel/pmac_pci.c	Fri Feb 11 00:19:51 2000
+++ linux/arch/ppc/kernel/pmac_pci.c	Sun Mar 26 23:15:04 2000
@@ -27,6 +27,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;
 
@@ -41,6 +50,10 @@
 static int uninorth_default = -1;
 
 static void add_bridges(struct device_node *dev);
+struct pci_bus *fix_chaos(struct bridge_data *);
+void fix_planb(struct pci_dev *);
+
+extern struct pci_ops generic_pci_ops;
 
 /*
  * Magic constants for enabling cache coherency in the bandit/PSX bridge.
@@ -54,6 +67,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)
 {
@@ -65,6 +82,16 @@
 }
 
 __pmac
+int pci_io_length(unsigned int bus)
+{
+	struct bridge_data *bp;
+
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
+		return 0;
+	return bp->io_length;
+}
+
+__pmac
 int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
 		   unsigned char *devfn_ptr)
 {
@@ -613,6 +640,7 @@
 			bp->cfg_data = 0;
 			/* is 0x10000 enough for io space ? */
 			bp->io_base = (void *)ioremap(addr->address, 0x10000);
+			bp->io_length = 0x10000;
 		} else if (strcmp(dev->name, "pci") == 0) {
 			/* XXX assume this is a mpc106 (grackle) */
 			bp->cfg_addr = (volatile unsigned int *)
@@ -620,6 +648,7 @@
 			bp->cfg_data = (volatile unsigned char *)
 				ioremap(0xfee00000, 0x1000);
                         bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
+			bp->io_length = 0x20000;
 #if 0 /* Disabled for now, HW problems */
 			grackle_set_stg(bp, 1);
 #endif
@@ -629,7 +658,8 @@
 				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_length = 0x800000;
 		}
 		if (isa_io_base == 0)
 			isa_io_base = (unsigned long) bp->io_base;
@@ -664,8 +694,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 %s.\n",
+				dev->irq, dev->slot_name);
+		}
 		break;
 	}
 }
@@ -674,35 +707,243 @@
 pmac_pcibios_fixup(void)
 {
 	struct pci_dev *dev;
+	struct bridge_data *bp;
+	struct resource *newres;
+	char *name;
+	int i, size;
 	
 	/*
-	 * 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.
+	 *
+	 * We also provide new IO port resources for each bus decribing
+	 * the available IO space.
 	 */
-	pci_for_each_dev(dev)
-	{
-		/*
-		 * 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.
-		 */
+	/* Count the host bridges */
+	for (bp = bridge_list, i = 0; bp != NULL; bp = bp->next, i++);
+
+	size = i * (sizeof(*newres) + 21);
+	if ((newres = kmalloc(size, GFP_KERNEL)) == 0) {
+		printk(KERN_ERR "PCI: Out of memory in pmac_pcibios_fixup!\n");
+		return;
+	}
+	memset(newres, 0, size);
+	name = (char *)(newres + i);
+	
+	for (bp = bridge_list; bp != NULL; bp = bp->next) {
+		struct pci_bus *bus = NULL;
+		int b = bp->bus_number;
+
+		if (strcmp(bp->node->name, "chaos") == 0) continue;
+/*			bus = fix_chaos(bp); */
+		else if (b == 0) {
+			/* hack to get at struct pci_bus for bus 0 */
+			pci_for_each_dev(dev) {
+				if (dev->bus->number != 0) continue;
+				bus = dev->bus;
+				break;
+			}
+		} else
+			bus = pci_scan_bus(b, &generic_pci_ops, NULL);
+
+		if (bus == NULL) continue; /* something went wrong */
+
+		sprintf(name, "%s PCI IO", bp->node->name);
+		newres->name = name;
+		newres->start = (unsigned long)pci_io_base(b);
+		newres->end = newres->start + pci_io_length(b);
+		newres->flags = IORESOURCE_IO;
+		bus->resource[0] = newres;
+		newres ++;	
+		name += 21;
+	}
+
+	pci_for_each_dev(dev) {
 		struct bridge_data *bp = bridges[dev->bus->number];
 		unsigned char pin;
+
+		DBG("PCI: Fixing device %s (%04x:%04x)\n",
+			dev->slot_name,
+			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.
+		 */
 			
-		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);
+		/* Is there an interrupt? */
+		if ( !(pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||
+		    !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);
+		}
+		/*
+		 * Since the PMac host bridges do translate IO accesses,
+		 * we correct the kernel PCI device database here with an
+		 * offset we add to IO region's base address. The exact
+		 * offset is provided by the bridge controling the
+		 * device's bus.
+		 */
+		if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) goto nextfix;
+
+		for(i=0; i<6; i++) {
+			struct resource *res = &dev->resource[i];
+			unsigned long base;
+			unsigned long a = res->start;
+
+			if (res->flags & PCI_BASE_ADDRESS_SPACE_IO) {
+				base = (unsigned long)
+					pci_io_base(dev->bus->number);
+				/* unassigned region? */
+				if (a == 0) continue;
+				/* strange value? */
+				if (a > 0x800000) continue;
+				if (a < base) a += base;
+				if (a > base) {
+					res->start = a;
+					res->end += base;
+					DBG("PCI: Correcting IO address %d on "
+					    "device %s, now %08lx.\n",
+					    i, dev->slot_name, a);
+				}
+			}
+		}
+nextfix:
+		/*
+		 * 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....
+		 *        Or maybe the new 2.3 resource code?
+		 */
+		pcibios_enable_device(dev);
+	}
+}
+
+/*
+ * 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.
+ */
+
+struct pci_bus * __init
+fix_chaos (struct bridge_data *bp)
+{
+	struct device_node *nd;
+	struct pci_dev temp;
+	struct pci_bus *b;
+
+	b = pci_alloc_primary_bus(bp->bus_number);
+	b->sysdata = NULL;
+	b->ops = &generic_pci_ops;
+	b->subordinate = bp->max_bus;
+	/*
+	 * 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;
+		}
+		temp.devfn = (nd->addrs[0].space >> 8) & 0xff;
+		temp.bus = b;
+		pci_scan_slot(&temp);
+	}
+	return b;
+}
+
+void __init
+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;
+	struct resource *res;
+	unsigned char bus, devfn, confreg;
+	unsigned int reg;
+	u32 sz;
+
+	DBG("PCI: fixing PlanB...\n");
+	planb_device = find_devices("planb");
+	if (planb_device == 0) {
+		printk(KERN_WARNING "PCI: Error fixing planb: no OF device.\n");
+		return;
+	}
+	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, ~0);
+	pcibios_read_config_dword(bus, devfn, confreg, &sz);
+	pcibios_write_config_dword(bus, devfn, confreg, PLANB_BASE);
+	res = &pcidev->resource[reg];
+	res->start = PLANB_BASE & PCI_BASE_ADDRESS_MEM_MASK;
+	sz = ~(sz & PCI_BASE_ADDRESS_MEM_MASK);
+	res->end = res->start + (unsigned long) sz;
+	/*
+	 * Everything else should be set up right from the generic scan
+	 * code. Now enable PlanB...
+	 */
+	pcibios_enable_device(pcidev);
+	return;
 }
 
 void __init
diff -uNr linux-2.3.paul/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- linux-2.3.paul/arch/ppc/kernel/pmac_setup.c	Wed Mar  8 00:19:16 2000
+++ linux/arch/ppc/kernel/pmac_setup.c	Sun Mar 26 09:31:15 2000
@@ -684,7 +684,8 @@
         ppc_ide_md.fix_driveid = pmac_ide_fix_driveid;
         ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
 
-        ppc_ide_md.io_base = _IO_BASE;	/* actually too early for this :-( */
+/*	ppc_ide_md.io_base = _IO_BASE;	 actually too early for this :-( */
+	ppc_ide_md.io_base = 0;
 #endif
 #ifdef CONFIG_BOOTX_TEXT
 	ppc_md.progress = pmac_progress;
diff -uNr linux-2.3.paul/drivers/pci/pci.c linux/drivers/pci/pci.c
--- linux-2.3.paul/drivers/pci/pci.c	Sat Mar 25 06:50:06 2000
+++ linux/drivers/pci/pci.c	Sun Mar 26 09:16:57 2000
@@ -23,6 +23,7 @@
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
 
 #undef DEBUG
+#define DEBUG
 
 #ifdef DEBUG
 #define DBG(x...) printk(x)
diff -uNr linux-2.3.paul/drivers/pci/proc.c linux/drivers/pci/proc.c
--- linux-2.3.paul/drivers/pci/proc.c	Sun Feb 27 09:26:19 2000
+++ linux/drivers/pci/proc.c	Sun Mar 26 16:50:18 2000
@@ -385,6 +385,7 @@
 	int nprinted, len, begin = 0;
 	struct pci_dev *dev;
 
+debug_dump_pci();
 	len = sprintf(buf, "PCI devices found:\n");
 
 	*eof = 1;
diff -uNr linux-2.3.paul/drivers/pci/quirks.c linux/drivers/pci/quirks.c
--- linux-2.3.paul/drivers/pci/quirks.c	Fri Mar  3 00:19:19 2000
+++ linux/drivers/pci/quirks.c	Sun Mar 26 16:50:18 2000
@@ -17,7 +17,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 
-#undef DEBUG
+#define DEBUG
 
 /* Deal with broken BIOS'es that neglect to enable passive release,
    which can cause problems in combination with the 82441FX/PPro MTRRs */
diff -uNr linux-2.3.paul/drivers/pci/setup-bus.c linux/drivers/pci/setup-bus.c
--- linux-2.3.paul/drivers/pci/setup-bus.c	Fri Jan 21 23:46:55 2000
+++ linux/drivers/pci/setup-bus.c	Sun Mar 26 16:50:18 2000
@@ -17,7 +17,7 @@
 #include <linux/cache.h>
 
 
-#define DEBUG_CONFIG 0
+#define DEBUG_CONFIG 1
 #if DEBUG_CONFIG
 # define DBGC(args)     printk args
 #else
diff -uNr linux-2.3.paul/drivers/pci/setup-irq.c linux/drivers/pci/setup-irq.c
--- linux-2.3.paul/drivers/pci/setup-irq.c	Fri Jan 21 23:46:55 2000
+++ linux/drivers/pci/setup-irq.c	Sun Mar 26 16:50:18 2000
@@ -18,7 +18,7 @@
 #include <linux/cache.h>
 
 
-#define DEBUG_CONFIG 0
+#define DEBUG_CONFIG 1
 #if DEBUG_CONFIG
 # define DBGC(args)     printk args
 #else
diff -uNr linux-2.3.paul/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c
--- linux-2.3.paul/drivers/pci/setup-res.c	Fri Jan 21 23:46:55 2000
+++ linux/drivers/pci/setup-res.c	Sun Mar 26 16:50:18 2000
@@ -19,7 +19,7 @@
 #include <linux/cache.h>
 
 
-#define DEBUG_CONFIG 0
+#define DEBUG_CONFIG 1
 #if DEBUG_CONFIG
 # define DBGC(args)     printk args
 #else
diff -uNr linux-2.3.paul/include/asm-ppc/io.h linux/include/asm-ppc/io.h
--- linux-2.3.paul/include/asm-ppc/io.h	Sat Mar 25 08:27:05 2000
+++ linux/include/asm-ppc/io.h	Sun Mar 26 09:55:27 2000
@@ -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.3.paul/include/asm-ppc/pci-bridge.h linux/include/asm-ppc/pci-bridge.h
--- linux-2.3.paul/include/asm-ppc/pci-bridge.h	Mon Oct 25 03:20:01 1999
+++ linux/include/asm-ppc/pci-bridge.h	Sun Mar 26 09:31:15 2000
@@ -21,6 +21,7 @@
 	volatile unsigned int *cfg_addr;
 	volatile unsigned char *cfg_data;
 	void *io_base;
+	int io_length;
 	int bus_number;
 	int max_bus;
 	struct bridge_data *next;
diff -uNr linux-2.3.paul/include/asm-ppc/pci.h linux/include/asm-ppc/pci.h
--- linux-2.3.paul/include/asm-ppc/pci.h	Sat Mar 25 08:27:05 2000
+++ linux/include/asm-ppc/pci.h	Sun Mar 26 17:13:42 2000
@@ -8,7 +8,7 @@
 #define pcibios_assign_all_busses()	0
 
 #define PCIBIOS_MIN_IO		0x1000
-#define PCIBIOS_MIN_MEM		0x10000000
+#define PCIBIOS_MIN_MEM		0xc0000000
 
 extern inline void pcibios_set_master(struct pci_dev *dev)
 {
