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(a)gmail.com>
Acked-by: Ronald G. Minnich <rminnich(a)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(a)openbios.org>
* Copyright (C) 2007 coresystems GmbH
+ * Copyright (C) 2008 Myles Watson <mylesgw(a)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(a)tyan.com> for Tyan)
* Copyright (C) 2005-2007 Stefan Reinauer <stepan(a)openbios.org>
+ * Copyright (C) 2008 Myles Watson <mylesgw(a)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 */