- Updates for 64bit resource support, handling missing devices and cpus in the config file

git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1664 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Eric Biederman
2004-10-14 21:25:53 +00:00
parent 992cd008f1
commit 03acab694b
7 changed files with 637 additions and 329 deletions

View File

@@ -22,6 +22,7 @@
#include <device/pci_ids.h>
#include <stdlib.h>
#include <string.h>
#include <smp/spinlock.h>
/** Linked list of ALL devices */
struct device *all_devices = &dev_root;
@@ -30,7 +31,7 @@ static struct device **last_dev_p = &dev_root.next;
/** The upper limit of MEM resource of the devices.
* Reserve 20M for the system */
#define DEVICE_MEM_HIGH 0xFEC00000UL
#define DEVICE_MEM_HIGH 0xFEBFFFFFUL
/** The lower limit of IO resource of the devices.
* Reserve 4k for ISA/Legacy devices */
#define DEVICE_IO_START 0x1000
@@ -53,6 +54,7 @@ device_t alloc_dev(struct bus *parent, struct device_path *path)
device_t dev, child;
int link;
spin_lock(&dev_lock);
/* Find the last child of our parent */
for(child = parent->children; child && child->sibling; ) {
child = child->sibling;
@@ -64,17 +66,15 @@ device_t alloc_dev(struct bus *parent, struct device_path *path)
memset(dev, 0, sizeof(*dev));
memcpy(&dev->path, path, sizeof(*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;
/* 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;
/* Add the new device to the list of children of the bus. */
dev->bus = parent;
@@ -83,9 +83,14 @@ device_t alloc_dev(struct bus *parent, struct device_path *path)
} else {
parent->children = dev;
}
/* If we don't have any other information about a device enable it */
dev->enabled = 1;
/* 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;
spin_unlock(&dev_lock);
return dev;
}
@@ -269,7 +274,7 @@ void compute_allocate_resource(
{
struct device *dev;
struct resource *resource;
unsigned long base;
resource_t base;
unsigned long align, min_align;
min_align = 0;
base = bridge->base;
@@ -302,7 +307,7 @@ void compute_allocate_resource(
* compute the addresses.
*/
while((dev = largest_resource(bus, &resource, type_mask, type))) {
unsigned long size;
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
@@ -314,6 +319,15 @@ void compute_allocate_resource(
bridge->align = resource->align;
}
/* Propogate 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;
}
/* Make certain we are dealing with a good minimum size */
size = resource->size;
align = resource->align;
@@ -341,19 +355,20 @@ void compute_allocate_resource(
base = 0x3e0;
}
}
if (((round(base, 1UL << align) + size) -1) <= resource->limit) {
if (((round(base, align) + size) -1) <= resource->limit) {
/* base must be aligned to size */
base = round(base, 1UL << align);
base = round(base, align);
resource->base = base;
resource->flags |= IORESOURCE_ASSIGNED;
resource->flags &= ~IORESOURCE_STORED;
base += size;
printk_spew(
"%s %02x * [0x%08lx - 0x%08lx] %s\n",
"%s %02x * [0x%08Lx - 0x%08Lx] %s\n",
dev_path(dev),
resource->index,
resource->base, resource->base + resource->size - 1,
resource->base,
resource->base + resource->size - 1,
(resource->flags & IORESOURCE_IO)? "io":
(resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem");
}
@@ -364,10 +379,10 @@ void compute_allocate_resource(
* know not to place something else at an address postitively
* decoded by the bridge.
*/
bridge->size = round(base, 1UL << bridge->gran) - bridge->base;
bridge->size = round(base, bridge->gran) - bridge->base;
printk_spew("%s compute_allocate_%s: base: %08lx size: %08lx align: %d gran: %d done\n",
dev_path(dev),
dev_path(bus->dev),
(bridge->flags & IORESOURCE_IO)? "io":
(bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem",
base, bridge->size, bridge->align, bridge->gran);
@@ -387,7 +402,8 @@ static void allocate_vga_resource(void)
vga = 0;
for(dev = all_devices; dev; dev = dev->next) {
if (((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
((dev->class >> 8) != PCI_CLASS_DISPLAY_OTHER)) {
((dev->class >> 8) != PCI_CLASS_DISPLAY_OTHER))
{
if (!vga) {
printk_debug("Allocating VGA resource %s\n",
dev_path(dev));
@@ -423,20 +439,22 @@ void assign_resources(struct bus *bus)
{
struct device *curdev;
printk_debug("ASSIGN RESOURCES, bus %d\n", bus->secondary);
printk_spew("%s assign_resources, bus %d link: %d\n",
dev_path(bus->dev), bus->secondary, bus->link);
for (curdev = bus->children; curdev; curdev = curdev->sibling) {
for(curdev = bus->children; curdev; curdev = curdev->sibling) {
if (!curdev->enabled || !curdev->resources) {
continue;
}
if (!curdev->ops || !curdev->ops->set_resources) {
printk_err("%s missing set_resources\n",
dev_path(curdev));
continue;
}
if (!curdev->enabled) {
continue;
}
curdev->ops->set_resources(curdev);
}
printk_debug("ASSIGNED RESOURCES, bus %d\n", bus->secondary);
printk_spew("%s assign_resources, bus %d link: %d\n",
dev_path(bus->dev), bus->secondary, bus->link);
}
/**
@@ -456,11 +474,11 @@ void assign_resources(struct bus *bus)
*/
void enable_resources(struct device *dev)
{
if (!dev->ops || !dev->ops->enable_resources) {
printk_err("%s missing enable_resources\n", dev_path(dev));
if (!dev->enabled) {
return;
}
if (!dev->enabled) {
if (!dev->ops || !dev->ops->enable_resources) {
printk_err("%s missing enable_resources\n", dev_path(dev));
return;
}
dev->ops->enable_resources(dev);
@@ -493,11 +511,12 @@ void dev_enumerate(void)
printk_info("done\n");
}
/**
* @brief Configure devices on the devices tree.
*
* Starting at the root of the dynamic device tree, travel recursively,
* compute resources needed by each device and allocate them.
* and compute resources needed by each device and allocate them.
*
* I/O resources start at DEVICE_IO_START and grow upward. MEM resources start
* at DEVICE_MEM_START and grow downward.
@@ -507,6 +526,7 @@ void dev_enumerate(void)
*/
void dev_configure(void)
{
struct resource *io, *mem;
struct device *root;
printk_info("Allocating resources...\n");
@@ -522,18 +542,19 @@ void dev_configure(void)
}
root->ops->read_resources(root);
/* Get the resources */
io = &root->resource[0];
mem = &root->resource[1];
/* Make certain the io devices are allocated somewhere safe. */
root->resource[0].base = DEVICE_IO_START;
root->resource[0].flags |= IORESOURCE_ASSIGNED;
root->resource[0].flags &= ~IORESOURCE_STORED;
io->base = DEVICE_IO_START;
io->flags |= IORESOURCE_ASSIGNED;
io->flags &= ~IORESOURCE_STORED;
/* Now reallocate the pci resources memory with the
* highest addresses I can manage.
*/
root->resource[1].base =
round_down(DEVICE_MEM_HIGH - root->resource[1].size,
1UL << root->resource[1].align);
root->resource[1].flags |= IORESOURCE_ASSIGNED;
root->resource[1].flags &= ~IORESOURCE_STORED;
mem->base = resource_max(&root->resource[1]);
mem->flags |= IORESOURCE_ASSIGNED;
mem->flags &= ~IORESOURCE_STORED;
/* Allocate the VGA I/O resource.. */
allocate_vga_resource();
@@ -541,6 +562,11 @@ void dev_configure(void)
/* Store the computed resource allocations into device registers ... */
root->ops->set_resources(root);
#if 0
mem->flags |= IORESOURCE_STORED;
report_resource_stored(root, mem, "");
#endif
printk_info("done.\n");
}
@@ -571,9 +597,12 @@ void dev_initialize(void)
struct device *dev;
printk_info("Initializing devices...\n");
for (dev = all_devices; dev; dev = dev->next) {
if (dev->enabled && dev->ops && dev->ops->init) {
for(dev = all_devices; dev; dev = dev->next) {
if (dev->enabled && !dev->initialized &&
dev->ops && dev->ops->init)
{
printk_debug("%s init\n", dev_path(dev));
dev->initialized = 1;
dev->ops->init(dev);
}
}