diff -u -r 30_sci/arch/ia64/hp/zx1/hpzx1_misc.c 40_pcibios_segment/arch/ia64/hp/zx1/hpzx1_misc.c --- 30_sci/arch/ia64/hp/zx1/hpzx1_misc.c Sat Jul 20 16:31:07 2002 +++ 40_pcibios_segment/arch/ia64/hp/zx1/hpzx1_misc.c Sat Jul 20 16:33:47 2002 @@ -30,13 +30,16 @@ int sizing; // in middle of BAR sizing operation? }; +#define PCI_FAKE_DEV(dev) ((struct fake_pci_dev *) \ + PCI_CONTROLLER(dev)->platform_data) + static struct pci_ops *orig_pci_ops; #define HP_CFG_RD(sz, bits, name) \ static int hp_cfg_read##sz (struct pci_dev *dev, int where, u##bits *value) \ { \ struct fake_pci_dev *fake_dev; \ - if (!(fake_dev = (struct fake_pci_dev *) dev->sysdata)) \ + if (!(fake_dev = PCI_FAKE_DEV(dev))) \ return orig_pci_ops->name(dev, where, value); \ \ if (where == PCI_BASE_ADDRESS_0) { \ @@ -60,7 +63,7 @@ { \ struct fake_pci_dev *fake_dev; \ \ - if (!(fake_dev = (struct fake_pci_dev *) dev->sysdata)) \ + if (!(fake_dev = PCI_FAKE_DEV(dev))) \ return orig_pci_ops->name(dev, where, value); \ \ if (where == PCI_BASE_ADDRESS_0) { \ @@ -91,16 +94,26 @@ static void hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned int size) { + struct pci_controller *controller; struct fake_pci_dev *fake; int slot; struct pci_dev *dev; struct pci_bus *b, *bus = NULL; u8 hdr; + controller = kmalloc(sizeof(*controller), GFP_KERNEL); + if (!controller) { + printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name, + (void *) addr); + return; + } + memset(controller, 0, sizeof(*controller)); + fake = kmalloc(sizeof(*fake), GFP_KERNEL); if (!fake) { printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name, (void *) addr); + kfree(controller); return; } @@ -109,6 +122,7 @@ fake->csr_size = size; fake->mapped_csrs = (unsigned long) ioremap(addr, size); fake->sizing = 0; + controller->platform_data = fake; pci_for_each_bus(b) if (busnum == b->number) { @@ -120,6 +134,7 @@ printk(KERN_ERR PFX "No host bus 0x%02x for %s (0x%p)\n", busnum, name, (void *) addr); kfree(fake); + kfree(controller); return; } @@ -131,6 +146,7 @@ printk(KERN_ERR PFX "No space for %s (0x%p) on bus 0x%02x\n", name, (void *) addr, busnum); kfree(fake); + kfree(controller); return; } @@ -139,6 +155,7 @@ printk(KERN_ERR PFX "No memory for %s (0x%p)\n", name, (void *) addr); kfree(fake); + kfree(controller); return; } @@ -146,7 +163,7 @@ memset(dev, 0, sizeof(*dev)); dev->bus = bus; - dev->sysdata = fake; + dev->sysdata = controller; dev->devfn = PCI_DEVFN(slot, 0); pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor); pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device); 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 Sat Jul 20 16:31:07 2002 +++ 40_pcibios_segment/arch/ia64/kernel/pci.c Sat Jul 20 16:33:47 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 */ +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 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_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(int bus) +pcibios_scan_root(void *handle, int seg, int bus) { - struct list_head *list = NULL; - struct pci_bus *pci_bus = NULL; + struct pci_controller *controller; - list_for_each(list, &pci_root_buses) { - pci_bus = pci_bus_b(list); - if (pci_bus->number == bus) { - /* Already scanned */ - printk("PCI: Bus (%02x) already probed\n", bus); - return pci_bus; - } - } + printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus); - printk("PCI: Probing PCI hardware on bus (%02x)\n", bus); + controller = alloc_pci_controller(seg); + if (!controller) + return NULL; - return pci_scan_bus(bus, pci_root_ops, 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) */ diff -u -r 30_sci/drivers/acpi/pci_root.c 40_pcibios_segment/drivers/acpi/pci_root.c --- 30_sci/drivers/acpi/pci_root.c Sat Jul 20 16:31:08 2002 +++ 40_pcibios_segment/drivers/acpi/pci_root.c Sat Jul 20 16:33:47 2002 @@ -103,8 +103,6 @@ switch (status) { case AE_OK: root->id.segment = (u16) value; - printk("_SEG exists! Unsupported. Abort.\n"); - BUG(); break; case AE_NOT_FOUND: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -162,7 +160,8 @@ * PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ - root->bus = pcibios_scan_root(root->id.bus); + root->bus = pcibios_scan_root(root->handle, root->id.segment, + root->id.bus); if (!root->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 Sat Jul 20 16:31:09 2002 +++ 40_pcibios_segment/include/asm-ia64/pci.h Sat Jul 20 16:33:47 2002 @@ -20,7 +20,7 @@ #define PCIBIOS_MIN_MEM 0x10000000 void pcibios_config_init(void); -struct pci_bus * pcibios_scan_root(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); @@ -81,5 +81,15 @@ #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; + + void *platform_data; +}; + +#define PCI_CONTROLLER(dev) ((struct pci_controller *) dev->sysdata) +#define PCI_SEGMENT(dev) (PCI_CONTROLLER(dev)->segment) #endif /* _ASM_IA64_PCI_H */