diff -u -r 30_sci/arch/ia64/kernel/pci.c 40_pcibios_segment/arch/ia64/kernel/pci.c --- 30_sci/arch/ia64/kernel/pci.c Mon Jul 22 07:25:09 2002 +++ 40_pcibios_segment/arch/ia64/kernel/pci.c Mon Jul 22 09:55:40 2002 @@ -53,11 +53,12 @@ /* * Low-level SAL-based PCI configuration access functions. Note that SAL * calls are already serialized (via sal_lock), so we don't need another - * synchronization mechanism here. Not using segment number (yet). + * synchronization mechanism here. */ -#define PCI_SAL_ADDRESS(bus, dev, fn, reg) \ - ((u64)(bus << 16) | (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg)) +#define PCI_SAL_ADDRESS(seg, bus, dev, fn, reg) \ + ((u64)(seg << 24) | (u64)(bus << 16) | \ + (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg)) static int pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) @@ -65,10 +66,10 @@ int result = 0; u64 data = 0; - if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if (!value || (seg > 255) || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) return -EINVAL; - result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, &data); + result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, dev, fn, reg), len, &data); *value = (u32) data; @@ -78,10 +79,10 @@ static int pci_sal_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) { - if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if ((seg > 255) || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) return -EINVAL; - return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, value); + return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(seg, bus, dev, fn, reg), len, value); } @@ -94,7 +95,7 @@ if (!value) return -EINVAL; - result = pci_sal_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + result = pci_sal_read(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 1, &data); *value = (u8) data; @@ -111,7 +112,7 @@ if (!value) return -EINVAL; - result = pci_sal_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + result = pci_sal_read(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 2, &data); *value = (u16) data; @@ -125,28 +126,28 @@ if (!value) return -EINVAL; - return pci_sal_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + return pci_sal_read(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 4, value); } static int pci_sal_write_config_byte (struct pci_dev *dev, int where, u8 value) { - return pci_sal_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + return pci_sal_write(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 1, value); } static int pci_sal_write_config_word (struct pci_dev *dev, int where, u16 value) { - return pci_sal_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + return pci_sal_write(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 2, value); } static int pci_sal_write_config_dword (struct pci_dev *dev, int where, u32 value) { - return pci_sal_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + return pci_sal_write(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 4, value); } @@ -164,24 +165,64 @@ * Initialization. Uses the SAL interface */ -struct pci_bus * -pcibios_scan_root(int seg, int bus) +static struct pci_controller * +alloc_pci_controller(int seg) +{ + struct pci_controller *controller; + + controller = kmalloc(sizeof(*controller), GFP_KERNEL); + if (!controller) + return NULL; + + memset(controller, 0, sizeof(*controller)); + controller->segment = seg; + return controller; +} + +static struct pci_bus * +scan_root_bus(int bus, struct pci_ops *ops, void *sysdata) { - struct list_head *list = NULL; - struct pci_bus *pci_bus = NULL; + struct pci_bus *b; + + /* + * We know this is a new root bus we haven't seen before, so + * scan it, even if we've seen the same bus number in a different + * segment. + */ + b = kmalloc(sizeof(*b), GFP_KERNEL); + if (!b) + return NULL; + + memset(b, 0, sizeof(*b)); + INIT_LIST_HEAD(&b->children); + INIT_LIST_HEAD(&b->devices); - list_for_each(list, &pci_root_buses) { - pci_bus = pci_bus_b(list); - if (pci_bus->number == bus) { - /* Already scanned */ - printk("PCI: Bus (%02x:%02x) already probed\n", seg, bus); - return pci_bus; - } - } + list_add_tail(&b->node, &pci_root_buses); + + b->number = b->secondary = bus; + b->resource[0] = &ioport_resource; + b->resource[1] = &iomem_resource; + + b->sysdata = sysdata; + b->ops = ops; + b->subordinate = pci_do_scan_bus(b); + + return b; +} + +struct pci_bus * +pcibios_scan_root(void *handle, int seg, int bus) +{ + struct pci_controller *controller; printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus); - return pci_scan_bus(bus, pci_root_ops, NULL); + controller = alloc_pci_controller(seg); + if (!controller) + return NULL; + + controller->acpi_handle = handle; + return scan_root_bus(bus, pci_root_ops, controller); } void __init @@ -204,6 +245,7 @@ { # define PCI_BUSES_TO_SCAN 255 int i = 0; + struct pci_controller *controller; #ifdef CONFIG_IA64_MCA ia64_mca_check_errors(); /* For post-failure MCA error logging */ @@ -214,8 +256,10 @@ platform_pci_fixup(0); /* phase 0 fixups (before buses scanned) */ printk("PCI: Probing PCI hardware\n"); - for (i = 0; i < PCI_BUSES_TO_SCAN; i++) - pci_scan_bus(i, pci_root_ops, NULL); + controller = alloc_pci_controller(0); + if (controller) + for (i = 0; i < PCI_BUSES_TO_SCAN; i++) + pci_scan_bus(i, pci_root_ops, controller); platform_pci_fixup(1); /* phase 1 fixups (after buses scanned) */ return 0; diff -u -r 30_sci/drivers/acpi/acpi_pci_root.c 40_pcibios_segment/drivers/acpi/acpi_pci_root.c --- 30_sci/drivers/acpi/acpi_pci_root.c Mon Jul 22 07:25:09 2002 +++ 40_pcibios_segment/drivers/acpi/acpi_pci_root.c Mon Jul 22 09:55:40 2002 @@ -653,7 +653,7 @@ * PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ - root->data.bus = pcibios_scan_root(root->data.id.segment, root->data.id.bus); + root->data.bus = pcibios_scan_root(root->handle, root->data.id.segment, root->data.id.bus); if (!root->data.bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Bus %02x:%02x not present in PCI namespace\n", diff -u -r 30_sci/include/asm-ia64/pci.h 40_pcibios_segment/include/asm-ia64/pci.h --- 30_sci/include/asm-ia64/pci.h Mon Jul 22 07:35:12 2002 +++ 40_pcibios_segment/include/asm-ia64/pci.h Mon Jul 22 09:55:40 2002 @@ -21,7 +21,7 @@ #define PCIBIOS_MIN_MEM 0x10000000 void pcibios_config_init(void); -struct pci_bus * pcibios_scan_root(int seg, int bus); +struct pci_bus *pcibios_scan_root(void *acpi_handle, int segment, int bus); extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value); extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value); @@ -95,5 +95,13 @@ #define HAVE_PCI_MMAP 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_controller { + void *acpi_handle; + int segment; +}; + +#define PCI_CONTROLLER(dev) ((struct pci_controller *) dev->sysdata) +#define PCI_SEGMENT(dev) (PCI_CONTROLLER(dev)->segment) #endif /* _ASM_IA64_PCI_H */