+/**
+ * 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 return the resource type of a resource
+ * @param resource the resource type to decode.
+ */
+const char *resource_type(struct resource *resource)
+{
+ static char buffer[RESOURCE_TYPE_MAX];
+ sprintf(buffer, "%s%s%s%s",
+ ((resource->flags & IORESOURCE_READONLY)? "ro": ""),
+ ((resource->flags & IORESOURCE_PREFETCH)? "pref":""),
+ ((resource->flags == 0)? "unused":
+ (resource->flags & IORESOURCE_IO)? "io":
+ (resource->flags & IORESOURCE_DRQ)? "drq":
+ (resource->flags & IORESOURCE_IRQ)? "irq":
+ (resource->flags & IORESOURCE_MEM)? "mem":"??????"),
+ ((resource->flags & IORESOURCE_PCI64)?"64":""));
+ return buffer;
+}
+
+/**
+ * @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) {
+ char buf[10];
+ unsigned long long base, end;
+ base = resource->base;
+ end = resource_end(resource);
+ buf[0] = '\0';
+ if (resource->flags & IORESOURCE_PCI_BRIDGE) {
+#if PCI_BUS_SEGN_BITS
+ sprintf(buf, "bus %04x:%02x ", dev->bus->secondary>>8, dev->link[0].secondary & 0xff);
+#else
+ sprintf(buf, "bus %02x ", dev->link[0].secondary);
+#endif
+ }
+ printk_debug(
+ "%s %02lx <- [0x%010Lx - 0x%010Lx] size 0x%08Lx gran 0x%02x %s%s%s\n",
+ dev_path(dev),
+ resource->index,
+ base, end,
+ resource->size, resource->gran,
+ buf,
+ resource_type(resource),
+ comment);
+ }
+}
+
+void search_bus_resources(struct bus *bus,
+ unsigned long type_mask, unsigned long type,
+ resource_search_t search, void *gp)
+{
+ struct device *curdev;
+ for(curdev = bus->children; curdev; curdev = curdev->sibling) {
+ int i;
+ /* Ignore disabled devices */
+ if (!curdev->have_resources) continue;
+ for(i = 0; i < curdev->resources; i++) {
+ struct resource *resource = &curdev->resource[i];
+ /* If it isn't the right kind of resource ignore it */
+ if ((resource->flags & type_mask) != type) {
+ continue;
+ }
+ /* If it is a subtractive resource recurse */
+ if (resource->flags & IORESOURCE_SUBTRACTIVE) {
+ struct bus * subbus;
+ subbus = &curdev->link[IOINDEX_SUBTRACTIVE_LINK(resource->index)];
+ search_bus_resources(subbus, type_mask, type, search, gp);
+ continue;
+ }
+ search(gp, curdev, resource);
+ }
+ }
+}
+
+void search_global_resources(
+ unsigned long type_mask, unsigned long type,
+ resource_search_t search, void *gp)
+{
+ struct device *curdev;
+ for(curdev = all_devices; curdev; curdev = curdev->next) {
+ int i;
+ /* Ignore disabled devices */
+ if (!curdev->have_resources) continue;
+ for(i = 0; i < curdev->resources; i++) {
+ struct resource *resource = &curdev->resource[i];
+ /* If it isn't the right kind of resource ignore it */
+ if ((resource->flags & type_mask) != type) {
+ continue;
+ }
+ /* If it is a subtractive resource ignore it */
+ if (resource->flags & IORESOURCE_SUBTRACTIVE) {
+ continue;
+ }
+ search(gp, curdev, resource);
+ }
+ }
+}
+
+void dev_set_enabled(device_t dev, int enable)
+{
+ if (dev->enabled == enable) {
+ return;
+ }
+ dev->enabled = enable;
+ if (dev->ops && dev->ops->enable) {
+ dev->ops->enable(dev);
+ }
+ else if (dev->chip_ops && dev->chip_ops->enable_dev) {
+ dev->chip_ops->enable_dev(dev);
+ }
+}
+
+void disable_children(struct bus *bus)
+{
+ device_t child;
+ for(child = bus->children; child; child = child->sibling) {
+ int link;
+ for(link = 0; link < child->links; link++) {
+ disable_children(&child->link[link]);
+ }
+ dev_set_enabled(child, 0);
+ }
+}