- 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
diff --git a/src/devices/chip.c b/src/devices/chip.c
index 8315fab..6882a4b 100644
--- a/src/devices/chip.c
+++ b/src/devices/chip.c
@@ -112,8 +112,9 @@
 			struct chip_resource *res, *res_limit;
 			printk_spew("path (%p) %s %s", 
 				dev, dev_path(dev), identical_paths?"identical":"");
-			printk_spew(" parent: (%p) %s\n",
-				dev->bus->dev,  dev_path(dev->bus->dev));
+			printk_spew(" parent: (%p):%d %s\n",
+				dev->bus->dev,  dev->bus->link,
+				dev_path(dev->bus->dev));
 			dev->chip = chip;
 			dev->enabled = chip->path[i].enabled;
 			dev->links = link + 1;
@@ -127,7 +128,7 @@
 			for(; res < res_limit; res++) {
 				if (res->flags) {
 					struct resource *resource;
-					resource = get_resource(dev, res->index);
+					resource = new_resource(dev, res->index);
 					resource->flags = res->flags | IORESOURCE_FIXED | IORESOURCE_ASSIGNED;
 					resource->base = res->base;
 				}
@@ -208,7 +209,24 @@
  */
 void enumerate_static_devices(void)
 {
+	struct chip *child;
+	int i;
 	printk_info("Enumerating static devices...\n");
 	static_root.dev = &dev_root;
+	dev_root.links  = MAX_LINKS;
+	for(i = 0; i < MAX_LINKS; i++) {
+		dev_root.link[i].link = i;
+		dev_root.link[i].dev = &dev_root;
+		for(child = static_root.children; child; child = child->next) {
+			if (!child->bus && child->link == i) {
+				child->bus = &dev_root.link[i];
+			}
+		}
+	}
+	for(child = static_root.children; child; child = child->next) {
+		if (!child->bus) {
+			child->bus = &dev_root.link[0];
+		}
+	}
 	enumerate_static_device_chain(&static_root);
 }
diff --git a/src/devices/device.c b/src/devices/device.c
index 4b7d872..7ef65e2 100644
--- a/src/devices/device.c
+++ b/src/devices/device.c
@@ -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 @@
 
 /** 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 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 @@
 	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 @@
 	} 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 @@
 {
 	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 @@
 	 * 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 @@
 			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 @@
 				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 @@
 	 * 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 @@
 	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 @@
 {
 	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 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 @@
 	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_configure(void)
 {
+	struct resource *io, *mem;
 	struct device *root;
 
 	printk_info("Allocating resources...\n");
@@ -522,18 +542,19 @@
 	}
 	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 @@
 	/* 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 @@
 	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);
 		}
 	}
diff --git a/src/devices/device_util.c b/src/devices/device_util.c
index f5f8bb4..7a942b4 100644
--- a/src/devices/device_util.c
+++ b/src/devices/device_util.c
@@ -4,6 +4,24 @@
 #include <device/pci.h>
 #include <string.h>
 
+/**
+ * @brief See if a device structure exists for path
+ *
+ * @param bus The bus to find the device on
+ * @param path The relative path from the bus to the appropriate device
+ * @return pointer to a device structure for the device on bus at path
+ *         or 0/NULL if no device is found
+ */
+device_t find_dev_path(struct bus *parent, struct device_path *path)
+{
+	device_t child;
+	for(child = parent->children; child; child = child->sibling) {
+		if (path_eq(path, &child->path)) {
+			break;
+		}
+	}
+	return child;
+}
 
 /**
  * @brief See if a device structure already exists and if not allocate it
@@ -15,12 +33,11 @@
 device_t alloc_find_dev(struct bus *parent, struct device_path *path)
 {
 	device_t child;
-	for(child = parent->children; child; child = child->sibling) {
-		if (path_eq(path, &child->path)) {
-			return child;
-		}
+	child = find_dev_path(parent, path);
+	if (!child) {
+		child = alloc_dev(parent, path);
 	}
-	return alloc_dev(parent, path);
+	return child;
 }
 
 /**
@@ -96,6 +113,9 @@
 		case DEVICE_PATH_ROOT:
 			memcpy(buffer, "Root Device", 12);
 			break;
+		case DEVICE_PATH_DEFAULT_CPU:
+			memcpy(buffer, "Default CPU", 12);
+			break;
 		case DEVICE_PATH_PCI:
 			sprintf(buffer, "PCI: %02x:%02x.%01x",
 				dev->bus->secondary, 
@@ -109,6 +129,10 @@
 			sprintf(buffer, "I2C: %02x",
 				dev->path.u.i2c.device);
 			break;
+		case DEVICE_PATH_APIC:
+			sprintf(buffer, "APIC: %02x",
+				dev->path.u.apic.apic_id);
+			break;
 		default:
 			printk_err("Unknown device path type: %d\n", dev->path.type);
 			break;
@@ -127,6 +151,9 @@
 		case DEVICE_PATH_ROOT:
 			equal = 1;
 			break;
+		case DEVICE_PATH_DEFAULT_CPU:
+			equal = 1;
+			break;
 		case DEVICE_PATH_PCI:
 			equal = (path1->u.pci.bus == path2->u.pci.bus) &&
 				(path1->u.pci.devfn == path2->u.pci.devfn);
@@ -138,6 +165,9 @@
 		case DEVICE_PATH_I2C:
 			equal = (path1->u.i2c.device == path2->u.i2c.device);
 			break;
+		case DEVICE_PATH_APIC:
+			equal = (path1->u.apic.apic_id == path2->u.apic.apic_id);
+			break;
 		default:
 			printk_err("Uknown device type: %d\n", path1->type);
 			break;
@@ -168,20 +198,17 @@
 	}
 }
 
+
 /**
- * See if a resource structure already exists for a given index and if
- * not allocate one.
+ * See if a resource structure already exists for a given index
  * @param dev The device to find the resource on
  * @param index  The index of the resource on the device.
+ * @return the resource if it already exists
  */
-struct resource *get_resource(device_t dev, unsigned index)
+struct resource *probe_resource(device_t dev, unsigned index)
 {
 	struct resource *resource;
 	int i;
-
-	/* First move all of the free resources to the end */
-	compact_resources(dev);
-
 	/* See if there is a resource with the appropriate index */
 	resource = 0;
 	for(i = 0; i < dev->resources; i++) {
@@ -190,6 +217,25 @@
 			break;
 		}
 	}
+	return resource;
+}
+
+/**
+ * See if a resource structure already exists for a given index and if
+ * not allocate one.  Then initialize the initialize the resource
+ * to default values.
+ * @param dev The device to find the resource on
+ * @param index  The index of the resource on the device.
+ */
+struct resource *new_resource(device_t dev, unsigned index)
+{
+	struct resource *resource;
+
+	/* First move all of the free resources to the end */
+	compact_resources(dev);
+
+	/* See if there is a resource with the appropriate index */
+	resource = probe_resource(dev, index);
 	if (!resource) {
 		if (dev->resources == MAX_RESOURCES) {
 			die("MAX_RESOURCES exceeded.");
@@ -212,3 +258,120 @@
 	return resource;
 }
 
+/**
+ * Return an existing resource structure for a given index.
+ * @param dev The device to find the resource on
+ * @param index  The index of the resource on the device.
+ */
+struct resource *find_resource(device_t dev, unsigned index)
+{
+	struct resource *resource;
+
+	/* See if there is a resource with the appropriate index */
+	resource = probe_resource(dev, index);
+	if (!resource) {
+		printk_emerg("%s missing resource: %02x\n",
+			dev_path(dev), index);
+		die("");
+	}
+	return resource;
+}
+
+
+/**
+ * @brief round a number up to the next multiple of gran
+ * @param val the starting value
+ * @param gran granularity we are aligning the number to.
+ * @returns aligned value
+ */
+static resource_t align_up(resource_t val, unsigned long gran)
+{
+	resource_t mask;
+	mask = (1ULL << gran) - 1ULL;
+	val += mask;
+	val &= ~mask;
+	return val;
+}
+
+/**
+ * @brief round a number up to the previous multiple of gran
+ * @param val the starting value
+ * @param gran granularity we are aligning the number to.
+ * @returns aligned value
+ */
+static resource_t align_down(resource_t val, unsigned long gran)
+{
+	resource_t mask;
+	mask = (1ULL << gran) - 1ULL;
+	val &= ~mask;
+	return val;
+}
+
+/**
+ * @brief Compute the maximum address that is part of a resource
+ * @param resource the resource whose limit is desired
+ * @returns the end
+ */
+resource_t resource_end(struct resource *resource)
+{
+	resource_t base, end;
+	/* get the base address */
+	base = resource->base;
+
+	/* For a non bridge resource granularity and alignment are the same.
+	 * For a bridge resource align is the largest needed alignment below
+	 * the bridge.  While the granularity is simply how many low bits of the
+	 * address cannot be set.
+	 */
+	
+	/* Get the end (rounded up) */
+	end = base + align_up(resource->size, resource->gran) - 1;
+
+	return end;
+}
+
+/**
+ * @brief Compute the maximum legal value for resource->base
+ * @param resource the resource whose maximum is desired
+ * @returns the maximum
+ */
+resource_t resource_max(struct resource *resource)
+{
+	resource_t max;
+
+	max = align_down(resource->limit - resource->size + 1, resource->align);
+
+	return max;
+}
+
+/**
+ * @brief print the resource that was just stored.
+ * @param dev the device the stored resorce lives on
+ * @param resource the resource that was just stored.
+ */
+void report_resource_stored(device_t dev, struct resource *resource, const char *comment)
+{
+	if (resource->flags & IORESOURCE_STORED) {
+		unsigned char buf[10];
+		unsigned long long base, end;
+		base = resource->base;
+		end = resource_end(resource);
+		buf[0] = '\0';
+		if (resource->flags & IORESOURCE_PCI_BRIDGE) {
+			sprintf(buf, "bus %d ", dev->link[0].secondary);
+		}
+		printk_debug(
+			"%s %02x <- [0x%010Lx - 0x%010Lx] %s%s%s%s\n",
+			dev_path(dev),
+			resource->index,
+			base, end,
+			buf,
+			(resource->flags & IORESOURCE_PREFETCH) ? "pref" : "",
+			(resource->flags & IORESOURCE_IO)? "io":
+			(resource->flags & IORESOURCE_DRQ)? "drq":
+			(resource->flags & IORESOURCE_IRQ)? "irq":
+			(resource->flags & IORESOURCE_MEM)? "mem": 
+			"????",
+			comment);
+	}
+}
diff --git a/src/devices/hypertransport.c b/src/devices/hypertransport.c
index 2126889..344f23f 100644
--- a/src/devices/hypertransport.c
+++ b/src/devices/hypertransport.c
@@ -14,9 +14,9 @@
 	device_t first, last;
 	first = *old_devices;
 	last = first;
-	while (last && last->sibling && 
-	       (last->sibling->path.type == DEVICE_PATH_PCI) &&
-	       (last->sibling->path.u.pci.devfn > last->path.u.pci.devfn)) {
+	while(last && last->sibling && 
+		(last->sibling->path.type == DEVICE_PATH_PCI) &&
+		(last->sibling->path.u.pci.devfn > last->path.u.pci.devfn)) {
 		last = last->sibling;
 	}
 	if (first) {
@@ -264,19 +264,21 @@
 			*chain_last = dev;
 			/* Run the magice enable sequence for the device */
 			if (dev->chip && dev->chip->control && dev->chip->control->enable_dev) {
-				int enable  = dev->enabled;
-				dev->enabled = 1;
 				dev->chip->control->enable_dev(dev);
-				dev->enabled = enable;
 			}
 			/* Now read the vendor and device id */
 			id = pci_read_config32(dev, PCI_VENDOR_ID);
 
+			
 			/* If the chain is fully enumerated quit */
 			if (id == 0xffffffff || id == 0x00000000 ||
-				id == 0x0000ffff || id == 0xffff0000) {
-				printk_err("Missing static device: %s\n",
-					dev_path(dev));
+				id == 0x0000ffff || id == 0xffff0000) 
+			{
+				if (dev->enabled) {
+					printk_info("Disabling static device: %s\n",
+						dev_path(dev));
+					dev->enabled = 0;
+				}
 				break;
 			}
 		}
diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c
index 6f7fabf..5d72f03 100644
--- a/src/devices/pci_device.c
+++ b/src/devices/pci_device.c
@@ -21,125 +21,200 @@
 #include <device/chip.h>
 #include <part/hard_reset.h>
 #include <part/fallback_boot.h>
+#include <delay.h>
+
+static uint8_t pci_moving_config8(struct device *dev, unsigned reg)
+{
+	uint8_t value, ones, zeroes;
+	value = pci_read_config8(dev, reg);
+	
+	pci_write_config8(dev, reg, 0xff);
+	ones = pci_read_config8(dev, reg);
+
+	pci_write_config8(dev, reg, 0x00);
+	zeroes = pci_read_config8(dev, reg);
+
+	pci_write_config8(dev, reg, value);
+
+	return ones ^ zeroes;
+}
+static uint16_t pci_moving_config16(struct device *dev, unsigned reg)
+{
+	uint16_t value, ones, zeroes;
+	value = pci_read_config16(dev, reg);
+	
+	pci_write_config16(dev, reg, 0xffff);
+	ones = pci_read_config16(dev, reg);
+
+	pci_write_config16(dev, reg, 0x0000);
+	zeroes = pci_read_config16(dev, reg);
+
+	pci_write_config16(dev, reg, value);
+
+	return ones ^ zeroes;
+}
+static uint32_t pci_moving_config32(struct device *dev, unsigned reg)
+{
+	uint32_t value, ones, zeroes;
+	value = pci_read_config32(dev, reg);
+	
+	pci_write_config32(dev, reg, 0xffffffff);
+	ones = pci_read_config32(dev, reg);
+
+	pci_write_config32(dev, reg, 0x00000000);
+	zeroes = pci_read_config32(dev, reg);
+
+	pci_write_config32(dev, reg, value);
+
+	return ones ^ zeroes;
+}
+
+unsigned pci_find_capability(device_t dev, unsigned cap)
+{
+	unsigned pos;
+	pos = 0;
+	switch(dev->hdr_type & 0x7f) {
+	case PCI_HEADER_TYPE_NORMAL:
+	case PCI_HEADER_TYPE_BRIDGE:
+		pos = PCI_CAPABILITY_LIST;
+		break;
+	}
+	if (pos > PCI_CAP_LIST_NEXT) {
+		pos = pci_read_config8(dev, pos);
+	}
+	while(pos != 0) {   /* loop through the linked list */
+		int this_cap;
+		this_cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
+		if (this_cap == cap) {
+			return pos;
+		}
+	}
+	return 0;
+}
+
 
 /** Given a device and register, read the size of the BAR for that register. 
  * @param dev       Pointer to the device structure
  * @param resource  Pointer to the resource structure
  * @param index     Address of the pci configuration register
  */
-static struct resource *pci_get_resource(struct device *dev, unsigned long index)
+struct resource *pci_get_resource(struct device *dev, unsigned long index)
 {
 	struct resource *resource;
-	uint32_t addr, size, base;
-	unsigned long type;
+	unsigned long value, attr;
+	resource_t  moving, limit;
 
 	/* Initialize the resources to nothing */
-	resource = get_resource(dev, index);
+	resource = new_resource(dev, index);
 
-	addr = pci_read_config32(dev, index);
+	/* Get the initial value */
+	value = pci_read_config32(dev, index);
 
-	/* FIXME: more consideration for 64-bit PCI devices,
-	 * we currently detect their size but otherwise
-	 * treat them as 32-bit resources
+	/* See which bits move */
+	moving = pci_moving_config32(dev, index);
+	
+	/* Initialize attr to the bits that do not move */
+	attr = value & ~moving;
+
+	/* If it is a 64bit resource look at the high half as well */
+	if (((attr & PCI_BASE_ADDRESS_SPACE_IO) == 0) &&
+		((attr & PCI_BASE_ADDRESS_MEM_LIMIT_MASK) == PCI_BASE_ADDRESS_MEM_LIMIT_64))
+	{
+		/* Find the high bits that move */
+		moving |= ((resource_t)pci_moving_config32(dev, index + 4)) << 32;
+	}
+	/* Find the resource constraints. 
+	 *
+	 * Start by finding the bits that move. From there:
+	 * - Size is the least significant bit of the bits that move.
+	 * - Limit is all of the bits that move plus all of the lower bits.
+	 * See PCI Spec 6.2.5.1 ...
 	 */
-	/* get the size */
-	pci_write_config32(dev, index, ~0);
-	size = pci_read_config32(dev,  index);
-
-	/* get the minimum value the bar can be set to */
-	pci_write_config32(dev, index, 0);
-	base = pci_read_config32(dev, index);
-
-	/* restore addr */
-	pci_write_config32(dev, index, addr);
-
+	limit = 0;
+	if (moving) {
+		resource->size = 1;
+		resource->align = resource->gran = 0;
+		while(!(moving & resource->size)) {
+			resource->size <<= 1;
+			resource->align += 1;
+			resource->gran  += 1;
+		}
+		resource->limit = limit = moving | (resource->size - 1);
+	}
 	/*
 	 * some broken hardware has read-only registers that do not 
-	 * really size correctly. You can tell this if addr == size
+	 * really size correctly.
 	 * Example: the acer m7229 has BARs 1-4 normally read-only. 
 	 * so BAR1 at offset 0x10 reads 0x1f1. If you size that register
 	 * by writing 0xffffffff to it, it will read back as 0x1f1 -- a 
 	 * violation of the spec. 
-	 * We catch this case and ignore it by settting size and type to 0.
-	 * This incidentally catches the common case where registers 
-	 * read back as 0 for both address and size. 
+	 * We catch this case and ignore it by observing which bits move,
+	 * This also catches the common case unimplemented registers
+	 * that always read back as 0.
 	 */
-	if ((addr == size) && (addr == base)) {
-		if (size != 0) {
+	if (moving == 0) {
+		if (value != 0) {
 			printk_debug(
 				"%s register %02x(%08x), read-only ignoring it\n",
-				dev_path(dev),
-				index, addr);
+				dev_path(dev), index, value);
 		}
 		resource->flags = 0;
 	}
-	/* Now compute the actual size, See PCI Spec 6.2.5.1 ...  */
-	else if (size & PCI_BASE_ADDRESS_SPACE_IO) {
-		type = size & (~PCI_BASE_ADDRESS_IO_MASK);
-		/* BUG! Top 16 bits can be zero (or not) 
-		 * So set them to 0xffff so they go away ...
-		 */
-		resource->size = (~((size | 0xffff0000) & PCI_BASE_ADDRESS_IO_MASK)) +1;
-		resource->align = log2(resource->size);
-		resource->gran = resource->align;
+	else if (attr & PCI_BASE_ADDRESS_SPACE_IO) {
+		/* An I/O mapped base address */
+		attr &= PCI_BASE_ADDRESS_IO_ATTR_MASK;
 		resource->flags |= IORESOURCE_IO;
+		/* I don't want to deal with 32bit I/O resources */
 		resource->limit = 0xffff;
 	} 
 	else {
 		/* A Memory mapped base address */
-		type = size & (~PCI_BASE_ADDRESS_MEM_MASK);
-		resource->size = (~(size &PCI_BASE_ADDRESS_MEM_MASK)) +1;
-		resource->align = log2(resource->size);
-		resource->gran = resource->align;
+		attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
 		resource->flags |= IORESOURCE_MEM;
-		if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+		if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH) {
 			resource->flags |= IORESOURCE_PREFETCH;
 		}
-		type &= PCI_BASE_ADDRESS_MEM_TYPE_MASK;
-		if (type == PCI_BASE_ADDRESS_MEM_TYPE_32) {
+		attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
+		if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
 			/* 32bit limit */
 			resource->limit = 0xffffffffUL;
 		}
-		else if (type == PCI_BASE_ADDRESS_MEM_TYPE_1M) {
+		else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
 			/* 1MB limit */
 			resource->limit = 0x000fffffUL;
 		}
-		else if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
-			unsigned long index_hi;
-			/* 64bit limit 
-			 * For now just treat this as a 32bit limit
-			 */
-			index_hi = index + 4;
-			resource->limit = 0xffffffffUL;
+		else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
+			/* 64bit limit */
+			resource->limit = 0xffffffffffffffffULL;
 			resource->flags |= IORESOURCE_PCI64;
-			addr = pci_read_config32( dev, index_hi);
-			/* get the extended size */
-			pci_write_config32(dev, index_hi, 0xffffffffUL);
-			size = pci_read_config32( dev, index_hi);
-
-			/* get the minimum value the bar can be set to */
-			pci_write_config32(dev, index_hi, 0);
-			base = pci_read_config32(dev,  index_hi);
-
-			/* restore addr */
-			pci_write_config32(dev, index_hi, addr);
-			
-			if ((size == 0xffffffff) && (base == 0)) {
-				/* Clear the top half of the bar */
-				pci_write_config32(dev, index_hi, 0);
-			}
-			else {
-				printk_err("%s Unable to handle 64-bit address\n",
-					dev_path(dev));
-				resource->flags = IORESOURCE_PCI64;
-			}
-		} 
+		}
 		else {
 			/* Invalid value */
 			resource->flags = 0;
 		}
 	}
-	/* dev->size holds the flags... */
+	/* Don't let the limit exceed which bits can move */
+	if (resource->limit > limit) {
+		resource->limit = limit;
+	}
+#if 0
+	if (resource->flags) {
+		printk_debug("%s %02x ->",
+			dev_path(dev), resource->index);
+		printk_debug(" value: 0x%08Lx zeroes: 0x%08Lx ones: 0x%08Lx attr: %08lx\n",
+			value, zeroes, ones, attr);
+		printk_debug(
+			"%s %02x -> size: 0x%08Lx max: 0x%08Lx %s%s\n ",
+			dev_path(dev),
+			resource->index,
+			resource->size,	resource->limit,
+			(resource->flags == 0) ? "unused":
+			(resource->flags & IORESOURCE_IO)? "io":
+			(resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem",
+			(resource->flags & IORESOURCE_PCI64)?"64":"");
+	}
+#endif
+
 	return resource;
 }
 
@@ -159,42 +234,90 @@
 	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 index, unsigned long mask, unsigned long type)
+{
+	/* Initiliaze the constraints on the current bus */
+	struct resource *resource;
+	resource = 0;
+	if (moving) {
+		unsigned long gran;
+		resource_t step;
+		resource = new_resource(dev, index);
+		resource->size = 0;
+		gran = 0;
+		step = 1;
+		while((moving & step) == 0) {
+			gran += 1;
+			step <<= 1;
+		}
+		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;
+		}
+	}
+	return;
+}
+
+
 static void pci_bridge_read_bases(struct device *dev)
 {
-	struct resource *resource;
+	resource_t moving_base, moving_limit, moving;
 
-	/* FIXME handle bridges without some of the optional resources */
+
+	/* See if the bridge I/O resources are implemented */
+	moving_base = ((uint32_t)pci_moving_config8(dev, PCI_IO_BASE)) << 8;
+	moving_base |= ((uint32_t)pci_moving_config16(dev, PCI_IO_BASE_UPPER16)) << 16;
+
+	moving_limit = ((uint32_t)pci_moving_config8(dev, PCI_IO_LIMIT)) << 8;
+	moving_limit |= ((uint32_t)pci_moving_config16(dev, PCI_IO_LIMIT_UPPER16)) << 16;
+
+	moving = moving_base & moving_limit;
 
 	/* Initialize the io space constraints on the current bus */
-	resource = get_resource(dev, PCI_IO_BASE);
-	resource->size  = 0;
-	resource->align = log2(PCI_IO_BRIDGE_ALIGN);
-	resource->gran  = log2(PCI_IO_BRIDGE_ALIGN);
-	resource->limit = 0xffffUL;
-	resource->flags |= IORESOURCE_IO | IORESOURCE_PCI_BRIDGE;
-	compute_allocate_resource(&dev->link[0], resource,
+	pci_record_bridge_resource(
+		dev, moving, PCI_IO_BASE, 
 		IORESOURCE_IO, IORESOURCE_IO);
 
+
+	/* See if the bridge prefmem resources are implemented */
+	moving_base =  ((resource_t)pci_moving_config16(dev, PCI_PREF_MEMORY_BASE)) << 16;
+	moving_base |= ((resource_t)pci_moving_config32(dev, PCI_PREF_BASE_UPPER32)) << 32;
+
+	moving_limit =  ((resource_t)pci_moving_config16(dev, PCI_PREF_MEMORY_LIMIT)) << 16;
+	moving_limit |= ((resource_t)pci_moving_config32(dev, PCI_PREF_LIMIT_UPPER32)) << 32;
+	
+	moving = moving_base & moving_limit;
 	/* Initiliaze the prefetchable memory constraints on the current bus */
-	resource = get_resource(dev, PCI_PREF_MEMORY_BASE);
-	resource->size = 0;
-	resource->align = log2(PCI_MEM_BRIDGE_ALIGN);
-	resource->gran  = log2(PCI_MEM_BRIDGE_ALIGN);
-	resource->limit = 0xffffffffUL;
-	resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_PCI_BRIDGE;
-	resource->index = PCI_PREF_MEMORY_BASE;
-	compute_allocate_resource(&dev->link[0], resource,
-		IORESOURCE_MEM | IORESOURCE_PREFETCH, 
+	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 */
+	moving_base = ((uint32_t)pci_moving_config16(dev, PCI_MEMORY_BASE)) << 16;
+	moving_limit = ((uint32_t)pci_moving_config16(dev, PCI_MEMORY_LIMIT)) << 16;
+
+	moving = moving_base & moving_limit;
 
 	/* Initialize the memory resources on the current bus */
-	resource = get_resource(dev, PCI_MEMORY_BASE);
-	resource->size = 0;
-	resource->align = log2(PCI_MEM_BRIDGE_ALIGN);
-	resource->gran  = log2(PCI_MEM_BRIDGE_ALIGN);
-	resource->limit = 0xffffffffUL;
-	resource->flags = IORESOURCE_MEM | IORESOURCE_PCI_BRIDGE;
-	compute_allocate_resource(&dev->link[0], resource,
+	pci_record_bridge_resource(
+		dev, moving, PCI_MEMORY_BASE, 
 		IORESOURCE_MEM | IORESOURCE_PREFETCH,
 		IORESOURCE_MEM);
 
@@ -222,27 +345,9 @@
 	dev->rom_address = (addr == 0xffffffff)? 0 : addr;
 }
 
-/**
- * @brief round a number up to the next multiple of gran
- * @param val the starting value
- * @param gran granularity we are aligning the number to.
- * @returns aligned value
- */
-static unsigned long align(unsigned long val, unsigned long gran)
-{
-	/* GRAN MUST BE A POWER OF TWO. */
-	unsigned long mask;
-	mask = ~(gran - 1);
-	val += (gran - 1);
-	val &= mask;
-	return val;
-}
-
 static void pci_set_resource(struct device *dev, struct resource *resource)
 {
-	unsigned long base, limit;
-	unsigned char buf[10];
-	unsigned long gran;
+	resource_t base, end;
 
 	/* Make certain the resource has actually been set */
 	if (!(resource->flags & IORESOURCE_ASSIGNED)) {
@@ -256,82 +361,77 @@
 		return;
 	}
 
+	/* If the resources is substractive don't worry about it */
+	if (resource->flags & IORESOURCE_SUBTRACTIVE) {
+		return;
+	}
+
 	/* Only handle PCI memory and IO resources for now */
 	if (!(resource->flags & (IORESOURCE_MEM |IORESOURCE_IO)))
 		return;
 
-	if (resource->flags & IORESOURCE_MEM) {
-		dev->command |= PCI_COMMAND_MEMORY;
-	}
-	if (resource->flags & IORESOURCE_IO) {
-		dev->command |= PCI_COMMAND_IO;
-	}
-	if (resource->flags & IORESOURCE_PCI_BRIDGE) {
-		dev->command |= PCI_COMMAND_MASTER;
+	/* Enable the resources in the command register */
+	if (resource->size) {
+		if (resource->flags & IORESOURCE_MEM) {
+			dev->command |= PCI_COMMAND_MEMORY;
+		}
+		if (resource->flags & IORESOURCE_IO) {
+			dev->command |= PCI_COMMAND_IO;
+		}
+		if (resource->flags & IORESOURCE_PCI_BRIDGE) {
+			dev->command |= PCI_COMMAND_MASTER;
+		}
 	}
 	/* Get the base address */
 	base = resource->base;
-	/* Get the resource granularity */
-	gran = 1UL << resource->gran;
 
-	/* For a non bridge resource granularity and alignment are the same.
-	 * For a bridge resource align is the largest needed alignment below
-	 * the bridge.  While the granularity is simply how many low bits of the
-	 * address cannot be set.
-	 */
-	
-	/* Get the limit (rounded up) */
-	limit = base + align(resource->size, gran) - 1UL;
+	/* Get the end */
+	end = resource_end(resource);
 	
 	/* Now store the resource */
 	resource->flags |= IORESOURCE_STORED;
 	if (!(resource->flags & IORESOURCE_PCI_BRIDGE)) {
+		unsigned long base_lo, base_hi;
 		/*
 		 * some chipsets allow us to set/clear the IO bit. 
 		 * (e.g. VIA 82c686a.) So set it to be safe)
 		 */
-		limit = base + resource->size -1;
+		base_lo = base & 0xffffffff;
+		base_hi = (base >> 32) & 0xffffffff;
 		if (resource->flags & IORESOURCE_IO) {
-			base |= PCI_BASE_ADDRESS_SPACE_IO;
+			base_lo |= PCI_BASE_ADDRESS_SPACE_IO;
 		}
-		pci_write_config32(dev, resource->index, base & 0xffffffff);
+		pci_write_config32(dev, resource->index, base_lo);
 		if (resource->flags & IORESOURCE_PCI64) {
-			/* FIXME handle real 64bit base addresses */
-			pci_write_config32(dev, resource->index + 4, 0);
+			pci_write_config32(dev, resource->index + 4, base_hi);
 		}
 	}
 	else if (resource->index == PCI_IO_BASE) {
-		/* set the IO ranges
-		 * WARNING: we don't really do 32-bit addressing for IO yet! 
-		 */
+		/* set the IO ranges */
 		compute_allocate_resource(&dev->link[0], resource, 
 			IORESOURCE_IO, IORESOURCE_IO);
-		pci_write_config8(dev, PCI_IO_BASE,  base >> 8);
-		pci_write_config8(dev, PCI_IO_LIMIT, limit >> 8);
-		pci_write_config16(dev, PCI_IO_BASE_UPPER16, 0);
-		pci_write_config16(dev, PCI_IO_LIMIT_UPPER16, 0);
+		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
-		 */
+		/* 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, limit >> 16);
+		pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16);
 	}
 	else if (resource->index == PCI_PREF_MEMORY_BASE) {
-		/* set the prefetchable memory range
-		 * WARNING: we don't really do 64-bit addressing 
-		 * for prefetchable memory yet!
-		 */
+		/* 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_config16(dev, PCI_PREF_MEMORY_LIMIT, limit >> 16);
-		pci_write_config32(dev, PCI_PREF_BASE_UPPER32, 0);
-		pci_write_config32(dev, PCI_PREF_LIMIT_UPPER32, 0);
+		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);
+		pci_write_config32(dev, PCI_PREF_LIMIT_UPPER32, end >> 32);
 	}
 	else {
 		/* Don't let me think I stored the resource */
@@ -339,18 +439,7 @@
 		printk_err("ERROR: invalid resource->index %x\n",
 			resource->index);
 	}
-	buf[0] = '\0';
-	if (resource->flags & IORESOURCE_PCI_BRIDGE) {
-		sprintf(buf, "bus %d ", dev->link[0].secondary);
-	}
-	printk_debug(
-		"%s %02x <- [0x%08lx - 0x%08lx] %s%s\n",
-		dev_path(dev),
-		resource->index, 
-		(unsigned long)(resource->base), limit,
-		buf,
-		(resource->flags & IORESOURCE_IO)? "io":
-		(resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem");
+	report_resource_stored(dev, resource, "");
 	return;
 }
 
@@ -392,7 +481,20 @@
 
 void pci_dev_enable_resources(struct device *dev)
 {
+	struct pci_operations *ops;
 	uint16_t command;
+
+	/* Set the subsystem vendor and device id for mainboard devices */
+	ops = ops_pci(dev);
+	if (dev->chip && ops && ops->set_subsystem) {
+		printk_debug("%s subsystem <- %02x/%02x\n",
+			dev_path(dev), 
+			MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID,
+			MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID);
+		ops->set_subsystem(dev, 
+			MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID,
+			MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID);
+	}
 	command = pci_read_config16(dev, PCI_COMMAND);
 	command |= dev->command;
 	command |= (PCI_COMMAND_PARITY + PCI_COMMAND_SERR); /* error check */
@@ -414,22 +516,39 @@
 	pci_dev_enable_resources(dev);
 }
 
+static void pci_dev_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+	pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, 
+		((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
 /** Default device operation for PCI devices */
+static struct pci_operations pci_ops_pci_dev = {
+	.set_subsystem = pci_dev_set_subsystem,
+};
+
 struct device_operations default_pci_ops_dev = {
 	.read_resources   = pci_dev_read_resources,
 	.set_resources    = pci_dev_set_resources,
 	.enable_resources = pci_dev_enable_resources,
 	.init		  = 0,
 	.scan_bus	  = 0,
+	.enable           = 0,
+	.ops_pci          = &pci_ops_pci_dev,
 };
 
 /** Default device operations for PCI bridges */
+static struct pci_operations pci_ops_pci_bus = {
+	.set_subsystem = 0,
+};
 struct device_operations default_pci_ops_bus = {
 	.read_resources   = pci_bus_read_resources,
 	.set_resources    = pci_dev_set_resources,
 	.enable_resources = pci_bus_enable_resources,
 	.init		  = 0,
 	.scan_bus	  = pci_scan_bridge,
+	.enable           = 0,
+	.ops_pci          = &pci_ops_pci_bus,
 };
 
 /**
@@ -443,7 +562,6 @@
 static void set_pci_ops(struct device *dev)
 {
 	struct pci_driver *driver;
-
 	if (dev->ops) {
 		return;
 	}
@@ -464,17 +582,6 @@
 		}
 	}
 
-#if 0
-	extern struct pci_driver generic_vga_driver;
-	/* TODO: Install generic VGA driver for VGA devices, base on the
-	 * class ID */
-	if ((dev->class >> 8)  == PCI_CLASS_DISPLAY_VGA) {
-		printk_debug("setting up generic VGA driver\n");
-		dev->ops = generic_vga_driver.ops;
-		return;
-	}
-#endif
-
 	/* If I don't have a specific driver use the default operations */
 	switch(dev->hdr_type & 0x7f) {	/* header type */
 	case PCI_HEADER_TYPE_NORMAL:	/* standard header */
@@ -501,7 +608,7 @@
 }
 
 /**
- * @brief Find a specific device structure on a list of device structures
+ * @brief See if we have already allocated a device structure for a given devfn.
  *
  * Given a linked list of PCI device structures and a devfn number, find the
  * device structure correspond to the devfn, if present.
@@ -515,9 +622,6 @@
 static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn)
 {
 	struct device *dev;
-
-	 printk_spew("%s, looking for devfn: %02x.%01x\n", __FUNCTION__,
-		 devfn >> 3, devfn & 7);
 	dev = 0;
 	for(; *list; list = &(*list)->sibling) {
 		if ((*list)->path.type != DEVICE_PATH_PCI) {
@@ -538,7 +642,6 @@
 	 * we removed all of the parents children, and now we are interleaving
 	 * static and dynamic devices in order on the bus.
 	 */
-	printk_spew("%s, found dev %08x\n", __FUNCTION__, dev);
 	if (dev) {
 		device_t child;
 		/* Find the last child of our parent */
@@ -595,14 +698,11 @@
 		uint32_t id, class;
 		uint8_t hdr_type;
 
-		/* device structures for PCI devices associated with static
-		 * devices are already created during the static device
-		 * enumeration, find out if it is the case for this devfn */
+		/* First thing setup the device structure */
 		dev = pci_scan_get_dev(&old_devices, devfn);
-
+	
+		/* Detect if a device is present */
 		if (!dev) {
-			/* it's not associated with a static device, detect if
-			 * this device is present */
 			struct device dummy;
 			dummy.bus              = bus;
 			dummy.path.type        = DEVICE_PATH_PCI;
@@ -628,10 +728,11 @@
 			dev = alloc_dev(bus, &dummy.path);
 		}
 		else {
-			/* If at all possible enable the device, if desired
-			 * we will disable the device later, once we have
-			 * found it's device specific operations.
-			 *
+			/* Enable/disable the device.  Once we have
+			 * found the device specific operations this
+			 * operations we will disable the device with
+			 * those as well.
+			 * 
 			 * This is geared toward devices that have subfunctions
 			 * that do not show up by default.
 			 * 
@@ -642,13 +743,25 @@
 			if (	dev->chip && dev->chip->control && 
 				dev->chip->control->enable_dev) 
 			{
-				int enabled  = dev->enabled;
-				dev->enabled = 1;
 				dev->chip->control->enable_dev(dev);
-				dev->enabled = enabled;
 			}
 			/* Now read the vendor and device id */
 			id = pci_read_config32(dev, PCI_VENDOR_ID);
+			
+			/* If the device does not have a pci id disable it.
+			 * Possibly this is because we have already disabled
+			 * the device.  But this also handles optional devices
+			 * that may not always show up.
+			 */
+			if (id == 0xffffffff || id == 0x00000000 ||
+				id == 0x0000ffff || id == 0xffff0000) 
+			{
+				if (dev->enabled) {
+					printk_info("Disabling static device: %s\n",
+						dev_path(dev));
+					dev->enabled = 0;
+				}
+			}
 		}
 		/* Read the rest of the pci configuration information */
 		hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
@@ -661,6 +774,13 @@
 		/* class code, the upper 3 bytes of PCI_CLASS_REVISION */
 		dev->class = class >> 8;
 
+		/* Architectural/System devices always need to
+		 * be bus masters.
+		 */
+		if ((dev->class >> 16) == PCI_BASE_CLASS_SYSTEM) {
+			dev->command |= PCI_COMMAND_MASTER;
+		}
+
 		/* Look at the vendor and device id, or at least the 
 		 * header type and class and figure out which set of
 		 * configuration methods to use.  Unless we already
@@ -678,16 +798,11 @@
 		if (dev->ops && dev->ops->enable) {
 			dev->ops->enable(dev);
 		}
-		else if (dev->chip && dev->chip->control && 
-			dev->chip->control->enable_dev) 
-		{
-			dev->chip->control->enable_dev(dev);
-		}
 
 		printk_debug("%s [%04x/%04x] %s\n", 
-			     dev_path(dev),
-			     dev->vendor, dev->device, 
-			     dev->enabled?"enabled": "disabled");
+			dev_path(dev),
+			dev->vendor, dev->device, 
+			dev->enabled?"enabled": "disabled");
 
 		if (PCI_FUNC(devfn) == 0x00 && (hdr_type & 0x80) != 0x80) {
 			/* if this is not a multi function device, 
@@ -800,18 +915,10 @@
 {
 	unsigned short intBits = inb(0x4d0) | (((unsigned) inb(0x4d1)) << 8);
 
-<<<<<<< pci_device.c
 	printk_spew("%s: current ints are 0x%x\n", __func__, intBits);
-=======
-	printk_debug("%s: current ints are 0x%x\n", __FUNCTION__, intBits);
->>>>>>> 1.25
 	intBits |= (1 << intNum);
 
-<<<<<<< pci_device.c
 	printk_spew("%s: try to set ints 0x%x\n", __func__, intBits);
-=======
-	printk_debug("%s: try to set ints 0x%x\n", __FUNCTION__, intBits);
->>>>>>> 1.25
 
 	// Write new values
 	outb((unsigned char) intBits, 0x4d0);
diff --git a/src/devices/pnp_device.c b/src/devices/pnp_device.c
index 4bdb67e..9ecfe63 100644
--- a/src/devices/pnp_device.c
+++ b/src/devices/pnp_device.c
@@ -69,7 +69,7 @@
 {
 	if (!(resource->flags & IORESOURCE_ASSIGNED)) {
 		printk_err("ERROR: %s %02x not allocated\n",
-			   dev_path(dev), resource->index);
+			dev_path(dev), resource->index);
 		return;
 	}
 
@@ -90,16 +90,7 @@
 	}
 	resource->flags |= IORESOURCE_STORED;
 
-	printk_debug(
-		"%s %02x <- [0x%08lx - 0x%08lx] %s\n",
-		dev_path(dev),
-		resource->index,
-		resource->base,  resource->base + resource->size - 1,
-		(resource->flags & IORESOURCE_IO)? "io":
-		(resource->flags & IORESOURCE_DRQ)? "drq":
-		(resource->flags & IORESOURCE_IRQ)? "irq":
-		(resource->flags & IORESOURCE_MEM)? "mem":
-		"???");
+	report_resource_stored(dev, resource, "");
 }
 
 void pnp_set_resources(device_t dev)
@@ -143,7 +134,7 @@
 	struct resource *resource;
 	uint32_t size;
 
-	resource = get_resource(dev, index);
+	resource = new_resource(dev, index);
 	
 	/* Initilize the resource */
 	resource->limit = 0xffff;
@@ -173,22 +164,22 @@
 		pnp_get_ioresource(dev, PNP_IDX_IO3, &info->io3);
 	}
 	if (info->flags & PNP_IRQ0) {
-		resource = get_resource(dev, PNP_IDX_IRQ0);
+		resource = new_resource(dev, PNP_IDX_IRQ0);
 		resource->size = 1;
 		resource->flags |= IORESOURCE_IRQ;
 	}
 	if (info->flags & PNP_IRQ1) {
-		resource = get_resource(dev, PNP_IDX_IRQ1);
+		resource = new_resource(dev, PNP_IDX_IRQ1);
 		resource->size = 1;
 		resource->flags |= IORESOURCE_IRQ;
 	}
 	if (info->flags & PNP_DRQ0) {
-		resource = get_resource(dev, PNP_IDX_DRQ0);
+		resource = new_resource(dev, PNP_IDX_DRQ0);
 		resource->size = 1;
 		resource->flags |= IORESOURCE_DRQ;
 	}
 	if (info->flags & PNP_DRQ1) {
-		resource = get_resource(dev, PNP_IDX_DRQ1);
+		resource = new_resource(dev, PNP_IDX_DRQ1);
 		resource->size = 1;
 		resource->flags |= IORESOURCE_DRQ;
 	}	
diff --git a/src/devices/root_device.c b/src/devices/root_device.c
index 04c9677..1642e8b 100644
--- a/src/devices/root_device.c
+++ b/src/devices/root_device.c
@@ -9,34 +9,29 @@
  */
 void root_dev_read_resources(device_t root)
 {
-	int res = 0;
+	struct resource *resource;
 
 	/* Initialize the system wide io space constraints */
-	root->resource[res].base  = 0x400;
-	root->resource[res].size  = 0;
-	root->resource[res].align = 0;
-	root->resource[res].gran  = 0;
-	root->resource[res].limit = 0xffffUL;
-	root->resource[res].flags = IORESOURCE_IO;
-	root->resource[res].index = 0;
-	compute_allocate_resource(&root->link[0], &root->resource[res], 
+	resource = new_resource(root, 0);
+	resource->base  = 0x400;
+	resource->size  = 0;
+	resource->align = 0;
+	resource->gran  = 0;
+	resource->limit = 0xffffUL;
+	resource->flags = IORESOURCE_IO;
+	compute_allocate_resource(&root->link[0], resource, 
 		IORESOURCE_IO, IORESOURCE_IO);
-	res++;
 
 	/* Initialize the system wide memory resources constraints */
-	root->resource[res].base  = 0;
-	root->resource[res].size  = 0;
-	root->resource[res].align = 0;
-	root->resource[res].gran  = 0;
-	root->resource[res].limit = 0xffffffffUL;
-	root->resource[res].flags = IORESOURCE_MEM;
-	root->resource[res].index = 1;
-	compute_allocate_resource(&root->link[0], &root->resource[res], 
+	resource = new_resource(root, 1);
+	resource->base  = 0;
+	resource->size  = 0;
+	resource->align = 0;
+	resource->gran  = 0;
+	resource->limit = 0xffffffffUL;
+	resource->flags = IORESOURCE_MEM;
+	compute_allocate_resource(&root->link[0], resource,
 		IORESOURCE_MEM, IORESOURCE_MEM);
-	res++;
-
-	root->resources = res;
-	printk_spew("%s DONE\n", __func__);
 }
 
 /**
@@ -124,8 +119,13 @@
 	}
 }
 
+void root_dev_enable_resources(device_t dev)
+{
+	enable_childrens_resources(dev);
+}
+
 /**
- * @brief Scan root bus for generic PCI systems
+ * @brief Scan root bus for generic systems
  *
  * @param root The root device structure
  * @param max The current bus number scanned so fat, usually 0x00
@@ -135,9 +135,14 @@
  * generic PCI bus system is at Bus 0, Dev 0, Fun 0 so we scan the whole PCI
  * buses from there. 
  */
-unsigned int root_dev_scan_pci_bus(device_t root, unsigned int max)
+unsigned int root_dev_scan_bus(device_t root, unsigned int max)
 {
-	return pci_scan_bus(&root->link[0], 0, 0xff, max);
+	return scan_static_bus(root, max);
+}
+
+void root_dev_init(device_t root)
+{
+	initialize_cpus(root);
 }
 
 /**
@@ -153,9 +158,9 @@
 struct device_operations default_dev_ops_root = {
 	.read_resources   = root_dev_read_resources,
 	.set_resources    = root_dev_set_resources,
-	.enable_resources = enable_childrens_resources,
-	.init             = 0,
-	.scan_bus         = root_dev_scan_pci_bus,
+	.enable_resources = root_dev_enable_resources,
+	.init             = root_dev_init,
+	.scan_bus         = root_dev_scan_bus,
 };
 
 /**
@@ -169,11 +174,4 @@
 	.bus = &dev_root.link[0],
 	.path = { .type = DEVICE_PATH_ROOT },
 	.enabled = 1,
-	.links = 1,
-	.link = {
-		[0] = {
-			.dev = &dev_root,
-			.link = 0,
-		},
-	},
 };