struct device *all_devices = &dev_root;
/** Pointer to the last device */
extern struct device **last_dev_p;
+/** Linked list of free resources */
+struct resource *free_resources = NULL;
/**
*
* @see device_path
*/
-static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;
+
+DECLARE_SPIN_LOCK(dev_lock)
+
device_t alloc_dev(struct bus *parent, struct device_path *path)
{
device_t dev, child;
- int link;
spin_lock(&dev_lock);
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;
{
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 {
* the allocator. Also this allows handling of other types of bridges.
*
*/
-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;
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",
/* 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)
* 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));
/* 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);
}
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,
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",
* @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;
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",
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,
? "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,
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",
/* 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)
* 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));
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];
- if (!res->size)
- continue;
+ 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)
continue;
/* Is it already outside the limits? */
- if (res->size && (((res->base + res->size -1) < lim->base) ||
- (res->base > lim->limit)))
+ if (((res->base + res->size -1) < lim->base) || (res->base > lim->limit))
continue;
/* Choose to be above or below fixed resources. This
}
/* 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);
{
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;
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))
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;
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? */
}
}
-#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;
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;
}
/* 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;
{
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);
}
/**
return;
}
if (!dev->ops || !dev->ops->enable_resources) {
- printk_err("%s missing enable_resources\n", dev_path(dev));
+ printk(BIOS_ERR, "%s missing enable_resources\n", dev_path(dev));
return;
}
dev->ops->enable_resources(dev);
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;
void dev_enumerate(void)
{
struct device *root;
- 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;
}
scan_bus(root, 0);
- printk_info("done\n");
+ printk(BIOS_INFO, "done\n");
}
/**
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;
/* 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;
}
}
/* 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;
}
/* 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");
}
/**
*/
void dev_enable(void)
{
- printk_info("Enabling resources...\n");
+ printk(BIOS_INFO, "Enabling resources...\n");
/* now enable everything. */
enable_resources(&dev_root);
- printk_info("done.\n");
+ printk(BIOS_INFO, "done.\n");
}
/**
{
struct device *dev;
- printk_info("Initializing devices...\n");
+ printk(BIOS_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]->",
+ printk(BIOS_DEBUG, "smbus: %s[%d]->",
dev_path(dev->bus->dev),
- dev->bus->link);
+ dev->bus->link_num);
}
- printk_debug("%s init\n", dev_path(dev));
+ printk(BIOS_DEBUG, "%s init\n", dev_path(dev));
dev->initialized = 1;
dev->ops->init(dev);
}
}
- printk_info("Devices initialized\n");
- show_all_devs(BIOS_DEBUG, "After init.");
+ printk(BIOS_INFO, "Devices initialized\n");
+ show_all_devs(BIOS_SPEW, "After init.");
}