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 <[email protected]>
Acked-by: Ronald G. Minnich <[email protected]>



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 <[email protected]>
  * Copyright (C) 2007 coresystems GmbH
+ * Copyright (C) 2008 Myles Watson <[email protected]>
  */
 
 /*
@@ -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 <[email protected]> for Tyan)
  * Copyright (C) 2005-2007 Stefan Reinauer <[email protected]>
+ * Copyright (C) 2008 Myles Watson <[email protected]>
  */
 
 /*
@@ -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 */


--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to