[coreboot] r1089 - in coreboot-v3: device include/device

svn at coreboot.org svn at coreboot.org
Wed Dec 31 20:43:35 CET 2008


Author: myles
Date: 2008-12-31 20:43:34 +0100 (Wed, 31 Dec 2008)
New Revision: 1089

Modified:
   coreboot-v3/device/cardbus_device.c
   coreboot-v3/device/device.c
   coreboot-v3/device/device_util.c
   coreboot-v3/device/pci_device.c
   coreboot-v3/device/pci_ops.c
   coreboot-v3/device/root_device.c
   coreboot-v3/include/device/device.h
   coreboot-v3/include/device/resource.h
Log:
This patch simplifies the resource allocator by splitting it into distinct
phases.  One benefit of this is that it makes the call chain easier to follow.

device/device.c:
	Remove references to have_resources.
	Remove read_resources from compute allocate resources.
	Split compute_allocate_resources into two
	1. compute_resource_needs
		A. Traverse the tree depth first
		B. Sum resources
		C. Adjust limits and bases
		D. Update bridge resources sizes
	2. assign_resource_values
		A. Traverse the tree breadth first
		B. Assign resource values

device/device_util.c:
	Remove references to have_resources.

device/pci_device.c:
	Remove saved values stubs (they're not needed now.)
		1. Sizing function restores values
	Fix 64-bit flag masking.
	Add an error message for an invalid value.
	Update pci_record_bridge_resource:
		1. remove compute_allocate_resource call
		2. remove pci_set_resource call
	Update pci_bus_read_resources to read children's too.
	Update pci_set_resource:
		1. change logic for setting zero-size resources
			A. Set range to [limit->limit-2^gran]
				(Could have been any range with base > limit)
		2. remove compute_allocate_resource calls
		3. Change phase4_assign_resources ->phase4_set_resources

device/pci_ops.c:
	Change an error message to be more helpful.

device/root_device.c:
	Remove code for read_resources and set resources.
	Add a .id to the ops.

include/device/device.h:
	Remove have_resources.
	Comment out assign_resources.  I think we could comment out more here.
	Add debugging function prototypes.
	Change phase4_assign_resources to phase4_set_resources.

include/device/resource.h
	Add a IORESOURCE_BRIDGE flag.

device/cardbus_device.c
	Remove compute_allocate_resource call.
	Use probe_resource (doesn't die) instead of find_resource.

Signed-off-by: Myles Watson <mylesgw at gmail.com>
Acked-by: Ronald G. Minnich <rminnich at gmail.com>



Modified: coreboot-v3/device/cardbus_device.c
===================================================================
--- coreboot-v3/device/cardbus_device.c	2008-12-30 07:02:52 UTC (rev 1088)
+++ coreboot-v3/device/cardbus_device.c	2008-12-31 19:43:34 UTC (rev 1089)
@@ -75,11 +75,10 @@
 {
 	struct resource *resource;
 	resource_t min_size;
-	resource = find_resource(dev, index);
+	resource = probe_resource(dev, index);
 	if (resource) {
 		min_size = resource->size;
-		compute_allocate_resource(&dev->link[0], resource,
-					  resource->flags, resource->flags);
+
 		/* Always allocate at least the minimum size to a
 		 * cardbus bridge in case a new card is plugged in.
 		 */

Modified: coreboot-v3/device/device.c
===================================================================
--- coreboot-v3/device/device.c	2008-12-30 07:02:52 UTC (rev 1088)
+++ coreboot-v3/device/device.c	2008-12-31 19:43:34 UTC (rev 1089)
@@ -13,6 +13,7 @@
  * (Written by Yinghai Lu for Tyan)
  * Copyright (C) 2005-2006 Stefan Reinauer <stepan at openbios.org>
  * Copyright (C) 2007 coresystems GmbH
+ * Copyright (C) 2008 Myles Watson <mylesgw at gmail.com>
  */
 
 /*
@@ -48,18 +49,6 @@
 struct device **last_dev_p;
 
 /**
- * The upper limit of MEM resource of the devices.
- * Reserve 20M for the system.
- */
-#define DEVICE_MEM_HIGH 0xFEBFFFFFUL
-
-/**
- * The lower limit of I/O resource of the devices.
- * Reserve 4K for ISA/Legacy devices.
- */
-#define DEVICE_IO_START 0x1000
-
-/**
  * device memory. All the device tree wil live here
  */
 
@@ -110,7 +99,7 @@
 /**
  * Given a path, locate the device_operations for it from all_device_operations.
  *
- * @param id TODO
+ * @param id a device ID to match
  * @return Pointer to the ops or 0, if none found.
  * @see device_path
  */
@@ -127,7 +116,8 @@
 		printk(BIOS_SPEW, "%s: cons id %s\n",
 		       __func__, dev_id_string(&c->id));
 		if (id_eq(&c->id, id)) {
-			printk(BIOS_SPEW, "%s: match\n", __func__);
+			printk(BIOS_SPEW, "%s: match %s\n",
+			       __func__, dev_id_string(&c->id));
 			return c;
 		}
 	}
@@ -138,10 +128,9 @@
 /**
  * Initialization tasks for the device tree code.
  *
- * Sets up last_dev_p, which used to be done by
- * Fucking Magic (FM) in the config tool. Also, for each of the
- * devices, tries to find the constructor, and from there, the ops,
- * for the device.
+ * Sets up last_dev_p, which used to be done by magic in the config tool. Also,
+ * for each of the devices, tries to find the constructor, and from there, the
+ * ops, for the device.
  */
 void dev_init(void)
 {
@@ -206,7 +195,7 @@
  *
  * @param parent Parent bus the newly created device is attached to.
  * @param path Path to the device to be created.
- * @param devid TODO
+ * @param devid ID of the device we want allocated.
  * @return Pointer to the newly created device structure.
  * @see device_path
  */
@@ -254,7 +243,7 @@
 	last_dev_p = &dev->next;
 
 	/* Give the device a name. */
-	if (dev->id.type == DEVICE_ID_PNP && 
+	if (dev->id.type == DEVICE_ID_PNP &&
 	    parent->dev->id.type == DEVICE_ID_PNP)
 		sprintf(dev->dtsname, "%s_pnp_child_%d", parent->dev->dtsname,
 			dev->path.pnp.device);
@@ -292,17 +281,12 @@
 
 	/* Walk through all devices and find which resources they need. */
 	for (curdev = bus->children; curdev; curdev = curdev->sibling) {
-		unsigned int links;
 		int i;
 		printk(BIOS_SPEW,
-		       "%s: %s(%s) dtsname %s have_resources %d enabled %d\n",
+		       "%s: %s(%s) dtsname %s enabled %d\n",
 		       __func__, bus->dev ? bus->dev->dtsname : "NOBUSDEV",
 		       bus->dev ? dev_path(bus->dev) : "NOBUSDEV",
-		       curdev->dtsname,
-		       curdev->have_resources, curdev->enabled);
-		if (curdev->have_resources) {
-			continue;
-		}
+		       curdev->dtsname, curdev->enabled);
 		if (!curdev->enabled) {
 			continue;
 		}
@@ -313,28 +297,10 @@
 			continue;
 		}
 		curdev->ops->phase4_read_resources(curdev);
-		curdev->have_resources = 1;
 
-		/* Read in subtractive resources behind the current device. */
-		links = 0;
-		for (i = 0; i < curdev->resources && (curdev->links > 0); i++) {
-			struct resource *resource;
-			unsigned int link;
-			resource = &curdev->resource[i];
-			if (!(resource->flags & IORESOURCE_SUBTRACTIVE))
-				continue;
-			link = IOINDEX_SUBTRACTIVE_LINK(resource->index);
-			if (link > MAX_LINKS) {
-				printk(BIOS_ERR,
-				       "%s subtractive index on link: %d\n",
-				       dev_path(curdev), link);
-				continue;
-			}
-			if (!(links & (1 << link))) {
-				links |= (1 << link);
-				read_resources(&curdev->link[link]);
-			}
-		}
+		/* Read in children's resources behind the current device. */
+		for (i = 0; i< curdev->links; i++)
+			read_resources(&curdev->link[i]);
 	}
 	printk(BIOS_SPEW, "%s: %s(%s) read_resources bus %d link: %d done\n",
 	       __func__, bus->dev->dtsname, dev_path(bus->dev), bus->secondary,
@@ -398,7 +364,7 @@
 }
 
 /**
- * This function is the guts of the resource allocator.
+ * This function is the first part of the resource allocator.
  *
  * The problem.
  *  - Allocate resource locations for every device.
@@ -424,85 +390,199 @@
  *   a device with a couple of resources, and not need to special case it in
  *   the allocator. Also this allows handling of other types of bridges.
  *
- * @param bus TODO
- * @param bridge TODO
- * @param type_mask TODO
- * @param type TODO
+ * - This function calculates how large the resources are behind the bridges.
+ *
+ * @param bus The bus we are traversing.
+ * @param bridge The bridge resource which will contain the bus' resources.
+ * @param type_mask This value gets anded with the resource type.
+ * @param type This value must match the result of the and.
  */
-void compute_allocate_resource(struct bus *bus, struct resource *bridge,
+void compute_resource_needs(struct bus *bus, struct resource *bridge,
 			       unsigned long type_mask, unsigned long type)
 {
 	struct device *dev;
 	struct resource *resource;
 	resource_t base;
-	unsigned long align, min_align;
-	min_align = 0;
-	base = bridge->base;
+	base = align_up(bridge->base, bridge->align);
 
 	printk(BIOS_SPEW,
-	       "%s compute_allocate_%s: base: %08llx size: %08llx align: %d gran: %d limit: %08llx\n",
-	       dev_path(bus->dev),
-	       (bridge->flags & IORESOURCE_IO) ? "io" : (bridge->flags &
-							 IORESOURCE_PREFETCH) ?
-	       "prefmem" : "mem", base, bridge->size, bridge->align,
+	       "%s %s_%s: base: %llx size: %llx align: %d gran: %d limit: %llx\n",
+	       dev_path(bus->dev), __func__,
+	       (type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
+						"prefmem" : "mem",
+	       base, bridge->size, bridge->align,
 	       bridge->gran, bridge->limit);
 
-	/* We want different minimum alignments for different kinds of
-	 * resources. These minimums are not device type specific but
-	 * resource type specific.
-	 */
-	if (bridge->flags & IORESOURCE_IO) {
-		min_align = log2c(DEVICE_IO_ALIGN);
+	/* For each child which is a bridge, compute_resource_needs. */
+	for (dev = bus->children; dev; dev = dev->sibling) {
+		unsigned i;
+		struct resource *child_bridge;
+
+		if (!dev->links)
+			continue;
+
+		/* Find the resources with matching type flags. */
+		for (i=0; i< dev->resources; i++){
+			child_bridge = &dev->resource[i];
+
+			if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
+			     (child_bridge->flags & type_mask) != type)
+				continue;
+
+			/* Split prefetchable memory if combined.  Many domains
+			 * use the same address space for prefetchable memory
+			 * and non-prefetchable memory.  Bridges below them
+			 * need it separated.  Add the PREFETCH flag to the
+			 * type_mask and type.
+			 */
+			compute_resource_needs(&dev->link[0], child_bridge,
+					       type_mask | IORESOURCE_PREFETCH,
+					       type | (child_bridge->flags &
+						       IORESOURCE_PREFETCH));
+		}
 	}
-	if (bridge->flags & IORESOURCE_MEM) {
-		min_align = log2c(DEVICE_MEM_ALIGN);
-	}
 
-	/* Make certain we have read in all of the resources. */
-	read_resources(bus);
-
 	/* Remember we haven't found anything yet. */
 	resource = NULL;
 
-	/* Walk through all the devices on the current bus and
-	 * compute the addresses.
+	/* Walk through all the resources on the current bus and compute the
+	 * amount of address space taken by them.  Take granularity and
+	 * alignment into account.
 	 */
 	while ((dev = largest_resource(bus, &resource, type_mask, type))) {
-		resource_t size;
 
-		/* Do NOT, I repeat do not, ignore resources which have zero
-		 * size. If they need to be ignored dev->read_resources should
-		 * not even return them. Some resources must be set even when
-		 * they have no size. PCI bridge resources are a good example
-		 * of this.
-		 */
-
-		/* Make certain we are dealing with a good minimum size. */
-		size = resource->size;
-		align = resource->align;
-		if (align < min_align) {
-			align = min_align;
+		/* Size 0 resources can be skipped. */
+		if (!resource->size) {
+			continue;
 		}
 
-		/* Propagate the resource alignment to the bridge register  */
-		if (align > bridge->align) {
-			bridge->align = align;
+		/* Propagate the resource alignment to the bridge resource. */
+		if (resource->align > bridge->align) {
+			bridge->align = resource->align;
 		}
 
-		if (resource->flags & IORESOURCE_FIXED) {
-			continue;
-		}
-
 		/* Propagate the resource limit to the bridge register. */
 		if (bridge->limit > resource->limit) {
 			bridge->limit = resource->limit;
 		}
 
-		/* Artificially deny limits between DEVICE_MEM_HIGH and 0xffffffff. */
-		if ((bridge->limit > DEVICE_MEM_HIGH)
-		    && (bridge->limit <= 0xffffffff)) {
-			bridge->limit = DEVICE_MEM_HIGH;
+		/* I'm not sure what to do here.  I'd really like this to go
+		 * away into some PCI-specific file, but I don't see how to do
+		 * it.  I'm also not sure how to guarantee that larger
+		 * allocations don't conflict with this address set.
+		 * The example is 0x1000-0x13ff overlaps, but since the base
+		 * doesn't, then this check doesn't trigger.  It wouldn't do
+		 * any good, though, since you can't move it to avoid the
+		 * conflict.
+		 */
+		if (resource->flags & IORESOURCE_IO) {
+			/* Don't allow potential aliases over the legacy PCI
+			 * expansion card addresses. The legacy PCI decodes
+			 * only 10 bits, uses 0x100 - 0x3ff. Therefore, only
+			 * 0x00 - 0xff can be used out of each 0x400 block of
+			 * I/O space.
+			 */
+			if ((base & 0x300) != 0) {
+				base = (base & ~0x3ff) + 0x400;
+			}
+			/* Don't allow allocations in the VGA I/O range.
+			 * PCI has special cases for that.
+			 */
+			else if ((base >= 0x3b0) && (base <= 0x3df)) {
+				base = 0x3e0;
+			}
 		}
+		/* Base must be aligned. */
+		base = align_up(base, resource->align);
+		resource->base = base;
+		base += resource->size;
+
+		printk(BIOS_SPEW, "%s %02lx *  [0x%llx - 0x%llx] %s\n",
+		       dev_path(dev), resource->index, resource->base,
+		       resource->base + resource->size - 1,
+		       (resource->flags & IORESOURCE_IO) ? "io" :
+		       (resource-> flags & IORESOURCE_PREFETCH) ? "prefmem" :
+		        "mem");
+	}
+	/* Bridge resources have a minimum granularity. Round the size up to
+	 * that minimum granularity so we know not to place something else at
+	 * an address positively decoded by the bridge.
+	 */
+	bridge->size = align_up(base, bridge->gran) -
+		       align_up(bridge->base, bridge->align);
+
+	printk(BIOS_SPEW,
+	       "%s %s_%s: base: %llx size: %llx align: %d gran: %d limit: %llx done\n",
+	       dev_path(bus->dev), __func__,
+	       (type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
+						"prefmem" : "mem",
+	       base, bridge->size, bridge->align,
+	       bridge->gran, bridge->limit);
+}
+
+/**
+ * This function is the second part of the resource allocator.
+ *
+ * The problem.
+ *  - Allocate resource locations for every device.
+ *  - Don't overlap, and follow the rules of bridges.
+ *  - Don't overlap with resources in fixed locations.
+ *  - Be efficient so we don't have ugly strategies.
+ *
+ * The strategy.
+ * - Devices that have fixed addresses are the minority so don't
+ *   worry about them too much. Instead only use part of the address
+ *   space for devices with programmable addresses. This easily handles
+ *   everything except bridges.
+ *
+ * - PCI devices are required to have their sizes and their alignments
+ *   equal. In this case an optimal solution to the packing problem
+ *   exists. Allocate all devices from highest alignment to least
+ *   alignment or vice versa. Use this.
+ *
+ * - So we can handle more than PCI run two allocation passes on bridges. The
+ *   first to see how large the resources are behind the bridge, and what
+ *   their alignment requirements are. The second to assign a safe address to
+ *   the devices behind the bridge. This allows us to treat a bridge as just
+ *   a device with a couple of resources, and not need to special case it in
+ *   the allocator. Also this allows handling of other types of bridges.
+ *
+ * - This function assigns the resources a value.
+ *
+ * @param bus The bus we are traversing.
+ * @param bridge The bridge resource which must contain the bus' resources.
+ * @param type_mask This value gets anded with the resource type.
+ * @param type This value must match the result of the and.
+ */
+void assign_resource_values(struct bus *bus, struct resource *bridge,
+			       unsigned long type_mask, unsigned long type)
+{
+	struct device *dev;
+	struct resource *resource;
+	resource_t base;
+	base = bridge->base;
+
+	printk(BIOS_SPEW,
+	       "%s %s_%s: base:%llx size:%llx align:%d gran:%d limit:%llx\n",
+	       dev_path(bus->dev), __func__,
+	       (type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
+						"prefmem" : "mem",
+	       base, bridge->size, bridge->align,
+	       bridge->gran, bridge->limit);
+
+	/* Remember we haven't found anything yet. */
+	resource = NULL;
+
+	/* Walk through all the resources on the current bus and allocate them
+	 * address space.
+	 */
+	while ((dev = largest_resource(bus, &resource, type_mask, type))) {
+
+		/* Size 0 resources can be skipped. */
+		if (!resource->size) {
+			continue;
+		}
+
 		if (resource->flags & IORESOURCE_IO) {
 			/* Don't allow potential aliases over the legacy PCI
 			 * expansion card addresses. The legacy PCI decodes
@@ -520,42 +600,210 @@
 				base = 0x3e0;
 			}
 		}
-		if (((align_up(base, align) + size) - 1) <= resource->limit) {
-			/* Base must be aligned to size. */
-			base = align_up(base, align);
+
+
+		if ((align_up(base, resource->align) + resource->size - 1) <=
+		     resource->limit) {
+			/* Base must be aligned. */
+			base = align_up(base, resource->align);
 			resource->base = base;
 			resource->flags |= IORESOURCE_ASSIGNED;
 			resource->flags &= ~IORESOURCE_STORED;
-			base += size;
+			base += resource->size;
+		} else {
+			printk(BIOS_ERR, "!! Resource didn't fit !!\n");
+			printk(BIOS_ERR, "   aligned base %llx size %llx limit %llx\n",
+			       align_up(base, resource->align), resource->size, resource->limit);
+			printk(BIOS_ERR, "   %llx needs to be <= %llx (limit)\n",
+			       (align_up(base, resource->align)+resource->size)-1, resource->limit);
+			printk(BIOS_ERR, "   %s%s %02lx *  [0x%llx - 0x%llx] %s\n",
+		       (resource->flags & IORESOURCE_ASSIGNED) ? "Assigned: "
+							       : "",
+		       dev_path(dev), resource->index, resource->base,
+		       resource->base + resource->size - 1,
+		       (resource->flags & IORESOURCE_IO) ? "io" :
+		       (resource-> flags & IORESOURCE_PREFETCH) ? "prefmem" :
+		        "mem");
+		}
 
-			printk(BIOS_SPEW,
-			       "%s %02lx *  [0x%08llx - 0x%08llx] %s\n",
-			       dev_path(dev),
-			       resource->index,
-			       resource->base,
-			       resource->base + resource->size - 1,
-			       (resource->flags & IORESOURCE_IO) ? "io" :
-			       (resource->
-				flags & IORESOURCE_PREFETCH) ? "prefmem" :
-			       "mem");
-		}
+		printk(BIOS_SPEW, "%s%s %02lx *  [0x%llx - 0x%llx] %s\n",
+		       (resource->flags & IORESOURCE_ASSIGNED) ? "Assigned: "
+							       : "",
+		       dev_path(dev), resource->index, resource->base,
+
+			resource->size?  resource->base + resource->size - 1 :
+			resource->base,
+
+		       (resource->flags & IORESOURCE_IO) ? "io" :
+		       (resource-> flags & IORESOURCE_PREFETCH) ? "prefmem" :
+		        "mem");
 	}
 	/* A PCI bridge resource does not need to be a power of two size, but
 	 * it does have a minimum granularity. Round the size up to that
 	 * minimum granularity so we know not to place something else at an
 	 * address positively decoded by the bridge.
 	 */
-	bridge->size = align_up(base, bridge->gran) - bridge->base;
 
+	bridge->flags |= IORESOURCE_ASSIGNED;
+
 	printk(BIOS_SPEW,
-	       "%s compute_allocate_%s: base: %08llx size: %08llx align: %d gran: %d done\n",
-	       dev_path(bus->dev),
-	       (bridge->flags & IORESOURCE_IO) ? "io" : (bridge->flags &
-							 IORESOURCE_PREFETCH) ?
-	       "prefmem" : "mem", base, bridge->size, bridge->align,
+	       "%s %s_%s: next_base: %llx size: %llx align: %d gran: %d done\n",
+	       dev_path(bus->dev), __func__,
+	       (type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
+						"prefmem" : "mem",
+	       base, bridge->size, bridge->align,
 	       bridge->gran);
+
+	/* For each child which is a bridge, assign_resource_values. */
+	for (dev = bus->children; dev; dev = dev->sibling) {
+		unsigned i;
+		struct resource *child_bridge;
+
+		if (!dev->links)
+			continue;
+
+		/* Find the resources with matching type flags. */
+		for (i=0; i< dev->resources; i++){
+			child_bridge = &dev->resource[i];
+
+			if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
+			     (child_bridge->flags & type_mask) != type)
+				continue;
+
+			/* Split prefetchable memory if combined.  Many domains
+			 * use the same address space for prefetchable memory
+			 * and non-prefetchable memory.  Bridges below them
+			 * need it separated.  Add the PREFETCH flag to the
+			 * type_mask and type.
+			 */
+			assign_resource_values(&dev->link[0], child_bridge,
+					       type_mask | IORESOURCE_PREFETCH,
+					       type | (child_bridge->flags &
+						       IORESOURCE_PREFETCH));
+		}
+	}
 }
 
+struct constraints {
+	struct resource pref, io, mem;
+};
+
+static void constrain_resources(struct device *dev, struct constraints* limits)
+{
+	struct device *child;
+	struct resource *res;
+	struct resource *lim;
+	int i;
+
+#ifdef CONFIG_PCI_64BIT_PREF_MEM
+	#define MEM_MASK (IORESOURCE_PREFETCH | IORESOURCE_MEM)
+#else
+	#define MEM_MASK (IORESOURCE_MEM)
+#endif
+#define IO_MASK (IORESOURCE_IO)
+#define PREF_TYPE (IORESOURCE_PREFETCH | IORESOURCE_MEM)
+#define MEM_TYPE (IORESOURCE_MEM)
+#define IO_TYPE (IORESOURCE_IO)
+
+	/* Descend into every child and look for fixed resources. */
+	for (child=dev->link[0].children; child; child = child->sibling) {
+		constrain_resources(child, limits);
+		for (i = 0; i<child->resources; i++) {
+			res = &child->resource[i];
+			if (!(res->flags & IORESOURCE_FIXED))
+				continue;
+
+			/* PREFETCH, MEM, or I/O - skip any others. */
+			if ((res->flags & MEM_MASK) == PREF_TYPE)
+				lim = &limits->pref;
+			else if ((res->flags & MEM_MASK) == MEM_TYPE)
+				lim = &limits->mem;
+			else if ((res->flags & IO_MASK) == IO_TYPE)
+				lim = &limits->io;
+			else
+				continue;
+
+			/* Is it already outside the limits? */
+			if (res->size &&
+			    (((res->base + res->size -1) < lim->base) ||
+			     (res->base > lim->limit)))
+				continue;
+
+			/* Choose to be above or below fixed resources.  This
+			 * check is signed so that "negative" amounts of space
+			 * are handled correctly.
+			 */
+			if ((s64)(lim->limit - (res->base + res->size -1)) >
+			    (s64)(res->base - lim->base))
+				lim->base = res->base + res->size;
+			else
+				lim->limit = res->base -1;
+		}
+	}
+}
+
+static void avoid_fixed_resources(struct device *dev)
+{
+	struct constraints limits;
+	struct resource *res;
+	int i;
+
+	/* Initialize constraints to maximum size. */
+
+	limits.pref.base = 0;
+	limits.pref.limit = 0xffffffffffffffffULL;
+	limits.io.base = 0;
+	limits.io.limit = 0xffffffffffffffffULL;
+	limits.mem.base = 0;
+	limits.mem.limit = 0xffffffffffffffffULL;
+
+	/* Constrain the limits to dev's initial resources. */
+	for (i = 0; i<dev->resources; i++) {
+		res = &dev->resource[i];
+		if ((res->flags & IORESOURCE_FIXED) ||
+		    !(res->flags & IORESOURCE_BRIDGE))
+			continue;
+		if ((res->flags & MEM_MASK) == PREF_TYPE &&
+		    (res->limit < limits.pref.limit))
+			limits.pref.limit = res->limit;
+		if ((res->flags & MEM_MASK) == MEM_TYPE &&
+		    (res->limit < limits.mem.limit))
+			limits.mem.limit = res->limit;
+		if ((res->flags & IO_MASK) == IO_TYPE &&
+		    (res->limit < limits.io.limit))
+			limits.io.limit = res->limit;
+	}
+
+	/* Look through the tree for fixed resources and update the limits. */
+	constrain_resources(dev, &limits);
+
+	/* Update dev's resources with new limits. */
+	for (i = 0; i<dev->resources; i++) {
+		struct resource *lim;
+		res = &dev->resource[i];
+
+		if ((res->flags & IORESOURCE_FIXED) ||
+		    !(res->flags & IORESOURCE_BRIDGE))
+			continue;
+
+		/* PREFETCH, MEM, or I/O - skip any others. */
+		if ((res->flags & MEM_MASK) == PREF_TYPE)
+			lim = &limits.pref;
+		else if ((res->flags & MEM_MASK) == MEM_TYPE)
+			lim = &limits.mem;
+		else if ((res->flags & IO_MASK) == IO_TYPE)
+			lim = &limits.io;
+		else
+			continue;
+
+		/* Is the resource outside the limits? */
+		if ( lim->base > res->base )
+			res->base = lim->base;
+		if ( res->limit > lim->limit )
+			res->limit = lim->limit;
+	}
+}
+
 #ifdef CONFIG_PCI_OPTION_ROM_RUN
 struct device *vga_pri = 0;
 int vga_inited = 0;
@@ -639,16 +887,16 @@
  * has to recurse into every down stream buses.
  *
  * Mutual recursion:
- *	assign_resources() -> device_operation::set_resources()
- *	device_operation::set_resources() -> assign_resources()
+ *	phase4_set_resources() -> device_operation::set_resources()
+ *	device_operation::set_resources() -> phase4_set_resources()
  *
  * @param bus Pointer to the structure for this bus.
  */
-void phase4_assign_resources(struct bus *bus)
+void phase4_set_resources(struct bus *bus)
 {
 	struct device *curdev;
 
-	printk(BIOS_SPEW, "%s(%s) assign_resources, bus %d link: %d\n",
+	printk(BIOS_SPEW, "%s(%s) %s, bus %d link: %d\n", __func__,
 	       bus->dev->dtsname, dev_path(bus->dev), bus->secondary,
 	       bus->link);
 
@@ -669,7 +917,7 @@
 		}
 		curdev->ops->phase4_set_resources(curdev);
 	}
-	printk(BIOS_SPEW, "%s(%s) assign_resources done, bus %d link: %d\n",
+	printk(BIOS_SPEW, "%s(%s) %s done, bus %d link: %d\n", __func__,
 	       bus->dev->dtsname, dev_path(bus->dev), bus->secondary,
 	       bus->link);
 }
@@ -895,7 +1143,7 @@
 	       dtsname : "NULL");
 	for (i = 0; i < root->resources; i++) {
 		printk(BIOS_DEBUG,
-		       "%s%s resource base %llx size %llx align %x gran %x limit %llx flags %lx index %lx\n",
+		       "%s%s resource base %llx size %llx align %d gran %d limit %llx flags %lx index %lx\n",
 		       indent, dev_path(root), root->resource[i].base,
 		       root->resource[i].size, root->resource[i].align,
 		       root->resource[i].gran, root->resource[i].limit,
@@ -919,129 +1167,140 @@
 	}
 
 	/* Bail if not printing to screen. */
-	if (!printk(debug_level, "Show all resources in tree form...%s\n", msg))
+	if (!printk(debug_level, "Show resources in subtree (%s)...%s\n",
+		    root->dtsname, msg))
 		return;
 	resource_tree(root, debug_level, 0);
 }
 
 /**
- * Configure devices on the device tree.
+ * Allocate resources.
  *
- * Starting at the root of the device tree, travel it recursively in two
- * passes. In the first pass, we compute and allocate resources (ranges)
- * required by each device. In the second pass, the resources ranges are
- * relocated to their final position and stored to the hardware.
+ * Starting at the root of the device tree, travel it recursively in four
+ * passes. In the first pass, we read all the resources.  In the second pass we
+ * compute the resource needs.  In the third pass we assign final values to the
+ * resources.  In the fourth pass we set them.
  *
- * I/O resources start at DEVICE_IO_START and grow upward. MEM resources start
- * at DEVICE_MEM_START and grow downward.
+ * I/O resources start at the bottom of the domain's resource and grow upward.
+ * MEM resources start at the top of the domain's resource and grow downward.
  *
- * Since the assignment is hierarchical we set the values into the dev_root
- * struct.
  */
 void dev_phase4(void)
 {
-	struct resource *io, *mem;
+	struct resource *res;
 	struct device *root;
+	struct device * child;
+	int i;
 
 	printk(BIOS_INFO, "Phase 4: Allocating resources...\n");
 
 	root = &dev_root;
-	if (!root->ops) {
-		printk(BIOS_ERR,
-		       "Phase 4: dev_root missing ops initialization\nPhase 4: Failed.\n");
-		return;
-	}
-	if (!root->ops->phase4_read_resources) {
-		printk(BIOS_ERR,
-		       "dev_root ops missing read_resources\nPhase 4: Failed.\n");
-		return;
-	}
 
-	if (!root->ops->phase4_set_resources) {
-		printk(BIOS_ERR,
-		       "dev_root ops missing set_resources\nPhase 4: Failed.\n");
-		return;
-	}
+	/* Each domain should create resources which contain the entire address
+	 * space for IO, MEM, and PREFMEM resources in the domain. The
+	 * allocation of device resources will be done from this address space.
+	 */
 
 	printk(BIOS_INFO, "Phase 4: Reading resources...\n");
-	root->ops->phase4_read_resources(root);
+
+	/* Read the resources for the entire tree. */
+	read_resources(&root->link[0]);
+
 	printk(BIOS_INFO, "Phase 4: Done reading resources.\n");
 
-	/* We have read the resources. We now compute the global allocation of
-	 * resources. We have to create a root resource for the base of the
-	 * tree. The root resource should contain the entire address space for
-	 * IO and MEM resources. The allocation of device resources will be done
-	 * from this resource address space.
-	 */
+	printk(BIOS_INFO, "Phase 4: Constrain resources.\n");
 
-	/* Allocate a resource from the root device resource pool and initialize
-	 * the system-wide I/O space constraints.
-	 */
-	io = new_resource(root, 0);
-	io->base = 0x400;
-	io->size = 0;
-	io->align = 0;
-	io->gran = 0;
-	io->limit = 0xffffUL;
-	io->flags = IORESOURCE_IO;
+	/* For all domains. */
+	for (child = root->link[0].children; child;
+	     child=child->sibling)
+		if (child->path.type == DEVICE_PATH_PCI_DOMAIN)
+			avoid_fixed_resources(child);
 
-	/* Allocate a resource from the root device resource pool and initialize
-	 * the system-wide memory resources constraints.
-	 */
-	mem = new_resource(root, 1);
-	mem->base = 0;
-	mem->size = 0;
-	mem->align = 0;
-	mem->gran = 0;
-	mem->limit = 0xffffffffUL;
-	mem->flags = IORESOURCE_MEM;
+	print_resource_tree(root, BIOS_DEBUG, "Original.");
 
-	compute_allocate_resource(&root->link[0], io,
-				  IORESOURCE_IO, IORESOURCE_IO);
+	/* Compute resources for all domains. */
+	for (child = root->link[0].children; child; child=child->sibling) {
+		if (!(child->path.type == DEVICE_PATH_PCI_DOMAIN))
+			continue;
+		for (i=0; i< child->resources; i++) {
+			res = &child->resource[i];
+			if ( res->flags & IORESOURCE_FIXED )
+				continue;
+			if ( res->flags & IORESOURCE_PREFETCH ) {
+				compute_resource_needs(&child->link[0],
+					       res, MEM_MASK, PREF_TYPE);
+				continue;
+			}
+			if ( res->flags & IORESOURCE_MEM ) {
+				compute_resource_needs(&child->link[0],
+					       res, MEM_MASK, MEM_TYPE);
+				continue;
+			}
+			if ( res->flags & IORESOURCE_IO ) {
+				compute_resource_needs(&child->link[0],
+					       res, IO_MASK, IO_TYPE);
+				continue;
+			}
+		}
+	}
 
-	compute_allocate_resource(&root->link[0], mem,
-				  IORESOURCE_MEM, IORESOURCE_MEM);
+	print_resource_tree(root, BIOS_DEBUG, "After summations.");
 
-	print_resource_tree(root, BIOS_DEBUG, "After first compute_allocate.");
-
 	/* Now we need to adjust the resources. The issue is that mem grows
-	 * downward.
+	 * downward. Reallocate the MEM resources with the highest addresses
+	 * I can manage.
 	 */
-	/* Make certain the I/O devices are allocated somewhere safe. */
-	io->base = DEVICE_IO_START;
-	io->flags |= IORESOURCE_ASSIGNED;
-	io->flags &= ~IORESOURCE_STORED;
+	for (child = root->link[0].children; child; child=child->sibling) {
+		if (child->path.type != DEVICE_PATH_PCI_DOMAIN)
+			continue;
+		for (i=0; i< child->resources; i++) {
+			res = &child->resource[i];
+			if (!(res->flags & IORESOURCE_MEM) ||
+			    res->flags & IORESOURCE_FIXED )
+				continue;
+			res->base = resource_max(res);
+		}
+	}
 
-	/* Now reallocate the PCI resources memory with the
-	 * highest addresses I can manage.
-	 */
-	mem->base = resource_max(&root->resource[1]);
-	mem->flags |= IORESOURCE_ASSIGNED;
-	mem->flags &= ~IORESOURCE_STORED;
-
 #ifdef CONFIG_PCI_OPTION_ROM_RUN
 	/* Allocate the VGA I/O resource. */
 	allocate_vga_resource();
+	print_resource_tree(root, BIOS_DEBUG, "After VGA.");
 #endif
 
-	/* now rerun the compute allocate with the adjusted resources */
-	compute_allocate_resource(&root->link[0], io,
-				  IORESOURCE_IO, IORESOURCE_IO);
+	/* Assign values to the resources for all domains. */
+	/* If the domain has a prefetchable memory resource, use it. */
+	for (child = root->link[0].children; child; child=child->sibling) {
+		if (!(child->path.type == DEVICE_PATH_PCI_DOMAIN))
+			continue;
+		for (i=0; i< child->resources; i++) {
+			res = &child->resource[i];
+			if ( res->flags & IORESOURCE_FIXED )
+				continue;
+			if ( res->flags & IORESOURCE_PREFETCH ) {
+				assign_resource_values(&child->link[0],
+					       res, MEM_MASK, PREF_TYPE);
+				continue;
+			}
+			if ( res->flags & IORESOURCE_MEM ) {
+				assign_resource_values(&child->link[0],
+					       res, MEM_MASK, MEM_TYPE);
+				continue;
+			}
+			if ( res->flags & IORESOURCE_IO ) {
+				assign_resource_values(&child->link[0],
+					       res, IO_MASK, IO_TYPE);
+				continue;
+			}
+		}
+	}
 
-	compute_allocate_resource(&root->link[0], mem,
-				  IORESOURCE_MEM, IORESOURCE_MEM);
+	print_resource_tree(root, BIOS_DEBUG, "After assigning values.");
 
-	print_resource_tree(root, BIOS_DEBUG, "After second compute_allocate.");
-
 	/* Store the computed resource allocations into device registers. */
 	printk(BIOS_INFO, "Phase 4: Setting resources...\n");
-	root->ops->phase4_set_resources(root);
+	phase4_set_resources(&root->link[0]);
 	print_resource_tree(root, BIOS_DEBUG, "After setting resources.");
-	printk(BIOS_INFO, "Phase 4: Done setting resources.\n");
-#if 0
-	mem->flags |= IORESOURCE_STORED;
-	report_resource_stored(root, mem, "");
-#endif
 
 	printk(BIOS_INFO, "Phase 4: Done allocating resources.\n");
 }
@@ -1132,21 +1391,21 @@
 		return;
 	for (dev = all_devices; dev; dev = dev->next) {
 		printk(debug_level,
-		       "%s(%s): enabled %d have_resources %d\n",
+		       "%s(%s): enabled %d, %d resources\n",
 		       dev->dtsname, dev_path(dev), dev->enabled,
-		       dev->have_resources);
+		       dev->resources);
 	}
 }
 
-void show_one_resource(struct device *dev, struct resource *resource,
-		       const char *comment)
+void show_one_resource(int debug_level, struct device *dev,
+		       struct resource *resource, const char *comment)
 {
 	char buf[10];
 	unsigned long long base, end;
 	base = resource->base;
 	end = resource_end(resource);
 	buf[0] = '\0';
-	if (resource->flags & IORESOURCE_PCI_BRIDGE) {
+	if (resource->flags & IORESOURCE_BRIDGE) {
 #if PCI_BUS_SEGN_BITS
 		sprintf(buf, "bus %04x:%02x ", dev->bus->secondary >> 8,
 			dev->link[0].secondary & 0xff);
@@ -1154,7 +1413,7 @@
 		sprintf(buf, "bus %02x ", dev->link[0].secondary);
 #endif
 	}
-	printk(BIOS_DEBUG, "%s %02lx <- [0x%010llx - 0x%010llx] "
+	printk(debug_level, "%s %02lx <- [0x%010llx - 0x%010llx] "
 	       "size 0x%08Lx gran 0x%02x %s%s%s\n",
 	       dev_path(dev), resource->index, base, end,
 	       resource->size, resource->gran, buf,
@@ -1162,18 +1421,20 @@
 
 }
 
-void show_all_devs_resources(void)
+void show_all_devs_resources(int debug_level, const char* msg)
 {
 	struct device *dev;
 
-	printk(BIOS_INFO, "Show all devs...\n");
+	if(!printk(debug_level, "Show all devs with resources...%s\n", msg))
+		return;
+
 	for (dev = all_devices; dev; dev = dev->next) {
 		int i;
-		printk(BIOS_SPEW,
-		       "%s(%s): enabled %d have_resources %d\n",
+		printk(debug_level,
+		       "%s(%s): enabled %d, %d resources\n",
 		       dev->dtsname, dev_path(dev), dev->enabled,
-		       dev->have_resources);
+		       dev->resources);
 		for (i = 0; i < dev->resources; i++)
-			show_one_resource(dev, &dev->resource[i], "");
+			show_one_resource(debug_level, dev, &dev->resource[i], "");
 	}
 }

Modified: coreboot-v3/device/device_util.c
===================================================================
--- coreboot-v3/device/device_util.c	2008-12-30 07:02:52 UTC (rev 1088)
+++ coreboot-v3/device/device_util.c	2008-12-31 19:43:34 UTC (rev 1089)
@@ -241,7 +241,7 @@
 				dev->path.ioport.iobase);
 			break;
 		default:
-			printk(BIOS_ERR, "%s: Unknown device path type: %d\n",
+			printk(BIOS_ERR, "%s: Unknown device path type: %x\n",
 			       dev->dtsname, dev->path.type);
 			break;
 		}
@@ -293,7 +293,7 @@
 				id->cpu_bus.vendor, id->cpu_bus.device);
 			break;
 		default:
-			printk(BIOS_ERR, "%s: Unknown device ID type: %d\n",
+			printk(BIOS_ERR, "%s: Unknown device ID type: %x\n",
 			       __func__, id->type);
 			memcpy(buffer, "Unknown", 8);
 			break;
@@ -349,8 +349,8 @@
 			equal = (path1->cpu_bus.id == path2->cpu_bus.id);
 			break;
 		default:
-			printk(BIOS_ERR, "Unknown device type: %d\n",
-			       path1->type);
+			printk(BIOS_ERR, "%s: Unknown device type: %x\n",
+			       __func__, path1->type);
 			break;
 		}
 	}
@@ -403,8 +403,8 @@
 			    && (path1->cpu_bus.device == path2->cpu_bus.device);
 			break;
 		default:
-			printk(BIOS_ERR, "Unknown device type: %d\n",
-			       path1->type);
+			printk(BIOS_ERR, "%s: Unknown device type: %x\n",
+			       __func__, path1->type);
 			break;
 		}
 	}
@@ -615,26 +615,29 @@
 void report_resource_stored(struct device *dev, struct resource *resource,
 			    const char *comment)
 {
-	if (resource->flags & IORESOURCE_STORED) {
-		char buf[10];
-		unsigned long long base, end;
-		base = resource->base;
-		end = resource_end(resource);
-		buf[0] = '\0';
-		if (resource->flags & IORESOURCE_PCI_BRIDGE) {
+	char buf[10];
+	unsigned long long base, end;
+	base = resource->base;
+	end = resource_end(resource);
+	buf[0] = '\0';
+
+	if (!(resource->flags & IORESOURCE_STORED))
+		printk(BIOS_DEBUG, "%s lying: %s(%s) %02lx\n",
+		       __func__, dev_path(dev), dev->dtsname, resource->index);
+
+	if (resource->flags & IORESOURCE_BRIDGE) {
 #if PCI_BUS_SEGN_BITS
-			sprintf(buf, "bus %04x:%02x ", dev->bus->secondary >> 8,
-				dev->link[0].secondary & 0xff);
+		sprintf(buf, "bus %04x:%02x ", dev->bus->secondary >> 8,
+			dev->link[0].secondary & 0xff);
 #else
-			sprintf(buf, "bus %02x ", dev->link[0].secondary);
+		sprintf(buf, "bus %02x ", dev->link[0].secondary);
 #endif
-		}
-		printk(BIOS_DEBUG, "%s %02lx <- [0x%010llx - 0x%010llx] "
-		       "size 0x%08Lx gran 0x%02x %s%s%s\n",
-		       dev_path(dev), resource->index, base, end,
-		       resource->size, resource->gran, buf,
-		       resource_type(resource), comment);
 	}
+	printk(BIOS_DEBUG, "%s %02lx <- [0x%010llx - 0x%010llx] "
+	       "size 0x%08Lx gran 0x%02x %s%s %s\n",
+	       dev_path(dev), resource->index, base, end,
+	       resource->size, resource->gran, buf,
+	       resource_type(resource), comment);
 }
 
 void search_bus_resources(struct bus *bus,
@@ -644,9 +647,6 @@
 	struct device *curdev;
 	for (curdev = bus->children; curdev; curdev = curdev->sibling) {
 		int i;
-		/* Ignore disabled devices. */
-		if (!curdev->have_resources)
-			continue;
 		for (i = 0; i < curdev->resources; i++) {
 			struct resource *resource = &curdev->resource[i];
 			/* If it isn't the right kind of resource ignore it. */
@@ -676,12 +676,8 @@
 	for (curdev = all_devices; curdev; curdev = curdev->next) {
 		int i;
 		printk(BIOS_SPEW,
-		       "%s: dev %s, have_resources %d #resources %d\n",
-		       __func__, curdev->dtsname, curdev->have_resources,
-		       curdev->resources);
-		/* Ignore disabled devices. */
-		if (!curdev->have_resources)
-			continue;
+		       "%s: dev %s, #resources %d\n",
+		       __func__, curdev->dtsname, curdev->resources);
 		for (i = 0; i < curdev->resources; i++) {
 			struct resource *resource = &curdev->resource[i];
 			printk(BIOS_SPEW,

Modified: coreboot-v3/device/pci_device.c
===================================================================
--- coreboot-v3/device/pci_device.c	2008-12-30 07:02:52 UTC (rev 1088)
+++ coreboot-v3/device/pci_device.c	2008-12-31 19:43:34 UTC (rev 1089)
@@ -11,6 +11,7 @@
  * Copyright (C) 2005-2006 Tyan
  * (Written by Yinghai Lu <yhlu at tyan.com> for Tyan)
  * Copyright (C) 2005-2007 Stefan Reinauer <stepan at openbios.org>
+ * Copyright (C) 2008 Myles Watson <mylesgw at gmail.com>
  */
 
 /*
@@ -153,7 +154,7 @@
 struct resource *pci_get_resource(struct device *dev, unsigned long index)
 {
 	struct resource *resource;
-	unsigned long value, attr, base;
+	unsigned long value, attr;
 	resource_t moving, limit;
 
 	/* Initialize the resources to nothing. */
@@ -162,15 +163,9 @@
 	/* Get the initial value. */
 	value = pci_read_config32(dev, index);
 
-	/* save the base address */
-	if (value & PCI_BASE_ADDRESS_SPACE_IO)
-		base = value & ~PCI_BASE_ADDRESS_IO_ATTR_MASK;
-	else
-		base = value & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
-
 	/* See which bits move. */
 	moving = pci_moving_config32(dev, index);
-	/* Next step: save the base in the dev struct. For later next week */
+
 	/* Initialize attr to the bits that do not move. */
 	attr = value & ~moving;
 
@@ -222,7 +217,7 @@
 		 * Shouldn't zero because we'll get off with 64-bit BARs.
 		 * Are there any others to save?
 		 */
-		resource->flags &= ~IORESOURCE_PCI64;
+		resource->flags &= IORESOURCE_PCI64;
 	} else if (attr & PCI_BASE_ADDRESS_SPACE_IO) {
 		/* An I/O mapped base address. */
 		attr &= PCI_BASE_ADDRESS_IO_ATTR_MASK;
@@ -248,6 +243,8 @@
 			resource->limit = 0xffffffffffffffffULL;
 		} else {
 			/* Invalid value. */
+			printk(BIOS_ERR,"Broken BAR with value %lx\n",attr);
+			printk(BIOS_ERR," on dev %s at index %02lx\n",dev->dtsname,index);
 			resource->flags = 0;
 		}
 	}
@@ -347,15 +344,12 @@
 	compact_resources(dev);
 }
 
-static void pci_set_resource(struct device *dev, struct resource *resource);
-
 static void pci_record_bridge_resource(struct device *dev, resource_t moving,
-				       unsigned int index, unsigned long mask,
-				       unsigned long type)
+				       unsigned int index, unsigned long type)
 {
 	/* Initialize the constraints on the current bus. */
 	struct resource *resource;
-	resource = 0;
+	resource = NULL;
 	if (moving) {
 		unsigned long gran;
 		resource_t step;
@@ -370,18 +364,7 @@
 		resource->gran = gran;
 		resource->align = gran;
 		resource->limit = moving | (step - 1);
-		resource->flags = type | IORESOURCE_PCI_BRIDGE;
-		compute_allocate_resource(&dev->link[0], resource, mask, type);
-		/* If there is nothing behind the resource,
-		 * clear it and forget it.
-		 */
-		if (resource->size == 0) {
-			resource->base = moving;
-			resource->flags |= IORESOURCE_ASSIGNED;
-			resource->flags &= ~IORESOURCE_STORED;
-			pci_set_resource(dev, resource);
-			resource->flags = 0;
-		}
+		resource->flags = type | IORESOURCE_PCI_BRIDGE | IORESOURCE_BRIDGE;
 	}
 	return;
 }
@@ -402,8 +385,7 @@
 	moving = moving_base & moving_limit;
 
 	/* Initialize the I/O space constraints on the current bus. */
-	pci_record_bridge_resource(dev, moving, PCI_IO_BASE,
-				   IORESOURCE_IO, IORESOURCE_IO);
+	pci_record_bridge_resource(dev, moving, PCI_IO_BASE, IORESOURCE_IO);
 
 	/* See if the bridge prefmem resources are implemented. */
 	moving_base =
@@ -416,7 +398,6 @@
 	moving = moving_base & moving_limit;
 	/* Initialize the prefetchable memory constraints on the current bus. */
 	pci_record_bridge_resource(dev, moving, PCI_PREF_MEMORY_BASE,
-				   IORESOURCE_MEM | IORESOURCE_PREFETCH,
 				   IORESOURCE_MEM | IORESOURCE_PREFETCH);
 
 	/* See if the bridge mem resources are implemented. */
@@ -427,7 +408,6 @@
 
 	/* Initialize the memory resources on the current bus. */
 	pci_record_bridge_resource(dev, moving, PCI_MEMORY_BASE,
-				   IORESOURCE_MEM | IORESOURCE_PREFETCH,
 				   IORESOURCE_MEM);
 
 	compact_resources(dev);
@@ -441,9 +421,24 @@
 
 void pci_bus_read_resources(struct device *dev)
 {
+	struct device *child;
+
+	printk(BIOS_DEBUG, "%s: %s bus %s\n",
+	       __func__, dev_path(dev), dev->bus? dev_path(dev->bus->dev):"NULL");
 	pci_bridge_read_bases(dev);
 	pci_read_bases(dev, 2);
 	pci_get_rom_resource(dev, PCI_ROM_ADDRESS1);
+	if (!dev->bus){
+		printk(BIOS_ERR, "%s: %s bus %s\n",
+		       __func__, dev_path(dev), dev->bus? dev_path(dev->bus->dev):"NULL");
+	}
+
+	for (child = dev->link[0].children; child; child = child->sibling)
+		if (child->ops && child->ops->phase4_read_resources)
+			child->ops->phase4_read_resources(child);
+		else
+			printk(BIOS_ERR, "%s: %s missing Phase4\n",
+			       __func__, dev_path(child));
 }
 
 /**
@@ -462,22 +457,22 @@
 	/* Initialize the system-wide I/O space constraints. */
 	res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
 	res->limit = 0xffffUL;
-	res->flags =
-	    IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+	res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
+		     IORESOURCE_ASSIGNED | IORESOURCE_BRIDGE;
 
 	/* Initialize the system-wide memory resources constraints. */
 	res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
 	res->limit = 0xffffffffULL;
-	res->flags =
-	    IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+	res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
+		     IORESOURCE_ASSIGNED | IORESOURCE_BRIDGE;
 }
 
 static void pci_set_resource(struct device *dev, struct resource *resource)
 {
 	resource_t base, end;
 
-	/* Make certain the resource has actually been set. */
-	if (!(resource->flags & IORESOURCE_ASSIGNED)) {
+	/* Make certain the resource has actually been assigned a value. */
+	if (!(resource->flags & IORESOURCE_ASSIGNED) && resource->size!=0) {
 		printk(BIOS_ERR,
 		       "ERROR: %s %02lx %s size: 0x%010llx not assigned\n",
 		       dev_path(dev), resource->index, resource_type(resource),
@@ -519,6 +514,16 @@
 
 	/* Now store the resource. */
 	resource->flags |= IORESOURCE_STORED;
+	/* PCI Bridges have no enable bit.  They are disabled if the base of
+	 * the range is greater than the limit.  If the size is zero, disable
+	 * by setting the base = limit and end = limit - 2^gran.
+	 */
+	if (resource->size == 0 && (resource->flags & IORESOURCE_PCI_BRIDGE)) {
+		base = resource->limit;
+		end = resource->limit - (1<<resource->gran);
+		resource->base = base;
+	}
+
 	if (!(resource->flags & IORESOURCE_PCI_BRIDGE)) {
 		unsigned long base_lo, base_hi;
 		/* Some chipsets allow us to set/clear the I/O bit
@@ -535,24 +540,16 @@
 		}
 	} else if (resource->index == PCI_IO_BASE) {
 		/* Set the I/O ranges. */
-		compute_allocate_resource(&dev->link[0], resource,
-					  IORESOURCE_IO, IORESOURCE_IO);
 		pci_write_config8(dev, PCI_IO_BASE, base >> 8);
 		pci_write_config16(dev, PCI_IO_BASE_UPPER16, base >> 16);
 		pci_write_config8(dev, PCI_IO_LIMIT, end >> 8);
 		pci_write_config16(dev, PCI_IO_LIMIT_UPPER16, end >> 16);
 	} else if (resource->index == PCI_MEMORY_BASE) {
 		/* Set the memory range. */
-		compute_allocate_resource(&dev->link[0], resource,
-					  IORESOURCE_MEM | IORESOURCE_PREFETCH,
-					  IORESOURCE_MEM);
 		pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16);
 		pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16);
 	} else if (resource->index == PCI_PREF_MEMORY_BASE) {
 		/* Set the prefetchable memory range. */
-		compute_allocate_resource(&dev->link[0], resource,
-					  IORESOURCE_MEM | IORESOURCE_PREFETCH,
-					  IORESOURCE_MEM | IORESOURCE_PREFETCH);
 		pci_write_config16(dev, PCI_PREF_MEMORY_BASE, base >> 16);
 		pci_write_config32(dev, PCI_PREF_BASE_UPPER32, base >> 32);
 		pci_write_config16(dev, PCI_PREF_MEMORY_LIMIT, end >> 16);
@@ -563,7 +560,7 @@
 		printk(BIOS_ERR, "ERROR: invalid resource->index %lx\n",
 		       resource->index);
 	}
-	report_resource_stored(dev, resource, "");
+	report_resource_stored(dev, resource, __func__);
 	return;
 }
 
@@ -582,7 +579,7 @@
 		struct bus *bus;
 		bus = &dev->link[link];
 		if (bus->children) {
-			phase4_assign_resources(bus);
+			phase4_set_resources(bus);
 		}
 	}
 

Modified: coreboot-v3/device/pci_ops.c
===================================================================
--- coreboot-v3/device/pci_ops.c	2008-12-30 07:02:52 UTC (rev 1088)
+++ coreboot-v3/device/pci_ops.c	2008-12-31 19:43:34 UTC (rev 1089)
@@ -36,7 +36,7 @@
 	struct bus *pbus = dev->bus;
 	while (pbus && pbus->dev && !ops_pci_bus(pbus)) {
 		if (pbus->dev == dev) {
-			printk(BIOS_EMERG, "Loop: dev->dtsname dev->bus->dev\n");
+			printk(BIOS_EMERG, "Loop: %s->bus->dev\n", dev->dtsname);
 			printk(BIOS_EMERG, "To fix this, set ops_pci_bus in dts\n");
 			die("loop due to insufficient dts");
 		}

Modified: coreboot-v3/device/root_device.c
===================================================================
--- coreboot-v3/device/root_device.c	2008-12-30 07:02:52 UTC (rev 1088)
+++ coreboot-v3/device/root_device.c	2008-12-31 19:43:34 UTC (rev 1089)
@@ -35,13 +35,7 @@
  */
 void root_dev_read_resources(struct device *root)
 {
-	void read_resources(struct bus *bus);
-	void show_all_devs_resources(void);
-
-	read_resources(&root->link[0]);
-
-	printk(BIOS_DEBUG, "%s: Done allocating\n", __FUNCTION__);
-	show_all_devs_resources();
+	printk(BIOS_DEBUG, "This shouldn't be called!\n");
 }
 
 /**
@@ -52,7 +46,7 @@
  */
 void root_dev_set_resources(struct device *root)
 {
-	phase4_assign_resources(&root->link[0]);
+	printk(BIOS_DEBUG, "This shouldn't be called!\n");
 }
 
 /**
@@ -193,6 +187,7 @@
  * mainboard directory. 
  */
 struct device_operations default_dev_ops_root = {
+	.id = {.type = DEVICE_ID_ROOT},
 	.phase3_scan             = root_dev_scan_bus,
 	.phase4_read_resources   = root_dev_read_resources,
 	.phase4_set_resources    = root_dev_set_resources,

Modified: coreboot-v3/include/device/device.h
===================================================================
--- coreboot-v3/include/device/device.h	2008-12-30 07:02:52 UTC (rev 1088)
+++ coreboot-v3/include/device/device.h	2008-12-31 19:43:34 UTC (rev 1089)
@@ -199,12 +199,11 @@
 	u16 subsystem_vendor;
 	u16 subsystem_device;
 
-	unsigned int	class;			/* 3 bytes: (base,sub,prog-if) */
-	unsigned int	hdr_type;		/* PCI header type */
-	unsigned int	enabled:1;		/* set if we should enable the device */
-	unsigned int	have_resources:1;	/* Set if we have read the devices resources */
-	unsigned int	on_mainboard:1;
-	unsigned long	rom_address;
+	unsigned int	class;		/* 3 bytes: (base,sub,prog-if) */
+	unsigned int	hdr_type;	/* PCI header type */
+	unsigned int    enabled : 1;	/* set if we should enable the device */
+	unsigned int    on_mainboard : 1;
+	unsigned long   rom_address;
 
 	u8 command;
 
@@ -239,9 +238,7 @@
 /* Generic device helper functions */
 int reset_bus(struct bus *bus);
 unsigned int scan_bus(struct device *bus, unsigned int max);
-void compute_allocate_resource(struct bus *bus, struct resource *bridge,
-			       unsigned long type_mask, unsigned long type);
-void assign_resources(struct bus *bus);
+//void assign_resources(struct bus *bus);
 void enable_resources(struct device *dev);
 void enumerate_static_device(void);
 void enumerate_static_devices(void);
@@ -267,13 +264,10 @@
 				const struct device_operations *constructor);
 void show_all_devs(int debug_level, const char *msg);
 void show_all_devs_tree(int debug_level, const char *msg);
+void show_all_devs(int debug_level, const char *msg);
+void show_all_devs_tree(int debug_level, const char *msg);
+void print_resource_tree(const struct device * const dev, int debug_level, const char* msg);
 
-/* Rounding for boundaries. 
- * Due to some chip bugs, go ahead and round IO to 16
- */
-#define DEVICE_IO_ALIGN 16
-#define DEVICE_MEM_ALIGN 4096
-
 resource_t align_up(resource_t val, unsigned long gran);
 resource_t align_down(resource_t val, unsigned long gran);
 
@@ -296,7 +290,7 @@
 void dev_root_phase5(void);
 void dev_phase6(void);
 
-void phase4_assign_resources(struct bus *bus);
+void phase4_set_resources(struct bus *bus);
 unsigned int dev_phase3(struct device *bus, unsigned int max);
 void dev_phase5(struct device *dev);
 

Modified: coreboot-v3/include/device/resource.h
===================================================================
--- coreboot-v3/include/device/resource.h	2008-12-30 07:02:52 UTC (rev 1088)
+++ coreboot-v3/include/device/resource.h	2008-12-31 19:43:34 UTC (rev 1089)
@@ -36,6 +36,7 @@
 #define IORESOURCE_SUBTRACTIVE  0x00040000	/* This resource filters all of the unclaimed transactions
 						 * to the bus below.
 						 */
+#define IORESOURCE_BRIDGE	0x00080000	/* The IO resource has a bus below it. */
 #define IORESOURCE_STORED	0x20000000	/* The IO resource assignment has been stored in the device */
 #define IORESOURCE_ASSIGNED	0x40000000	/* An IO resource that has been assigned a value */
 #define IORESOURCE_FIXED	0x80000000	/* An IO resource the allocator must not change */





More information about the coreboot mailing list