All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.