* [Linux-ia64] [PATCH] 2/4 multi-ioport space support for 2.5
@ 2003-04-24 22:25 Bjorn Helgaas
0 siblings, 0 replies; only message in thread
From: Bjorn Helgaas @ 2003-04-24 22:25 UTC (permalink / raw)
To: linux-ia64
diff -u -ur linux-2.5.67-ia64-030416-io1/arch/ia64/pci/pci.c linux-2.5.67-ia64-030416-io2/arch/ia64/pci/pci.c
--- linux-2.5.67-ia64-030416-io1/arch/ia64/pci/pci.c 2003-04-24 10:10:58.000000000 -0600
+++ linux-2.5.67-ia64-030416-io2/arch/ia64/pci/pci.c 2003-04-24 12:36:53.000000000 -0600
@@ -116,24 +116,31 @@
subsys_initcall(pci_acpi_init);
-static void __init
-pcibios_fixup_resource(struct resource *res, u64 offset)
-{
- res->start += offset;
- res->end += offset;
-}
-
void __init
-pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
+pcibios_fixup_device_resources (struct pci_dev *dev, struct pci_bus *bus)
{
- int i;
+ struct pci_controller *controller = PCI_CONTROLLER(dev);
+ struct pci_window *window;
+ int i, j;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
if (!dev->resource[i].start)
continue;
- if (dev->resource[i].flags & IORESOURCE_MEM)
- pcibios_fixup_resource(&dev->resource[i],
- PCI_CONTROLLER(dev)->mem_offset);
+
+#define contains(win, res) ((res)->start >= (win)->start && \
+ (res)->end <= (win)->end)
+
+ for (j = 0; j < controller->windows; j++) {
+ window = &controller->window[j];
+ if (((dev->resource[i].flags & IORESOURCE_MEM &&
+ window->resource.flags & IORESOURCE_MEM) ||
+ (dev->resource[i].flags & IORESOURCE_IO &&
+ window->resource.flags & IORESOURCE_IO)) &&
+ contains(&window->resource, &dev->resource[i])) {
+ dev->resource[i].start += window->offset;
+ dev->resource[i].end += window->offset;
+ }
+ }
}
}
@@ -184,23 +191,127 @@
return b;
}
+static u64
+add_io_space (struct acpi_resource_address64 *addr)
+{
+ u64 offset;
+ int sparse = 0;
+ int i;
+
+ if (addr->address_translation_offset = 0)
+ return IO_SPACE_BASE(0); /* part of legacy IO space */
+
+ if (addr->attribute.io.translation_attribute = ACPI_SPARSE_TRANSLATION)
+ sparse = 1;
+
+ offset = (u64) ioremap(addr->address_translation_offset, 0);
+ for (i = 0; i < num_io_spaces; i++)
+ if (io_space[i].mmio_base = offset &&
+ io_space[i].sparse = sparse)
+ return IO_SPACE_BASE(i);
+
+ if (num_io_spaces = MAX_IO_SPACES) {
+ printk("Too many IO port spaces\n");
+ return ~0;
+ }
+
+ i = num_io_spaces++;
+ io_space[i].mmio_base = offset;
+ io_space[i].sparse = sparse;
+
+ return IO_SPACE_BASE(i);
+}
+
+static acpi_status
+count_window (struct acpi_resource *resource, void *data)
+{
+ unsigned int *windows = (unsigned int *) data;
+ struct acpi_resource_address64 addr;
+ acpi_status status;
+
+ status = acpi_resource_to_address64(resource, &addr);
+ if (ACPI_SUCCESS(status))
+ if (addr.resource_type = ACPI_MEMORY_RANGE ||
+ addr.resource_type = ACPI_IO_RANGE)
+ (*windows)++;
+
+ return AE_OK;
+}
+
+struct pci_root_info {
+ struct pci_controller *controller;
+ char *name;
+};
+
+static acpi_status
+add_window (struct acpi_resource *res, void *data)
+{
+ struct pci_root_info *info = (struct pci_root_info *) data;
+ struct pci_window *window;
+ struct acpi_resource_address64 addr;
+ acpi_status status;
+ unsigned long flags, offset = 0;
+
+ status = acpi_resource_to_address64(res, &addr);
+ if (ACPI_SUCCESS(status)) {
+ if (addr.resource_type = ACPI_MEMORY_RANGE) {
+ flags = IORESOURCE_MEM;
+ offset = addr.address_translation_offset;
+ } else if (addr.resource_type = ACPI_IO_RANGE) {
+ flags = IORESOURCE_IO;
+ offset = add_io_space(&addr);
+ if (offset = ~0)
+ return AE_OK;
+ } else
+ return AE_OK;
+
+ window = &info->controller->window[info->controller->windows++];
+ window->resource.flags |= flags;
+ window->resource.start = addr.min_address_range;
+ window->resource.end = addr.max_address_range;
+ window->offset = offset;
+ }
+
+ return AE_OK;
+}
+
struct pci_bus *
-pcibios_scan_root(void *handle, int seg, int bus)
+pcibios_scan_root (void *handle, int seg, int bus)
{
+ struct pci_root_info info;
struct pci_controller *controller;
- u64 base, size, offset;
+ unsigned int windows = 0;
+ char *name;
printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus);
controller = alloc_pci_controller(seg);
if (!controller)
- return NULL;
+ goto out1;
controller->acpi_handle = handle;
- acpi_get_addr_space(handle, ACPI_MEMORY_RANGE, &base, &size, &offset);
- controller->mem_offset = offset;
+ acpi_walk_resources(handle, METHOD_NAME__CRS, count_window, &windows);
+ controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL);
+ if (!controller->window)
+ goto out2;
+
+ name = kmalloc(16, GFP_KERNEL);
+ if (!name)
+ goto out3;
+
+ sprintf(name, "PCI Bus %02x:%02x", seg, bus);
+ info.controller = controller;
+ info.name = name;
+ acpi_walk_resources(handle, METHOD_NAME__CRS, add_window, &info);
return scan_root_bus(bus, pci_root_ops, controller);
+
+out3:
+ kfree(controller->window);
+out2:
+ kfree(controller);
+out1:
+ return NULL;
}
/*
diff -u -ur linux-2.5.67-ia64-030416-io1/include/asm-ia64/pci.h linux-2.5.67-ia64-030416-io2/include/asm-ia64/pci.h
--- linux-2.5.67-ia64-030416-io1/include/asm-ia64/pci.h 2003-04-24 10:10:58.000000000 -0600
+++ linux-2.5.67-ia64-030416-io2/include/asm-ia64/pci.h 2003-04-24 11:17:10.000000000 -0600
@@ -97,12 +97,18 @@
extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
+struct pci_window {
+ struct resource resource;
+ u64 offset;
+};
+
struct pci_controller {
void *acpi_handle;
void *iommu;
int segment;
- u64 mem_offset;
+ unsigned int windows;
+ struct pci_window *window;
};
#define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2003-04-24 22:25 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-04-24 22:25 [Linux-ia64] [PATCH] 2/4 multi-ioport space support for 2.5 Bjorn Helgaas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox