Various Doxygen comment fixes, typo fixes, etc.
[coreboot.git] / src / devices / device.c
index 64b3c106a07166ee87691d1594c7c32053e50a39..d7335c95a15899d7107ea96385f8e927ebe8217e 100644 (file)
 /** Linked list of ALL devices */
 struct device *all_devices = &dev_root;
 /** Pointer to the last device */
-extern struct device **last_dev_p;
+extern struct device *last_dev;
+/** Linked list of free resources */
+struct resource *free_resources = NULL;
 
+DECLARE_SPIN_LOCK(dev_lock)
 
 /**
- * @brief Allocate a new device structure.
+ * Allocate a new device structure.
  *
- * Allocte a new device structure and attached it to the device tree as a
+ * Allocte a new device structure and attach it to the device tree as a
  * child of the parent bus.
  *
- * @param parent parent bus the newly created device attached to.
- * @param path path to the device to be created.
- *
- * @return pointer to the newly created device structure.
+ * @param parent Parent bus the newly created device should be attached to.
+ * @param path Path to the device to be created.
+ * @return Pointer to the newly created device structure.
  *
  * @see device_path
  */
-static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;
 device_t alloc_dev(struct bus *parent, struct device_path *path)
 {
        device_t dev, child;
-       int link;
 
        spin_lock(&dev_lock);
 
@@ -78,12 +78,6 @@ device_t alloc_dev(struct bus *parent, struct device_path *path)
        memset(dev, 0, sizeof(*dev));
        memcpy(&dev->path, path, sizeof(*path));
 
-       /* Initialize the back pointers in the link fields. */
-       for (link = 0; link < MAX_LINKS; link++) {
-               dev->link[link].dev = dev;
-               dev->link[link].link = link;
-       }
-
        /* By default devices are enabled. */
        dev->enabled = 1;
 
@@ -98,18 +92,19 @@ device_t alloc_dev(struct bus *parent, struct device_path *path)
        /* Append a new device to the global device list.
         * The list is used to find devices once everything is set up.
         */
-       *last_dev_p = dev;
-       last_dev_p = &dev->next;
+       last_dev->next = dev;
+       last_dev = dev;
 
        spin_unlock(&dev_lock);
        return dev;
 }
 
 /**
- * @brief round a number up to an alignment.
- * @param val the starting value
- * @param roundup Alignment as a power of two
- * @returns rounded up number
+ * Round a number up to an alignment.
+ *
+ * @param val The starting value.
+ * @param roundup Alignment as a power of two.
+ * @return Rounded up number.
  */
 static resource_t round(resource_t val, unsigned long pow)
 {
@@ -120,35 +115,37 @@ static resource_t round(resource_t val, unsigned long pow)
        return val;
 }
 
