]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - arch/ia64/pci/pci.c
Pull pnpacpi into acpica branch
[linux-2.6.git] / arch / ia64 / pci / pci.c
index 017cfc3f47890ba85dc2dcba952fafaa6e6c7fbb..337abd50c6ea34eb297d3bac39df4b70af3e7eef 100644 (file)
@@ -95,7 +95,7 @@ pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn,
 }
 
 static struct pci_raw_ops pci_sal_ops = {
-       .read =         pci_sal_read,
+       .read =         pci_sal_read,
        .write =        pci_sal_write
 };
 
@@ -137,35 +137,98 @@ alloc_pci_controller (int seg)
        return controller;
 }
 
-static u64 __devinit
-add_io_space (struct acpi_resource_address64 *addr)
+struct pci_root_info {
+       struct pci_controller *controller;
+       char *name;
+};
+
+static unsigned int
+new_space (u64 phys_base, int sparse)
 {
-       u64 offset;
-       int sparse = 0;
+       u64 mmio_base;
        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;
+       if (phys_base == 0)
+               return 0;       /* legacy I/O port space */
 
-       offset = (u64) ioremap(addr->address_translation_offset, 0);
+       mmio_base = (u64) ioremap(phys_base, 0);
        for (i = 0; i < num_io_spaces; i++)
-               if (io_space[i].mmio_base == offset &&
+               if (io_space[i].mmio_base == mmio_base &&
                    io_space[i].sparse == sparse)
-                       return IO_SPACE_BASE(i);
+                       return i;
 
        if (num_io_spaces == MAX_IO_SPACES) {
-               printk("Too many IO port spaces\n");
+               printk(KERN_ERR "PCI: Too many IO port spaces "
+                       "(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES);
                return ~0;
        }
 
        i = num_io_spaces++;
-       io_space[i].mmio_base = offset;
+       io_space[i].mmio_base = mmio_base;
        io_space[i].sparse = sparse;
 
-       return IO_SPACE_BASE(i);
+       return i;
+}
+
+static u64 __devinit
+add_io_space (struct pci_root_info *info, struct acpi_resource_address64 *addr)
+{
+       struct resource *resource;
+       char *name;
+       u64 base, min, max, base_port;
+       unsigned int sparse = 0, space_nr, len;
+
+       resource = kzalloc(sizeof(*resource), GFP_KERNEL);
+       if (!resource) {
+               printk(KERN_ERR "PCI: No memory for %s I/O port space\n",
+                       info->name);
+               goto out;
+       }
+
+       len = strlen(info->name) + 32;
+       name = kzalloc(len, GFP_KERNEL);
+       if (!name) {
+               printk(KERN_ERR "PCI: No memory for %s I/O port space name\n",
+                       info->name);
+               goto free_resource;
+       }
+
+       min = addr->minimum;
+       max = min + addr->address_length - 1;
+       if (addr->info.io.translation_type == ACPI_SPARSE_TRANSLATION)
+               sparse = 1;
+
+       space_nr = new_space(addr->translation_offset, sparse);
+       if (space_nr == ~0)
+               goto free_name;
+
+       base = __pa(io_space[space_nr].mmio_base);
+       base_port = IO_SPACE_BASE(space_nr);
+       snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name,
+               base_port + min, base_port + max);
+
+       /*
+        * The SDM guarantees the legacy 0-64K space is sparse, but if the
+        * mapping is done by the processor (not the bridge), ACPI may not
+        * mark it as sparse.
+        */
+       if (space_nr == 0)
+               sparse = 1;
+
+       resource->name  = name;
+       resource->flags = IORESOURCE_MEM;
+       resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
+       resource->end   = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max);
+       insert_resource(&iomem_resource, resource);
+
+       return base_port;
+
+free_name:
+       kfree(name);
+free_resource:
+       kfree(resource);
+out:
+       return ~0;
 }
 
 static acpi_status __devinit resource_to_window(struct acpi_resource *resource,
@@ -205,11 +268,6 @@ count_window (struct acpi_resource *resource, void *data)
        return AE_OK;
 }
 
-struct pci_root_info {
-       struct pci_controller *controller;
-       char *name;
-};
-
 static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
 {
        struct pci_root_info *info = data;
@@ -227,11 +285,11 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
        if (addr.resource_type == ACPI_MEMORY_RANGE) {
                flags = IORESOURCE_MEM;
                root = &iomem_resource;
-               offset = addr.address_translation_offset;
+               offset = addr.translation_offset;
        } else if (addr.resource_type == ACPI_IO_RANGE) {
                flags = IORESOURCE_IO;
                root = &ioport_resource;
-               offset = add_io_space(&addr);
+               offset = add_io_space(info, &addr);
                if (offset == ~0)
                        return AE_OK;
        } else
@@ -240,8 +298,8 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
        window = &info->controller->window[info->controller->windows++];
        window->resource.name = info->name;
        window->resource.flags = flags;
-       window->resource.start = addr.min_address_range + offset;
-       window->resource.end = addr.max_address_range + offset;
+       window->resource.start = addr.minimum + offset;
+       window->resource.end = window->resource.start + addr.address_length - 1;
        window->resource.child = NULL;
        window->offset = offset;
 
@@ -642,7 +700,7 @@ int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
  */
 int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size)
 {
-       int ret = 0;
+       int ret = size;
 
        switch (size) {
        case 1:
@@ -739,7 +797,7 @@ int pci_vector_resources(int last, int nr_released)
 {
        int count = nr_released;
 
-       count += (IA64_LAST_DEVICE_VECTOR - last);
+       count += (IA64_LAST_DEVICE_VECTOR - last);
 
        return count;
 }