-/** Read the resources on all devices of a given bus.
- * @param bus bus to read the resources on.
+/**
+ * Read the resources on all devices of a given bus.
+ *
+ * @param bus Bus to read the resources on.
  */
 static void read_resources(struct bus *bus)
 {
        struct device *curdev;
 
-       printk_spew("%s %s bus %x link: %d\n", dev_path(bus->dev), __func__,
-                   bus->secondary, bus->link);
+       printk(BIOS_SPEW, "%s %s bus %x link: %d\n", dev_path(bus->dev),
+              __func__, bus->secondary, bus->link_num);
 
        /* Walk through all devices and find which resources they need. */
        for (curdev = bus->children; curdev; curdev = curdev->sibling) {
-               int i;
+               struct bus *link;
                if (!curdev->enabled) {
                        continue;
                }
                if (!curdev->ops || !curdev->ops->read_resources) {
-                       printk_err("%s missing read_resources\n",
+                       printk(BIOS_ERR, "%s missing read_resources\n",
                                   dev_path(curdev));
                        continue;
                }
                curdev->ops->read_resources(curdev);
 
                /* Read in the resources behind the current device's links. */
-               for (i = 0; i < curdev->links; i++)
-                       read_resources(&curdev->link[i]);
+               for (link = curdev->link_list; link; link = link->next)
+                       read_resources(link);
        }
-       printk_spew("%s read_resources bus %d link: %d done\n",
-                   dev_path(bus->dev), bus->secondary, bus->link);
+       printk(BIOS_SPEW, "%s read_resources bus %d link: %d done\n",
+                   dev_path(bus->dev), bus->secondary, bus->link_num);
 }
 
 struct pick_largest_state {
@@ -208,7 +205,8 @@ static struct device *largest_resource(struct bus *bus,
        return state.result_dev;
 }
 
-/* Compute allocate resources is the guts of the resource allocator.
+/**
+ * Compute allocate resources is the guts of the resource allocator.
  *
  * The problem.
  *  - Allocate resource locations for every device.
@@ -234,8 +232,13 @@ static struct device *largest_resource(struct bus *bus,
  *   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 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.
+ * @return TODO
  */
-void compute_resources(struct bus *bus, struct resource *bridge,
+static void compute_resources(struct bus *bus, struct resource *bridge,
                       unsigned long type_mask, unsigned long type)
 {
        struct device *dev;
@@ -243,7 +246,7 @@ void compute_resources(struct bus *bus, struct resource *bridge,
        resource_t base;
        base = round(bridge->base, bridge->align);
 
-       printk_spew( "%s %s_%s: base: %llx size: %llx align: %d gran: %d limit: %llx\n",
+       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",
@@ -251,16 +254,15 @@ void compute_resources(struct bus *bus, struct resource *bridge,
 
        /* 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)
+               if (!dev->link_list)
                        continue;
 
                /* Find the resources with matching type flags. */
-               for (i = 0; i < dev->resources; i++) {
-                       unsigned link;
-                       child_bridge = &dev->resource[i];
+               for (child_bridge = dev->resource_list; child_bridge;
+                    child_bridge = child_bridge->next) {
+                       struct bus* link;
 
                        if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
                            (child_bridge->flags & type_mask) != type)
@@ -272,8 +274,15 @@ void compute_resources(struct bus *bus, struct resource *bridge,
                         * need it separated.  Add the PREFETCH flag to the
                         * type_mask and type.
                         */
-                       link = IOINDEX_LINK(child_bridge->index);
-                       compute_resources(&dev->link[link], child_bridge,
+                       link = dev->link_list;
+                       while (link && link->link_num !=
+                                       IOINDEX_LINK(child_bridge->index))
+                               link = link->next;
+                       if (link == NULL)
+                               printk(BIOS_ERR, "link %ld not found on %s\n",
+                                      IOINDEX_LINK(child_bridge->index),
+                                      dev_path(dev));
+                       compute_resources(link, child_bridge,
                                          type_mask | IORESOURCE_PREFETCH,
                                          type | (child_bridge->flags &
                                                  IORESOURCE_PREFETCH));
@@ -307,8 +316,8 @@ void compute_resources(struct bus *bus, struct resource *bridge,
                /* Warn if it looks like APICs aren't declared. */
                if ((resource->limit == 0xffffffff) &&
                    (resource->flags & IORESOURCE_ASSIGNED)) {
-                       printk_err("Resource limit looks wrong! (no APIC?)\n");
-                       printk_err("%s %02lx limit %08Lx\n", dev_path(dev),
+                       printk(BIOS_ERR, "Resource limit looks wrong! (no APIC?)\n");
+                       printk(BIOS_ERR, "%s %02lx limit %08Lx\n", dev_path(dev),
                                   resource->index, resource->limit);
                }
 
@@ -334,7 +343,7 @@ void compute_resources(struct bus *bus, struct resource *bridge,
                resource->base = base;
                base += resource->size;
 
-               printk_spew("%s %02lx *  [0x%llx - 0x%llx] %s\n",
+               printk(BIOS_SPEW, "%s %02lx *  [0x%llx - 0x%llx] %s\n",
                            dev_path(dev), resource->index,
                            resource->base,
                            resource->base + resource->size - 1,
@@ -351,7 +360,7 @@ void compute_resources(struct bus *bus, struct resource *bridge,
        bridge->size = round(base, bridge->gran) -
                       round(bridge->base, bridge->align);
 
-       printk_spew("%s %s_%s: base: %llx size: %llx align: %d gran: %d limit: %llx done\n",
+       printk(BIOS_SPEW, "%s %s_%s: base: %llx size: %llx align: %d gran: %d limit: %llx done\n",
                    dev_path(bus->dev), __func__,
                    (bridge->flags & IORESOURCE_IO) ? "io" :
                     (bridge->flags & IORESOURCE_PREFETCH) ?  "prefmem" : "mem",
@@ -389,10 +398,10 @@ void compute_resources(struct bus *bus, struct resource *bridge,
  *
  * @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.
+ * @param type_mask This value gets ANDed with the resource type.
+ * @param type This value must match the result of the AND.
  */
-void allocate_resources(struct bus *bus, struct resource *bridge,
+static void allocate_resources(struct bus *bus, struct resource *bridge,
                        unsigned long type_mask, unsigned long type)
 {
        struct device *dev;
@@ -400,7 +409,7 @@ void allocate_resources(struct bus *bus, struct resource *bridge,
        resource_t base;
        base = bridge->base;
 
-       printk_spew("%s %s_%s: base:%llx size:%llx align:%d gran:%d limit:%llx\n",
+       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",
@@ -454,14 +463,14 @@ void allocate_resources(struct bus *bus, struct resource *bridge,
                        resource->flags &= ~IORESOURCE_STORED;
                        base += resource->size;
                } else {
-                       printk_err("!! Resource didn't fit !!\n");
-                       printk_err("   aligned base %llx size %llx limit %llx\n",
+                       printk(BIOS_ERR, "!! Resource didn't fit !!\n");
+                       printk(BIOS_ERR, "   aligned base %llx size %llx limit %llx\n",
                               round(base, resource->align), resource->size,
                               resource->limit);
-                       printk_err("   %llx needs to be <= %llx (limit)\n",
+                       printk(BIOS_ERR, "   %llx needs to be <= %llx (limit)\n",
                               (round(base, resource->align) +
                                resource->size) - 1, resource->limit);
-                       printk_err("   %s%s %02lx *  [0x%llx - 0x%llx] %s\n",
+                       printk(BIOS_ERR, "   %s%s %02lx *  [0x%llx - 0x%llx] %s\n",
                               (resource->
                                flags & IORESOURCE_ASSIGNED) ? "Assigned: " :
                               "", dev_path(dev), resource->index,
@@ -474,7 +483,7 @@ void allocate_resources(struct bus *bus, struct resource *bridge,
                               ? "prefmem" : "mem");
                }
 
-               printk_spew("%s%s %02lx *  [0x%llx - 0x%llx] %s\n",
+               printk(BIOS_SPEW, "%s%s %02lx *  [0x%llx - 0x%llx] %s\n",
                       (resource->flags & IORESOURCE_ASSIGNED) ? "Assigned: "
                       : "",
                       dev_path(dev), resource->index, resource->base,
@@ -492,7 +501,7 @@ void allocate_resources(struct bus *bus, struct resource *bridge,
 
        bridge->flags |= IORESOURCE_ASSIGNED;
 
-       printk_spew("%s %s_%s: next_base: %llx size: %llx align: %d gran: %d done\n",
+       printk(BIOS_SPEW, "%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",
@@ -500,16 +509,15 @@ void allocate_resources(struct bus *bus, struct resource *bridge,
 
        /* For each child which is a bridge, allocate_resources. */
        for (dev = bus->children; dev; dev = dev->sibling) {
-               unsigned i;
                struct resource *child_bridge;
 
-               if (!dev->links)
+               if (!dev->link_list)
                        continue;
 
                /* Find the resources with matching type flags. */
-               for (i = 0; i < dev->resources; i++) {
-                       unsigned link;
-                       child_bridge = &dev->resource[i];
+               for (child_bridge = dev->resource_list; child_bridge;
+                    child_bridge = child_bridge->next) {
+                       struct bus* link;
 
                        if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
                            (child_bridge->flags & type_mask) != type)
@@ -521,8 +529,15 @@ void allocate_resources(struct bus *bus, struct resource *bridge,
                         * need it separated.  Add the PREFETCH flag to the
                         * type_mask and type.
                         */
-                       link = IOINDEX_LINK(child_bridge->index);
-                       allocate_resources(&dev->link[link], child_bridge,
+                       link = dev->link_list;
+                       while (link && link->link_num !=
+                                      IOINDEX_LINK(child_bridge->index))
+                               link = link->next;
+                       if (link == NULL)
+                               printk(BIOS_ERR, "link %ld not found on %s\n",
+                                      IOINDEX_LINK(child_bridge->index),
+                                      dev_path(dev));
+                       allocate_resources(link, child_bridge,
                                           type_mask | IORESOURCE_PREFETCH,
                                           type | (child_bridge->flags &
                                                   IORESOURCE_PREFETCH));
@@ -531,10 +546,11 @@ void allocate_resources(struct bus *bus, struct resource *bridge,
 }
 
 #if CONFIG_PCI_64BIT_PREF_MEM == 1
-       #define MEM_MASK (IORESOURCE_PREFETCH | IORESOURCE_MEM)
+#define MEM_MASK (IORESOURCE_PREFETCH | IORESOURCE_MEM)
 #else
-       #define MEM_MASK (IORESOURCE_MEM)
+#define MEM_MASK (IORESOURCE_MEM)
 #endif
+
 #define IO_MASK (IORESOURCE_IO)
 #define PREF_TYPE (IORESOURCE_PREFETCH | IORESOURCE_MEM)
 #define MEM_TYPE (IORESOURCE_MEM)
@@ -549,15 +565,20 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
        struct device *child;
        struct resource *res;
        struct resource *lim;
-       int i;
+       struct bus *link;
 
-       printk_spew("%s: %s\n", __func__, dev_path(dev));
+       printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
 
        /* Constrain limits based on the fixed resources of this device. */
-       for (i = 0; i < dev->resources; i++) {
-               res = &dev->resource[i];
+       for (res = dev->resource_list; res; res = res->next) {
                if (!(res->flags & IORESOURCE_FIXED))
                        continue;
+               if (!res->size) {
+                       /* It makes no sense to have 0-sized, fixed resources.*/
+                       printk(BIOS_ERR, "skipping %s@%lx fixed resource, size=0!\n",
+                                  dev_path(dev), res->index);
+                       continue;
+               }
 
                /* PREFETCH, MEM, or I/O - skip any others. */
                if ((res->flags & MEM_MASK) == PREF_TYPE)
@@ -569,9 +590,10 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
                else
                        continue;
 
-               /* Is it already outside the limits? */
-               if (res->size && (((res->base + res->size -1) < lim->base) ||
-                                 (res->base > lim->limit)))
+               /* Is it a fixed resource outside the current known region?
+                  If so, we don't have to consider it - it will be handled
+                  correctly and doesn't affect current region's limits */
+               if (((res->base + res->size -1) < lim->base) || (res->base > lim->limit))
                        continue;
 
                /* Choose to be above or below fixed resources.  This
@@ -586,8 +608,8 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
        }
 
        /* Descend into every enabled child and look for fixed resources. */
-       for (i = 0; i < dev->links; i++)
-               for (child = dev->link[i].children; child;
+       for (link = dev->link_list; link; link = link->next)
+               for (child = link->children; child;
                     child = child->sibling)
                        if (child->enabled)
                                constrain_resources(child, limits);
@@ -597,9 +619,8 @@ static void avoid_fixed_resources(struct device *dev)
 {
        struct constraints limits;
        struct resource *res;
-       int i;
 
-       printk_spew("%s: %s\n", __func__, dev_path(dev));
+       printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
        /* Initialize constraints to maximum size. */
 
        limits.pref.base = 0;
@@ -610,11 +631,10 @@ static void avoid_fixed_resources(struct device *dev)
        limits.mem.limit = 0xffffffffffffffffULL;
 
        /* Constrain the limits to dev's initial resources. */
-       for (i = 0; i < dev->resources; i++) {
-               res = &dev->resource[i];
+       for (res = dev->resource_list; res; res = res->next) {
                if ((res->flags & IORESOURCE_FIXED))
                        continue;
-               printk_spew("%s:@%s %02lx limit %08Lx\n", __func__,
+               printk(BIOS_SPEW, "%s:@%s %02lx limit %08Lx\n", __func__,
                             dev_path(dev), res->index, res->limit);
                if ((res->flags & MEM_MASK) == PREF_TYPE &&
                    (res->limit < limits.pref.limit))
@@ -631,9 +651,8 @@ static void avoid_fixed_resources(struct device *dev)
        constrain_resources(dev, &limits);
 
        /* Update dev's resources with new limits. */
-       for (i = 0; i < dev->resources; i++) {
+       for (res = dev->resource_list; res; res = res->next) {
                struct resource *lim;
-               res = &dev->resource[i];
 
                if ((res->flags & IORESOURCE_FIXED))
                        continue;
@@ -648,9 +667,9 @@ static void avoid_fixed_resources(struct device *dev)
                else
                        continue;
 
-               printk_spew("%s2: %s@%02lx limit %08Lx\n", __func__,
+               printk(BIOS_SPEW, "%s2: %s@%02lx limit %08Lx\n", __func__,
                             dev_path(dev), res->index, res->limit);
-               printk_spew("\tlim->base %08Lx lim->limit %08Lx\n",
+               printk(BIOS_SPEW, "\tlim->base %08Lx lim->limit %08Lx\n",
                             lim->base, lim->limit);
 
                /* Is the resource outside the limits? */
@@ -661,12 +680,15 @@ static void avoid_fixed_resources(struct device *dev)
        }
 }
 
-#if CONFIG_CONSOLE_VGA == 1
+#if CONFIG_VGA_BRIDGE_SETUP == 1
 device_t vga_pri = 0;
 static void set_vga_bridge_bits(void)
 {
-#warning "FIXME modify set_vga_bridge so it is less pci centric!"
-#warning "This function knows too much about PCI stuff, it should be just a iterator/visitor."
+       /*
+        * FIXME: Modify set_vga_bridge so it is less PCI centric!
+        * This function knows too much about PCI stuff, it should be just
+        * an iterator/visitor.
+        */
 
        /* FIXME: Handle the VGA palette snooping. */
        struct device *dev, *vga, *vga_onboard, *vga_first, *vga_last;
@@ -716,7 +738,7 @@ static void set_vga_bridge_bits(void)
 
        if (vga) {
                /* VGA is first add on card or the only onboard VGA. */
-               printk_debug("Setting up VGA for %s\n", dev_path(vga));
+               printk(BIOS_DEBUG, "Setting up VGA for %s\n", dev_path(vga));
                /* All legacy VGA cards have MEM & I/O space registers. */
                vga->command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
                vga_pri = vga;
@@ -724,7 +746,7 @@ static void set_vga_bridge_bits(void)
        }
        /* Now walk up the bridges setting the VGA enable. */
        while (bus) {
-               printk_debug("Setting PCI_BRIDGE_CTL_VGA for bridge %s\n",
+               printk(BIOS_DEBUG, "Setting PCI_BRIDGE_CTL_VGA for bridge %s\n",
                             dev_path(bus->dev));
                bus->bridge_ctrl |= PCI_BRIDGE_CTL_VGA;
                bus = (bus == bus->dev->bus) ? 0 : bus->dev->bus;
@@ -734,9 +756,7 @@ static void set_vga_bridge_bits(void)
 #endif
 
 /**
- * @brief  Assign the computed resources to the devices on the bus.
- *
- * @param bus Pointer to the structure for this bus
+ * Assign the computed resources to the devices on the bus.
  *
  * Use the device specific set_resources method to store the computed
  * resources to hardware. For bridge devices, the set_resources() method
@@ -745,68 +765,66 @@ static void set_vga_bridge_bits(void)
  * Mutual recursion:
  *     assign_resources() -> device_operation::set_resources()
  *     device_operation::set_resources() -> assign_resources()
+ *
+ * @param bus Pointer to the structure for this bus.
  */
 void assign_resources(struct bus *bus)
 {
        struct device *curdev;
 
-       printk_spew("%s assign_resources, bus %d link: %d\n",
-                   dev_path(bus->dev), bus->secondary, bus->link);
+       printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n",
+                   dev_path(bus->dev), bus->secondary, bus->link_num);
 
        for (curdev = bus->children; curdev; curdev = curdev->sibling) {
-               if (!curdev->enabled || !curdev->resources) {
+               if (!curdev->enabled || !curdev->resource_list) {
                        continue;
                }
                if (!curdev->ops || !curdev->ops->set_resources) {
-                       printk_err("%s missing set_resources\n",
+                       printk(BIOS_ERR, "%s missing set_resources\n",
                                   dev_path(curdev));
                        continue;
                }
                curdev->ops->set_resources(curdev);
        }
-       printk_spew("%s assign_resources, bus %d link: %d\n",
-                   dev_path(bus->dev), bus->secondary, bus->link);
+       printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n",
+                   dev_path(bus->dev), bus->secondary, bus->link_num);
 }
 
 /**
- * @brief Enable the resources for a specific device
- *
- * @param dev the device whose resources are to be enabled
+ * Enable the resources for devices on a link.
  *
  * Enable resources of the device by calling the device specific
  * enable_resources() method.
  *
  * The parent's resources should be enabled first to avoid having enabling
  * order problem. This is done by calling the parent's enable_resources()
- * method and let that method to call it's children's enable_resoruces()
- * method via the (global) enable_childrens_resources().
+ * method before its childrens' enable_resources() methods.
  *
- * Indirect mutual recursion:
- *     enable_resources() -> device_operations::enable_resource()
- *     device_operations::enable_resource() -> enable_children_resources()
- *     enable_children_resources() -> enable_resources()
+ * @param link The link whose devices' resources are to be enabled.
  */
-void enable_resources(struct device *dev)
+static void enable_resources(struct bus *link)
 {
-       if (!dev->enabled) {
-               return;
+       struct device *dev;
+       struct bus *c_link;
+
+       for (dev = link->children; dev; dev = dev->sibling) {
+               if (dev->enabled && dev->ops && dev->ops->enable_resources) {
+                       dev->ops->enable_resources(dev);
+               }
        }
-       if (!dev->ops || !dev->ops->enable_resources) {
-               printk_err("%s missing enable_resources\n", dev_path(dev));
-               return;
+
+       for (dev = link->children; dev; dev = dev->sibling) {
+               for (c_link = dev->link_list; c_link; c_link = c_link->next) {
+                       enable_resources(c_link);
+               }
        }
-       dev->ops->enable_resources(dev);
 }
 
 /**
- * @brief Reset all of the devices a bus
- *
  * Reset all of the devices on a bus and clear the bus's reset_needed flag.
  *
- * @param bus pointer to the bus structure
- *
+ * @param bus Pointer to the bus structure.
  * @return 1 if the bus was successfully reset, 0 otherwise.
- *
  */
 int reset_bus(struct bus *bus)
 {
@@ -819,7 +837,7 @@ int reset_bus(struct bus *bus)
 }
 
 /**
- * @brief Scan for devices on a bus.
+ * Scan for devices on a bus.
  *
  * If there are bridges on the bus, recursively scan the buses behind the
  * bridges. If the setting up and tuning of the bus causes a reset to be
@@ -840,12 +858,12 @@ unsigned int scan_bus(struct device *busdev, unsigned int max)
 
        do_scan_bus = 1;
        while (do_scan_bus) {
-               int link;
+               struct bus *link;
                new_max = busdev->ops->scan_bus(busdev, max);
                do_scan_bus = 0;
-               for (link = 0; link < busdev->links; link++) {
-                       if (busdev->link[link].reset_needed) {
-                               if (reset_bus(&busdev->link[link])) {
+               for (link = busdev->link_list; link; link = link->next) {
+                       if (link->reset_needed) {
+                               if (reset_bus(link)) {
                                        do_scan_bus = 1;
                                } else {
                                        busdev->bus->reset_needed = 1;
@@ -857,7 +875,7 @@ unsigned int scan_bus(struct device *busdev, unsigned int max)
 }
 
 /**
- * @brief Determine the existence of devices and extend the device tree.
+ * Determine the existence of devices and extend the device tree.
  *
  * Most of the devices in the system are listed in the mainboard Config.lb
  * file. The device structures for these devices are generated at compile
@@ -881,28 +899,26 @@ unsigned int scan_bus(struct device *busdev, unsigned int max)
 void dev_enumerate(void)
 {
        struct device *root;
-       unsigned subordinate;
-       printk_info("Enumerating buses...\n");
+       printk(BIOS_INFO, "Enumerating buses...\n");
        root = &dev_root;
 
-       show_all_devs(BIOS_DEBUG, "Before Device Enumeration.");
-       printk_debug("Compare with tree...\n");
-
-       show_devs_tree(root, BIOS_DEBUG, 0, 0);
+       show_all_devs(BIOS_SPEW, "Before Device Enumeration.");
+       printk(BIOS_SPEW, "Compare with tree...\n");
+       show_devs_tree(root, BIOS_SPEW, 0, 0);
 
        if (root->chip_ops && root->chip_ops->enable_dev) {
                root->chip_ops->enable_dev(root);
        }
        if (!root->ops || !root->ops->scan_bus) {
-               printk_err("dev_root missing scan_bus operation");
+               printk(BIOS_ERR, "dev_root missing scan_bus operation");
                return;
        }
-       subordinate = scan_bus(root, 0);
-       printk_info("done\n");
+       scan_bus(root, 0);
+       printk(BIOS_INFO, "done\n");
 }
 
 /**
- * @brief Configure devices on the devices tree.
+ * Configure devices on the devices tree.
  *
  * Starting at the root of the device tree, travel it recursively in two
  * passes. In the first pass, we compute and allocate resources (ranges)
@@ -919,13 +935,12 @@ void dev_configure(void)
        struct resource *res;
        struct device *root;
        struct device *child;
-       int i;
 
-#if CONFIG_CONSOLE_VGA == 1
+#if CONFIG_VGA_BRIDGE_SETUP == 1
        set_vga_bridge_bits();
 #endif
 
-       printk_info("Allocating resources...\n");
+       printk(BIOS_INFO, "Allocating resources...\n");
 
        root = &dev_root;
 
@@ -936,32 +951,31 @@ void dev_configure(void)
 
        /* Read the resources for the entire tree. */
 
-       printk_info("Reading resources...\n");
-       read_resources(&root->link[0]);
-       printk_info("Done reading resources.\n");
+       printk(BIOS_INFO, "Reading resources...\n");
+       read_resources(root->link_list);
+       printk(BIOS_INFO, "Done reading resources.\n");
 
-       print_resource_tree(root, BIOS_DEBUG, "After reading.");
+       print_resource_tree(root, BIOS_SPEW, "After reading.");
 
        /* Compute resources for all domains. */
-       for (child = root->link[0].children; child; child = child->sibling) {
+       for (child = root->link_list->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];
+               for (res = child->resource_list; res; res = res->next) {
                        if (res->flags & IORESOURCE_FIXED)
                                continue;
                        if (res->flags & IORESOURCE_PREFETCH) {
-                               compute_resources(&child->link[0],
+                               compute_resources(child->link_list,
                                               res, MEM_MASK, PREF_TYPE);
                                continue;
                        }
                        if (res->flags & IORESOURCE_MEM) {
-                               compute_resources(&child->link[0],
+                               compute_resources(child->link_list,
                                               res, MEM_MASK, MEM_TYPE);
                                continue;
                        }
                        if (res->flags & IORESOURCE_IO) {
-                               compute_resources(&child->link[0],
+                               compute_resources(child->link_list,
                                               res, IO_MASK, IO_TYPE);
                                continue;
                        }
@@ -969,18 +983,17 @@ void dev_configure(void)
        }
 
        /* For all domains. */
-       for (child = root->link[0].children; child; child=child->sibling)
+       for (child = root->link_list->children; child; child=child->sibling)
                if (child->path.type == DEVICE_PATH_PCI_DOMAIN)
                        avoid_fixed_resources(child);
 
        /* Now we need to adjust the resources. MEM resources need to start at
         * the highest address managable.
         */
-       for (child = root->link[0].children; child; child = child->sibling) {
+       for (child = root->link_list->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];
+               for (res = child->resource_list; res; res = res->next) {
                        if (!(res->flags & IORESOURCE_MEM) ||
                            res->flags & IORESOURCE_FIXED)
                                continue;
@@ -989,79 +1002,118 @@ void dev_configure(void)
        }
 
        /* Store the computed resource allocations into device registers ... */
-       printk_info("Setting resources...\n");
-       for (child = root->link[0].children; child; child = child->sibling) {
+       printk(BIOS_INFO, "Setting resources...\n");
+       for (child = root->link_list->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];
+               for (res = child->resource_list; res; res = res->next) {
                        if (res->flags & IORESOURCE_FIXED)
                                continue;
                        if (res->flags & IORESOURCE_PREFETCH) {
-                               allocate_resources(&child->link[0],
+                               allocate_resources(child->link_list,
                                               res, MEM_MASK, PREF_TYPE);
                                continue;
                        }
                        if (res->flags & IORESOURCE_MEM) {
-                               allocate_resources(&child->link[0],
+                               allocate_resources(child->link_list,
                                               res, MEM_MASK, MEM_TYPE);
                                continue;
                        }
                        if (res->flags & IORESOURCE_IO) {
-                               allocate_resources(&child->link[0],
+                               allocate_resources(child->link_list,
                                               res, IO_MASK, IO_TYPE);
                                continue;
                        }
                }
        }
-       assign_resources(&root->link[0]);
-       printk_info("Done setting resources.\n");
-       print_resource_tree(root, BIOS_DEBUG, "After assigning values.");
+       assign_resources(root->link_list);
+       printk(BIOS_INFO, "Done setting resources.\n");
+       print_resource_tree(root, BIOS_SPEW, "After assigning values.");
 
-       printk_info("Done allocating resources.\n");
+       printk(BIOS_INFO, "Done allocating resources.\n");
 }
 
 /**
- * @brief Enable devices on the device tree.
+ * Enable devices on the device tree.
  *
  * Starting at the root, walk the tree and enable all devices/bridges by
  * calling the device's enable_resources() method.
  */
 void dev_enable(void)
 {
-       printk_info("Enabling resources...\n");
+       struct bus *link;
+
+       printk(BIOS_INFO, "Enabling resources...\n");
 
        /* now enable everything. */
-       enable_resources(&dev_root);
+       for (link = dev_root.link_list; link; link = link->next)
+               enable_resources(link);
 
-       printk_info("done.\n");
+       printk(BIOS_INFO, "done.\n");
 }
 
 /**
- * @brief Initialize all devices in the global device list.
+ * Initialize a specific device.
+ *
+ * The parent should be initialized first to avoid having an ordering
+ * problem. This is done by calling the parent's init()
+ * method before its childrens' init() methods.
  *
- * Starting at the first device on the global device link list,
- * walk the list and call the device's init() method to do deivce
- * specific setup.
+ * @param dev The device to be initialized.
  */
-void dev_initialize(void)
+static void init_dev(struct device *dev)
+{
+       if (!dev->enabled) {
+               return;
+       }
+
+       if (!dev->initialized && dev->ops && dev->ops->init) {
+               if (dev->path.type == DEVICE_PATH_I2C) {
+                       printk(BIOS_DEBUG, "smbus: %s[%d]->",
+                              dev_path(dev->bus->dev), dev->bus->link_num);
+               }
+
+               printk(BIOS_DEBUG, "%s init\n", dev_path(dev));
+               dev->initialized = 1;
+               dev->ops->init(dev);
+       }
+}
+
+static void init_link(struct bus *link)
 {
        struct device *dev;
+       struct bus *c_link;
 
-       printk_info("Initializing devices...\n");
-       for (dev = all_devices; dev; dev = dev->next) {
-               if (dev->enabled && !dev->initialized &&
-                   dev->ops && dev->ops->init) {
-                       if (dev->path.type == DEVICE_PATH_I2C) {
-                               printk_debug("smbus: %s[%d]->",
-                                            dev_path(dev->bus->dev),
-                                            dev->bus->link);
-                       }
-                       printk_debug("%s init\n", dev_path(dev));
-                       dev->initialized = 1;
-                       dev->ops->init(dev);
+       for (dev = link->children; dev; dev = dev->sibling) {
+               init_dev(dev);
+       }
+
+       for (dev = link->children; dev; dev = dev->sibling) {
+               for (c_link = dev->link_list; c_link; c_link = c_link->next) {
+                       init_link(c_link);
                }
        }
-       printk_info("Devices initialized\n");
-       show_all_devs(BIOS_DEBUG, "After init.");
+}
+
+/**
+ * Initialize all devices in the global device tree.
+ *
+ * Starting at the root device, call the device's init() method to do
+ * device-specific setup, then call each child's init() method.
+ */
+void dev_initialize(void)
+{
+       struct bus *link;
+
+       printk(BIOS_INFO, "Initializing devices...\n");
+
+       /* First call the mainboard init. */
+       init_dev(&dev_root);
+
+       /* now initialize everything. */
+       for (link = dev_root.link_list; link; link = link->next)
+               init_link(link);
+
+       printk(BIOS_INFO, "Devices initialized\n");
+       show_all_devs(BIOS_SPEW, "After init.");
 }