i386: move pci
authorThomas Gleixner <tglx@linutronix.de>
Thu, 11 Oct 2007 09:16:36 +0000 (11:16 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 11 Oct 2007 09:16:36 +0000 (11:16 +0200)
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
40 files changed:
arch/i386/Makefile
arch/i386/pci/Makefile [deleted file]
arch/i386/pci/Makefile_32 [deleted file]
arch/i386/pci/acpi.c [deleted file]
arch/i386/pci/common.c [deleted file]
arch/i386/pci/direct.c [deleted file]
arch/i386/pci/early.c [deleted file]
arch/i386/pci/fixup.c [deleted file]
arch/i386/pci/i386.c [deleted file]
arch/i386/pci/init.c [deleted file]
arch/i386/pci/irq.c [deleted file]
arch/i386/pci/legacy.c [deleted file]
arch/i386/pci/mmconfig-shared.c [deleted file]
arch/i386/pci/mmconfig_32.c [deleted file]
arch/i386/pci/numa.c [deleted file]
arch/i386/pci/pcbios.c [deleted file]
arch/i386/pci/pci.h [deleted file]
arch/i386/pci/visws.c [deleted file]
arch/x86/pci/Makefile [new file with mode: 0644]
arch/x86/pci/Makefile_32 [new file with mode: 0644]
arch/x86/pci/acpi.c [new file with mode: 0644]
arch/x86/pci/common.c [new file with mode: 0644]
arch/x86/pci/direct.c [new file with mode: 0644]
arch/x86/pci/early.c [new file with mode: 0644]
arch/x86/pci/fixup.c [new file with mode: 0644]
arch/x86/pci/i386.c [new file with mode: 0644]
arch/x86/pci/init.c [new file with mode: 0644]
arch/x86/pci/irq.c [new file with mode: 0644]
arch/x86/pci/legacy.c [new file with mode: 0644]
arch/x86/pci/mmconfig-shared.c [new file with mode: 0644]
arch/x86/pci/mmconfig_32.c [new file with mode: 0644]
arch/x86/pci/numa.c [new file with mode: 0644]
arch/x86/pci/pcbios.c [new file with mode: 0644]
arch/x86/pci/pci.h [new file with mode: 0644]
arch/x86/pci/visws.c [new file with mode: 0644]
arch/x86_64/pci/Makefile
arch/x86_64/pci/Makefile_64
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/cpqphp_pci.c
drivers/pci/hotplug/ibmphp_core.c

index da64799484a779df277fdc136a0c31f81bb46bd0..87c959d5f354a0830baaae6a74ba0a0fdfb98001 100644 (file)
@@ -107,7 +107,7 @@ core-y                                      += arch/i386/kernel/ \
                                           $(mcore-y)/ \
                                           arch/x86/crypto/
 drivers-$(CONFIG_MATH_EMULATION)       += arch/x86/math-emu/
-drivers-$(CONFIG_PCI)                  += arch/i386/pci/
+drivers-$(CONFIG_PCI)                  += arch/x86/pci/
 # must be linked after kernel/
 drivers-$(CONFIG_OPROFILE)             += arch/i386/oprofile/
 drivers-$(CONFIG_PM)                   += arch/x86/power/
diff --git a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile
deleted file mode 100644 (file)
index d04d8f9..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-ifeq ($(CONFIG_X86_32),y)
-include ${srctree}/arch/i386/pci/Makefile_32
-else
-include ${srctree}/arch/x86_64/pci/Makefile_64
-endif
diff --git a/arch/i386/pci/Makefile_32 b/arch/i386/pci/Makefile_32
deleted file mode 100644 (file)
index cdd6828..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-obj-y                          := i386.o init.o
-
-obj-$(CONFIG_PCI_BIOS)         += pcbios.o
-obj-$(CONFIG_PCI_MMCONFIG)     += mmconfig_32.o direct.o mmconfig-shared.o
-obj-$(CONFIG_PCI_DIRECT)       += direct.o
-
-pci-y                          := fixup.o
-pci-$(CONFIG_ACPI)             += acpi.o
-pci-y                          += legacy.o irq.o
-
-pci-$(CONFIG_X86_VISWS)                := visws.o fixup.o
-pci-$(CONFIG_X86_NUMAQ)                := numa.o irq.o
-
-obj-y                          += $(pci-y) common.o early.o
diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c
deleted file mode 100644 (file)
index bc8a44b..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#include <linux/pci.h>
-#include <linux/acpi.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <asm/numa.h>
-#include "pci.h"
-
-struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
-{
-       struct pci_bus *bus;
-       struct pci_sysdata *sd;
-       int pxm;
-
-       /* Allocate per-root-bus (not per bus) arch-specific data.
-        * TODO: leak; this memory is never freed.
-        * It's arguable whether it's worth the trouble to care.
-        */
-       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
-       if (!sd) {
-               printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
-               return NULL;
-       }
-
-       if (domain != 0) {
-               printk(KERN_WARNING "PCI: Multiple domains not supported\n");
-               kfree(sd);
-               return NULL;
-       }
-
-       sd->node = -1;
-
-       pxm = acpi_get_pxm(device->handle);
-#ifdef CONFIG_ACPI_NUMA
-       if (pxm >= 0)
-               sd->node = pxm_to_node(pxm);
-#endif
-
-       bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
-       if (!bus)
-               kfree(sd);
-
-#ifdef CONFIG_ACPI_NUMA
-       if (bus != NULL) {
-               if (pxm >= 0) {
-                       printk("bus %d -> pxm %d -> node %d\n",
-                               busnum, pxm, sd->node);
-               }
-       }
-#endif
-       
-       return bus;
-}
-
-extern int pci_routeirq;
-static int __init pci_acpi_init(void)
-{
-       struct pci_dev *dev = NULL;
-
-       if (pcibios_scanned)
-               return 0;
-
-       if (acpi_noirq)
-               return 0;
-
-       printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-       acpi_irq_penalty_init();
-       pcibios_scanned++;
-       pcibios_enable_irq = acpi_pci_irq_enable;
-       pcibios_disable_irq = acpi_pci_irq_disable;
-
-       if (pci_routeirq) {
-               /*
-                * PCI IRQ routing is set up by pci_enable_device(), but we
-                * also do it here in case there are still broken drivers that
-                * don't use pci_enable_device().
-                */
-               printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
-               for_each_pci_dev(dev)
-                       acpi_pci_irq_enable(dev);
-       } else
-               printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\".  If it helps, post a report\n");
-
-#ifdef CONFIG_X86_IO_APIC
-       if (acpi_ioapic)
-               print_IO_APIC();
-#endif
-
-       return 0;
-}
-subsys_initcall(pci_acpi_init);
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
deleted file mode 100644 (file)
index ebc6f3c..0000000
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- *     Low-Level PCI Support for PC
- *
- *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
- */
-
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/dmi.h>
-
-#include <asm/acpi.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-
-#include "pci.h"
-
-unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
-                               PCI_PROBE_MMCONF;
-
-static int pci_bf_sort;
-int pci_routeirq;
-int pcibios_last_bus = -1;
-unsigned long pirq_table_addr;
-struct pci_bus *pci_root_bus;
-struct pci_raw_ops *raw_pci_ops;
-
-static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
-{
-       return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
-}
-
-static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
-{
-       return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
-}
-
-struct pci_ops pci_root_ops = {
-       .read = pci_read,
-       .write = pci_write,
-};
-
-/*
- * legacy, numa, and acpi all want to call pcibios_scan_root
- * from their initcalls. This flag prevents that.
- */
-int pcibios_scanned;
-
-/*
- * This interrupt-safe spinlock protects all accesses to PCI
- * configuration space.
- */
-DEFINE_SPINLOCK(pci_config_lock);
-
-/*
- * Several buggy motherboards address only 16 devices and mirror
- * them to next 16 IDs. We try to detect this `feature' on all
- * primary buses (those containing host bridges as they are
- * expected to be unique) and remove the ghost devices.
- */
-
-static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
-{
-       struct list_head *ln, *mn;
-       struct pci_dev *d, *e;
-       int mirror = PCI_DEVFN(16,0);
-       int seen_host_bridge = 0;
-       int i;
-
-       DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
-       list_for_each(ln, &b->devices) {
-               d = pci_dev_b(ln);
-               if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
-                       seen_host_bridge++;
-               for (mn=ln->next; mn != &b->devices; mn=mn->next) {
-                       e = pci_dev_b(mn);
-                       if (e->devfn != d->devfn + mirror ||
-                           e->vendor != d->vendor ||
-                           e->device != d->device ||
-                           e->class != d->class)
-                               continue;
-                       for(i=0; i<PCI_NUM_RESOURCES; i++)
-                               if (e->resource[i].start != d->resource[i].start ||
-                                   e->resource[i].end != d->resource[i].end ||
-                                   e->resource[i].flags != d->resource[i].flags)
-                                       continue;
-                       break;
-               }
-               if (mn == &b->devices)
-                       return;
-       }
-       if (!seen_host_bridge)
-               return;
-       printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number);
-
-       ln = &b->devices;
-       while (ln->next != &b->devices) {
-               d = pci_dev_b(ln->next);
-               if (d->devfn >= mirror) {
-                       list_del(&d->global_list);
-                       list_del(&d->bus_list);
-                       kfree(d);
-               } else
-                       ln = ln->next;
-       }
-}
-
-/*
- *  Called after each bus is probed, but before its children
- *  are examined.
- */
-
-void __devinit  pcibios_fixup_bus(struct pci_bus *b)
-{
-       pcibios_fixup_ghosts(b);
-       pci_read_bridge_bases(b);
-}
-
-/*
- * Only use DMI information to set this if nothing was passed
- * on the kernel command line (which was parsed earlier).
- */
-
-static int __devinit set_bf_sort(struct dmi_system_id *d)
-{
-       if (pci_bf_sort == pci_bf_sort_default) {
-               pci_bf_sort = pci_dmi_bf;
-               printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident);
-       }
-       return 0;
-}
-
-/*
- * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
- */
-#ifdef __i386__
-static int __devinit assign_all_busses(struct dmi_system_id *d)
-{
-       pci_probe |= PCI_ASSIGN_ALL_BUSSES;
-       printk(KERN_INFO "%s detected: enabling PCI bus# renumbering"
-                       " (pci=assign-busses)\n", d->ident);
-       return 0;
-}
-#endif
-
-static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
-#ifdef __i386__
-/*
- * Laptops which need pci=assign-busses to see Cardbus cards
- */
-       {
-               .callback = assign_all_busses,
-               .ident = "Samsung X20 Laptop",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"),
-               },
-       },
-#endif         /* __i386__ */
-       {
-               .callback = set_bf_sort,
-               .ident = "Dell PowerEdge 1950",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "Dell PowerEdge 1955",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "Dell PowerEdge 2900",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "Dell PowerEdge 2950",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "Dell PowerEdge R900",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL20p G3",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL20p G4",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL30p G1",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL25p G1",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL35p G1",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL45p G1",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL45p G2",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL460c G1",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL465c G1",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL480c G1",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"),
-               },
-       },
-       {
-               .callback = set_bf_sort,
-               .ident = "HP ProLiant BL685c G1",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
-               },
-       },
-       {}
-};
-
-struct pci_bus * __devinit pcibios_scan_root(int busnum)
-{
-       struct pci_bus *bus = NULL;
-       struct pci_sysdata *sd;
-
-       dmi_check_system(pciprobe_dmi_table);
-
-       while ((bus = pci_find_next_bus(bus)) != NULL) {
-               if (bus->number == busnum) {
-                       /* Already scanned */
-                       return bus;
-               }
-       }
-
-       /* Allocate per-root-bus (not per bus) arch-specific data.
-        * TODO: leak; this memory is never freed.
-        * It's arguable whether it's worth the trouble to care.
-        */
-       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
-       if (!sd) {
-               printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
-               return NULL;
-       }
-
-       printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
-
-       return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
-}
-
-extern u8 pci_cache_line_size;
-
-static int __init pcibios_init(void)
-{
-       struct cpuinfo_x86 *c = &boot_cpu_data;
-
-       if (!raw_pci_ops) {
-               printk(KERN_WARNING "PCI: System does not support PCI\n");
-               return 0;
-       }
-
-       /*
-        * Assume PCI cacheline size of 32 bytes for all x86s except K7/K8
-        * and P4. It's also good for 386/486s (which actually have 16)
-        * as quite a few PCI devices do not support smaller values.
-        */
-       pci_cache_line_size = 32 >> 2;
-       if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
-               pci_cache_line_size = 64 >> 2;  /* K7 & K8 */
-       else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL)
-               pci_cache_line_size = 128 >> 2; /* P4 */
-
-       pcibios_resource_survey();
-
-       if (pci_bf_sort >= pci_force_bf)
-               pci_sort_breadthfirst();
-#ifdef CONFIG_PCI_BIOS
-       if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
-               pcibios_sort();
-#endif
-       return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-char * __devinit  pcibios_setup(char *str)
-{
-       if (!strcmp(str, "off")) {
-               pci_probe = 0;
-               return NULL;
-       } else if (!strcmp(str, "bfsort")) {
-               pci_bf_sort = pci_force_bf;
-               return NULL;
-       } else if (!strcmp(str, "nobfsort")) {
-               pci_bf_sort = pci_force_nobf;
-               return NULL;
-       }
-#ifdef CONFIG_PCI_BIOS
-       else if (!strcmp(str, "bios")) {
-               pci_probe = PCI_PROBE_BIOS;
-               return NULL;
-       } else if (!strcmp(str, "nobios")) {
-               pci_probe &= ~PCI_PROBE_BIOS;
-               return NULL;
-       } else if (!strcmp(str, "nosort")) {
-               pci_probe |= PCI_NO_SORT;
-               return NULL;
-       } else if (!strcmp(str, "biosirq")) {
-               pci_probe |= PCI_BIOS_IRQ_SCAN;
-               return NULL;
-       } else if (!strncmp(str, "pirqaddr=", 9)) {
-               pirq_table_addr = simple_strtoul(str+9, NULL, 0);
-               return NULL;
-       }
-#endif
-#ifdef CONFIG_PCI_DIRECT
-       else if (!strcmp(str, "conf1")) {
-               pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS;
-               return NULL;
-       }
-       else if (!strcmp(str, "conf2")) {
-               pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS;
-               return NULL;
-       }
-#endif
-#ifdef CONFIG_PCI_MMCONFIG
-       else if (!strcmp(str, "nommconf")) {
-               pci_probe &= ~PCI_PROBE_MMCONF;
-               return NULL;
-       }
-#endif
-       else if (!strcmp(str, "noacpi")) {
-               acpi_noirq_set();
-               return NULL;
-       }
-       else if (!strcmp(str, "noearly")) {
-               pci_probe |= PCI_PROBE_NOEARLY;
-               return NULL;
-       }
-#ifndef CONFIG_X86_VISWS
-       else if (!strcmp(str, "usepirqmask")) {
-               pci_probe |= PCI_USE_PIRQ_MASK;
-               return NULL;
-       } else if (!strncmp(str, "irqmask=", 8)) {
-               pcibios_irq_mask = simple_strtol(str+8, NULL, 0);
-               return NULL;
-       } else if (!strncmp(str, "lastbus=", 8)) {
-               pcibios_last_bus = simple_strtol(str+8, NULL, 0);
-               return NULL;
-       }
-#endif
-       else if (!strcmp(str, "rom")) {
-               pci_probe |= PCI_ASSIGN_ROMS;
-               return NULL;
-       } else if (!strcmp(str, "assign-busses")) {
-               pci_probe |= PCI_ASSIGN_ALL_BUSSES;
-               return NULL;
-       } else if (!strcmp(str, "routeirq")) {
-               pci_routeirq = 1;
-               return NULL;
-       }
-       return str;
-}
-
-unsigned int pcibios_assign_all_busses(void)
-{
-       return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-       int err;
-
-       if ((err = pcibios_enable_resources(dev, mask)) < 0)
-               return err;
-
-       if (!dev->msi_enabled)
-               return pcibios_enable_irq(dev);
-       return 0;
-}
-
-void pcibios_disable_device (struct pci_dev *dev)
-{
-       if (!dev->msi_enabled && pcibios_disable_irq)
-               pcibios_disable_irq(dev);
-}
-
-struct pci_bus *pci_scan_bus_with_sysdata(int busno)
-{
-       struct pci_bus *bus = NULL;
-       struct pci_sysdata *sd;
-
-       /*
-        * Allocate per-root-bus (not per bus) arch-specific data.
-        * TODO: leak; this memory is never freed.
-        * It's arguable whether it's worth the trouble to care.
-        */
-       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
-       if (!sd) {
-               printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
-               return NULL;
-       }
-       sd->node = -1;
-       bus = pci_scan_bus(busno, &pci_root_ops, sd);
-       if (!bus)
-               kfree(sd);
-
-       return bus;
-}
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
deleted file mode 100644 (file)
index 431c9a5..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * direct.c - Low-level direct PCI config space access
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/dmi.h>
-#include "pci.h"
-
-/*
- * Functions for accessing PCI configuration space with type 1 accesses
- */
-
-#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
-       (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
-
-int pci_conf1_read(unsigned int seg, unsigned int bus,
-                         unsigned int devfn, int reg, int len, u32 *value)
-{
-       unsigned long flags;
-
-       if ((bus > 255) || (devfn > 255) || (reg > 255)) {
-               *value = -1;
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
-
-       switch (len) {
-       case 1:
-               *value = inb(0xCFC + (reg & 3));
-               break;
-       case 2:
-               *value = inw(0xCFC + (reg & 2));
-               break;
-       case 4:
-               *value = inl(0xCFC);
-               break;
-       }
-
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return 0;
-}
-
-int pci_conf1_write(unsigned int seg, unsigned int bus,
-                          unsigned int devfn, int reg, int len, u32 value)
-{
-       unsigned long flags;
-
-       if ((bus > 255) || (devfn > 255) || (reg > 255)) 
-               return -EINVAL;
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
-
-       switch (len) {
-       case 1:
-               outb((u8)value, 0xCFC + (reg & 3));
-               break;
-       case 2:
-               outw((u16)value, 0xCFC + (reg & 2));
-               break;
-       case 4:
-               outl((u32)value, 0xCFC);
-               break;
-       }
-
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return 0;
-}
-
-#undef PCI_CONF1_ADDRESS
-
-struct pci_raw_ops pci_direct_conf1 = {
-       .read =         pci_conf1_read,
-       .write =        pci_conf1_write,
-};
-
-
-/*
- * Functions for accessing PCI configuration space with type 2 accesses
- */
-
-#define PCI_CONF2_ADDRESS(dev, reg)    (u16)(0xC000 | (dev << 8) | reg)
-
-static int pci_conf2_read(unsigned int seg, unsigned int bus,
-                         unsigned int devfn, int reg, int len, u32 *value)
-{
-       unsigned long flags;
-       int dev, fn;
-
-       if ((bus > 255) || (devfn > 255) || (reg > 255)) {
-               *value = -1;
-               return -EINVAL;
-       }
-
-       dev = PCI_SLOT(devfn);
-       fn = PCI_FUNC(devfn);
-
-       if (dev & 0x10) 
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       outb((u8)(0xF0 | (fn << 1)), 0xCF8);
-       outb((u8)bus, 0xCFA);
-
-       switch (len) {
-       case 1:
-               *value = inb(PCI_CONF2_ADDRESS(dev, reg));
-               break;
-       case 2:
-               *value = inw(PCI_CONF2_ADDRESS(dev, reg));
-               break;
-       case 4:
-               *value = inl(PCI_CONF2_ADDRESS(dev, reg));
-               break;
-       }
-
-       outb(0, 0xCF8);
-
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return 0;
-}
-
-static int pci_conf2_write(unsigned int seg, unsigned int bus,
-                          unsigned int devfn, int reg, int len, u32 value)
-{
-       unsigned long flags;
-       int dev, fn;
-
-       if ((bus > 255) || (devfn > 255) || (reg > 255)) 
-               return -EINVAL;
-
-       dev = PCI_SLOT(devfn);
-       fn = PCI_FUNC(devfn);
-
-       if (dev & 0x10) 
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       outb((u8)(0xF0 | (fn << 1)), 0xCF8);
-       outb((u8)bus, 0xCFA);
-
-       switch (len) {
-       case 1:
-               outb((u8)value, PCI_CONF2_ADDRESS(dev, reg));
-               break;
-       case 2:
-               outw((u16)value, PCI_CONF2_ADDRESS(dev, reg));
-               break;
-       case 4:
-               outl((u32)value, PCI_CONF2_ADDRESS(dev, reg));
-               break;
-       }
-
-       outb(0, 0xCF8);    
-
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return 0;
-}
-
-#undef PCI_CONF2_ADDRESS
-
-static struct pci_raw_ops pci_direct_conf2 = {
-       .read =         pci_conf2_read,
-       .write =        pci_conf2_write,
-};
-
-
-/*
- * Before we decide to use direct hardware access mechanisms, we try to do some
- * trivial checks to ensure it at least _seems_ to be working -- we just test
- * whether bus 00 contains a host bridge (this is similar to checking
- * techniques used in XFree86, but ours should be more reliable since we
- * attempt to make use of direct access hints provided by the PCI BIOS).
- *
- * This should be close to trivial, but it isn't, because there are buggy
- * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
- */
-static int __init pci_sanity_check(struct pci_raw_ops *o)
-{
-       u32 x = 0;
-       int devfn;
-
-       if (pci_probe & PCI_NO_CHECKS)
-               return 1;
-       /* Assume Type 1 works for newer systems.
-          This handles machines that don't have anything on PCI Bus 0. */
-       if (dmi_get_year(DMI_BIOS_DATE) >= 2001)
-               return 1;
-
-       for (devfn = 0; devfn < 0x100; devfn++) {
-               if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x))
-                       continue;
-               if (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)
-                       return 1;
-
-               if (o->read(0, 0, devfn, PCI_VENDOR_ID, 2, &x))
-                       continue;
-               if (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)
-                       return 1;
-       }
-
-       DBG(KERN_WARNING "PCI: Sanity check failed\n");
-       return 0;
-}
-
-static int __init pci_check_type1(void)
-{
-       unsigned long flags;
-       unsigned int tmp;
-       int works = 0;
-
-       local_irq_save(flags);
-
-       outb(0x01, 0xCFB);
-       tmp = inl(0xCF8);
-       outl(0x80000000, 0xCF8);
-       if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) {
-               works = 1;
-       }
-       outl(tmp, 0xCF8);
-       local_irq_restore(flags);
-
-       return works;
-}
-
-static int __init pci_check_type2(void)
-{
-       unsigned long flags;
-       int works = 0;
-
-       local_irq_save(flags);
-
-       outb(0x00, 0xCFB);
-       outb(0x00, 0xCF8);
-       outb(0x00, 0xCFA);
-       if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 &&
-           pci_sanity_check(&pci_direct_conf2)) {
-               works = 1;
-       }
-
-       local_irq_restore(flags);
-
-       return works;
-}
-
-void __init pci_direct_init(int type)
-{
-       if (type == 0)
-               return;
-       printk(KERN_INFO "PCI: Using configuration type %d\n", type);
-       if (type == 1)
-               raw_pci_ops = &pci_direct_conf1;
-       else
-               raw_pci_ops = &pci_direct_conf2;
-}
-
-int __init pci_direct_probe(void)
-{
-       struct resource *region, *region2;
-
-       if ((pci_probe & PCI_PROBE_CONF1) == 0)
-               goto type2;
-       region = request_region(0xCF8, 8, "PCI conf1");
-       if (!region)
-               goto type2;
-
-       if (pci_check_type1())
-               return 1;
-       release_resource(region);
-
- type2:
-       if ((pci_probe & PCI_PROBE_CONF2) == 0)
-               return 0;
-       region = request_region(0xCF8, 4, "PCI conf2");
-       if (!region)
-               return 0;
-       region2 = request_region(0xC000, 0x1000, "PCI conf2");
-       if (!region2)
-               goto fail2;
-
-       if (pci_check_type2()) {
-               printk(KERN_INFO "PCI: Using configuration type 2\n");
-               raw_pci_ops = &pci_direct_conf2;
-               return 2;
-       }
-
-       release_resource(region2);
- fail2:
-       release_resource(region);
-       return 0;
-}
diff --git a/arch/i386/pci/early.c b/arch/i386/pci/early.c
deleted file mode 100644 (file)
index 42df4b6..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <asm/pci-direct.h>
-#include <asm/io.h>
-#include "pci.h"
-
-/* Direct PCI access. This is used for PCI accesses in early boot before
-   the PCI subsystem works. */
-
-#define PDprintk(x...)
-
-u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset)
-{
-       u32 v;
-       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
-       v = inl(0xcfc);
-       if (v != 0xffffffff)
-               PDprintk("%x reading 4 from %x: %x\n", slot, offset, v);
-       return v;
-}
-
-u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset)
-{
-       u8 v;
-       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
-       v = inb(0xcfc + (offset&3));
-       PDprintk("%x reading 1 from %x: %x\n", slot, offset, v);
-       return v;
-}
-
-u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
-{
-       u16 v;
-       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
-       v = inw(0xcfc + (offset&2));
-       PDprintk("%x reading 2 from %x: %x\n", slot, offset, v);
-       return v;
-}
-
-void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
-                                   u32 val)
-{
-       PDprintk("%x writing to %x: %x\n", slot, offset, val);
-       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
-       outl(val, 0xcfc);
-}
-
-void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val)
-{
-       PDprintk("%x writing to %x: %x\n", slot, offset, val);
-       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
-       outb(val, 0xcfc);
-}
-
-int early_pci_allowed(void)
-{
-       return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
-                       PCI_PROBE_CONF1;
-}
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
deleted file mode 100644 (file)
index c82cbf4..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
- */
-
-#include <linux/delay.h>
-#include <linux/dmi.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include "pci.h"
-
-
-static void __devinit pci_fixup_i450nx(struct pci_dev *d)
-{
-       /*
-        * i450NX -- Find and scan all secondary buses on all PXB's.
-        */
-       int pxb, reg;
-       u8 busno, suba, subb;
-
-       printk(KERN_WARNING "PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
-       reg = 0xd0;
-       for(pxb=0; pxb<2; pxb++) {
-               pci_read_config_byte(d, reg++, &busno);
-               pci_read_config_byte(d, reg++, &suba);
-               pci_read_config_byte(d, reg++, &subb);
-               DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
-               if (busno)
-                       pci_scan_bus_with_sysdata(busno);       /* Bus A */
-               if (suba < subb)
-                       pci_scan_bus_with_sysdata(suba+1);      /* Bus B */
-       }
-       pcibios_last_bus = -1;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
-
-static void __devinit pci_fixup_i450gx(struct pci_dev *d)
-{
-       /*
-        * i450GX and i450KX -- Find and scan all secondary buses.
-        * (called separately for each PCI bridge found)
-        */
-       u8 busno;
-       pci_read_config_byte(d, 0x4a, &busno);
-       printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno);
-       pci_scan_bus_with_sysdata(busno);
-       pcibios_last_bus = -1;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
-
-static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)
-{
-       /*
-        * UM8886BF IDE controller sets region type bits incorrectly,
-        * therefore they look like memory despite of them being I/O.
-        */
-       int i;
-
-       printk(KERN_WARNING "PCI: Fixing base address flags for device %s\n", pci_name(d));
-       for(i=0; i<4; i++)
-               d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide);
-
-static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)
-{
-       /*
-        * NCR 53C810 returns class code 0 (at least on some systems).
-        * Fix class to be PCI_CLASS_STORAGE_SCSI
-        */
-       if (!d->class) {
-               printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", pci_name(d));
-               d->class = PCI_CLASS_STORAGE_SCSI << 8;
-       }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810);
-
-static void __devinit  pci_fixup_latency(struct pci_dev *d)
-{
-       /*
-        *  SiS 5597 and 5598 chipsets require latency timer set to
-        *  at most 32 to avoid lockups.
-        */
-       DBG("PCI: Setting max latency to 32\n");
-       pcibios_max_latency = 32;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency);
-
-static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
-{
-       /*
-        * PIIX4 ACPI device: hardwired IRQ9
-        */
-       d->irq = 9;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi);
-
-/*
- * Addresses issues with problems in the memory write queue timer in
- * certain VIA Northbridges.  This bugfix is per VIA's specifications,
- * except for the KL133/KM133: clearing bit 5 on those Northbridges seems
- * to trigger a bug in its integrated ProSavage video card, which
- * causes screen corruption.  We only clear bits 6 and 7 for that chipset,
- * until VIA can provide us with definitive information on why screen
- * corruption occurs, and what exactly those bits do.
- *
- * VIA 8363,8622,8361 Northbridges:
- *  - bits  5, 6, 7 at offset 0x55 need to be turned off
- * VIA 8367 (KT266x) Northbridges:
- *  - bits  5, 6, 7 at offset 0x95 need to be turned off
- * VIA 8363 rev 0x81/0x84 (KL133/KM133) Northbridges:
- *  - bits     6, 7 at offset 0x55 need to be turned off
- */
-
-#define VIA_8363_KL133_REVISION_ID 0x81
-#define VIA_8363_KM133_REVISION_ID 0x84
-
-static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
-{
-       u8 v;
-       int where = 0x55;
-       int mask = 0x1f; /* clear bits 5, 6, 7 by default */
-
-       if (d->device == PCI_DEVICE_ID_VIA_8367_0) {
-               /* fix pci bus latency issues resulted by NB bios error
-                  it appears on bug free^Wreduced kt266x's bios forces
-                  NB latency to zero */
-               pci_write_config_byte(d, PCI_LATENCY_TIMER, 0);
-
-               where = 0x95; /* the memory write queue timer register is 
-                               different for the KT266x's: 0x95 not 0x55 */
-       } else if (d->device == PCI_DEVICE_ID_VIA_8363_0 &&
-                       (d->revision == VIA_8363_KL133_REVISION_ID ||
-                       d->revision == VIA_8363_KM133_REVISION_ID)) {
-                       mask = 0x3f; /* clear only bits 6 and 7; clearing bit 5
-                                       causes screen corruption on the KL133/KM133 */
-       }
-
-       pci_read_config_byte(d, where, &v);
-       if (v & ~mask) {
-               printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
-                       d->device, d->revision, where, v, mask, v & mask);
-               v &= mask;
-               pci_write_config_byte(d, where, v);
-       }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
-
-/*
- * For some reasons Intel decided that certain parts of their
- * 815, 845 and some other chipsets must look like PCI-to-PCI bridges
- * while they are obviously not. The 82801 family (AA, AB, BAM/CAM,
- * BA/CA/DB and E) PCI bridges are actually HUB-to-PCI ones, according
- * to Intel terminology. These devices do forward all addresses from
- * system to PCI bus no matter what are their window settings, so they are
- * "transparent" (or subtractive decoding) from programmers point of view.
- */
-static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev)
-{
-       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
-           (dev->device & 0xff00) == 0x2400)
-               dev->transparent = 1;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge);
-
-/*
- * Fixup for C1 Halt Disconnect problem on nForce2 systems.
- *
- * From information provided by "Allen Martin" <AMartin@nvidia.com>:
- *
- * A hang is caused when the CPU generates a very fast CONNECT/HALT cycle
- * sequence.  Workaround is to set the SYSTEM_IDLE_TIMEOUT to 80 ns.
- * This allows the state-machine and timer to return to a proper state within
- * 80 ns of the CONNECT and probe appearing together.  Since the CPU will not
- * issue another HALT within 80 ns of the initial HALT, the failure condition
- * is avoided.
- */
-static void pci_fixup_nforce2(struct pci_dev *dev)
-{
-       u32 val;
-
-       /*
-        * Chip  Old value   New value
-        * C17   0x1F0FFF01  0x1F01FF01
-        * C18D  0x9F0FFF01  0x9F01FF01
-        *
-        * Northbridge chip version may be determined by
-        * reading the PCI revision ID (0xC1 or greater is C18D).
-        */
-       pci_read_config_dword(dev, 0x6c, &val);
-
-       /*
-        * Apply fixup if needed, but don't touch disconnect state
-        */
-       if ((val & 0x00FF0000) != 0x00010000) {
-               printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n");
-               pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000);
-       }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
-
-/* Max PCI Express root ports */
-#define MAX_PCIEROOT   6
-static int quirk_aspm_offset[MAX_PCIEROOT << 3];
-
-#define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7))
-
-static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
-{
-       return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
-}
-
-/*
- * Replace the original pci bus ops for write with a new one that will filter
- * the request to insure ASPM cannot be enabled.
- */
-static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
-{
-       u8 offset;
-
-       offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)];
-
-       if ((offset) && (where == offset))
-               value = value & 0xfffffffc;
-       
-       return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
-}
-
-static struct pci_ops quirk_pcie_aspm_ops = {
-       .read = quirk_pcie_aspm_read,
-       .write = quirk_pcie_aspm_write,
-};
-
-/*
- * Prevents PCI Express ASPM (Active State Power Management) being enabled.
- *
- * Save the register offset, where the ASPM control bits are located,
- * for each PCI Express device that is in the device list of
- * the root port in an array for fast indexing. Replace the bus ops
- * with the modified one.
- */
-static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
-{
-       int cap_base, i;
-       struct pci_bus  *pbus;
-       struct pci_dev *dev;
-
-       if ((pbus = pdev->subordinate) == NULL)
-               return;
-
-       /*
-        * Check if the DID of pdev matches one of the six root ports. This
-        * check is needed in the case this function is called directly by the
-        * hot-plug driver.
-        */
-       if ((pdev->device < PCI_DEVICE_ID_INTEL_MCH_PA) ||
-           (pdev->device > PCI_DEVICE_ID_INTEL_MCH_PC1))
-               return;
-
-       if (list_empty(&pbus->devices)) {
-               /*
-                * If no device is attached to the root port at power-up or
-                * after hot-remove, the pbus->devices is empty and this code
-                * will set the offsets to zero and the bus ops to parent's bus
-                * ops, which is unmodified.
-                */
-               for (i= GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i)
-                       quirk_aspm_offset[i] = 0;
-
-               pbus->ops = pbus->parent->ops;
-       } else {
-               /*
-                * If devices are attached to the root port at power-up or
-                * after hot-add, the code loops through the device list of
-                * each root port to save the register offsets and replace the
-                * bus ops.
-                */
-               list_for_each_entry(dev, &pbus->devices, bus_list) {
-                       /* There are 0 to 8 devices attached to this bus */
-                       cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP);
-                       quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)]= cap_base + 0x10;
-               }
-               pbus->ops = &quirk_pcie_aspm_ops;
-       }
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PA,     pcie_rootport_aspm_quirk );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PA1,    pcie_rootport_aspm_quirk );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PB,     pcie_rootport_aspm_quirk );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PB1,    pcie_rootport_aspm_quirk );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PC,     pcie_rootport_aspm_quirk );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PC1,    pcie_rootport_aspm_quirk );
-
-/*
- * Fixup to mark boot BIOS video selected by BIOS before it changes
- *
- * From information provided by "Jon Smirl" <jonsmirl@gmail.com>
- *
- * The standard boot ROM sequence for an x86 machine uses the BIOS
- * to select an initial video card for boot display. This boot video
- * card will have it's BIOS copied to C0000 in system RAM.
- * IORESOURCE_ROM_SHADOW is used to associate the boot video
- * card with this copy. On laptops this copy has to be used since
- * the main ROM may be compressed or combined with another image.
- * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
- * is marked here since the boot video device will be the only enabled
- * video device at this point.
- */
-
-static void __devinit pci_fixup_video(struct pci_dev *pdev)
-{
-       struct pci_dev *bridge;
-       struct pci_bus *bus;
-       u16 config;
-
-       if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
-               return;
-
-       /* Is VGA routed to us? */
-       bus = pdev->bus;
-       while (bus) {
-               bridge = bus->self;
-
-               /*
-                * From information provided by
-                * "David Miller" <davem@davemloft.net>
-                * The bridge control register is valid for PCI header
-                * type BRIDGE, or CARDBUS. Host to PCI controllers use
-                * PCI header type NORMAL.
-                */
-               if (bridge
-                   &&((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE)
-                      ||(bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) {
-                       pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
-                                               &config);
-                       if (!(config & PCI_BRIDGE_CTL_VGA))
-                               return;
-               }
-               bus = bus->parent;
-       }
-       pci_read_config_word(pdev, PCI_COMMAND, &config);
-       if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
-               pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-               printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
-       }
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
-
-/*
- * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
- *
- * We pretend to bring them out of full D3 state, and restore the proper
- * IRQ, PCI cache line size, and BARs, otherwise the device won't function
- * properly.  In some cases, the device will generate an interrupt on
- * the wrong IRQ line, causing any devices sharing the line it's
- * *supposed* to use to be disabled by the kernel's IRQ debug code.
- */
-static u16 toshiba_line_size;
-
-static struct dmi_system_id __devinitdata toshiba_ohci1394_dmi_table[] = {
-       {
-               .ident = "Toshiba PS5 based laptop",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"),
-               },
-       },
-       {
-               .ident = "Toshiba PSM4 based laptop",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"),
-               },
-       },
-       {
-               .ident = "Toshiba A40 based laptop",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "PSA40U"),
-               },
-       },
-       { }
-};
-
-static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
-{
-       if (!dmi_check_system(toshiba_ohci1394_dmi_table))
-               return; /* only applies to certain Toshibas (so far) */
-
-       dev->current_state = PCI_D3cold;
-       pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size);
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032,
-                        pci_pre_fixup_toshiba_ohci1394);
-
-static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
-{
-       if (!dmi_check_system(toshiba_ohci1394_dmi_table))
-               return; /* only applies to certain Toshibas (so far) */
-
-       /* Restore config space on Toshiba laptops */
-       pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size);
-       pci_read_config_byte(dev, PCI_INTERRUPT_LINE, (u8 *)&dev->irq);
-       pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-                              pci_resource_start(dev, 0));
-       pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
-                              pci_resource_start(dev, 1));
-}
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
-                        pci_post_fixup_toshiba_ohci1394);
-
-
-/*
- * Prevent the BIOS trapping accesses to the Cyrix CS5530A video device
- * configuration space.
- */
-static void pci_early_fixup_cyrix_5530(struct pci_dev *dev)
-{
-       u8 r;
-       /* clear 'F4 Video Configuration Trap' bit */
-       pci_read_config_byte(dev, 0x42, &r);
-       r &= 0xfd;
-       pci_write_config_byte(dev, 0x42, r);
-}
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
-                       pci_early_fixup_cyrix_5530);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
-                       pci_early_fixup_cyrix_5530);
-
-/*
- * Siemens Nixdorf AG FSC Multiprocessor Interrupt Controller:
- * prevent update of the BAR0, which doesn't look like a normal BAR.
- */
-static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev)
-{
-       dev->resource[0].flags |= IORESOURCE_PCI_FIXED;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015,
-                         pci_siemens_interrupt_controller);
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
deleted file mode 100644 (file)
index bcd2f94..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- *     Low-Level PCI Access for i386 machines
- *
- * Copyright 1993, 1994 Drew Eckhardt
- *      Visionary Computing
- *      (Unix and Linux consulting and custom programming)
- *      Drew@Colorado.EDU
- *      +1 (303) 786-7975
- *
- * Drew's work was sponsored by:
- *     iX Multiuser Multitasking Magazine
- *     Hannover, Germany
- *     hm@ix.de
- *
- * Copyright 1997--2000 Martin Mares <mj@ucw.cz>
- *
- * For more information, please consult the following manuals (look at
- * http://www.pcisig.com/ for how to get them):
- *
- * PCI BIOS Specification
- * PCI Local Bus Specification
- * PCI to PCI Bridge Specification
- * PCI System Design Guide
- *
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-
-#include "pci.h"
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void
-pcibios_align_resource(void *data, struct resource *res,
-                       resource_size_t size, resource_size_t align)
-{
-       if (res->flags & IORESOURCE_IO) {
-               resource_size_t start = res->start;
-
-               if (start & 0x300) {
-                       start = (start + 0x3ff) & ~0x3ff;
-                       res->start = start;
-               }
-       }
-}
-
-
-/*
- *  Handle resources of PCI devices.  If the world were perfect, we could
- *  just allocate all the resource regions and do nothing more.  It isn't.
- *  On the other hand, we cannot just re-allocate all devices, as it would
- *  require us to know lots of host bridge internals.  So we attempt to
- *  keep as much of the original configuration as possible, but tweak it
- *  when it's found to be wrong.
- *
- *  Known BIOS problems we have to work around:
- *     - I/O or memory regions not configured
- *     - regions configured, but not enabled in the command register
- *     - bogus I/O addresses above 64K used
- *     - expansion ROMs left enabled (this may sound harmless, but given
- *       the fact the PCI specs explicitly allow address decoders to be
- *       shared between expansion ROMs and other resource regions, it's
- *       at least dangerous)
- *
- *  Our solution:
- *     (1) Allocate resources for all buses behind PCI-to-PCI bridges.
- *         This gives us fixed barriers on where we can allocate.
- *     (2) Allocate resources for all enabled devices.  If there is
- *         a collision, just mark the resource as unallocated. Also
- *         disable expansion ROMs during this step.
- *     (3) Try to allocate resources for disabled devices.  If the
- *         resources were assigned correctly, everything goes well,
- *         if they weren't, they won't disturb allocation of other
- *         resources.
- *     (4) Assign new addresses to resources which were either
- *         not configured at all or misconfigured.  If explicitly
- *         requested by the user, configure expansion ROM address
- *         as well.
- */
-
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
-{
-       struct pci_bus *bus;
-       struct pci_dev *dev;
-       int idx;
-       struct resource *r, *pr;
-
-       /* Depth-First Search on bus tree */
-       list_for_each_entry(bus, bus_list, node) {
-               if ((dev = bus->self)) {
-                       for (idx = PCI_BRIDGE_RESOURCES;
-                           idx < PCI_NUM_RESOURCES; idx++) {
-                               r = &dev->resource[idx];
-                               if (!r->flags)
-                                       continue;
-                               pr = pci_find_parent_resource(dev, r);
-                               if (!r->start || !pr ||
-                                   request_resource(pr, r) < 0) {
-                                       printk(KERN_ERR "PCI: Cannot allocate "
-                                               "resource region %d "
-                                               "of bridge %s\n",
-                                               idx, pci_name(dev));
-                                       /*
-                                        * Something is wrong with the region.
-                                        * Invalidate the resource to prevent
-                                        * child resource allocations in this
-                                        * range.
-                                        */
-                                       r->flags = 0;
-                               }
-                       }
-               }
-               pcibios_allocate_bus_resources(&bus->children);
-       }
-}
-
-static void __init pcibios_allocate_resources(int pass)
-{
-       struct pci_dev *dev = NULL;
-       int idx, disabled;
-       u16 command;
-       struct resource *r, *pr;
-
-       for_each_pci_dev(dev) {
-               pci_read_config_word(dev, PCI_COMMAND, &command);
-               for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
-                       r = &dev->resource[idx];
-                       if (r->parent)          /* Already allocated */
-                               continue;
-                       if (!r->start)          /* Address not assigned at all */
-                               continue;
-                       if (r->flags & IORESOURCE_IO)
-                               disabled = !(command & PCI_COMMAND_IO);
-                       else
-                               disabled = !(command & PCI_COMMAND_MEMORY);
-                       if (pass == disabled) {
-                               DBG("PCI: Resource %08lx-%08lx "
-                                   "(f=%lx, d=%d, p=%d)\n",
-                                   r->start, r->end, r->flags, disabled, pass);
-                               pr = pci_find_parent_resource(dev, r);
-                               if (!pr || request_resource(pr, r) < 0) {
-                                       printk(KERN_ERR "PCI: Cannot allocate "
-                                               "resource region %d "
-                                               "of device %s\n",
-                                               idx, pci_name(dev));
-                                       /* We'll assign a new address later */
-                                       r->end -= r->start;
-                                       r->start = 0;
-                               }
-                       }
-               }
-               if (!pass) {
-                       r = &dev->resource[PCI_ROM_RESOURCE];
-                       if (r->flags & IORESOURCE_ROM_ENABLE) {
-                               /* Turn the ROM off, leave the resource region,
-                                * but keep it unregistered. */
-                               u32 reg;
-                               DBG("PCI: Switching off ROM of %s\n",
-                                       pci_name(dev));
-                               r->flags &= ~IORESOURCE_ROM_ENABLE;
-                               pci_read_config_dword(dev,
-                                               dev->rom_base_reg, &reg);
-                               pci_write_config_dword(dev, dev->rom_base_reg,
-                                               reg & ~PCI_ROM_ADDRESS_ENABLE);
-                       }
-               }
-       }
-}
-
-static int __init pcibios_assign_resources(void)
-{
-       struct pci_dev *dev = NULL;
-       struct resource *r, *pr;
-
-       if (!(pci_probe & PCI_ASSIGN_ROMS)) {
-               /*
-                * Try to use BIOS settings for ROMs, otherwise let
-                * pci_assign_unassigned_resources() allocate the new
-                * addresses.
-                */
-               for_each_pci_dev(dev) {
-                       r = &dev->resource[PCI_ROM_RESOURCE];
-                       if (!r->flags || !r->start)
-                               continue;
-                       pr = pci_find_parent_resource(dev, r);
-                       if (!pr || request_resource(pr, r) < 0) {
-                               r->end -= r->start;
-                               r->start = 0;
-                       }
-               }
-       }
-
-       pci_assign_unassigned_resources();
-
-       return 0;
-}
-
-void __init pcibios_resource_survey(void)
-{
-       DBG("PCI: Allocating resources\n");
-       pcibios_allocate_bus_resources(&pci_root_buses);
-       pcibios_allocate_resources(0);
-       pcibios_allocate_resources(1);
-}
-
-/**
- * called in fs_initcall (one below subsys_initcall),
- * give a chance for motherboard reserve resources
- */
-fs_initcall(pcibios_assign_resources);
-
-int pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
-       u16 cmd, old_cmd;
-       int idx;
-       struct resource *r;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       old_cmd = cmd;
-       for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
-               /* Only set up the requested stuff */
-               if (!(mask & (1 << idx)))
-                       continue;
-
-               r = &dev->resource[idx];
-               if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
-                       continue;
-               if ((idx == PCI_ROM_RESOURCE) &&
-                               (!(r->flags & IORESOURCE_ROM_ENABLE)))
-                       continue;
-               if (!r->start && r->end) {
-                       printk(KERN_ERR "PCI: Device %s not available "
-                               "because of resource %d collisions\n",
-                               pci_name(dev), idx);
-                       return -EINVAL;
-               }
-               if (r->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (r->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-       if (cmd != old_cmd) {
-               printk("PCI: Enabling device %s (%04x -> %04x)\n",
-                       pci_name(dev), old_cmd, cmd);
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-       }
-       return 0;
-}
-
-/*
- *  If we set up a device for bus mastering, we need to check the latency
- *  timer as certain crappy BIOSes forget to set it properly.
- */
-unsigned int pcibios_max_latency = 255;
-
-void pcibios_set_master(struct pci_dev *dev)
-{
-       u8 lat;
-       pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
-       if (lat < 16)
-               lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
-       else if (lat > pcibios_max_latency)
-               lat = pcibios_max_latency;
-       else
-               return;
-       printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n",
-               pci_name(dev), lat);
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
-}
-
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       unsigned long prot;
-
-       /* I/O space cannot be accessed via normal processor loads and
-        * stores on this platform.
-        */
-       if (mmap_state == pci_mmap_io)
-               return -EINVAL;
-
-       /* Leave vm_pgoff as-is, the PCI space address is the physical
-        * address on this platform.
-        */
-       prot = pgprot_val(vma->vm_page_prot);
-       if (boot_cpu_data.x86 > 3)
-               prot |= _PAGE_PCD | _PAGE_PWT;
-       vma->vm_page_prot = __pgprot(prot);
-
-       /* Write-combine setting is ignored, it is changed via the mtrr
-        * interfaces on this platform.
-        */
-       if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start,
-                              vma->vm_page_prot))
-               return -EAGAIN;
-
-       return 0;
-}
diff --git a/arch/i386/pci/init.c b/arch/i386/pci/init.c
deleted file mode 100644 (file)
index 3de9f9b..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <linux/pci.h>
-#include <linux/init.h>
-#include "pci.h"
-
-/* arch_initcall has too random ordering, so call the initializers
-   in the right sequence from here. */
-static __init int pci_access_init(void)
-{
-       int type __maybe_unused = 0;
-
-#ifdef CONFIG_PCI_DIRECT
-       type = pci_direct_probe();
-#endif
-#ifdef CONFIG_PCI_MMCONFIG
-       pci_mmcfg_init(type);
-#endif
-       if (raw_pci_ops)
-               return 0;
-#ifdef CONFIG_PCI_BIOS
-       pci_pcbios_init();
-#endif
-       /*
-        * don't check for raw_pci_ops here because we want pcbios as last
-        * fallback, yet it's needed to run first to set pcibios_last_bus
-        * in case legacy PCI probing is used. otherwise detecting peer busses
-        * fails.
-        */
-#ifdef CONFIG_PCI_DIRECT
-       pci_direct_init(type);
-#endif
-       if (!raw_pci_ops)
-               printk(KERN_ERR
-               "PCI: Fatal: No config space access function found\n");
-
-       return 0;
-}
-arch_initcall(pci_access_init);
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
deleted file mode 100644 (file)
index 8434f23..0000000
+++ /dev/null
@@ -1,1173 +0,0 @@
-/*
- *     Low-Level PCI Support for PC -- Routing of Interrupts
- *
- *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/dmi.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/io_apic.h>
-#include <linux/irq.h>
-#include <linux/acpi.h>
-
-#include "pci.h"
-
-#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
-#define PIRQ_VERSION 0x0100
-
-static int broken_hp_bios_irq9;
-static int acer_tm360_irqrouting;
-
-static struct irq_routing_table *pirq_table;
-
-static int pirq_enable_irq(struct pci_dev *dev);
-
-/*
- * Never use: 0, 1, 2 (timer, keyboard, and cascade)
- * Avoid using: 13, 14 and 15 (FP error and IDE).
- * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
- */
-unsigned int pcibios_irq_mask = 0xfff8;
-
-static int pirq_penalty[16] = {
-       1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
-       0, 0, 0, 0, 1000, 100000, 100000, 100000
-};
-
-struct irq_router {
-       char *name;
-       u16 vendor, device;
-       int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
-       int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
-};
-
-struct irq_router_handler {
-       u16 vendor;
-       int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
-};
-
-int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
-void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
-
-/*
- *  Check passed address for the PCI IRQ Routing Table signature
- *  and perform checksum verification.
- */
-
-static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
-{
-       struct irq_routing_table *rt;
-       int i;
-       u8 sum;
-
-       rt = (struct irq_routing_table *) addr;
-       if (rt->signature != PIRQ_SIGNATURE ||
-           rt->version != PIRQ_VERSION ||
-           rt->size % 16 ||
-           rt->size < sizeof(struct irq_routing_table))
-               return NULL;
-       sum = 0;
-       for (i=0; i < rt->size; i++)
-               sum += addr[i];
-       if (!sum) {
-               DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", rt);
-               return rt;
-       }
-       return NULL;
-}
-
-
-
-/*
- *  Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
- */
-
-static struct irq_routing_table * __init pirq_find_routing_table(void)
-{
-       u8 *addr;
-       struct irq_routing_table *rt;
-
-       if (pirq_table_addr) {
-               rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
-               if (rt)
-                       return rt;
-               printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
-       }
-       for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
-               rt = pirq_check_routing_table(addr);
-               if (rt)
-                       return rt;
-       }
-       return NULL;
-}
-
-/*
- *  If we have a IRQ routing table, use it to search for peer host
- *  bridges.  It's a gross hack, but since there are no other known
- *  ways how to get a list of buses, we have to go this way.
- */
-
-static void __init pirq_peer_trick(void)
-{
-       struct irq_routing_table *rt = pirq_table;
-       u8 busmap[256];
-       int i;
-       struct irq_info *e;
-
-       memset(busmap, 0, sizeof(busmap));
-       for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
-               e = &rt->slots[i];
-#ifdef DEBUG
-               {
-                       int j;
-                       DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
-                       for(j=0; j<4; j++)
-                               DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
-                       DBG("\n");
-               }
-#endif
-               busmap[e->bus] = 1;
-       }
-       for(i = 1; i < 256; i++) {
-               if (!busmap[i] || pci_find_bus(0, i))
-                       continue;
-               if (pci_scan_bus_with_sysdata(i))
-                       printk(KERN_INFO "PCI: Discovered primary peer "
-                              "bus %02x [IRQ]\n", i);
-       }
-       pcibios_last_bus = -1;
-}
-
-/*
- *  Code for querying and setting of IRQ routes on various interrupt routers.
- */
-
-void eisa_set_level_irq(unsigned int irq)
-{
-       unsigned char mask = 1 << (irq & 7);
-       unsigned int port = 0x4d0 + (irq >> 3);
-       unsigned char val;
-       static u16 eisa_irq_mask;
-
-       if (irq >= 16 || (1 << irq) & eisa_irq_mask)
-               return;
-
-       eisa_irq_mask |= (1 << irq);
-       printk(KERN_DEBUG "PCI: setting IRQ %u as level-triggered\n", irq);
-       val = inb(port);
-       if (!(val & mask)) {
-               DBG(KERN_DEBUG " -> edge");
-               outb(val | mask, port);
-       }
-}
-
-/*
- * Common IRQ routing practice: nybbles in config space,
- * offset by some magic constant.
- */
-static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
-{
-       u8 x;
-       unsigned reg = offset + (nr >> 1);
-
-       pci_read_config_byte(router, reg, &x);
-       return (nr & 1) ? (x >> 4) : (x & 0xf);
-}
-
-static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val)
-{
-       u8 x;
-       unsigned reg = offset + (nr >> 1);
-
-       pci_read_config_byte(router, reg, &x);
-       x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val);
-       pci_write_config_byte(router, reg, x);
-}
-
-/*
- * ALI pirq entries are damn ugly, and completely undocumented.
- * This has been figured out from pirq tables, and it's not a pretty
- * picture.
- */
-static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
-
-       return irqmap[read_config_nybble(router, 0x48, pirq-1)];
-}
-
-static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
-       unsigned int val = irqmap[irq];
-               
-       if (val) {
-               write_config_nybble(router, 0x48, pirq-1, val);
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * The Intel PIIX4 pirq rules are fairly simple: "pirq" is
- * just a pointer to the config space.
- */
-static int pirq_piix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       u8 x;
-
-       pci_read_config_byte(router, pirq, &x);
-       return (x < 16) ? x : 0;
-}
-
-static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       pci_write_config_byte(router, pirq, irq);
-       return 1;
-}
-
-/*
- * The VIA pirq rules are nibble-based, like ALI,
- * but without the ugly irq number munging.
- * However, PIRQD is in the upper instead of lower 4 bits.
- */
-static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
-}
-
-static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
-       return 1;
-}
-
-/*
- * The VIA pirq rules are nibble-based, like ALI,
- * but without the ugly irq number munging.
- * However, for 82C586, nibble map is different .
- */
-static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
-       return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
-}
-
-static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
-       write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
-       return 1;
-}
-
-/*
- * ITE 8330G pirq rules are nibble-based
- * FIXME: pirqmap may be { 1, 0, 3, 2 },
- *       2+3 are both mapped to irq 9 on my system
- */
-static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
-       return read_config_nybble(router,0x43, pirqmap[pirq-1]);
-}
-
-static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
-       write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
-       return 1;
-}
-
-/*
- * OPTI: high four bits are nibble pointer..
- * I wonder what the low bits do?
- */
-static int pirq_opti_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       return read_config_nybble(router, 0xb8, pirq >> 4);
-}
-
-static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       write_config_nybble(router, 0xb8, pirq >> 4, irq);
-       return 1;
-}
-
-/*
- * Cyrix: nibble offset 0x5C
- * 0x5C bits 7:4 is INTB bits 3:0 is INTA 
- * 0x5D bits 7:4 is INTD bits 3:0 is INTC
- */
-static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       return read_config_nybble(router, 0x5C, (pirq-1)^1);
-}
-
-static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       write_config_nybble(router, 0x5C, (pirq-1)^1, irq);
-       return 1;
-}
-
-/*
- *     PIRQ routing for SiS 85C503 router used in several SiS chipsets.
- *     We have to deal with the following issues here:
- *     - vendors have different ideas about the meaning of link values
- *     - some onboard devices (integrated in the chipset) have special
- *       links and are thus routed differently (i.e. not via PCI INTA-INTD)
- *     - different revision of the router have a different layout for
- *       the routing registers, particularly for the onchip devices
- *
- *     For all routing registers the common thing is we have one byte
- *     per routeable link which is defined as:
- *              bit 7      IRQ mapping enabled (0) or disabled (1)
- *              bits [6:4] reserved (sometimes used for onchip devices)
- *              bits [3:0] IRQ to map to
- *                  allowed: 3-7, 9-12, 14-15
- *                  reserved: 0, 1, 2, 8, 13
- *
- *     The config-space registers located at 0x41/0x42/0x43/0x44 are
- *     always used to route the normal PCI INT A/B/C/D respectively.
- *     Apparently there are systems implementing PCI routing table using
- *     link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D.
- *     We try our best to handle both link mappings.
- *     
- *     Currently (2003-05-21) it appears most SiS chipsets follow the
- *     definition of routing registers from the SiS-5595 southbridge.
- *     According to the SiS 5595 datasheets the revision id's of the
- *     router (ISA-bridge) should be 0x01 or 0xb0.
- *
- *     Furthermore we've also seen lspci dumps with revision 0x00 and 0xb1.
- *     Looks like these are used in a number of SiS 5xx/6xx/7xx chipsets.
- *     They seem to work with the current routing code. However there is
- *     some concern because of the two USB-OHCI HCs (original SiS 5595
- *     had only one). YMMV.
- *
- *     Onchip routing for router rev-id 0x01/0xb0 and probably 0x00/0xb1:
- *
- *     0x61:   IDEIRQ:
- *             bits [6:5] must be written 01
- *             bit 4 channel-select primary (0), secondary (1)
- *
- *     0x62:   USBIRQ:
- *             bit 6 OHCI function disabled (0), enabled (1)
- *     
- *     0x6a:   ACPI/SCI IRQ: bits 4-6 reserved
- *
- *     0x7e:   Data Acq. Module IRQ - bits 4-6 reserved
- *
- *     We support USBIRQ (in addition to INTA-INTD) and keep the
- *     IDE, ACPI and DAQ routing untouched as set by the BIOS.
- *
- *     Currently the only reported exception is the new SiS 65x chipset
- *     which includes the SiS 69x southbridge. Here we have the 85C503
- *     router revision 0x04 and there are changes in the register layout
- *     mostly related to the different USB HCs with USB 2.0 support.
- *
- *     Onchip routing for router rev-id 0x04 (try-and-error observation)
- *
- *     0x60/0x61/0x62/0x63:    1xEHCI and 3xOHCI (companion) USB-HCs
- *                             bit 6-4 are probably unused, not like 5595
- */
-
-#define PIRQ_SIS_IRQ_MASK      0x0f
-#define PIRQ_SIS_IRQ_DISABLE   0x80
-#define PIRQ_SIS_USB_ENABLE    0x40
-
-static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       u8 x;
-       int reg;
-
-       reg = pirq;
-       if (reg >= 0x01 && reg <= 0x04)
-               reg += 0x40;
-       pci_read_config_byte(router, reg, &x);
-       return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK);
-}
-
-static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       u8 x;
-       int reg;
-
-       reg = pirq;
-       if (reg >= 0x01 && reg <= 0x04)
-               reg += 0x40;
-       pci_read_config_byte(router, reg, &x);
-       x &= ~(PIRQ_SIS_IRQ_MASK | PIRQ_SIS_IRQ_DISABLE);
-       x |= irq ? irq: PIRQ_SIS_IRQ_DISABLE;
-       pci_write_config_byte(router, reg, x);
-       return 1;
-}
-
-
-/*
- * VLSI: nibble offset 0x74 - educated guess due to routing table and
- *       config space of VLSI 82C534 PCI-bridge/router (1004:0102)
- *       Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard
- *       devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6
- *       for the busbridge to the docking station.
- */
-
-static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       if (pirq > 8) {
-               printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
-               return 0;
-       }
-       return read_config_nybble(router, 0x74, pirq-1);
-}
-
-static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       if (pirq > 8) {
-               printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
-               return 0;
-       }
-       write_config_nybble(router, 0x74, pirq-1, irq);
-       return 1;
-}
-
-/*
- * ServerWorks: PCI interrupts mapped to system IRQ lines through Index
- * and Redirect I/O registers (0x0c00 and 0x0c01).  The Index register
- * format is (PCIIRQ## | 0x10), e.g.: PCIIRQ10=0x1a.  The Redirect
- * register is a straight binary coding of desired PIC IRQ (low nibble).
- *
- * The 'link' value in the PIRQ table is already in the correct format
- * for the Index register.  There are some special index values:
- * 0x00 for ACPI (SCI), 0x01 for USB, 0x02 for IDE0, 0x04 for IDE1,
- * and 0x03 for SMBus.
- */
-static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       outb_p(pirq, 0xc00);
-       return inb(0xc01) & 0xf;
-}
-
-static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       outb_p(pirq, 0xc00);
-       outb_p(irq, 0xc01);
-       return 1;
-}
-
-/* Support for AMD756 PCI IRQ Routing
- * Jhon H. Caicedo <jhcaiced@osso.org.co>
- * Jun/21/2001 0.2.0 Release, fixed to use "nybble" functions... (jhcaiced)
- * Jun/19/2001 Alpha Release 0.1.0 (jhcaiced)
- * The AMD756 pirq rules are nibble-based
- * offset 0x56 0-3 PIRQA  4-7  PIRQB
- * offset 0x57 0-3 PIRQC  4-7  PIRQD
- */
-static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
-       u8 irq;
-       irq = 0;
-       if (pirq <= 4)
-       {
-               irq = read_config_nybble(router, 0x56, pirq - 1);
-       }
-       printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
-               dev->vendor, dev->device, pirq, irq);
-       return irq;
-}
-
-static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", 
-               dev->vendor, dev->device, pirq, irq);
-       if (pirq <= 4)
-       {
-               write_config_nybble(router, 0x56, pirq - 1, irq);
-       }
-       return 1;
-}
-
-#ifdef CONFIG_PCI_BIOS
-
-static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
-       struct pci_dev *bridge;
-       int pin = pci_get_interrupt_pin(dev, &bridge);
-       return pcibios_set_irq_routing(bridge, pin, irq);
-}
-
-#endif
-
-static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
-{
-       static struct pci_device_id __initdata pirq_440gx[] = {
-               { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
-               { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
-               { },
-       };
-
-       /* 440GX has a proprietary PIRQ router -- don't use it */
-       if (pci_dev_present(pirq_440gx))
-               return 0;
-
-       switch(device)
-       {
-               case PCI_DEVICE_ID_INTEL_82371FB_0:
-               case PCI_DEVICE_ID_INTEL_82371SB_0:
-               case PCI_DEVICE_ID_INTEL_82371AB_0:
-               case PCI_DEVICE_ID_INTEL_82371MX:
-               case PCI_DEVICE_ID_INTEL_82443MX_0:
-               case PCI_DEVICE_ID_INTEL_82801AA_0:
-               case PCI_DEVICE_ID_INTEL_82801AB_0:
-               case PCI_DEVICE_ID_INTEL_82801BA_0:
-               case PCI_DEVICE_ID_INTEL_82801BA_10:
-               case PCI_DEVICE_ID_INTEL_82801CA_0:
-               case PCI_DEVICE_ID_INTEL_82801CA_12:
-               case PCI_DEVICE_ID_INTEL_82801DB_0:
-               case PCI_DEVICE_ID_INTEL_82801E_0:
-               case PCI_DEVICE_ID_INTEL_82801EB_0:
-               case PCI_DEVICE_ID_INTEL_ESB_1:
-               case PCI_DEVICE_ID_INTEL_ICH6_0:
-               case PCI_DEVICE_ID_INTEL_ICH6_1:
-               case PCI_DEVICE_ID_INTEL_ICH7_0:
-               case PCI_DEVICE_ID_INTEL_ICH7_1:
-               case PCI_DEVICE_ID_INTEL_ICH7_30:
-               case PCI_DEVICE_ID_INTEL_ICH7_31:
-               case PCI_DEVICE_ID_INTEL_ESB2_0:
-               case PCI_DEVICE_ID_INTEL_ICH8_0:
-               case PCI_DEVICE_ID_INTEL_ICH8_1:
-               case PCI_DEVICE_ID_INTEL_ICH8_2:
-               case PCI_DEVICE_ID_INTEL_ICH8_3:
-               case PCI_DEVICE_ID_INTEL_ICH8_4:
-               case PCI_DEVICE_ID_INTEL_ICH9_0:
-               case PCI_DEVICE_ID_INTEL_ICH9_1:
-               case PCI_DEVICE_ID_INTEL_ICH9_2:
-               case PCI_DEVICE_ID_INTEL_ICH9_3:
-               case PCI_DEVICE_ID_INTEL_ICH9_4:
-               case PCI_DEVICE_ID_INTEL_ICH9_5:
-               case PCI_DEVICE_ID_INTEL_TOLAPAI_0:
-                       r->name = "PIIX/ICH";
-                       r->get = pirq_piix_get;
-                       r->set = pirq_piix_set;
-                       return 1;
-       }
-       return 0;
-}
-
-static __init int via_router_probe(struct irq_router *r,
-                               struct pci_dev *router, u16 device)
-{
-       /* FIXME: We should move some of the quirk fixup stuff here */
-
-       /*
-        * work arounds for some buggy BIOSes
-        */
-       if (device == PCI_DEVICE_ID_VIA_82C586_0) {
-               switch(router->device) {
-               case PCI_DEVICE_ID_VIA_82C686:
-                       /*
-                        * Asus k7m bios wrongly reports 82C686A
-                        * as 586-compatible
-                        */
-                       device = PCI_DEVICE_ID_VIA_82C686;
-                       break;
-               case PCI_DEVICE_ID_VIA_8235:
-                       /**
-                        * Asus a7v-x bios wrongly reports 8235
-                        * as 586-compatible
-                        */
-                       device = PCI_DEVICE_ID_VIA_8235;
-                       break;
-               }
-       }
-
-       switch(device) {
-       case PCI_DEVICE_ID_VIA_82C586_0:
-               r->name = "VIA";
-               r->get = pirq_via586_get;
-               r->set = pirq_via586_set;
-               return 1;
-       case PCI_DEVICE_ID_VIA_82C596:
-       case PCI_DEVICE_ID_VIA_82C686:
-       case PCI_DEVICE_ID_VIA_8231:
-       case PCI_DEVICE_ID_VIA_8233A:
-       case PCI_DEVICE_ID_VIA_8235:
-       case PCI_DEVICE_ID_VIA_8237:
-               /* FIXME: add new ones for 8233/5 */
-               r->name = "VIA";
-               r->get = pirq_via_get;
-               r->set = pirq_via_set;
-               return 1;
-       }
-       return 0;
-}
-
-static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
-{
-       switch(device)
-       {
-               case PCI_DEVICE_ID_VLSI_82C534:
-                       r->name = "VLSI 82C534";
-                       r->get = pirq_vlsi_get;
-                       r->set = pirq_vlsi_set;
-                       return 1;
-       }
-       return 0;
-}
-
-
-static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
-{
-       switch(device)
-       {
-               case PCI_DEVICE_ID_SERVERWORKS_OSB4:
-               case PCI_DEVICE_ID_SERVERWORKS_CSB5:
-                       r->name = "ServerWorks";
-                       r->get = pirq_serverworks_get;
-                       r->set = pirq_serverworks_set;
-                       return 1;
-       }
-       return 0;
-}
-
-static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
-{
-       if (device != PCI_DEVICE_ID_SI_503)
-               return 0;
-               
-       r->name = "SIS";
-       r->get = pirq_sis_get;
-       r->set = pirq_sis_set;
-       return 1;
-}
-
-static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
-{
-       switch(device)
-       {
-               case PCI_DEVICE_ID_CYRIX_5520:
-                       r->name = "NatSemi";
-                       r->get = pirq_cyrix_get;
-                       r->set = pirq_cyrix_set;
-                       return 1;
-       }
-       return 0;
-}
-
-static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
-{
-       switch(device)
-       {
-               case PCI_DEVICE_ID_OPTI_82C700:
-                       r->name = "OPTI";
-                       r->get = pirq_opti_get;
-                       r->set = pirq_opti_set;
-                       return 1;
-       }
-       return 0;
-}
-
-static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
-{
-       switch(device)
-       {
-               case PCI_DEVICE_ID_ITE_IT8330G_0:
-                       r->name = "ITE";
-                       r->get = pirq_ite_get;
-                       r->set = pirq_ite_set;
-                       return 1;
-       }
-       return 0;
-}
-
-static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
-{
-       switch(device)
-       {
-       case PCI_DEVICE_ID_AL_M1533:
-       case PCI_DEVICE_ID_AL_M1563:
-               printk(KERN_DEBUG "PCI: Using ALI IRQ Router\n");
-               r->name = "ALI";
-               r->get = pirq_ali_get;
-               r->set = pirq_ali_set;
-               return 1;
-       }
-       return 0;
-}
-
-static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
-{
-       switch(device)
-       {
-               case PCI_DEVICE_ID_AMD_VIPER_740B:
-                       r->name = "AMD756";
-                       break;
-               case PCI_DEVICE_ID_AMD_VIPER_7413:
-                       r->name = "AMD766";
-                       break;
-               case PCI_DEVICE_ID_AMD_VIPER_7443:
-                       r->name = "AMD768";
-                       break;
-               default:
-                       return 0;
-       }
-       r->get = pirq_amd756_get;
-       r->set = pirq_amd756_set;
-       return 1;
-}
-               
-static __initdata struct irq_router_handler pirq_routers[] = {
-       { PCI_VENDOR_ID_INTEL, intel_router_probe },
-       { PCI_VENDOR_ID_AL, ali_router_probe },
-       { PCI_VENDOR_ID_ITE, ite_router_probe },
-       { PCI_VENDOR_ID_VIA, via_router_probe },
-       { PCI_VENDOR_ID_OPTI, opti_router_probe },
-       { PCI_VENDOR_ID_SI, sis_router_probe },
-       { PCI_VENDOR_ID_CYRIX, cyrix_router_probe },
-       { PCI_VENDOR_ID_VLSI, vlsi_router_probe },
-       { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
-       { PCI_VENDOR_ID_AMD, amd_router_probe },
-       /* Someone with docs needs to add the ATI Radeon IGP */
-       { 0, NULL }
-};
-static struct irq_router pirq_router;
-static struct pci_dev *pirq_router_dev;
-
-
-/*
- *     FIXME: should we have an option to say "generic for
- *     chipset" ?
- */
-static void __init pirq_find_router(struct irq_router *r)
-{
-       struct irq_routing_table *rt = pirq_table;
-       struct irq_router_handler *h;
-
-#ifdef CONFIG_PCI_BIOS
-       if (!rt->signature) {
-               printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n");
-               r->set = pirq_bios_set;
-               r->name = "BIOS";
-               return;
-       }
-#endif
-
-       /* Default unless a driver reloads it */
-       r->name = "default";
-       r->get = NULL;
-       r->set = NULL;
-       
-       DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n",
-           rt->rtr_vendor, rt->rtr_device);
-
-       pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn);
-       if (!pirq_router_dev) {
-               DBG(KERN_DEBUG "PCI: Interrupt router not found at "
-                       "%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
-               return;
-       }
-
-       for( h = pirq_routers; h->vendor; h++) {
-               /* First look for a router match */
-               if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device))
-                       break;
-               /* Fall back to a device match */
-               if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device))
-                       break;
-       }
-       printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
-               pirq_router.name,
-               pirq_router_dev->vendor,
-               pirq_router_dev->device,
-               pci_name(pirq_router_dev));
-
-       /* The device remains referenced for the kernel lifetime */
-}
-
-static struct irq_info *pirq_get_info(struct pci_dev *dev)
-{
-       struct irq_routing_table *rt = pirq_table;
-       int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
-       struct irq_info *info;
-
-       for (info = rt->slots; entries--; info++)
-               if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
-                       return info;
-       return NULL;
-}
-
-static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
-{
-       u8 pin;
-       struct irq_info *info;
-       int i, pirq, newirq;
-       int irq = 0;
-       u32 mask;
-       struct irq_router *r = &pirq_router;
-       struct pci_dev *dev2 = NULL;
-       char *msg = NULL;
-
-       /* Find IRQ pin */
-       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-       if (!pin) {
-               DBG(KERN_DEBUG " -> no interrupt pin\n");
-               return 0;
-       }
-       pin = pin - 1;
-
-       /* Find IRQ routing entry */
-
-       if (!pirq_table)
-               return 0;
-       
-       DBG(KERN_DEBUG "IRQ for %s[%c]", pci_name(dev), 'A' + pin);
-       info = pirq_get_info(dev);
-       if (!info) {
-               DBG(" -> not found in routing table\n" KERN_DEBUG);
-               return 0;
-       }
-       pirq = info->irq[pin].link;
-       mask = info->irq[pin].bitmap;
-       if (!pirq) {
-               DBG(" -> not routed\n" KERN_DEBUG);
-               return 0;
-       }
-       DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
-       mask &= pcibios_irq_mask;
-
-       /* Work around broken HP Pavilion Notebooks which assign USB to
-          IRQ 9 even though it is actually wired to IRQ 11 */
-
-       if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) {
-               dev->irq = 11;
-               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
-               r->set(pirq_router_dev, dev, pirq, 11);
-       }
-
-       /* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */
-       if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) {
-               pirq = 0x68;
-               mask = 0x400;
-               dev->irq = r->get(pirq_router_dev, dev, pirq);
-               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-       }
-
-       /*
-        * Find the best IRQ to assign: use the one
-        * reported by the device if possible.
-        */
-       newirq = dev->irq;
-       if (newirq && !((1 << newirq) & mask)) {
-               if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0;
-               else printk("\n" KERN_WARNING
-                       "PCI: IRQ %i for device %s doesn't match PIRQ mask "
-                       "- try pci=usepirqmask\n" KERN_DEBUG, newirq,
-                       pci_name(dev));
-       }
-       if (!newirq && assign) {
-               for (i = 0; i < 16; i++) {
-                       if (!(mask & (1 << i)))
-                               continue;
-                       if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, IRQF_SHARED))
-                               newirq = i;
-               }
-       }
-       DBG(" -> newirq=%d", newirq);
-
-       /* Check if it is hardcoded */
-       if ((pirq & 0xf0) == 0xf0) {
-               irq = pirq & 0xf;
-               DBG(" -> hardcoded IRQ %d\n", irq);
-               msg = "Hardcoded";
-       } else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
-       ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
-               DBG(" -> got IRQ %d\n", irq);
-               msg = "Found";
-               eisa_set_level_irq(irq);
-       } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
-               DBG(" -> assigning IRQ %d", newirq);
-               if (r->set(pirq_router_dev, dev, pirq, newirq)) {
-                       eisa_set_level_irq(newirq);
-                       DBG(" ... OK\n");
-                       msg = "Assigned";
-                       irq = newirq;
-               }
-       }
-
-       if (!irq) {
-               DBG(" ... failed\n");
-               if (newirq && mask == (1 << newirq)) {
-                       msg = "Guessed";
-                       irq = newirq;
-               } else
-                       return 0;
-       }
-       printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, pci_name(dev));
-
-       /* Update IRQ for all devices with the same pirq value */
-       while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
-               pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
-               if (!pin)
-                       continue;
-               pin--;
-               info = pirq_get_info(dev2);
-               if (!info)
-                       continue;
-               if (info->irq[pin].link == pirq) {
-                       /* We refuse to override the dev->irq information. Give a warning! */
-                       if ( dev2->irq && dev2->irq != irq && \
-                       (!(pci_probe & PCI_USE_PIRQ_MASK) || \
-                       ((1 << dev2->irq) & mask)) ) {
-#ifndef CONFIG_PCI_MSI
-                               printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
-                                      pci_name(dev2), dev2->irq, irq);
-#endif
-                               continue;
-                       }
-                       dev2->irq = irq;
-                       pirq_penalty[irq]++;
-                       if (dev != dev2)
-                               printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, pci_name(dev2));
-               }
-       }
-       return 1;
-}
-
-static void __init pcibios_fixup_irqs(void)
-{
-       struct pci_dev *dev = NULL;
-       u8 pin;
-
-       DBG(KERN_DEBUG "PCI: IRQ fixup\n");
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               /*
-                * If the BIOS has set an out of range IRQ number, just ignore it.
-                * Also keep track of which IRQ's are already in use.
-                */
-               if (dev->irq >= 16) {
-                       DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq);
-                       dev->irq = 0;
-               }
-               /* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
-               if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000)
-                       pirq_penalty[dev->irq] = 0;
-               pirq_penalty[dev->irq]++;
-       }
-
-       dev = NULL;
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-#ifdef CONFIG_X86_IO_APIC
-               /*
-                * Recalculate IRQ numbers if we use the I/O APIC.
-                */
-               if (io_apic_assign_pci_irqs)
-               {
-                       int irq;
-
-                       if (pin) {
-                               pin--;          /* interrupt pins are numbered starting from 1 */
-                               irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
-       /*
-        * Busses behind bridges are typically not listed in the MP-table.
-        * In this case we have to look up the IRQ based on the parent bus,
-        * parent slot, and pin number. The SMP code detects such bridged
-        * busses itself so we should get into this branch reliably.
-        */
-                               if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
-                                       struct pci_dev * bridge = dev->bus->self;
-
-                                       pin = (pin + PCI_SLOT(dev->devfn)) % 4;
-                                       irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
-                                                       PCI_SLOT(bridge->devfn), pin);
-                                       if (irq >= 0)
-                                               printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
-                                                       pci_name(bridge), 'A' + pin, irq);
-                               }
-                               if (irq >= 0) {
-                                       printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
-                                               pci_name(dev), 'A' + pin, irq);
-                                       dev->irq = irq;
-                               }
-                       }
-               }
-#endif
-               /*
-                * Still no IRQ? Try to lookup one...
-                */
-               if (pin && !dev->irq)
-                       pcibios_lookup_irq(dev, 0);
-       }
-}
-
-/*
- * Work around broken HP Pavilion Notebooks which assign USB to
- * IRQ 9 even though it is actually wired to IRQ 11
- */
-static int __init fix_broken_hp_bios_irq9(struct dmi_system_id *d)
-{
-       if (!broken_hp_bios_irq9) {
-               broken_hp_bios_irq9 = 1;
-               printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
-       }
-       return 0;
-}
-
-/*
- * Work around broken Acer TravelMate 360 Notebooks which assign
- * Cardbus to IRQ 11 even though it is actually wired to IRQ 10
- */
-static int __init fix_acer_tm360_irqrouting(struct dmi_system_id *d)
-{
-       if (!acer_tm360_irqrouting) {
-               acer_tm360_irqrouting = 1;
-               printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
-       }
-       return 0;
-}
-
-static struct dmi_system_id __initdata pciirq_dmi_table[] = {
-       {
-               .callback = fix_broken_hp_bios_irq9,
-               .ident = "HP Pavilion N5400 Series Laptop",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
-               },
-       },
-       {
-               .callback = fix_acer_tm360_irqrouting,
-               .ident = "Acer TravelMate 36x Laptop",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
-               },
-       },
-       { }
-};
-
-static int __init pcibios_irq_init(void)
-{
-       DBG(KERN_DEBUG "PCI: IRQ init\n");
-
-       if (pcibios_enable_irq || raw_pci_ops == NULL)
-               return 0;
-
-       dmi_check_system(pciirq_dmi_table);
-
-       pirq_table = pirq_find_routing_table();
-
-#ifdef CONFIG_PCI_BIOS
-       if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
-               pirq_table = pcibios_get_irq_routing_table();
-#endif
-       if (pirq_table) {
-               pirq_peer_trick();
-               pirq_find_router(&pirq_router);
-               if (pirq_table->exclusive_irqs) {
-                       int i;
-                       for (i=0; i<16; i++)
-                               if (!(pirq_table->exclusive_irqs & (1 << i)))
-                                       pirq_penalty[i] += 100;
-               }
-               /* If we're using the I/O APIC, avoid using the PCI IRQ routing table */
-               if (io_apic_assign_pci_irqs)
-                       pirq_table = NULL;
-       }
-
-       pcibios_enable_irq = pirq_enable_irq;
-
-       pcibios_fixup_irqs();
-       return 0;
-}
-
-subsys_initcall(pcibios_irq_init);
-
-
-static void pirq_penalize_isa_irq(int irq, int active)
-{
-       /*
-        *  If any ISAPnP device reports an IRQ in its list of possible
-        *  IRQ's, we try to avoid assigning it to PCI devices.
-        */
-       if (irq < 16) {
-               if (active)
-                       pirq_penalty[irq] += 1000;
-               else
-                       pirq_penalty[irq] += 100;
-       }
-}
-
-void pcibios_penalize_isa_irq(int irq, int active)
-{
-#ifdef CONFIG_ACPI
-       if (!acpi_noirq)
-               acpi_penalize_isa_irq(irq, active);
-       else
-#endif
-               pirq_penalize_isa_irq(irq, active);
-}
-
-static int pirq_enable_irq(struct pci_dev *dev)
-{
-       u8 pin;
-       struct pci_dev *temp_dev;
-
-       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-       if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
-               char *msg = "";
-
-               pin--;          /* interrupt pins are numbered starting from 1 */
-
-               if (io_apic_assign_pci_irqs) {
-                       int irq;
-
-                       irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
-                       /*
-                        * Busses behind bridges are typically not listed in the MP-table.
-                        * In this case we have to look up the IRQ based on the parent bus,
-                        * parent slot, and pin number. The SMP code detects such bridged
-                        * busses itself so we should get into this branch reliably.
-                        */
-                       temp_dev = dev;
-                       while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
-                               struct pci_dev * bridge = dev->bus->self;
-
-                               pin = (pin + PCI_SLOT(dev->devfn)) % 4;
-                               irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
-                                               PCI_SLOT(bridge->devfn), pin);
-                               if (irq >= 0)
-                                       printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
-                                               pci_name(bridge), 'A' + pin, irq);
-                               dev = bridge;
-                       }
-                       dev = temp_dev;
-                       if (irq >= 0) {
-                               printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
-                                       pci_name(dev), 'A' + pin, irq);
-                               dev->irq = irq;
-                               return 0;
-                       } else
-                               msg = " Probably buggy MP table.";
-               } else if (pci_probe & PCI_BIOS_IRQ_SCAN)
-                       msg = "";
-               else
-                       msg = " Please try using pci=biosirq.";
-
-               /* With IDE legacy devices the IRQ lookup failure is not a problem.. */
-               if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
-                       return 0;
-
-               printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
-                      'A' + pin, pci_name(dev), msg);
-       }
-       return 0;
-}
diff --git a/arch/i386/pci/legacy.c b/arch/i386/pci/legacy.c
deleted file mode 100644 (file)
index 5565d70..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * legacy.c - traditional, old school PCI bus probing
- */
-#include <linux/init.h>
-#include <linux/pci.h>
-#include "pci.h"
-
-/*
- * Discover remaining PCI buses in case there are peer host bridges.
- * We use the number of last PCI bus provided by the PCI BIOS.
- */
-static void __devinit pcibios_fixup_peer_bridges(void)
-{
-       int n, devfn;
-
-       if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
-               return;
-       DBG("PCI: Peer bridge fixup\n");
-
-       for (n=0; n <= pcibios_last_bus; n++) {
-               u32 l;
-               if (pci_find_bus(0, n))
-                       continue;
-               for (devfn = 0; devfn < 256; devfn += 8) {
-                       if (!raw_pci_ops->read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
-                           l != 0x0000 && l != 0xffff) {
-                               DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
-                               printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
-                               pci_scan_bus_with_sysdata(n);
-                               break;
-                       }
-               }
-       }
-}
-
-static int __init pci_legacy_init(void)
-{
-       if (!raw_pci_ops) {
-               printk("PCI: System does not support PCI\n");
-               return 0;
-       }
-
-       if (pcibios_scanned++)
-               return 0;
-
-       printk("PCI: Probing PCI hardware\n");
-       pci_root_bus = pcibios_scan_root(0);
-       if (pci_root_bus)
-               pci_bus_add_devices(pci_root_bus);
-
-       pcibios_fixup_peer_bridges();
-
-       return 0;
-}
-
-subsys_initcall(pci_legacy_init);
diff --git a/arch/i386/pci/mmconfig-shared.c b/arch/i386/pci/mmconfig-shared.c
deleted file mode 100644 (file)
index 4df637e..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * mmconfig-shared.c - Low-level direct PCI config space access via
- *                     MMCONFIG - common code between i386 and x86-64.
- *
- * This code does:
- * - known chipset handling
- * - ACPI decoding and validation
- *
- * Per-architecture code takes care of the mappings and accesses
- * themselves.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/bitmap.h>
-#include <asm/e820.h>
-
-#include "pci.h"
-
-/* aperture is up to 256MB but BIOS may reserve less */
-#define MMCONFIG_APER_MIN      (2 * 1024*1024)
-#define MMCONFIG_APER_MAX      (256 * 1024*1024)
-
-DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
-
-/* Indicate if the mmcfg resources have been placed into the resource table. */
-static int __initdata pci_mmcfg_resources_inserted;
-
-/* K8 systems have some devices (typically in the builtin northbridge)
-   that are only accessible using type1
-   Normally this can be expressed in the MCFG by not listing them
-   and assigning suitable _SEGs, but this isn't implemented in some BIOS.
-   Instead try to discover all devices on bus 0 that are unreachable using MM
-   and fallback for them. */
-static void __init unreachable_devices(void)
-{
-       int i, bus;
-       /* Use the max bus number from ACPI here? */
-       for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
-               for (i = 0; i < 32; i++) {
-                       unsigned int devfn = PCI_DEVFN(i, 0);
-                       u32 val1, val2;
-
-                       pci_conf1_read(0, bus, devfn, 0, 4, &val1);
-                       if (val1 == 0xffffffff)
-                               continue;
-
-                       if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
-                               raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
-                               if (val1 == val2)
-                                       continue;
-                       }
-                       set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
-                       printk(KERN_NOTICE "PCI: No mmconfig possible on device"
-                              " %02x:%02x\n", bus, i);
-               }
-       }
-}
-
-static const char __init *pci_mmcfg_e7520(void)
-{
-       u32 win;
-       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
-
-       win = win & 0xf000;
-       if(win == 0x0000 || win == 0xf000)
-               pci_mmcfg_config_num = 0;
-       else {
-               pci_mmcfg_config_num = 1;
-               pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
-               if (!pci_mmcfg_config)
-                       return NULL;
-               pci_mmcfg_config[0].address = win << 16;
-               pci_mmcfg_config[0].pci_segment = 0;
-               pci_mmcfg_config[0].start_bus_number = 0;
-               pci_mmcfg_config[0].end_bus_number = 255;
-       }
-
-       return "Intel Corporation E7520 Memory Controller Hub";
-}
-
-static const char __init *pci_mmcfg_intel_945(void)
-{
-       u32 pciexbar, mask = 0, len = 0;
-
-       pci_mmcfg_config_num = 1;
-
-       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
-
-       /* Enable bit */
-       if (!(pciexbar & 1))
-               pci_mmcfg_config_num = 0;
-
-       /* Size bits */
-       switch ((pciexbar >> 1) & 3) {
-       case 0:
-               mask = 0xf0000000U;
-               len  = 0x10000000U;
-               break;
-       case 1:
-               mask = 0xf8000000U;
-               len  = 0x08000000U;
-               break;
-       case 2:
-               mask = 0xfc000000U;
-               len  = 0x04000000U;
-               break;
-       default:
-               pci_mmcfg_config_num = 0;
-       }
-
-       /* Errata #2, things break when not aligned on a 256Mb boundary */
-       /* Can only happen in 64M/128M mode */
-
-       if ((pciexbar & mask) & 0x0fffffffU)
-               pci_mmcfg_config_num = 0;
-
-       /* Don't hit the APIC registers and their friends */
-       if ((pciexbar & mask) >= 0xf0000000U)
-               pci_mmcfg_config_num = 0;
-
-       if (pci_mmcfg_config_num) {
-               pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
-               if (!pci_mmcfg_config)
-                       return NULL;
-               pci_mmcfg_config[0].address = pciexbar & mask;
-               pci_mmcfg_config[0].pci_segment = 0;
-               pci_mmcfg_config[0].start_bus_number = 0;
-               pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
-       }
-
-       return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
-}
-
-struct pci_mmcfg_hostbridge_probe {
-       u32 vendor;
-       u32 device;
-       const char *(*probe)(void);
-};
-
-static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
-};
-
-static int __init pci_mmcfg_check_hostbridge(void)
-{
-       u32 l;
-       u16 vendor, device;
-       int i;
-       const char *name;
-
-       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
-       vendor = l & 0xffff;
-       device = (l >> 16) & 0xffff;
-
-       pci_mmcfg_config_num = 0;
-       pci_mmcfg_config = NULL;
-       name = NULL;
-
-       for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
-               if (pci_mmcfg_probes[i].vendor == vendor &&
-                   pci_mmcfg_probes[i].device == device)
-                       name = pci_mmcfg_probes[i].probe();
-       }
-
-       if (name) {
-               printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
-                      name, pci_mmcfg_config_num ? "with" : "without");
-       }
-
-       return name != NULL;
-}
-
-static void __init pci_mmcfg_insert_resources(unsigned long resource_flags)
-{
-#define PCI_MMCFG_RESOURCE_NAME_LEN 19
-       int i;
-       struct resource *res;
-       char *names;
-       unsigned num_buses;
-
-       res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
-                       pci_mmcfg_config_num, GFP_KERNEL);
-       if (!res) {
-               printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
-               return;
-       }
-
-       names = (void *)&res[pci_mmcfg_config_num];
-       for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
-               struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
-               num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
-               res->name = names;
-               snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
-                        cfg->pci_segment);
-               res->start = cfg->address;
-               res->end = res->start + (num_buses << 20) - 1;
-               res->flags = IORESOURCE_MEM | resource_flags;
-               insert_resource(&iomem_resource, res);
-               names += PCI_MMCFG_RESOURCE_NAME_LEN;
-       }
-
-       /* Mark that the resources have been inserted. */
-       pci_mmcfg_resources_inserted = 1;
-}
-
-static void __init pci_mmcfg_reject_broken(int type)
-{
-       typeof(pci_mmcfg_config[0]) *cfg;
-
-       if ((pci_mmcfg_config_num == 0) ||
-           (pci_mmcfg_config == NULL) ||
-           (pci_mmcfg_config[0].address == 0))
-               return;
-
-       cfg = &pci_mmcfg_config[0];
-
-       /*
-        * Handle more broken MCFG tables on Asus etc.
-        * They only contain a single entry for bus 0-0.
-        */
-       if (pci_mmcfg_config_num == 1 &&
-           cfg->pci_segment == 0 &&
-           (cfg->start_bus_number | cfg->end_bus_number) == 0) {
-               printk(KERN_ERR "PCI: start and end of bus number is 0. "
-                      "Rejected as broken MCFG.\n");
-               goto reject;
-       }
-
-       /*
-        * Only do this check when type 1 works. If it doesn't work
-        * assume we run on a Mac and always use MCFG
-        */
-       if (type == 1 && !e820_all_mapped(cfg->address,
-                                         cfg->address + MMCONFIG_APER_MIN,
-                                         E820_RESERVED)) {
-               printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
-                      " E820-reserved\n", cfg->address);
-               goto reject;
-       }
-       return;
-
-reject:
-       printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
-       kfree(pci_mmcfg_config);
-       pci_mmcfg_config = NULL;
-       pci_mmcfg_config_num = 0;
-}
-
-void __init pci_mmcfg_init(int type)
-{
-       int known_bridge = 0;
-
-       if ((pci_probe & PCI_PROBE_MMCONF) == 0)
-               return;
-
-       if (type == 1 && pci_mmcfg_check_hostbridge())
-               known_bridge = 1;
-
-       if (!known_bridge) {
-               acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
-               pci_mmcfg_reject_broken(type);
-       }
-
-       if ((pci_mmcfg_config_num == 0) ||
-           (pci_mmcfg_config == NULL) ||
-           (pci_mmcfg_config[0].address == 0))
-               return;
-
-       if (pci_mmcfg_arch_init()) {
-               if (type == 1)
-                       unreachable_devices();
-               if (known_bridge)
-                       pci_mmcfg_insert_resources(IORESOURCE_BUSY);
-               pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
-       } else {
-               /*
-                * Signal not to attempt to insert mmcfg resources because
-                * the architecture mmcfg setup could not initialize.
-                */
-               pci_mmcfg_resources_inserted = 1;
-       }
-}
-
-static int __init pci_mmcfg_late_insert_resources(void)
-{
-       /*
-        * If resources are already inserted or we are not using MMCONFIG,
-        * don't insert the resources.
-        */
-       if ((pci_mmcfg_resources_inserted == 1) ||
-           (pci_probe & PCI_PROBE_MMCONF) == 0 ||
-           (pci_mmcfg_config_num == 0) ||
-           (pci_mmcfg_config == NULL) ||
-           (pci_mmcfg_config[0].address == 0))
-               return 1;
-
-       /*
-        * Attempt to insert the mmcfg resources but not with the busy flag
-        * marked so it won't cause request errors when __request_region is
-        * called.
-        */
-       pci_mmcfg_insert_resources(0);
-
-       return 0;
-}
-
-/*
- * Perform MMCONFIG resource insertion after PCI initialization to allow for
- * misprogrammed MCFG tables that state larger sizes but actually conflict
- * with other system resources.
- */
-late_initcall(pci_mmcfg_late_insert_resources);
diff --git a/arch/i386/pci/mmconfig_32.c b/arch/i386/pci/mmconfig_32.c
deleted file mode 100644 (file)
index 1bf5816..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx>
- * Copyright (C) 2004 Intel Corp.
- *
- * This code is released under the GNU General Public License version 2.
- */
-
-/*
- * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <asm/e820.h>
-#include "pci.h"
-
-/* Assume systems with more busses have correct MCFG */
-#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
-
-/* The base address of the last MMCONFIG device accessed */
-static u32 mmcfg_last_accessed_device;
-static int mmcfg_last_accessed_cpu;
-
-/*
- * Functions for accessing PCI configuration space with MMCONFIG accesses
- */
-static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
-{
-       struct acpi_mcfg_allocation *cfg;
-       int cfg_num;
-
-       if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
-           test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
-               return 0;
-
-       for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
-               cfg = &pci_mmcfg_config[cfg_num];
-               if (cfg->pci_segment == seg &&
-                   (cfg->start_bus_number <= bus) &&
-                   (cfg->end_bus_number >= bus))
-                       return cfg->address;
-       }
-
-       /* Fall back to type 0 */
-       return 0;
-}
-
-/*
- * This is always called under pci_config_lock
- */
-static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
-{
-       u32 dev_base = base | (bus << 20) | (devfn << 12);
-       int cpu = smp_processor_id();
-       if (dev_base != mmcfg_last_accessed_device ||
-           cpu != mmcfg_last_accessed_cpu) {
-               mmcfg_last_accessed_device = dev_base;
-               mmcfg_last_accessed_cpu = cpu;
-               set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
-       }
-}
-
-static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
-                         unsigned int devfn, int reg, int len, u32 *value)
-{
-       unsigned long flags;
-       u32 base;
-
-       if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
-               *value = -1;
-               return -EINVAL;
-       }
-
-       base = get_base_addr(seg, bus, devfn);
-       if (!base)
-               return pci_conf1_read(seg,bus,devfn,reg,len,value);
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       pci_exp_set_dev_base(base, bus, devfn);
-
-       switch (len) {
-       case 1:
-               *value = mmio_config_readb(mmcfg_virt_addr + reg);
-               break;
-       case 2:
-               *value = mmio_config_readw(mmcfg_virt_addr + reg);
-               break;
-       case 4:
-               *value = mmio_config_readl(mmcfg_virt_addr + reg);
-               break;
-       }
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return 0;
-}
-
-static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
-                          unsigned int devfn, int reg, int len, u32 value)
-{
-       unsigned long flags;
-       u32 base;
-
-       if ((bus > 255) || (devfn > 255) || (reg > 4095))
-               return -EINVAL;
-
-       base = get_base_addr(seg, bus, devfn);
-       if (!base)
-               return pci_conf1_write(seg,bus,devfn,reg,len,value);
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       pci_exp_set_dev_base(base, bus, devfn);
-
-       switch (len) {
-       case 1:
-               mmio_config_writeb(mmcfg_virt_addr + reg, value);
-               break;
-       case 2:
-               mmio_config_writew(mmcfg_virt_addr + reg, value);
-               break;
-       case 4:
-               mmio_config_writel(mmcfg_virt_addr + reg, value);
-               break;
-       }
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return 0;
-}
-
-static struct pci_raw_ops pci_mmcfg = {
-       .read =         pci_mmcfg_read,
-       .write =        pci_mmcfg_write,
-};
-
-int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
-                                   unsigned int devfn)
-{
-       return get_base_addr(seg, bus, devfn) != 0;
-}
-
-int __init pci_mmcfg_arch_init(void)
-{
-       printk(KERN_INFO "PCI: Using MMCONFIG\n");
-       raw_pci_ops = &pci_mmcfg;
-       return 1;
-}
diff --git a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c
deleted file mode 100644 (file)
index f5f165f..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * numa.c - Low-level PCI access for NUMA-Q machines
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/nodemask.h>
-#include "pci.h"
-
-#define BUS2QUAD(global) (mp_bus_id_to_node[global])
-#define BUS2LOCAL(global) (mp_bus_id_to_local[global])
-#define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
-
-#define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
-       (0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
-
-static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
-                            unsigned int devfn, int reg, int len, u32 *value)
-{
-       unsigned long flags;
-
-       if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
-               return -EINVAL;
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus));
-
-       switch (len) {
-       case 1:
-               *value = inb_quad(0xCFC + (reg & 3), BUS2QUAD(bus));
-               break;
-       case 2:
-               *value = inw_quad(0xCFC + (reg & 2), BUS2QUAD(bus));
-               break;
-       case 4:
-               *value = inl_quad(0xCFC, BUS2QUAD(bus));
-               break;
-       }
-
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return 0;
-}
-
-static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
-                             unsigned int devfn, int reg, int len, u32 value)
-{
-       unsigned long flags;
-
-       if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
-               return -EINVAL;
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus));
-
-       switch (len) {
-       case 1:
-               outb_quad((u8)value, 0xCFC + (reg & 3), BUS2QUAD(bus));
-               break;
-       case 2:
-               outw_quad((u16)value, 0xCFC + (reg & 2), BUS2QUAD(bus));
-               break;
-       case 4:
-               outl_quad((u32)value, 0xCFC, BUS2QUAD(bus));
-               break;
-       }
-
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return 0;
-}
-
-#undef PCI_CONF1_MQ_ADDRESS
-
-static struct pci_raw_ops pci_direct_conf1_mq = {
-       .read   = pci_conf1_mq_read,
-       .write  = pci_conf1_mq_write
-};
-
-
-static void __devinit pci_fixup_i450nx(struct pci_dev *d)
-{
-       /*
-        * i450NX -- Find and scan all secondary buses on all PXB's.
-        */
-       int pxb, reg;
-       u8 busno, suba, subb;
-       int quad = BUS2QUAD(d->bus->number);
-
-       printk("PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
-       reg = 0xd0;
-       for(pxb=0; pxb<2; pxb++) {
-               pci_read_config_byte(d, reg++, &busno);
-               pci_read_config_byte(d, reg++, &suba);
-               pci_read_config_byte(d, reg++, &subb);
-               DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
-               if (busno) {
-                       /* Bus A */
-                       pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
-               }
-               if (suba < subb) {
-                       /* Bus B */
-                       pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1));
-               }
-       }
-       pcibios_last_bus = -1;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
-
-static int __init pci_numa_init(void)
-{
-       int quad;
-
-       raw_pci_ops = &pci_direct_conf1_mq;
-
-       if (pcibios_scanned++)
-               return 0;
-
-       pci_root_bus = pcibios_scan_root(0);
-       if (pci_root_bus)
-               pci_bus_add_devices(pci_root_bus);
-       if (num_online_nodes() > 1)
-               for_each_online_node(quad) {
-                       if (quad == 0)
-                               continue;
-                       printk("Scanning PCI bus %d for quad %d\n", 
-                               QUADLOCAL2BUS(quad,0), quad);
-                       pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0));
-               }
-       return 0;
-}
-
-subsys_initcall(pci_numa_init);
diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c
deleted file mode 100644 (file)
index 10ac8c3..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * BIOS32 and PCI BIOS handling.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include "pci.h"
-#include "pci-functions.h"
-
-
-/* BIOS32 signature: "_32_" */
-#define BIOS32_SIGNATURE       (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
-
-/* PCI signature: "PCI " */
-#define PCI_SIGNATURE          (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
-
-/* PCI service signature: "$PCI" */
-#define PCI_SERVICE            (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
-
-/* PCI BIOS hardware mechanism flags */
-#define PCIBIOS_HW_TYPE1               0x01
-#define PCIBIOS_HW_TYPE2               0x02
-#define PCIBIOS_HW_TYPE1_SPEC          0x10
-#define PCIBIOS_HW_TYPE2_SPEC          0x20
-
-/*
- * This is the standard structure used to identify the entry point
- * to the BIOS32 Service Directory, as documented in
- *     Standard BIOS 32-bit Service Directory Proposal
- *     Revision 0.4 May 24, 1993
- *     Phoenix Technologies Ltd.
- *     Norwood, MA
- * and the PCI BIOS specification.
- */
-
-union bios32 {
-       struct {
-               unsigned long signature;        /* _32_ */
-               unsigned long entry;            /* 32 bit physical address */
-               unsigned char revision;         /* Revision level, 0 */
-               unsigned char length;           /* Length in paragraphs should be 01 */
-               unsigned char checksum;         /* All bytes must add up to zero */
-               unsigned char reserved[5];      /* Must be zero */
-       } fields;
-       char chars[16];
-};
-
-/*
- * Physical address of the service directory.  I don't know if we're
- * allowed to have more than one of these or not, so just in case
- * we'll make pcibios_present() take a memory start parameter and store
- * the array there.
- */
-
-static struct {
-       unsigned long address;
-       unsigned short segment;
-} bios32_indirect = { 0, __KERNEL_CS };
-
-/*
- * Returns the entry point for the given service, NULL on error
- */
-
-static unsigned long bios32_service(unsigned long service)
-{
-       unsigned char return_code;      /* %al */
-       unsigned long address;          /* %ebx */
-       unsigned long length;           /* %ecx */
-       unsigned long entry;            /* %edx */
-       unsigned long flags;
-
-       local_irq_save(flags);
-       __asm__("lcall *(%%edi); cld"
-               : "=a" (return_code),
-                 "=b" (address),
-                 "=c" (length),
-                 "=d" (entry)
-               : "0" (service),
-                 "1" (0),
-                 "D" (&bios32_indirect));
-       local_irq_restore(flags);
-
-       switch (return_code) {
-               case 0:
-                       return address + entry;
-               case 0x80:      /* Not present */
-                       printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service);
-                       return 0;
-               default: /* Shouldn't happen */
-                       printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n",
-                               service, return_code);
-                       return 0;
-       }
-}
-
-static struct {
-       unsigned long address;
-       unsigned short segment;
-} pci_indirect = { 0, __KERNEL_CS };
-
-static int pci_bios_present;
-
-static int __devinit check_pcibios(void)
-{
-       u32 signature, eax, ebx, ecx;
-       u8 status, major_ver, minor_ver, hw_mech;
-       unsigned long flags, pcibios_entry;
-
-       if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
-               pci_indirect.address = pcibios_entry + PAGE_OFFSET;
-
-               local_irq_save(flags);
-               __asm__(
-                       "lcall *(%%edi); cld\n\t"
-                       "jc 1f\n\t"
-                       "xor %%ah, %%ah\n"
-                       "1:"
-                       : "=d" (signature),
-                         "=a" (eax),
-                         "=b" (ebx),
-                         "=c" (ecx)
-                       : "1" (PCIBIOS_PCI_BIOS_PRESENT),
-                         "D" (&pci_indirect)
-                       : "memory");
-               local_irq_restore(flags);
-
-               status = (eax >> 8) & 0xff;
-               hw_mech = eax & 0xff;
-               major_ver = (ebx >> 8) & 0xff;
-               minor_ver = ebx & 0xff;
-               if (pcibios_last_bus < 0)
-                       pcibios_last_bus = ecx & 0xff;
-               DBG("PCI: BIOS probe returned s=%02x hw=%02x ver=%02x.%02x l=%02x\n",
-                       status, hw_mech, major_ver, minor_ver, pcibios_last_bus);
-               if (status || signature != PCI_SIGNATURE) {
-                       printk (KERN_ERR "PCI: BIOS BUG #%x[%08x] found\n",
-                               status, signature);
-                       return 0;
-               }
-               printk(KERN_INFO "PCI: PCI BIOS revision %x.%02x entry at 0x%lx, last bus=%d\n",
-                       major_ver, minor_ver, pcibios_entry, pcibios_last_bus);
-#ifdef CONFIG_PCI_DIRECT
-               if (!(hw_mech & PCIBIOS_HW_TYPE1))
-                       pci_probe &= ~PCI_PROBE_CONF1;
-               if (!(hw_mech & PCIBIOS_HW_TYPE2))
-                       pci_probe &= ~PCI_PROBE_CONF2;
-#endif
-               return 1;
-       }
-       return 0;
-}
-
-static int __devinit pci_bios_find_device (unsigned short vendor, unsigned short device_id,
-                                       unsigned short index, unsigned char *bus, unsigned char *device_fn)
-{
-       unsigned short bx;
-       unsigned short ret;
-
-       __asm__("lcall *(%%edi); cld\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=b" (bx),
-                 "=a" (ret)
-               : "1" (PCIBIOS_FIND_PCI_DEVICE),
-                 "c" (device_id),
-                 "d" (vendor),
-                 "S" ((int) index),
-                 "D" (&pci_indirect));
-       *bus = (bx >> 8) & 0xff;
-       *device_fn = bx & 0xff;
-       return (int) (ret & 0xff00) >> 8;
-}
-
-static int pci_bios_read(unsigned int seg, unsigned int bus,
-                        unsigned int devfn, int reg, int len, u32 *value)
-{
-       unsigned long result = 0;
-       unsigned long flags;
-       unsigned long bx = (bus << 8) | devfn;
-
-       if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
-               return -EINVAL;
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       switch (len) {
-       case 1:
-               __asm__("lcall *(%%esi); cld\n\t"
-                       "jc 1f\n\t"
-                       "xor %%ah, %%ah\n"
-                       "1:"
-                       : "=c" (*value),
-                         "=a" (result)
-                       : "1" (PCIBIOS_READ_CONFIG_BYTE),
-                         "b" (bx),
-                         "D" ((long)reg),
-                         "S" (&pci_indirect));
-               break;
-       case 2:
-               __asm__("lcall *(%%esi); cld\n\t"
-                       "jc 1f\n\t"
-                       "xor %%ah, %%ah\n"
-                       "1:"
-                       : "=c" (*value),
-                         "=a" (result)
-                       : "1" (PCIBIOS_READ_CONFIG_WORD),
-                         "b" (bx),
-                         "D" ((long)reg),
-                         "S" (&pci_indirect));
-               break;
-       case 4:
-               __asm__("lcall *(%%esi); cld\n\t"
-                       "jc 1f\n\t"
-                       "xor %%ah, %%ah\n"
-                       "1:"
-                       : "=c" (*value),
-                         "=a" (result)
-                       : "1" (PCIBIOS_READ_CONFIG_DWORD),
-                         "b" (bx),
-                         "D" ((long)reg),
-                         "S" (&pci_indirect));
-               break;
-       }
-
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return (int)((result & 0xff00) >> 8);
-}
-
-static int pci_bios_write(unsigned int seg, unsigned int bus,
-                         unsigned int devfn, int reg, int len, u32 value)
-{
-       unsigned long result = 0;
-       unsigned long flags;
-       unsigned long bx = (bus << 8) | devfn;
-
-       if ((bus > 255) || (devfn > 255) || (reg > 255)) 
-               return -EINVAL;
-
-       spin_lock_irqsave(&pci_config_lock, flags);
-
-       switch (len) {
-       case 1:
-               __asm__("lcall *(%%esi); cld\n\t"
-                       "jc 1f\n\t"
-                       "xor %%ah, %%ah\n"
-                       "1:"
-                       : "=a" (result)
-                       : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
-                         "c" (value),
-                         "b" (bx),
-                         "D" ((long)reg),
-                         "S" (&pci_indirect));
-               break;
-       case 2:
-               __asm__("lcall *(%%esi); cld\n\t"
-                       "jc 1f\n\t"
-                       "xor %%ah, %%ah\n"
-                       "1:"
-                       : "=a" (result)
-                       : "0" (PCIBIOS_WRITE_CONFIG_WORD),
-                         "c" (value),
-                         "b" (bx),
-                         "D" ((long)reg),
-                         "S" (&pci_indirect));
-               break;
-       case 4:
-               __asm__("lcall *(%%esi); cld\n\t"
-                       "jc 1f\n\t"
-                       "xor %%ah, %%ah\n"
-                       "1:"
-                       : "=a" (result)
-                       : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
-                         "c" (value),
-                         "b" (bx),
-                         "D" ((long)reg),
-                         "S" (&pci_indirect));
-               break;
-       }
-
-       spin_unlock_irqrestore(&pci_config_lock, flags);
-
-       return (int)((result & 0xff00) >> 8);
-}
-
-
-/*
- * Function table for BIOS32 access
- */
-
-static struct pci_raw_ops pci_bios_access = {
-       .read =         pci_bios_read,
-       .write =        pci_bios_write
-};
-
-/*
- * Try to find PCI BIOS.
- */
-
-static struct pci_raw_ops * __devinit pci_find_bios(void)
-{
-       union bios32 *check;
-       unsigned char sum;
-       int i, length;
-
-       /*
-        * Follow the standard procedure for locating the BIOS32 Service
-        * directory by scanning the permissible address range from
-        * 0xe0000 through 0xfffff for a valid BIOS32 structure.
-        */
-
-       for (check = (union bios32 *) __va(0xe0000);
-            check <= (union bios32 *) __va(0xffff0);
-            ++check) {
-               long sig;
-               if (probe_kernel_address(&check->fields.signature, sig))
-                       continue;
-
-               if (check->fields.signature != BIOS32_SIGNATURE)
-                       continue;
-               length = check->fields.length * 16;
-               if (!length)
-                       continue;
-               sum = 0;
-               for (i = 0; i < length ; ++i)
-                       sum += check->chars[i];
-               if (sum != 0)
-                       continue;
-               if (check->fields.revision != 0) {
-                       printk("PCI: unsupported BIOS32 revision %d at 0x%p\n",
-                               check->fields.revision, check);
-                       continue;
-               }
-               DBG("PCI: BIOS32 Service Directory structure at 0x%p\n", check);
-               if (check->fields.entry >= 0x100000) {
-                       printk("PCI: BIOS32 entry (0x%p) in high memory, "
-                                       "cannot use.\n", check);
-                       return NULL;
-               } else {
-                       unsigned long bios32_entry = check->fields.entry;
-                       DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n",
-                                       bios32_entry);
-                       bios32_indirect.address = bios32_entry + PAGE_OFFSET;
-                       if (check_pcibios())
-                               return &pci_bios_access;
-               }
-               break;  /* Hopefully more than one BIOS32 cannot happen... */
-       }
-
-       return NULL;
-}
-
-/*
- * Sort the device list according to PCI BIOS. Nasty hack, but since some
- * fool forgot to define the `correct' device order in the PCI BIOS specs
- * and we want to be (possibly bug-to-bug ;-]) compatible with older kernels
- * which used BIOS ordering, we are bound to do this...
- */
-
-void __devinit pcibios_sort(void)
-{
-       LIST_HEAD(sorted_devices);
-       struct list_head *ln;
-       struct pci_dev *dev, *d;
-       int idx, found;
-       unsigned char bus, devfn;
-
-       DBG("PCI: Sorting device list...\n");
-       while (!list_empty(&pci_devices)) {
-               ln = pci_devices.next;
-               dev = pci_dev_g(ln);
-               idx = found = 0;
-               while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
-                       idx++;
-                       list_for_each(ln, &pci_devices) {
-                               d = pci_dev_g(ln);
-                               if (d->bus->number == bus && d->devfn == devfn) {
-                                       list_move_tail(&d->global_list, &sorted_devices);
-                                       if (d == dev)
-                                               found = 1;
-                                       break;
-                               }
-                       }
-                       if (ln == &pci_devices) {
-                               printk(KERN_WARNING "PCI: BIOS reporting unknown device %02x:%02x\n", bus, devfn);
-                               /*
-                                * We must not continue scanning as several buggy BIOSes
-                                * return garbage after the last device. Grr.
-                                */
-                               break;
-                       }
-               }
-               if (!found) {
-                       printk(KERN_WARNING "PCI: Device %s not found by BIOS\n",
-                               pci_name(dev));
-                       list_move_tail(&dev->global_list, &sorted_devices);
-               }
-       }
-       list_splice(&sorted_devices, &pci_devices);
-}
-
-/*
- *  BIOS Functions for IRQ Routing
- */
-
-struct irq_routing_options {
-       u16 size;
-       struct irq_info *table;
-       u16 segment;
-} __attribute__((packed));
-
-struct irq_routing_table * pcibios_get_irq_routing_table(void)
-{
-       struct irq_routing_options opt;
-       struct irq_routing_table *rt = NULL;
-       int ret, map;
-       unsigned long page;
-
-       if (!pci_bios_present)
-               return NULL;
-       page = __get_free_page(GFP_KERNEL);
-       if (!page)
-               return NULL;
-       opt.table = (struct irq_info *) page;
-       opt.size = PAGE_SIZE;
-       opt.segment = __KERNEL_DS;
-
-       DBG("PCI: Fetching IRQ routing table... ");
-       __asm__("push %%es\n\t"
-               "push %%ds\n\t"
-               "pop  %%es\n\t"
-               "lcall *(%%esi); cld\n\t"
-               "pop %%es\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=a" (ret),
-                 "=b" (map),
-                 "=m" (opt)
-               : "0" (PCIBIOS_GET_ROUTING_OPTIONS),
-                 "1" (0),
-                 "D" ((long) &opt),
-                 "S" (&pci_indirect),
-                 "m" (opt)
-               : "memory");
-       DBG("OK  ret=%d, size=%d, map=%x\n", ret, opt.size, map);
-       if (ret & 0xff00)
-               printk(KERN_ERR "PCI: Error %02x when fetching IRQ routing table.\n", (ret >> 8) & 0xff);
-       else if (opt.size) {
-               rt = kmalloc(sizeof(struct irq_routing_table) + opt.size, GFP_KERNEL);
-               if (rt) {
-                       memset(rt, 0, sizeof(struct irq_routing_table));
-                       rt->size = opt.size + sizeof(struct irq_routing_table);
-                       rt->exclusive_irqs = map;
-                       memcpy(rt->slots, (void *) page, opt.size);
-                       printk(KERN_INFO "PCI: Using BIOS Interrupt Routing Table\n");
-               }
-       }
-       free_page(page);
-       return rt;
-}
-EXPORT_SYMBOL(pcibios_get_irq_routing_table);
-
-int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
-{
-       int ret;
-
-       __asm__("lcall *(%%esi); cld\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=a" (ret)
-               : "0" (PCIBIOS_SET_PCI_HW_INT),
-                 "b" ((dev->bus->number << 8) | dev->devfn),
-                 "c" ((irq << 8) | (pin + 10)),
-                 "S" (&pci_indirect));
-       return !(ret & 0xff00);
-}
-EXPORT_SYMBOL(pcibios_set_irq_routing);
-
-void __init pci_pcbios_init(void)
-{
-       if ((pci_probe & PCI_PROBE_BIOS) 
-               && ((raw_pci_ops = pci_find_bios()))) {
-               pci_probe |= PCI_BIOS_SORT;
-               pci_bios_present = 1;
-       }
-}
-
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
deleted file mode 100644 (file)
index 8c66f27..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *     Low-Level PCI Access for i386 machines.
- *
- *     (c) 1999 Martin Mares <mj@ucw.cz>
- */
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-#define PCI_PROBE_BIOS         0x0001
-#define PCI_PROBE_CONF1                0x0002
-#define PCI_PROBE_CONF2                0x0004
-#define PCI_PROBE_MMCONF       0x0008
-#define PCI_PROBE_MASK         0x000f
-#define PCI_PROBE_NOEARLY      0x0010
-
-#define PCI_NO_SORT            0x0100
-#define PCI_BIOS_SORT          0x0200
-#define PCI_NO_CHECKS          0x0400
-#define PCI_USE_PIRQ_MASK      0x0800
-#define PCI_ASSIGN_ROMS                0x1000
-#define PCI_BIOS_IRQ_SCAN      0x2000
-#define PCI_ASSIGN_ALL_BUSSES  0x4000
-
-extern unsigned int pci_probe;
-extern unsigned long pirq_table_addr;
-
-enum pci_bf_sort_state {
-       pci_bf_sort_default,
-       pci_force_nobf,
-       pci_force_bf,
-       pci_dmi_bf,
-};
-
-/* pci-i386.c */
-
-extern unsigned int pcibios_max_latency;
-
-void pcibios_resource_survey(void);
-int pcibios_enable_resources(struct pci_dev *, int);
-
-/* pci-pc.c */
-
-extern int pcibios_last_bus;
-extern struct pci_bus *pci_root_bus;
-extern struct pci_ops pci_root_ops;
-
-/* pci-irq.c */
-
-struct irq_info {
-       u8 bus, devfn;                  /* Bus, device and function */
-       struct {
-               u8 link;                /* IRQ line ID, chipset dependent, 0=not routed */
-               u16 bitmap;             /* Available IRQs */
-       } __attribute__((packed)) irq[4];
-       u8 slot;                        /* Slot number, 0=onboard */
-       u8 rfu;
-} __attribute__((packed));
-
-struct irq_routing_table {
-       u32 signature;                  /* PIRQ_SIGNATURE should be here */
-       u16 version;                    /* PIRQ_VERSION */
-       u16 size;                       /* Table size in bytes */
-       u8 rtr_bus, rtr_devfn;          /* Where the interrupt router lies */
-       u16 exclusive_irqs;             /* IRQs devoted exclusively to PCI usage */
-       u16 rtr_vendor, rtr_device;     /* Vendor and device ID of interrupt router */
-       u32 miniport_data;              /* Crap */
-       u8 rfu[11];
-       u8 checksum;                    /* Modulo 256 checksum must give zero */
-       struct irq_info slots[0];
-} __attribute__((packed));
-
-extern unsigned int pcibios_irq_mask;
-
-extern int pcibios_scanned;
-extern spinlock_t pci_config_lock;
-
-extern int (*pcibios_enable_irq)(struct pci_dev *dev);
-extern void (*pcibios_disable_irq)(struct pci_dev *dev);
-
-extern int pci_conf1_write(unsigned int seg, unsigned int bus,
-                          unsigned int devfn, int reg, int len, u32 value);
-extern int pci_conf1_read(unsigned int seg, unsigned int bus,
-                         unsigned int devfn, int reg, int len, u32 *value);
-
-extern int pci_direct_probe(void);
-extern void pci_direct_init(int type);
-extern void pci_pcbios_init(void);
-extern void pci_mmcfg_init(int type);
-extern void pcibios_sort(void);
-
-/* pci-mmconfig.c */
-
-/* Verify the first 16 busses. We assume that systems with more busses
-   get MCFG right. */
-#define PCI_MMCFG_MAX_CHECK_BUS 16
-extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
-
-extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
-                                          unsigned int devfn);
-extern int __init pci_mmcfg_arch_init(void);
-
-/*
- * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
- * on their northbrige except through the * %eax register. As such, you MUST
- * NOT use normal IOMEM accesses, you need to only use the magic mmio-config
- * accessor functions.
- * In fact just use pci_config_*, nothing else please.
- */
-static inline unsigned char mmio_config_readb(void __iomem *pos)
-{
-       u8 val;
-       asm volatile("movb (%1),%%al" : "=a" (val) : "r" (pos));
-       return val;
-}
-
-static inline unsigned short mmio_config_readw(void __iomem *pos)
-{
-       u16 val;
-       asm volatile("movw (%1),%%ax" : "=a" (val) : "r" (pos));
-       return val;
-}
-
-static inline unsigned int mmio_config_readl(void __iomem *pos)
-{
-       u32 val;
-       asm volatile("movl (%1),%%eax" : "=a" (val) : "r" (pos));
-       return val;
-}
-
-static inline void mmio_config_writeb(void __iomem *pos, u8 val)
-{
-       asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory");
-}
-
-static inline void mmio_config_writew(void __iomem *pos, u16 val)
-{
-       asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory");
-}
-
-static inline void mmio_config_writel(void __iomem *pos, u32 val)
-{
-       asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory");
-}
diff --git a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c
deleted file mode 100644 (file)
index 8ecb1c7..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- *     Low-Level PCI Support for SGI Visual Workstation
- *
- *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include "cobalt.h"
-#include "lithium.h"
-
-#include "pci.h"
-
-
-extern struct pci_raw_ops pci_direct_conf1;
-
-static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
-static void pci_visws_disable_irq(struct pci_dev *dev) { }
-
-int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq;
-void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq;
-
-void __init pcibios_penalize_isa_irq(int irq, int active) {}
-
-
-unsigned int pci_bus0, pci_bus1;
-
-static inline u8 bridge_swizzle(u8 pin, u8 slot) 
-{
-       return (((pin - 1) + slot) % 4) + 1;
-}
-
-static u8 __init visws_swizzle(struct pci_dev *dev, u8 *pinp)
-{
-       u8 pin = *pinp;
-
-       while (dev->bus->self) {        /* Move up the chain of bridges. */
-               pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
-               dev = dev->bus->self;
-       }
-       *pinp = pin;
-
-       return PCI_SLOT(dev->devfn);
-}
-
-static int __init visws_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       int irq, bus = dev->bus->number;
-
-       pin--;
-
-       /* Nothing useful at PIIX4 pin 1 */
-       if (bus == pci_bus0 && slot == 4 && pin == 0)
-               return -1;
-
-       /* PIIX4 USB is on Bus 0, Slot 4, Line 3 */
-       if (bus == pci_bus0 && slot == 4 && pin == 3) {
-               irq = CO_IRQ(CO_APIC_PIIX4_USB);
-               goto out;
-       }
-
-       /* First pin spread down 1 APIC entry per slot */
-       if (pin == 0) {
-               irq = CO_IRQ((bus == pci_bus0 ? CO_APIC_PCIB_BASE0 :
-                                               CO_APIC_PCIA_BASE0) + slot);
-               goto out;
-       }
-
-       /* lines 1,2,3 from any slot is shared in this twirly pattern */
-       if (bus == pci_bus1) {
-               /* lines 1-3 from devices 0 1 rotate over 2 apic entries */
-               irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((slot + (pin - 1)) % 2));
-       } else { /* bus == pci_bus0 */
-               /* lines 1-3 from devices 0-3 rotate over 3 apic entries */
-               if (slot == 0)
-                       slot = 3; /* same pattern */
-               irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((3 - slot) + (pin - 1) % 3));
-       }
-out:
-       printk(KERN_DEBUG "PCI: Bus %d Slot %d Line %d -> IRQ %d\n", bus, slot, pin, irq);
-       return irq;
-}
-
-void __init pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
-static int __init pcibios_init(void)
-{
-       /* The VISWS supports configuration access type 1 only */
-       pci_probe = (pci_probe | PCI_PROBE_CONF1) &
-                   ~(PCI_PROBE_BIOS | PCI_PROBE_CONF2);
-
-       pci_bus0 = li_pcib_read16(LI_PCI_BUSNUM) & 0xff;
-       pci_bus1 = li_pcia_read16(LI_PCI_BUSNUM) & 0xff;
-
-       printk(KERN_INFO "PCI: Lithium bridge A bus: %u, "
-               "bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0);
-
-       raw_pci_ops = &pci_direct_conf1;
-       pci_scan_bus_with_sysdata(pci_bus0);
-       pci_scan_bus_with_sysdata(pci_bus1);
-       pci_fixup_irqs(visws_swizzle, visws_map_irq);
-       pcibios_resource_survey();
-       return 0;
-}
-
-subsys_initcall(pcibios_init);
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
new file mode 100644 (file)
index 0000000..b3e54c4
--- /dev/null
@@ -0,0 +1,5 @@
+ifeq ($(CONFIG_X86_32),y)
+include ${srctree}/arch/x86/pci/Makefile_32
+else
+include ${srctree}/arch/x86_64/pci/Makefile_64
+endif
diff --git a/arch/x86/pci/Makefile_32 b/arch/x86/pci/Makefile_32
new file mode 100644 (file)
index 0000000..cdd6828
--- /dev/null
@@ -0,0 +1,14 @@
+obj-y                          := i386.o init.o
+
+obj-$(CONFIG_PCI_BIOS)         += pcbios.o
+obj-$(CONFIG_PCI_MMCONFIG)     += mmconfig_32.o direct.o mmconfig-shared.o
+obj-$(CONFIG_PCI_DIRECT)       += direct.o
+
+pci-y                          := fixup.o
+pci-$(CONFIG_ACPI)             += acpi.o
+pci-y                          += legacy.o irq.o
+
+pci-$(CONFIG_X86_VISWS)                := visws.o fixup.o
+pci-$(CONFIG_X86_NUMAQ)                := numa.o irq.o
+
+obj-y                          += $(pci-y) common.o early.o
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
new file mode 100644 (file)
index 0000000..bc8a44b
--- /dev/null
@@ -0,0 +1,90 @@
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/numa.h>
+#include "pci.h"
+
+struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
+{
+       struct pci_bus *bus;
+       struct pci_sysdata *sd;
+       int pxm;
+
+       /* Allocate per-root-bus (not per bus) arch-specific data.
+        * TODO: leak; this memory is never freed.
+        * It's arguable whether it's worth the trouble to care.
+        */
+       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+       if (!sd) {
+               printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
+               return NULL;
+       }
+
+       if (domain != 0) {
+               printk(KERN_WARNING "PCI: Multiple domains not supported\n");
+               kfree(sd);
+               return NULL;
+       }
+
+       sd->node = -1;
+
+       pxm = acpi_get_pxm(device->handle);
+#ifdef CONFIG_ACPI_NUMA
+       if (pxm >= 0)
+               sd->node = pxm_to_node(pxm);
+#endif
+
+       bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
+       if (!bus)
+               kfree(sd);
+
+#ifdef CONFIG_ACPI_NUMA
+       if (bus != NULL) {
+               if (pxm >= 0) {
+                       printk("bus %d -> pxm %d -> node %d\n",
+                               busnum, pxm, sd->node);
+               }
+       }
+#endif
+       
+       return bus;
+}
+
+extern int pci_routeirq;
+static int __init pci_acpi_init(void)
+{
+       struct pci_dev *dev = NULL;
+
+       if (pcibios_scanned)
+               return 0;
+
+       if (acpi_noirq)
+               return 0;
+
+       printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
+       acpi_irq_penalty_init();
+       pcibios_scanned++;
+       pcibios_enable_irq = acpi_pci_irq_enable;
+       pcibios_disable_irq = acpi_pci_irq_disable;
+
+       if (pci_routeirq) {
+               /*
+                * PCI IRQ routing is set up by pci_enable_device(), but we
+                * also do it here in case there are still broken drivers that
+                * don't use pci_enable_device().
+                */
+               printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
+               for_each_pci_dev(dev)
+                       acpi_pci_irq_enable(dev);
+       } else
+               printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\".  If it helps, post a report\n");
+
+#ifdef CONFIG_X86_IO_APIC
+       if (acpi_ioapic)
+               print_IO_APIC();
+#endif
+
+       return 0;
+}
+subsys_initcall(pci_acpi_init);
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
new file mode 100644 (file)
index 0000000..ebc6f3c
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ *     Low-Level PCI Support for PC
+ *
+ *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ */
+
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+
+#include <asm/acpi.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+
+#include "pci.h"
+
+unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
+                               PCI_PROBE_MMCONF;
+
+static int pci_bf_sort;
+int pci_routeirq;
+int pcibios_last_bus = -1;
+unsigned long pirq_table_addr;
+struct pci_bus *pci_root_bus;
+struct pci_raw_ops *raw_pci_ops;
+
+static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+       return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
+}
+
+static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+       return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
+}
+
+struct pci_ops pci_root_ops = {
+       .read = pci_read,
+       .write = pci_write,
+};
+
+/*
+ * legacy, numa, and acpi all want to call pcibios_scan_root
+ * from their initcalls. This flag prevents that.
+ */
+int pcibios_scanned;
+
+/*
+ * This interrupt-safe spinlock protects all accesses to PCI
+ * configuration space.
+ */
+DEFINE_SPINLOCK(pci_config_lock);
+
+/*
+ * Several buggy motherboards address only 16 devices and mirror
+ * them to next 16 IDs. We try to detect this `feature' on all
+ * primary buses (those containing host bridges as they are
+ * expected to be unique) and remove the ghost devices.
+ */
+
+static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
+{
+       struct list_head *ln, *mn;
+       struct pci_dev *d, *e;
+       int mirror = PCI_DEVFN(16,0);
+       int seen_host_bridge = 0;
+       int i;
+
+       DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
+       list_for_each(ln, &b->devices) {
+               d = pci_dev_b(ln);
+               if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+                       seen_host_bridge++;
+               for (mn=ln->next; mn != &b->devices; mn=mn->next) {
+                       e = pci_dev_b(mn);
+                       if (e->devfn != d->devfn + mirror ||
+                           e->vendor != d->vendor ||
+                           e->device != d->device ||
+                           e->class != d->class)
+                               continue;
+                       for(i=0; i<PCI_NUM_RESOURCES; i++)
+                               if (e->resource[i].start != d->resource[i].start ||
+                                   e->resource[i].end != d->resource[i].end ||
+                                   e->resource[i].flags != d->resource[i].flags)
+                                       continue;
+                       break;
+               }
+               if (mn == &b->devices)
+                       return;
+       }
+       if (!seen_host_bridge)
+               return;
+       printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number);
+
+       ln = &b->devices;
+       while (ln->next != &b->devices) {
+               d = pci_dev_b(ln->next);
+               if (d->devfn >= mirror) {
+                       list_del(&d->global_list);
+                       list_del(&d->bus_list);
+                       kfree(d);
+               } else
+                       ln = ln->next;
+       }
+}
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+
+void __devinit  pcibios_fixup_bus(struct pci_bus *b)
+{
+       pcibios_fixup_ghosts(b);
+       pci_read_bridge_bases(b);
+}
+
+/*
+ * Only use DMI information to set this if nothing was passed
+ * on the kernel command line (which was parsed earlier).
+ */
+
+static int __devinit set_bf_sort(struct dmi_system_id *d)
+{
+       if (pci_bf_sort == pci_bf_sort_default) {
+               pci_bf_sort = pci_dmi_bf;
+               printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident);
+       }
+       return 0;
+}
+
+/*
+ * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
+ */
+#ifdef __i386__
+static int __devinit assign_all_busses(struct dmi_system_id *d)
+{
+       pci_probe |= PCI_ASSIGN_ALL_BUSSES;
+       printk(KERN_INFO "%s detected: enabling PCI bus# renumbering"
+                       " (pci=assign-busses)\n", d->ident);
+       return 0;
+}
+#endif
+
+static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
+#ifdef __i386__
+/*
+ * Laptops which need pci=assign-busses to see Cardbus cards
+ */
+       {
+               .callback = assign_all_busses,
+               .ident = "Samsung X20 Laptop",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"),
+               },
+       },
+#endif         /* __i386__ */
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge 1950",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge 1955",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge 2900",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge 2950",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge R900",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL20p G3",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL20p G4",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL30p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL25p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL35p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL45p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL45p G2",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL460c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL465c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL480c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL685c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
+               },
+       },
+       {}
+};
+
+struct pci_bus * __devinit pcibios_scan_root(int busnum)
+{
+       struct pci_bus *bus = NULL;
+       struct pci_sysdata *sd;
+
+       dmi_check_system(pciprobe_dmi_table);
+
+       while ((bus = pci_find_next_bus(bus)) != NULL) {
+               if (bus->number == busnum) {
+                       /* Already scanned */
+                       return bus;
+               }
+       }
+
+       /* Allocate per-root-bus (not per bus) arch-specific data.
+        * TODO: leak; this memory is never freed.
+        * It's arguable whether it's worth the trouble to care.
+        */
+       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+       if (!sd) {
+               printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
+               return NULL;
+       }
+
+       printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
+
+       return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
+}
+
+extern u8 pci_cache_line_size;
+
+static int __init pcibios_init(void)
+{
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+
+       if (!raw_pci_ops) {
+               printk(KERN_WARNING "PCI: System does not support PCI\n");
+               return 0;
+       }
+
+       /*
+        * Assume PCI cacheline size of 32 bytes for all x86s except K7/K8
+        * and P4. It's also good for 386/486s (which actually have 16)
+        * as quite a few PCI devices do not support smaller values.
+        */
+       pci_cache_line_size = 32 >> 2;
+       if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
+               pci_cache_line_size = 64 >> 2;  /* K7 & K8 */
+       else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL)
+               pci_cache_line_size = 128 >> 2; /* P4 */
+
+       pcibios_resource_survey();
+
+       if (pci_bf_sort >= pci_force_bf)
+               pci_sort_breadthfirst();
+#ifdef CONFIG_PCI_BIOS
+       if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
+               pcibios_sort();
+#endif
+       return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+char * __devinit  pcibios_setup(char *str)
+{
+       if (!strcmp(str, "off")) {
+               pci_probe = 0;
+               return NULL;
+       } else if (!strcmp(str, "bfsort")) {
+               pci_bf_sort = pci_force_bf;
+               return NULL;
+       } else if (!strcmp(str, "nobfsort")) {
+               pci_bf_sort = pci_force_nobf;
+               return NULL;
+       }
+#ifdef CONFIG_PCI_BIOS
+       else if (!strcmp(str, "bios")) {
+               pci_probe = PCI_PROBE_BIOS;
+               return NULL;
+       } else if (!strcmp(str, "nobios")) {
+               pci_probe &= ~PCI_PROBE_BIOS;
+               return NULL;
+       } else if (!strcmp(str, "nosort")) {
+               pci_probe |= PCI_NO_SORT;
+               return NULL;
+       } else if (!strcmp(str, "biosirq")) {
+               pci_probe |= PCI_BIOS_IRQ_SCAN;
+               return NULL;
+       } else if (!strncmp(str, "pirqaddr=", 9)) {
+               pirq_table_addr = simple_strtoul(str+9, NULL, 0);
+               return NULL;
+       }
+#endif
+#ifdef CONFIG_PCI_DIRECT
+       else if (!strcmp(str, "conf1")) {
+               pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS;
+               return NULL;
+       }
+       else if (!strcmp(str, "conf2")) {
+               pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS;
+               return NULL;
+       }
+#endif
+#ifdef CONFIG_PCI_MMCONFIG
+       else if (!strcmp(str, "nommconf")) {
+               pci_probe &= ~PCI_PROBE_MMCONF;
+               return NULL;
+       }
+#endif
+       else if (!strcmp(str, "noacpi")) {
+               acpi_noirq_set();
+               return NULL;
+       }
+       else if (!strcmp(str, "noearly")) {
+               pci_probe |= PCI_PROBE_NOEARLY;
+               return NULL;
+       }
+#ifndef CONFIG_X86_VISWS
+       else if (!strcmp(str, "usepirqmask")) {
+               pci_probe |= PCI_USE_PIRQ_MASK;
+               return NULL;
+       } else if (!strncmp(str, "irqmask=", 8)) {
+               pcibios_irq_mask = simple_strtol(str+8, NULL, 0);
+               return NULL;
+       } else if (!strncmp(str, "lastbus=", 8)) {
+               pcibios_last_bus = simple_strtol(str+8, NULL, 0);
+               return NULL;
+       }
+#endif
+       else if (!strcmp(str, "rom")) {
+               pci_probe |= PCI_ASSIGN_ROMS;
+               return NULL;
+       } else if (!strcmp(str, "assign-busses")) {
+               pci_probe |= PCI_ASSIGN_ALL_BUSSES;
+               return NULL;
+       } else if (!strcmp(str, "routeirq")) {
+               pci_routeirq = 1;
+               return NULL;
+       }
+       return str;
+}
+
+unsigned int pcibios_assign_all_busses(void)
+{
+       return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+       int err;
+
+       if ((err = pcibios_enable_resources(dev, mask)) < 0)
+               return err;
+
+       if (!dev->msi_enabled)
+               return pcibios_enable_irq(dev);
+       return 0;
+}
+
+void pcibios_disable_device (struct pci_dev *dev)
+{
+       if (!dev->msi_enabled && pcibios_disable_irq)
+               pcibios_disable_irq(dev);
+}
+
+struct pci_bus *pci_scan_bus_with_sysdata(int busno)
+{
+       struct pci_bus *bus = NULL;
+       struct pci_sysdata *sd;
+
+       /*
+        * Allocate per-root-bus (not per bus) arch-specific data.
+        * TODO: leak; this memory is never freed.
+        * It's arguable whether it's worth the trouble to care.
+        */
+       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+       if (!sd) {
+               printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
+               return NULL;
+       }
+       sd->node = -1;
+       bus = pci_scan_bus(busno, &pci_root_ops, sd);
+       if (!bus)
+               kfree(sd);
+
+       return bus;
+}
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c
new file mode 100644 (file)
index 0000000..431c9a5
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * direct.c - Low-level direct PCI config space access
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include "pci.h"
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+
+#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
+       (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
+
+int pci_conf1_read(unsigned int seg, unsigned int bus,
+                         unsigned int devfn, int reg, int len, u32 *value)
+{
+       unsigned long flags;
+
+       if ((bus > 255) || (devfn > 255) || (reg > 255)) {
+               *value = -1;
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
+
+       switch (len) {
+       case 1:
+               *value = inb(0xCFC + (reg & 3));
+               break;
+       case 2:
+               *value = inw(0xCFC + (reg & 2));
+               break;
+       case 4:
+               *value = inl(0xCFC);
+               break;
+       }
+
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return 0;
+}
+
+int pci_conf1_write(unsigned int seg, unsigned int bus,
+                          unsigned int devfn, int reg, int len, u32 value)
+{
+       unsigned long flags;
+
+       if ((bus > 255) || (devfn > 255) || (reg > 255)) 
+               return -EINVAL;
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
+
+       switch (len) {
+       case 1:
+               outb((u8)value, 0xCFC + (reg & 3));
+               break;
+       case 2:
+               outw((u16)value, 0xCFC + (reg & 2));
+               break;
+       case 4:
+               outl((u32)value, 0xCFC);
+               break;
+       }
+
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return 0;
+}
+
+#undef PCI_CONF1_ADDRESS
+
+struct pci_raw_ops pci_direct_conf1 = {
+       .read =         pci_conf1_read,
+       .write =        pci_conf1_write,
+};
+
+
+/*
+ * Functions for accessing PCI configuration space with type 2 accesses
+ */
+
+#define PCI_CONF2_ADDRESS(dev, reg)    (u16)(0xC000 | (dev << 8) | reg)
+
+static int pci_conf2_read(unsigned int seg, unsigned int bus,
+                         unsigned int devfn, int reg, int len, u32 *value)
+{
+       unsigned long flags;
+       int dev, fn;
+
+       if ((bus > 255) || (devfn > 255) || (reg > 255)) {
+               *value = -1;
+               return -EINVAL;
+       }
+
+       dev = PCI_SLOT(devfn);
+       fn = PCI_FUNC(devfn);
+
+       if (dev & 0x10) 
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       outb((u8)(0xF0 | (fn << 1)), 0xCF8);
+       outb((u8)bus, 0xCFA);
+
+       switch (len) {
+       case 1:
+               *value = inb(PCI_CONF2_ADDRESS(dev, reg));
+               break;
+       case 2:
+               *value = inw(PCI_CONF2_ADDRESS(dev, reg));
+               break;
+       case 4:
+               *value = inl(PCI_CONF2_ADDRESS(dev, reg));
+               break;
+       }
+
+       outb(0, 0xCF8);
+
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return 0;
+}
+
+static int pci_conf2_write(unsigned int seg, unsigned int bus,
+                          unsigned int devfn, int reg, int len, u32 value)
+{
+       unsigned long flags;
+       int dev, fn;
+
+       if ((bus > 255) || (devfn > 255) || (reg > 255)) 
+               return -EINVAL;
+
+       dev = PCI_SLOT(devfn);
+       fn = PCI_FUNC(devfn);
+
+       if (dev & 0x10) 
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       outb((u8)(0xF0 | (fn << 1)), 0xCF8);
+       outb((u8)bus, 0xCFA);
+
+       switch (len) {
+       case 1:
+               outb((u8)value, PCI_CONF2_ADDRESS(dev, reg));
+               break;
+       case 2:
+               outw((u16)value, PCI_CONF2_ADDRESS(dev, reg));
+               break;
+       case 4:
+               outl((u32)value, PCI_CONF2_ADDRESS(dev, reg));
+               break;
+       }
+
+       outb(0, 0xCF8);    
+
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return 0;
+}
+
+#undef PCI_CONF2_ADDRESS
+
+static struct pci_raw_ops pci_direct_conf2 = {
+       .read =         pci_conf2_read,
+       .write =        pci_conf2_write,
+};
+
+
+/*
+ * Before we decide to use direct hardware access mechanisms, we try to do some
+ * trivial checks to ensure it at least _seems_ to be working -- we just test
+ * whether bus 00 contains a host bridge (this is similar to checking
+ * techniques used in XFree86, but ours should be more reliable since we
+ * attempt to make use of direct access hints provided by the PCI BIOS).
+ *
+ * This should be close to trivial, but it isn't, because there are buggy
+ * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
+ */
+static int __init pci_sanity_check(struct pci_raw_ops *o)
+{
+       u32 x = 0;
+       int devfn;
+
+       if (pci_probe & PCI_NO_CHECKS)
+               return 1;
+       /* Assume Type 1 works for newer systems.
+          This handles machines that don't have anything on PCI Bus 0. */
+       if (dmi_get_year(DMI_BIOS_DATE) >= 2001)
+               return 1;
+
+       for (devfn = 0; devfn < 0x100; devfn++) {
+               if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x))
+                       continue;
+               if (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)
+                       return 1;
+
+               if (o->read(0, 0, devfn, PCI_VENDOR_ID, 2, &x))
+                       continue;
+               if (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)
+                       return 1;
+       }
+
+       DBG(KERN_WARNING "PCI: Sanity check failed\n");
+       return 0;
+}
+
+static int __init pci_check_type1(void)
+{
+       unsigned long flags;
+       unsigned int tmp;
+       int works = 0;
+
+       local_irq_save(flags);
+
+       outb(0x01, 0xCFB);
+       tmp = inl(0xCF8);
+       outl(0x80000000, 0xCF8);
+       if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) {
+               works = 1;
+       }
+       outl(tmp, 0xCF8);
+       local_irq_restore(flags);
+
+       return works;
+}
+
+static int __init pci_check_type2(void)
+{
+       unsigned long flags;
+       int works = 0;
+
+       local_irq_save(flags);
+
+       outb(0x00, 0xCFB);
+       outb(0x00, 0xCF8);
+       outb(0x00, 0xCFA);
+       if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 &&
+           pci_sanity_check(&pci_direct_conf2)) {
+               works = 1;
+       }
+
+       local_irq_restore(flags);
+
+       return works;
+}
+
+void __init pci_direct_init(int type)
+{
+       if (type == 0)
+               return;
+       printk(KERN_INFO "PCI: Using configuration type %d\n", type);
+       if (type == 1)
+               raw_pci_ops = &pci_direct_conf1;
+       else
+               raw_pci_ops = &pci_direct_conf2;
+}
+
+int __init pci_direct_probe(void)
+{
+       struct resource *region, *region2;
+
+       if ((pci_probe & PCI_PROBE_CONF1) == 0)
+               goto type2;
+       region = request_region(0xCF8, 8, "PCI conf1");
+       if (!region)
+               goto type2;
+
+       if (pci_check_type1())
+               return 1;
+       release_resource(region);
+
+ type2:
+       if ((pci_probe & PCI_PROBE_CONF2) == 0)
+               return 0;
+       region = request_region(0xCF8, 4, "PCI conf2");
+       if (!region)
+               return 0;
+       region2 = request_region(0xC000, 0x1000, "PCI conf2");
+       if (!region2)
+               goto fail2;
+
+       if (pci_check_type2()) {
+               printk(KERN_INFO "PCI: Using configuration type 2\n");
+               raw_pci_ops = &pci_direct_conf2;
+               return 2;
+       }
+
+       release_resource(region2);
+ fail2:
+       release_resource(region);
+       return 0;
+}
diff --git a/arch/x86/pci/early.c b/arch/x86/pci/early.c
new file mode 100644 (file)
index 0000000..42df4b6
--- /dev/null
@@ -0,0 +1,59 @@
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/pci-direct.h>
+#include <asm/io.h>
+#include "pci.h"
+
+/* Direct PCI access. This is used for PCI accesses in early boot before
+   the PCI subsystem works. */
+
+#define PDprintk(x...)
+
+u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset)
+{
+       u32 v;
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       v = inl(0xcfc);
+       if (v != 0xffffffff)
+               PDprintk("%x reading 4 from %x: %x\n", slot, offset, v);
+       return v;
+}
+
+u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset)
+{
+       u8 v;
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       v = inb(0xcfc + (offset&3));
+       PDprintk("%x reading 1 from %x: %x\n", slot, offset, v);
+       return v;
+}
+
+u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
+{
+       u16 v;
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       v = inw(0xcfc + (offset&2));
+       PDprintk("%x reading 2 from %x: %x\n", slot, offset, v);
+       return v;
+}
+
+void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
+                                   u32 val)
+{
+       PDprintk("%x writing to %x: %x\n", slot, offset, val);
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       outl(val, 0xcfc);
+}
+
+void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val)
+{
+       PDprintk("%x writing to %x: %x\n", slot, offset, val);
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       outb(val, 0xcfc);
+}
+
+int early_pci_allowed(void)
+{
+       return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
+                       PCI_PROBE_CONF1;
+}
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
new file mode 100644 (file)
index 0000000..c82cbf4
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
+ */
+
+#include <linux/delay.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci.h"
+
+
+static void __devinit pci_fixup_i450nx(struct pci_dev *d)
+{
+       /*
+        * i450NX -- Find and scan all secondary buses on all PXB's.
+        */
+       int pxb, reg;
+       u8 busno, suba, subb;
+
+       printk(KERN_WARNING "PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
+       reg = 0xd0;
+       for(pxb=0; pxb<2; pxb++) {
+               pci_read_config_byte(d, reg++, &busno);
+               pci_read_config_byte(d, reg++, &suba);
+               pci_read_config_byte(d, reg++, &subb);
+               DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
+               if (busno)
+                       pci_scan_bus_with_sysdata(busno);       /* Bus A */
+               if (suba < subb)
+                       pci_scan_bus_with_sysdata(suba+1);      /* Bus B */
+       }
+       pcibios_last_bus = -1;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
+
+static void __devinit pci_fixup_i450gx(struct pci_dev *d)
+{
+       /*
+        * i450GX and i450KX -- Find and scan all secondary buses.
+        * (called separately for each PCI bridge found)
+        */
+       u8 busno;
+       pci_read_config_byte(d, 0x4a, &busno);
+       printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno);
+       pci_scan_bus_with_sysdata(busno);
+       pcibios_last_bus = -1;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
+
+static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)
+{
+       /*
+        * UM8886BF IDE controller sets region type bits incorrectly,
+        * therefore they look like memory despite of them being I/O.
+        */
+       int i;
+
+       printk(KERN_WARNING "PCI: Fixing base address flags for device %s\n", pci_name(d));
+       for(i=0; i<4; i++)
+               d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide);
+
+static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)
+{
+       /*
+        * NCR 53C810 returns class code 0 (at least on some systems).
+        * Fix class to be PCI_CLASS_STORAGE_SCSI
+        */
+       if (!d->class) {
+               printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", pci_name(d));
+               d->class = PCI_CLASS_STORAGE_SCSI << 8;
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810);
+
+static void __devinit  pci_fixup_latency(struct pci_dev *d)
+{
+       /*
+        *  SiS 5597 and 5598 chipsets require latency timer set to
+        *  at most 32 to avoid lockups.
+        */
+       DBG("PCI: Setting max latency to 32\n");
+       pcibios_max_latency = 32;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency);
+
+static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
+{
+       /*
+        * PIIX4 ACPI device: hardwired IRQ9
+        */
+       d->irq = 9;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi);
+
+/*
+ * Addresses issues with problems in the memory write queue timer in
+ * certain VIA Northbridges.  This bugfix is per VIA's specifications,
+ * except for the KL133/KM133: clearing bit 5 on those Northbridges seems
+ * to trigger a bug in its integrated ProSavage video card, which
+ * causes screen corruption.  We only clear bits 6 and 7 for that chipset,
+ * until VIA can provide us with definitive information on why screen
+ * corruption occurs, and what exactly those bits do.
+ *
+ * VIA 8363,8622,8361 Northbridges:
+ *  - bits  5, 6, 7 at offset 0x55 need to be turned off
+ * VIA 8367 (KT266x) Northbridges:
+ *  - bits  5, 6, 7 at offset 0x95 need to be turned off
+ * VIA 8363 rev 0x81/0x84 (KL133/KM133) Northbridges:
+ *  - bits     6, 7 at offset 0x55 need to be turned off
+ */
+
+#define VIA_8363_KL133_REVISION_ID 0x81
+#define VIA_8363_KM133_REVISION_ID 0x84
+
+static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
+{
+       u8 v;
+       int where = 0x55;
+       int mask = 0x1f; /* clear bits 5, 6, 7 by default */
+
+       if (d->device == PCI_DEVICE_ID_VIA_8367_0) {
+               /* fix pci bus latency issues resulted by NB bios error
+                  it appears on bug free^Wreduced kt266x's bios forces
+                  NB latency to zero */
+               pci_write_config_byte(d, PCI_LATENCY_TIMER, 0);
+
+               where = 0x95; /* the memory write queue timer register is 
+                               different for the KT266x's: 0x95 not 0x55 */
+       } else if (d->device == PCI_DEVICE_ID_VIA_8363_0 &&
+                       (d->revision == VIA_8363_KL133_REVISION_ID ||
+                       d->revision == VIA_8363_KM133_REVISION_ID)) {
+                       mask = 0x3f; /* clear only bits 6 and 7; clearing bit 5
+                                       causes screen corruption on the KL133/KM133 */
+       }
+
+       pci_read_config_byte(d, where, &v);
+       if (v & ~mask) {
+               printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
+                       d->device, d->revision, where, v, mask, v & mask);
+               v &= mask;
+               pci_write_config_byte(d, where, v);
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
+
+/*
+ * For some reasons Intel decided that certain parts of their
+ * 815, 845 and some other chipsets must look like PCI-to-PCI bridges
+ * while they are obviously not. The 82801 family (AA, AB, BAM/CAM,
+ * BA/CA/DB and E) PCI bridges are actually HUB-to-PCI ones, according
+ * to Intel terminology. These devices do forward all addresses from
+ * system to PCI bus no matter what are their window settings, so they are
+ * "transparent" (or subtractive decoding) from programmers point of view.
+ */
+static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev)
+{
+       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
+           (dev->device & 0xff00) == 0x2400)
+               dev->transparent = 1;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge);
+
+/*
+ * Fixup for C1 Halt Disconnect problem on nForce2 systems.
+ *
+ * From information provided by "Allen Martin" <AMartin@nvidia.com>:
+ *
+ * A hang is caused when the CPU generates a very fast CONNECT/HALT cycle
+ * sequence.  Workaround is to set the SYSTEM_IDLE_TIMEOUT to 80 ns.
+ * This allows the state-machine and timer to return to a proper state within
+ * 80 ns of the CONNECT and probe appearing together.  Since the CPU will not
+ * issue another HALT within 80 ns of the initial HALT, the failure condition
+ * is avoided.
+ */
+static void pci_fixup_nforce2(struct pci_dev *dev)
+{
+       u32 val;
+
+       /*
+        * Chip  Old value   New value
+        * C17   0x1F0FFF01  0x1F01FF01
+        * C18D  0x9F0FFF01  0x9F01FF01
+        *
+        * Northbridge chip version may be determined by
+        * reading the PCI revision ID (0xC1 or greater is C18D).
+        */
+       pci_read_config_dword(dev, 0x6c, &val);
+
+       /*
+        * Apply fixup if needed, but don't touch disconnect state
+        */
+       if ((val & 0x00FF0000) != 0x00010000) {
+               printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n");
+               pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000);
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
+
+/* Max PCI Express root ports */
+#define MAX_PCIEROOT   6
+static int quirk_aspm_offset[MAX_PCIEROOT << 3];
+
+#define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7))
+
+static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+       return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
+}
+
+/*
+ * Replace the original pci bus ops for write with a new one that will filter
+ * the request to insure ASPM cannot be enabled.
+ */
+static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+       u8 offset;
+
+       offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)];
+
+       if ((offset) && (where == offset))
+               value = value & 0xfffffffc;
+       
+       return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
+}
+
+static struct pci_ops quirk_pcie_aspm_ops = {
+       .read = quirk_pcie_aspm_read,
+       .write = quirk_pcie_aspm_write,
+};
+
+/*
+ * Prevents PCI Express ASPM (Active State Power Management) being enabled.
+ *
+ * Save the register offset, where the ASPM control bits are located,
+ * for each PCI Express device that is in the device list of
+ * the root port in an array for fast indexing. Replace the bus ops
+ * with the modified one.
+ */
+static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
+{
+       int cap_base, i;
+       struct pci_bus  *pbus;
+       struct pci_dev *dev;
+
+       if ((pbus = pdev->subordinate) == NULL)
+               return;
+
+       /*
+        * Check if the DID of pdev matches one of the six root ports. This
+        * check is needed in the case this function is called directly by the
+        * hot-plug driver.
+        */
+       if ((pdev->device < PCI_DEVICE_ID_INTEL_MCH_PA) ||
+           (pdev->device > PCI_DEVICE_ID_INTEL_MCH_PC1))
+               return;
+
+       if (list_empty(&pbus->devices)) {
+               /*
+                * If no device is attached to the root port at power-up or
+                * after hot-remove, the pbus->devices is empty and this code
+                * will set the offsets to zero and the bus ops to parent's bus
+                * ops, which is unmodified.
+                */
+               for (i= GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i)
+                       quirk_aspm_offset[i] = 0;
+
+               pbus->ops = pbus->parent->ops;
+       } else {
+               /*
+                * If devices are attached to the root port at power-up or
+                * after hot-add, the code loops through the device list of
+                * each root port to save the register offsets and replace the
+                * bus ops.
+                */
+               list_for_each_entry(dev, &pbus->devices, bus_list) {
+                       /* There are 0 to 8 devices attached to this bus */
+                       cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP);
+                       quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)]= cap_base + 0x10;
+               }
+               pbus->ops = &quirk_pcie_aspm_ops;
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PA,     pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PA1,    pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PB,     pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PB1,    pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PC,     pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PC1,    pcie_rootport_aspm_quirk );
+
+/*
+ * Fixup to mark boot BIOS video selected by BIOS before it changes
+ *
+ * From information provided by "Jon Smirl" <jonsmirl@gmail.com>
+ *
+ * The standard boot ROM sequence for an x86 machine uses the BIOS
+ * to select an initial video card for boot display. This boot video
+ * card will have it's BIOS copied to C0000 in system RAM.
+ * IORESOURCE_ROM_SHADOW is used to associate the boot video
+ * card with this copy. On laptops this copy has to be used since
+ * the main ROM may be compressed or combined with another image.
+ * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
+ * is marked here since the boot video device will be the only enabled
+ * video device at this point.
+ */
+
+static void __devinit pci_fixup_video(struct pci_dev *pdev)
+{
+       struct pci_dev *bridge;
+       struct pci_bus *bus;
+       u16 config;
+
+       if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+               return;
+
+       /* Is VGA routed to us? */
+       bus = pdev->bus;
+       while (bus) {
+               bridge = bus->self;
+
+               /*
+                * From information provided by
+                * "David Miller" <davem@davemloft.net>
+                * The bridge control register is valid for PCI header
+                * type BRIDGE, or CARDBUS. Host to PCI controllers use
+                * PCI header type NORMAL.
+                */
+               if (bridge
+                   &&((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+                      ||(bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) {
+                       pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
+                                               &config);
+                       if (!(config & PCI_BRIDGE_CTL_VGA))
+                               return;
+               }
+               bus = bus->parent;
+       }
+       pci_read_config_word(pdev, PCI_COMMAND, &config);
+       if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+               pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+               printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
+
+/*
+ * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
+ *
+ * We pretend to bring them out of full D3 state, and restore the proper
+ * IRQ, PCI cache line size, and BARs, otherwise the device won't function
+ * properly.  In some cases, the device will generate an interrupt on
+ * the wrong IRQ line, causing any devices sharing the line it's
+ * *supposed* to use to be disabled by the kernel's IRQ debug code.
+ */
+static u16 toshiba_line_size;
+
+static struct dmi_system_id __devinitdata toshiba_ohci1394_dmi_table[] = {
+       {
+               .ident = "Toshiba PS5 based laptop",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"),
+               },
+       },
+       {
+               .ident = "Toshiba PSM4 based laptop",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"),
+               },
+       },
+       {
+               .ident = "Toshiba A40 based laptop",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "PSA40U"),
+               },
+       },
+       { }
+};
+
+static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
+{
+       if (!dmi_check_system(toshiba_ohci1394_dmi_table))
+               return; /* only applies to certain Toshibas (so far) */
+
+       dev->current_state = PCI_D3cold;
+       pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032,
+                        pci_pre_fixup_toshiba_ohci1394);
+
+static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
+{
+       if (!dmi_check_system(toshiba_ohci1394_dmi_table))
+               return; /* only applies to certain Toshibas (so far) */
+
+       /* Restore config space on Toshiba laptops */
+       pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size);
+       pci_read_config_byte(dev, PCI_INTERRUPT_LINE, (u8 *)&dev->irq);
+       pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+                              pci_resource_start(dev, 0));
+       pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
+                              pci_resource_start(dev, 1));
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
+                        pci_post_fixup_toshiba_ohci1394);
+
+
+/*
+ * Prevent the BIOS trapping accesses to the Cyrix CS5530A video device
+ * configuration space.
+ */
+static void pci_early_fixup_cyrix_5530(struct pci_dev *dev)
+{
+       u8 r;
+       /* clear 'F4 Video Configuration Trap' bit */
+       pci_read_config_byte(dev, 0x42, &r);
+       r &= 0xfd;
+       pci_write_config_byte(dev, 0x42, r);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
+                       pci_early_fixup_cyrix_5530);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
+                       pci_early_fixup_cyrix_5530);
+
+/*
+ * Siemens Nixdorf AG FSC Multiprocessor Interrupt Controller:
+ * prevent update of the BAR0, which doesn't look like a normal BAR.
+ */
+static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev)
+{
+       dev->resource[0].flags |= IORESOURCE_PCI_FIXED;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015,
+                         pci_siemens_interrupt_controller);
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
new file mode 100644 (file)
index 0000000..bcd2f94
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ *     Low-Level PCI Access for i386 machines
+ *
+ * Copyright 1993, 1994 Drew Eckhardt
+ *      Visionary Computing
+ *      (Unix and Linux consulting and custom programming)
+ *      Drew@Colorado.EDU
+ *      +1 (303) 786-7975
+ *
+ * Drew's work was sponsored by:
+ *     iX Multiuser Multitasking Magazine
+ *     Hannover, Germany
+ *     hm@ix.de
+ *
+ * Copyright 1997--2000 Martin Mares <mj@ucw.cz>
+ *
+ * For more information, please consult the following manuals (look at
+ * http://www.pcisig.com/ for how to get them):
+ *
+ * PCI BIOS Specification
+ * PCI Local Bus Specification
+ * PCI to PCI Bridge Specification
+ * PCI System Design Guide
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+
+#include "pci.h"
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void
+pcibios_align_resource(void *data, struct resource *res,
+                       resource_size_t size, resource_size_t align)
+{
+       if (res->flags & IORESOURCE_IO) {
+               resource_size_t start = res->start;
+
+               if (start & 0x300) {
+                       start = (start + 0x3ff) & ~0x3ff;
+                       res->start = start;
+               }
+       }
+}
+
+
+/*
+ *  Handle resources of PCI devices.  If the world were perfect, we could
+ *  just allocate all the resource regions and do nothing more.  It isn't.
+ *  On the other hand, we cannot just re-allocate all devices, as it would
+ *  require us to know lots of host bridge internals.  So we attempt to
+ *  keep as much of the original configuration as possible, but tweak it
+ *  when it's found to be wrong.
+ *
+ *  Known BIOS problems we have to work around:
+ *     - I/O or memory regions not configured
+ *     - regions configured, but not enabled in the command register
+ *     - bogus I/O addresses above 64K used
+ *     - expansion ROMs left enabled (this may sound harmless, but given
+ *       the fact the PCI specs explicitly allow address decoders to be
+ *       shared between expansion ROMs and other resource regions, it's
+ *       at least dangerous)
+ *
+ *  Our solution:
+ *     (1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ *         This gives us fixed barriers on where we can allocate.
+ *     (2) Allocate resources for all enabled devices.  If there is
+ *         a collision, just mark the resource as unallocated. Also
+ *         disable expansion ROMs during this step.
+ *     (3) Try to allocate resources for disabled devices.  If the
+ *         resources were assigned correctly, everything goes well,
+ *         if they weren't, they won't disturb allocation of other
+ *         resources.
+ *     (4) Assign new addresses to resources which were either
+ *         not configured at all or misconfigured.  If explicitly
+ *         requested by the user, configure expansion ROM address
+ *         as well.
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+       struct pci_bus *bus;
+       struct pci_dev *dev;
+       int idx;
+       struct resource *r, *pr;
+
+       /* Depth-First Search on bus tree */
+       list_for_each_entry(bus, bus_list, node) {
+               if ((dev = bus->self)) {
+                       for (idx = PCI_BRIDGE_RESOURCES;
+                           idx < PCI_NUM_RESOURCES; idx++) {
+                               r = &dev->resource[idx];
+                               if (!r->flags)
+                                       continue;
+                               pr = pci_find_parent_resource(dev, r);
+                               if (!r->start || !pr ||
+                                   request_resource(pr, r) < 0) {
+                                       printk(KERN_ERR "PCI: Cannot allocate "
+                                               "resource region %d "
+                                               "of bridge %s\n",
+                                               idx, pci_name(dev));
+                                       /*
+                                        * Something is wrong with the region.
+                                        * Invalidate the resource to prevent
+                                        * child resource allocations in this
+                                        * range.
+                                        */
+                                       r->flags = 0;
+                               }
+                       }
+               }
+               pcibios_allocate_bus_resources(&bus->children);
+       }
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+       struct pci_dev *dev = NULL;
+       int idx, disabled;
+       u16 command;
+       struct resource *r, *pr;
+
+       for_each_pci_dev(dev) {
+               pci_read_config_word(dev, PCI_COMMAND, &command);
+               for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+                       r = &dev->resource[idx];
+                       if (r->parent)          /* Already allocated */
+                               continue;
+                       if (!r->start)          /* Address not assigned at all */
+                               continue;
+                       if (r->flags & IORESOURCE_IO)
+                               disabled = !(command & PCI_COMMAND_IO);
+                       else
+                               disabled = !(command & PCI_COMMAND_MEMORY);
+                       if (pass == disabled) {
+                               DBG("PCI: Resource %08lx-%08lx "
+                                   "(f=%lx, d=%d, p=%d)\n",
+                                   r->start, r->end, r->flags, disabled, pass);
+                               pr = pci_find_parent_resource(dev, r);
+                               if (!pr || request_resource(pr, r) < 0) {
+                                       printk(KERN_ERR "PCI: Cannot allocate "
+                                               "resource region %d "
+                                               "of device %s\n",
+                                               idx, pci_name(dev));
+                                       /* We'll assign a new address later */
+                                       r->end -= r->start;
+                                       r->start = 0;
+                               }
+                       }
+               }
+               if (!pass) {
+                       r = &dev->resource[PCI_ROM_RESOURCE];
+                       if (r->flags & IORESOURCE_ROM_ENABLE) {
+                               /* Turn the ROM off, leave the resource region,
+                                * but keep it unregistered. */
+                               u32 reg;
+                               DBG("PCI: Switching off ROM of %s\n",
+                                       pci_name(dev));
+                               r->flags &= ~IORESOURCE_ROM_ENABLE;
+                               pci_read_config_dword(dev,
+                                               dev->rom_base_reg, &reg);
+                               pci_write_config_dword(dev, dev->rom_base_reg,
+                                               reg & ~PCI_ROM_ADDRESS_ENABLE);
+                       }
+               }
+       }
+}
+
+static int __init pcibios_assign_resources(void)
+{
+       struct pci_dev *dev = NULL;
+       struct resource *r, *pr;
+
+       if (!(pci_probe & PCI_ASSIGN_ROMS)) {
+               /*
+                * Try to use BIOS settings for ROMs, otherwise let
+                * pci_assign_unassigned_resources() allocate the new
+                * addresses.
+                */
+               for_each_pci_dev(dev) {
+                       r = &dev->resource[PCI_ROM_RESOURCE];
+                       if (!r->flags || !r->start)
+                               continue;
+                       pr = pci_find_parent_resource(dev, r);
+                       if (!pr || request_resource(pr, r) < 0) {
+                               r->end -= r->start;
+                               r->start = 0;
+                       }
+               }
+       }
+
+       pci_assign_unassigned_resources();
+
+       return 0;
+}
+
+void __init pcibios_resource_survey(void)
+{
+       DBG("PCI: Allocating resources\n");
+       pcibios_allocate_bus_resources(&pci_root_buses);
+       pcibios_allocate_resources(0);
+       pcibios_allocate_resources(1);
+}
+
+/**
+ * called in fs_initcall (one below subsys_initcall),
+ * give a chance for motherboard reserve resources
+ */
+fs_initcall(pcibios_assign_resources);
+
+int pcibios_enable_resources(struct pci_dev *dev, int mask)
+{
+       u16 cmd, old_cmd;
+       int idx;
+       struct resource *r;
+
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       old_cmd = cmd;
+       for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+               /* Only set up the requested stuff */
+               if (!(mask & (1 << idx)))
+                       continue;
+
+               r = &dev->resource[idx];
+               if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+                       continue;
+               if ((idx == PCI_ROM_RESOURCE) &&
+                               (!(r->flags & IORESOURCE_ROM_ENABLE)))
+                       continue;
+               if (!r->start && r->end) {
+                       printk(KERN_ERR "PCI: Device %s not available "
+                               "because of resource %d collisions\n",
+                               pci_name(dev), idx);
+                       return -EINVAL;
+               }
+               if (r->flags & IORESOURCE_IO)
+                       cmd |= PCI_COMMAND_IO;
+               if (r->flags & IORESOURCE_MEM)
+                       cmd |= PCI_COMMAND_MEMORY;
+       }
+       if (cmd != old_cmd) {
+               printk("PCI: Enabling device %s (%04x -> %04x)\n",
+                       pci_name(dev), old_cmd, cmd);
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       }
+       return 0;
+}
+
+/*
+ *  If we set up a device for bus mastering, we need to check the latency
+ *  timer as certain crappy BIOSes forget to set it properly.
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+       u8 lat;
+       pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+       if (lat < 16)
+               lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+       else if (lat > pcibios_max_latency)
+               lat = pcibios_max_latency;
+       else
+               return;
+       printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n",
+               pci_name(dev), lat);
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+                       enum pci_mmap_state mmap_state, int write_combine)
+{
+       unsigned long prot;
+
+       /* I/O space cannot be accessed via normal processor loads and
+        * stores on this platform.
+        */
+       if (mmap_state == pci_mmap_io)
+               return -EINVAL;
+
+       /* Leave vm_pgoff as-is, the PCI space address is the physical
+        * address on this platform.
+        */
+       prot = pgprot_val(vma->vm_page_prot);
+       if (boot_cpu_data.x86 > 3)
+               prot |= _PAGE_PCD | _PAGE_PWT;
+       vma->vm_page_prot = __pgprot(prot);
+
+       /* Write-combine setting is ignored, it is changed via the mtrr
+        * interfaces on this platform.
+        */
+       if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+                              vma->vm_end - vma->vm_start,
+                              vma->vm_page_prot))
+               return -EAGAIN;
+
+       return 0;
+}
diff --git a/arch/x86/pci/init.c b/arch/x86/pci/init.c
new file mode 100644 (file)
index 0000000..3de9f9b
--- /dev/null
@@ -0,0 +1,37 @@
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci.h"
+
+/* arch_initcall has too random ordering, so call the initializers
+   in the right sequence from here. */
+static __init int pci_access_init(void)
+{
+       int type __maybe_unused = 0;
+
+#ifdef CONFIG_PCI_DIRECT
+       type = pci_direct_probe();
+#endif
+#ifdef CONFIG_PCI_MMCONFIG
+       pci_mmcfg_init(type);
+#endif
+       if (raw_pci_ops)
+               return 0;
+#ifdef CONFIG_PCI_BIOS
+       pci_pcbios_init();
+#endif
+       /*
+        * don't check for raw_pci_ops here because we want pcbios as last
+        * fallback, yet it's needed to run first to set pcibios_last_bus
+        * in case legacy PCI probing is used. otherwise detecting peer busses
+        * fails.
+        */
+#ifdef CONFIG_PCI_DIRECT
+       pci_direct_init(type);
+#endif
+       if (!raw_pci_ops)
+               printk(KERN_ERR
+               "PCI: Fatal: No config space access function found\n");
+
+       return 0;
+}
+arch_initcall(pci_access_init);
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
new file mode 100644 (file)
index 0000000..8434f23
--- /dev/null
@@ -0,0 +1,1173 @@
+/*
+ *     Low-Level PCI Support for PC -- Routing of Interrupts
+ *
+ *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/io_apic.h>
+#include <linux/irq.h>
+#include <linux/acpi.h>
+
+#include "pci.h"
+
+#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
+#define PIRQ_VERSION 0x0100
+
+static int broken_hp_bios_irq9;
+static int acer_tm360_irqrouting;
+
+static struct irq_routing_table *pirq_table;
+
+static int pirq_enable_irq(struct pci_dev *dev);
+
+/*
+ * Never use: 0, 1, 2 (timer, keyboard, and cascade)
+ * Avoid using: 13, 14 and 15 (FP error and IDE).
+ * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
+ */
+unsigned int pcibios_irq_mask = 0xfff8;
+
+static int pirq_penalty[16] = {
+       1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
+       0, 0, 0, 0, 1000, 100000, 100000, 100000
+};
+
+struct irq_router {
+       char *name;
+       u16 vendor, device;
+       int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
+       int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
+};
+
+struct irq_router_handler {
+       u16 vendor;
+       int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
+};
+
+int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
+void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
+
+/*
+ *  Check passed address for the PCI IRQ Routing Table signature
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
+{
+       struct irq_routing_table *rt;
+       int i;
+       u8 sum;
+
+       rt = (struct irq_routing_table *) addr;
+       if (rt->signature != PIRQ_SIGNATURE ||
+           rt->version != PIRQ_VERSION ||
+           rt->size % 16 ||
+           rt->size < sizeof(struct irq_routing_table))
+               return NULL;
+       sum = 0;
+       for (i=0; i < rt->size; i++)
+               sum += addr[i];
+       if (!sum) {
+               DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", rt);
+               return rt;
+       }
+       return NULL;
+}
+
+
+
+/*
+ *  Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
+ */
+
+static struct irq_routing_table * __init pirq_find_routing_table(void)
+{
+       u8 *addr;
+       struct irq_routing_table *rt;
+
+       if (pirq_table_addr) {
+               rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+               if (rt)
+                       return rt;
+               printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
+       }
+       for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
+               rt = pirq_check_routing_table(addr);
+               if (rt)
+                       return rt;
+       }
+       return NULL;
+}
+
+/*
+ *  If we have a IRQ routing table, use it to search for peer host
+ *  bridges.  It's a gross hack, but since there are no other known
+ *  ways how to get a list of buses, we have to go this way.
+ */
+
+static void __init pirq_peer_trick(void)
+{
+       struct irq_routing_table *rt = pirq_table;
+       u8 busmap[256];
+       int i;
+       struct irq_info *e;
+
+       memset(busmap, 0, sizeof(busmap));
+       for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
+               e = &rt->slots[i];
+#ifdef DEBUG
+               {
+                       int j;
+                       DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
+                       for(j=0; j<4; j++)
+                               DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
+                       DBG("\n");
+               }
+#endif
+               busmap[e->bus] = 1;
+       }
+       for(i = 1; i < 256; i++) {
+               if (!busmap[i] || pci_find_bus(0, i))
+                       continue;
+               if (pci_scan_bus_with_sysdata(i))
+                       printk(KERN_INFO "PCI: Discovered primary peer "
+                              "bus %02x [IRQ]\n", i);
+       }
+       pcibios_last_bus = -1;
+}
+
+/*
+ *  Code for querying and setting of IRQ routes on various interrupt routers.
+ */
+
+void eisa_set_level_irq(unsigned int irq)
+{
+       unsigned char mask = 1 << (irq & 7);
+       unsigned int port = 0x4d0 + (irq >> 3);
+       unsigned char val;
+       static u16 eisa_irq_mask;
+
+       if (irq >= 16 || (1 << irq) & eisa_irq_mask)
+               return;
+
+       eisa_irq_mask |= (1 << irq);
+       printk(KERN_DEBUG "PCI: setting IRQ %u as level-triggered\n", irq);
+       val = inb(port);
+       if (!(val & mask)) {
+               DBG(KERN_DEBUG " -> edge");
+               outb(val | mask, port);
+       }
+}
+
+/*
+ * Common IRQ routing practice: nybbles in config space,
+ * offset by some magic constant.
+ */
+static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
+{
+       u8 x;
+       unsigned reg = offset + (nr >> 1);
+
+       pci_read_config_byte(router, reg, &x);
+       return (nr & 1) ? (x >> 4) : (x & 0xf);
+}
+
+static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val)
+{
+       u8 x;
+       unsigned reg = offset + (nr >> 1);
+
+       pci_read_config_byte(router, reg, &x);
+       x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val);
+       pci_write_config_byte(router, reg, x);
+}
+
+/*
+ * ALI pirq entries are damn ugly, and completely undocumented.
+ * This has been figured out from pirq tables, and it's not a pretty
+ * picture.
+ */
+static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+
+       return irqmap[read_config_nybble(router, 0x48, pirq-1)];
+}
+
+static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+       unsigned int val = irqmap[irq];
+               
+       if (val) {
+               write_config_nybble(router, 0x48, pirq-1, val);
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * The Intel PIIX4 pirq rules are fairly simple: "pirq" is
+ * just a pointer to the config space.
+ */
+static int pirq_piix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       u8 x;
+
+       pci_read_config_byte(router, pirq, &x);
+       return (x < 16) ? x : 0;
+}
+
+static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       pci_write_config_byte(router, pirq, irq);
+       return 1;
+}
+
+/*
+ * The VIA pirq rules are nibble-based, like ALI,
+ * but without the ugly irq number munging.
+ * However, PIRQD is in the upper instead of lower 4 bits.
+ */
+static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
+}
+
+static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
+       return 1;
+}
+
+/*
+ * The VIA pirq rules are nibble-based, like ALI,
+ * but without the ugly irq number munging.
+ * However, for 82C586, nibble map is different .
+ */
+static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+       return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
+}
+
+static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+       write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+       return 1;
+}
+
+/*
+ * ITE 8330G pirq rules are nibble-based
+ * FIXME: pirqmap may be { 1, 0, 3, 2 },
+ *       2+3 are both mapped to irq 9 on my system
+ */
+static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+       return read_config_nybble(router,0x43, pirqmap[pirq-1]);
+}
+
+static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+       write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
+       return 1;
+}
+
+/*
+ * OPTI: high four bits are nibble pointer..
+ * I wonder what the low bits do?
+ */
+static int pirq_opti_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       return read_config_nybble(router, 0xb8, pirq >> 4);
+}
+
+static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       write_config_nybble(router, 0xb8, pirq >> 4, irq);
+       return 1;
+}
+
+/*
+ * Cyrix: nibble offset 0x5C
+ * 0x5C bits 7:4 is INTB bits 3:0 is INTA 
+ * 0x5D bits 7:4 is INTD bits 3:0 is INTC
+ */
+static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       return read_config_nybble(router, 0x5C, (pirq-1)^1);
+}
+
+static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       write_config_nybble(router, 0x5C, (pirq-1)^1, irq);
+       return 1;
+}
+
+/*
+ *     PIRQ routing for SiS 85C503 router used in several SiS chipsets.
+ *     We have to deal with the following issues here:
+ *     - vendors have different ideas about the meaning of link values
+ *     - some onboard devices (integrated in the chipset) have special
+ *       links and are thus routed differently (i.e. not via PCI INTA-INTD)
+ *     - different revision of the router have a different layout for
+ *       the routing registers, particularly for the onchip devices
+ *
+ *     For all routing registers the common thing is we have one byte
+ *     per routeable link which is defined as:
+ *              bit 7      IRQ mapping enabled (0) or disabled (1)
+ *              bits [6:4] reserved (sometimes used for onchip devices)
+ *              bits [3:0] IRQ to map to
+ *                  allowed: 3-7, 9-12, 14-15
+ *                  reserved: 0, 1, 2, 8, 13
+ *
+ *     The config-space registers located at 0x41/0x42/0x43/0x44 are
+ *     always used to route the normal PCI INT A/B/C/D respectively.
+ *     Apparently there are systems implementing PCI routing table using
+ *     link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D.
+ *     We try our best to handle both link mappings.
+ *     
+ *     Currently (2003-05-21) it appears most SiS chipsets follow the
+ *     definition of routing registers from the SiS-5595 southbridge.
+ *     According to the SiS 5595 datasheets the revision id's of the
+ *     router (ISA-bridge) should be 0x01 or 0xb0.
+ *
+ *     Furthermore we've also seen lspci dumps with revision 0x00 and 0xb1.
+ *     Looks like these are used in a number of SiS 5xx/6xx/7xx chipsets.
+ *     They seem to work with the current routing code. However there is
+ *     some concern because of the two USB-OHCI HCs (original SiS 5595
+ *     had only one). YMMV.
+ *
+ *     Onchip routing for router rev-id 0x01/0xb0 and probably 0x00/0xb1:
+ *
+ *     0x61:   IDEIRQ:
+ *             bits [6:5] must be written 01
+ *             bit 4 channel-select primary (0), secondary (1)
+ *
+ *     0x62:   USBIRQ:
+ *             bit 6 OHCI function disabled (0), enabled (1)
+ *     
+ *     0x6a:   ACPI/SCI IRQ: bits 4-6 reserved
+ *
+ *     0x7e:   Data Acq. Module IRQ - bits 4-6 reserved
+ *
+ *     We support USBIRQ (in addition to INTA-INTD) and keep the
+ *     IDE, ACPI and DAQ routing untouched as set by the BIOS.
+ *
+ *     Currently the only reported exception is the new SiS 65x chipset
+ *     which includes the SiS 69x southbridge. Here we have the 85C503
+ *     router revision 0x04 and there are changes in the register layout
+ *     mostly related to the different USB HCs with USB 2.0 support.
+ *
+ *     Onchip routing for router rev-id 0x04 (try-and-error observation)
+ *
+ *     0x60/0x61/0x62/0x63:    1xEHCI and 3xOHCI (companion) USB-HCs
+ *                             bit 6-4 are probably unused, not like 5595
+ */
+
+#define PIRQ_SIS_IRQ_MASK      0x0f
+#define PIRQ_SIS_IRQ_DISABLE   0x80
+#define PIRQ_SIS_USB_ENABLE    0x40
+
+static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       u8 x;
+       int reg;
+
+       reg = pirq;
+       if (reg >= 0x01 && reg <= 0x04)
+               reg += 0x40;
+       pci_read_config_byte(router, reg, &x);
+       return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK);
+}
+
+static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       u8 x;
+       int reg;
+
+       reg = pirq;
+       if (reg >= 0x01 && reg <= 0x04)
+               reg += 0x40;
+       pci_read_config_byte(router, reg, &x);
+       x &= ~(PIRQ_SIS_IRQ_MASK | PIRQ_SIS_IRQ_DISABLE);
+       x |= irq ? irq: PIRQ_SIS_IRQ_DISABLE;
+       pci_write_config_byte(router, reg, x);
+       return 1;
+}
+
+
+/*
+ * VLSI: nibble offset 0x74 - educated guess due to routing table and
+ *       config space of VLSI 82C534 PCI-bridge/router (1004:0102)
+ *       Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard
+ *       devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6
+ *       for the busbridge to the docking station.
+ */
+
+static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       if (pirq > 8) {
+               printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
+               return 0;
+       }
+       return read_config_nybble(router, 0x74, pirq-1);
+}
+
+static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       if (pirq > 8) {
+               printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
+               return 0;
+       }
+       write_config_nybble(router, 0x74, pirq-1, irq);
+       return 1;
+}
+
+/*
+ * ServerWorks: PCI interrupts mapped to system IRQ lines through Index
+ * and Redirect I/O registers (0x0c00 and 0x0c01).  The Index register
+ * format is (PCIIRQ## | 0x10), e.g.: PCIIRQ10=0x1a.  The Redirect
+ * register is a straight binary coding of desired PIC IRQ (low nibble).
+ *
+ * The 'link' value in the PIRQ table is already in the correct format
+ * for the Index register.  There are some special index values:
+ * 0x00 for ACPI (SCI), 0x01 for USB, 0x02 for IDE0, 0x04 for IDE1,
+ * and 0x03 for SMBus.
+ */
+static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       outb_p(pirq, 0xc00);
+       return inb(0xc01) & 0xf;
+}
+
+static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       outb_p(pirq, 0xc00);
+       outb_p(irq, 0xc01);
+       return 1;
+}
+
+/* Support for AMD756 PCI IRQ Routing
+ * Jhon H. Caicedo <jhcaiced@osso.org.co>
+ * Jun/21/2001 0.2.0 Release, fixed to use "nybble" functions... (jhcaiced)
+ * Jun/19/2001 Alpha Release 0.1.0 (jhcaiced)
+ * The AMD756 pirq rules are nibble-based
+ * offset 0x56 0-3 PIRQA  4-7  PIRQB
+ * offset 0x57 0-3 PIRQC  4-7  PIRQD
+ */
+static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+       u8 irq;
+       irq = 0;
+       if (pirq <= 4)
+       {
+               irq = read_config_nybble(router, 0x56, pirq - 1);
+       }
+       printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
+               dev->vendor, dev->device, pirq, irq);
+       return irq;
+}
+
+static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", 
+               dev->vendor, dev->device, pirq, irq);
+       if (pirq <= 4)
+       {
+               write_config_nybble(router, 0x56, pirq - 1, irq);
+       }
+       return 1;
+}
+
+#ifdef CONFIG_PCI_BIOS
+
+static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+       struct pci_dev *bridge;
+       int pin = pci_get_interrupt_pin(dev, &bridge);
+       return pcibios_set_irq_routing(bridge, pin, irq);
+}
+
+#endif
+
+static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+       static struct pci_device_id __initdata pirq_440gx[] = {
+               { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
+               { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
+               { },
+       };
+
+       /* 440GX has a proprietary PIRQ router -- don't use it */
+       if (pci_dev_present(pirq_440gx))
+               return 0;
+
+       switch(device)
+       {
+               case PCI_DEVICE_ID_INTEL_82371FB_0:
+               case PCI_DEVICE_ID_INTEL_82371SB_0:
+               case PCI_DEVICE_ID_INTEL_82371AB_0:
+               case PCI_DEVICE_ID_INTEL_82371MX:
+               case PCI_DEVICE_ID_INTEL_82443MX_0:
+               case PCI_DEVICE_ID_INTEL_82801AA_0:
+               case PCI_DEVICE_ID_INTEL_82801AB_0:
+               case PCI_DEVICE_ID_INTEL_82801BA_0:
+               case PCI_DEVICE_ID_INTEL_82801BA_10:
+               case PCI_DEVICE_ID_INTEL_82801CA_0:
+               case PCI_DEVICE_ID_INTEL_82801CA_12:
+               case PCI_DEVICE_ID_INTEL_82801DB_0:
+               case PCI_DEVICE_ID_INTEL_82801E_0:
+               case PCI_DEVICE_ID_INTEL_82801EB_0:
+               case PCI_DEVICE_ID_INTEL_ESB_1:
+               case PCI_DEVICE_ID_INTEL_ICH6_0:
+               case PCI_DEVICE_ID_INTEL_ICH6_1:
+               case PCI_DEVICE_ID_INTEL_ICH7_0:
+               case PCI_DEVICE_ID_INTEL_ICH7_1:
+               case PCI_DEVICE_ID_INTEL_ICH7_30:
+               case PCI_DEVICE_ID_INTEL_ICH7_31:
+               case PCI_DEVICE_ID_INTEL_ESB2_0:
+               case PCI_DEVICE_ID_INTEL_ICH8_0:
+               case PCI_DEVICE_ID_INTEL_ICH8_1:
+               case PCI_DEVICE_ID_INTEL_ICH8_2:
+               case PCI_DEVICE_ID_INTEL_ICH8_3:
+               case PCI_DEVICE_ID_INTEL_ICH8_4:
+               case PCI_DEVICE_ID_INTEL_ICH9_0:
+               case PCI_DEVICE_ID_INTEL_ICH9_1:
+               case PCI_DEVICE_ID_INTEL_ICH9_2:
+               case PCI_DEVICE_ID_INTEL_ICH9_3:
+               case PCI_DEVICE_ID_INTEL_ICH9_4:
+               case PCI_DEVICE_ID_INTEL_ICH9_5:
+               case PCI_DEVICE_ID_INTEL_TOLAPAI_0:
+                       r->name = "PIIX/ICH";
+                       r->get = pirq_piix_get;
+                       r->set = pirq_piix_set;
+                       return 1;
+       }
+       return 0;
+}
+
+static __init int via_router_probe(struct irq_router *r,
+                               struct pci_dev *router, u16 device)
+{
+       /* FIXME: We should move some of the quirk fixup stuff here */
+
+       /*
+        * work arounds for some buggy BIOSes
+        */
+       if (device == PCI_DEVICE_ID_VIA_82C586_0) {
+               switch(router->device) {
+               case PCI_DEVICE_ID_VIA_82C686:
+                       /*
+                        * Asus k7m bios wrongly reports 82C686A
+                        * as 586-compatible
+                        */
+                       device = PCI_DEVICE_ID_VIA_82C686;
+                       break;
+               case PCI_DEVICE_ID_VIA_8235:
+                       /**
+                        * Asus a7v-x bios wrongly reports 8235
+                        * as 586-compatible
+                        */
+                       device = PCI_DEVICE_ID_VIA_8235;
+                       break;
+               }
+       }
+
+       switch(device) {
+       case PCI_DEVICE_ID_VIA_82C586_0:
+               r->name = "VIA";
+               r->get = pirq_via586_get;
+               r->set = pirq_via586_set;
+               return 1;
+       case PCI_DEVICE_ID_VIA_82C596:
+       case PCI_DEVICE_ID_VIA_82C686:
+       case PCI_DEVICE_ID_VIA_8231:
+       case PCI_DEVICE_ID_VIA_8233A:
+       case PCI_DEVICE_ID_VIA_8235:
+       case PCI_DEVICE_ID_VIA_8237:
+               /* FIXME: add new ones for 8233/5 */
+               r->name = "VIA";
+               r->get = pirq_via_get;
+               r->set = pirq_via_set;
+               return 1;
+       }
+       return 0;
+}
+
+static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+       switch(device)
+       {
+               case PCI_DEVICE_ID_VLSI_82C534:
+                       r->name = "VLSI 82C534";
+                       r->get = pirq_vlsi_get;
+                       r->set = pirq_vlsi_set;
+                       return 1;
+       }
+       return 0;
+}
+
+
+static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+       switch(device)
+       {
+               case PCI_DEVICE_ID_SERVERWORKS_OSB4:
+               case PCI_DEVICE_ID_SERVERWORKS_CSB5:
+                       r->name = "ServerWorks";
+                       r->get = pirq_serverworks_get;
+                       r->set = pirq_serverworks_set;
+                       return 1;
+       }
+       return 0;
+}
+
+static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+       if (device != PCI_DEVICE_ID_SI_503)
+               return 0;
+               
+       r->name = "SIS";
+       r->get = pirq_sis_get;
+       r->set = pirq_sis_set;
+       return 1;
+}
+
+static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+       switch(device)
+       {
+               case PCI_DEVICE_ID_CYRIX_5520:
+                       r->name = "NatSemi";
+                       r->get = pirq_cyrix_get;
+                       r->set = pirq_cyrix_set;
+                       return 1;
+       }
+       return 0;
+}
+
+static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+       switch(device)
+       {
+               case PCI_DEVICE_ID_OPTI_82C700:
+                       r->name = "OPTI";
+                       r->get = pirq_opti_get;
+                       r->set = pirq_opti_set;
+                       return 1;
+       }
+       return 0;
+}
+
+static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+       switch(device)
+       {
+               case PCI_DEVICE_ID_ITE_IT8330G_0:
+                       r->name = "ITE";
+                       r->get = pirq_ite_get;
+                       r->set = pirq_ite_set;
+                       return 1;
+       }
+       return 0;
+}
+
+static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+       switch(device)
+       {
+       case PCI_DEVICE_ID_AL_M1533:
+       case PCI_DEVICE_ID_AL_M1563:
+               printk(KERN_DEBUG "PCI: Using ALI IRQ Router\n");
+               r->name = "ALI";
+               r->get = pirq_ali_get;
+               r->set = pirq_ali_set;
+               return 1;
+       }
+       return 0;
+}
+
+static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+       switch(device)
+       {
+               case PCI_DEVICE_ID_AMD_VIPER_740B:
+                       r->name = "AMD756";
+                       break;
+               case PCI_DEVICE_ID_AMD_VIPER_7413:
+                       r->name = "AMD766";
+                       break;
+               case PCI_DEVICE_ID_AMD_VIPER_7443:
+                       r->name = "AMD768";
+                       break;
+               default:
+                       return 0;
+       }
+       r->get = pirq_amd756_get;
+       r->set = pirq_amd756_set;
+       return 1;
+}
+               
+static __initdata struct irq_router_handler pirq_routers[] = {
+       { PCI_VENDOR_ID_INTEL, intel_router_probe },
+       { PCI_VENDOR_ID_AL, ali_router_probe },
+       { PCI_VENDOR_ID_ITE, ite_router_probe },
+       { PCI_VENDOR_ID_VIA, via_router_probe },
+       { PCI_VENDOR_ID_OPTI, opti_router_probe },
+       { PCI_VENDOR_ID_SI, sis_router_probe },
+       { PCI_VENDOR_ID_CYRIX, cyrix_router_probe },
+       { PCI_VENDOR_ID_VLSI, vlsi_router_probe },
+       { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
+       { PCI_VENDOR_ID_AMD, amd_router_probe },
+       /* Someone with docs needs to add the ATI Radeon IGP */
+       { 0, NULL }
+};
+static struct irq_router pirq_router;
+static struct pci_dev *pirq_router_dev;
+
+
+/*
+ *     FIXME: should we have an option to say "generic for
+ *     chipset" ?
+ */
+static void __init pirq_find_router(struct irq_router *r)
+{
+       struct irq_routing_table *rt = pirq_table;
+       struct irq_router_handler *h;
+
+#ifdef CONFIG_PCI_BIOS
+       if (!rt->signature) {
+               printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n");
+               r->set = pirq_bios_set;
+               r->name = "BIOS";
+               return;
+       }
+#endif
+
+       /* Default unless a driver reloads it */
+       r->name = "default";
+       r->get = NULL;
+       r->set = NULL;
+       
+       DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n",
+           rt->rtr_vendor, rt->rtr_device);
+
+       pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn);
+       if (!pirq_router_dev) {
+               DBG(KERN_DEBUG "PCI: Interrupt router not found at "
+                       "%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
+               return;
+       }
+
+       for( h = pirq_routers; h->vendor; h++) {
+               /* First look for a router match */
+               if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device))
+                       break;
+               /* Fall back to a device match */
+               if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device))
+                       break;
+       }
+       printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
+               pirq_router.name,
+               pirq_router_dev->vendor,
+               pirq_router_dev->device,
+               pci_name(pirq_router_dev));
+
+       /* The device remains referenced for the kernel lifetime */
+}
+
+static struct irq_info *pirq_get_info(struct pci_dev *dev)
+{
+       struct irq_routing_table *rt = pirq_table;
+       int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+       struct irq_info *info;
+
+       for (info = rt->slots; entries--; info++)
+               if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
+                       return info;
+       return NULL;
+}
+
+static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
+{
+       u8 pin;
+       struct irq_info *info;
+       int i, pirq, newirq;
+       int irq = 0;
+       u32 mask;
+       struct irq_router *r = &pirq_router;
+       struct pci_dev *dev2 = NULL;
+       char *msg = NULL;
+
+       /* Find IRQ pin */
+       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+       if (!pin) {
+               DBG(KERN_DEBUG " -> no interrupt pin\n");
+               return 0;
+       }
+       pin = pin - 1;
+
+       /* Find IRQ routing entry */
+
+       if (!pirq_table)
+               return 0;
+       
+       DBG(KERN_DEBUG "IRQ for %s[%c]", pci_name(dev), 'A' + pin);
+       info = pirq_get_info(dev);
+       if (!info) {
+               DBG(" -> not found in routing table\n" KERN_DEBUG);
+               return 0;
+       }
+       pirq = info->irq[pin].link;
+       mask = info->irq[pin].bitmap;
+       if (!pirq) {
+               DBG(" -> not routed\n" KERN_DEBUG);
+               return 0;
+       }
+       DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
+       mask &= pcibios_irq_mask;
+
+       /* Work around broken HP Pavilion Notebooks which assign USB to
+          IRQ 9 even though it is actually wired to IRQ 11 */
+
+       if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) {
+               dev->irq = 11;
+               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+               r->set(pirq_router_dev, dev, pirq, 11);
+       }
+
+       /* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */
+       if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) {
+               pirq = 0x68;
+               mask = 0x400;
+               dev->irq = r->get(pirq_router_dev, dev, pirq);
+               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+       }
+
+       /*
+        * Find the best IRQ to assign: use the one
+        * reported by the device if possible.
+        */
+       newirq = dev->irq;
+       if (newirq && !((1 << newirq) & mask)) {
+               if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0;
+               else printk("\n" KERN_WARNING
+                       "PCI: IRQ %i for device %s doesn't match PIRQ mask "
+                       "- try pci=usepirqmask\n" KERN_DEBUG, newirq,
+                       pci_name(dev));
+       }
+       if (!newirq && assign) {
+               for (i = 0; i < 16; i++) {
+                       if (!(mask & (1 << i)))
+                               continue;
+                       if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, IRQF_SHARED))
+                               newirq = i;
+               }
+       }
+       DBG(" -> newirq=%d", newirq);
+
+       /* Check if it is hardcoded */
+       if ((pirq & 0xf0) == 0xf0) {
+               irq = pirq & 0xf;
+               DBG(" -> hardcoded IRQ %d\n", irq);
+               msg = "Hardcoded";
+       } else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
+       ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
+               DBG(" -> got IRQ %d\n", irq);
+               msg = "Found";
+               eisa_set_level_irq(irq);
+       } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
+               DBG(" -> assigning IRQ %d", newirq);
+               if (r->set(pirq_router_dev, dev, pirq, newirq)) {
+                       eisa_set_level_irq(newirq);
+                       DBG(" ... OK\n");
+                       msg = "Assigned";
+                       irq = newirq;
+               }
+       }
+
+       if (!irq) {
+               DBG(" ... failed\n");
+               if (newirq && mask == (1 << newirq)) {
+                       msg = "Guessed";
+                       irq = newirq;
+               } else
+                       return 0;
+       }
+       printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, pci_name(dev));
+
+       /* Update IRQ for all devices with the same pirq value */
+       while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
+               pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
+               if (!pin)
+                       continue;
+               pin--;
+               info = pirq_get_info(dev2);
+               if (!info)
+                       continue;
+               if (info->irq[pin].link == pirq) {
+                       /* We refuse to override the dev->irq information. Give a warning! */
+                       if ( dev2->irq && dev2->irq != irq && \
+                       (!(pci_probe & PCI_USE_PIRQ_MASK) || \
+                       ((1 << dev2->irq) & mask)) ) {
+#ifndef CONFIG_PCI_MSI
+                               printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
+                                      pci_name(dev2), dev2->irq, irq);
+#endif
+                               continue;
+                       }
+                       dev2->irq = irq;
+                       pirq_penalty[irq]++;
+                       if (dev != dev2)
+                               printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, pci_name(dev2));
+               }
+       }
+       return 1;
+}
+
+static void __init pcibios_fixup_irqs(void)
+{
+       struct pci_dev *dev = NULL;
+       u8 pin;
+
+       DBG(KERN_DEBUG "PCI: IRQ fixup\n");
+       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+               /*
+                * If the BIOS has set an out of range IRQ number, just ignore it.
+                * Also keep track of which IRQ's are already in use.
+                */
+               if (dev->irq >= 16) {
+                       DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq);
+                       dev->irq = 0;
+               }
+               /* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
+               if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000)
+                       pirq_penalty[dev->irq] = 0;
+               pirq_penalty[dev->irq]++;
+       }
+
+       dev = NULL;
+       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+               pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+#ifdef CONFIG_X86_IO_APIC
+               /*
+                * Recalculate IRQ numbers if we use the I/O APIC.
+                */
+               if (io_apic_assign_pci_irqs)
+               {
+                       int irq;
+
+                       if (pin) {
+                               pin--;          /* interrupt pins are numbered starting from 1 */
+                               irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
+       /*
+        * Busses behind bridges are typically not listed in the MP-table.
+        * In this case we have to look up the IRQ based on the parent bus,
+        * parent slot, and pin number. The SMP code detects such bridged
+        * busses itself so we should get into this branch reliably.
+        */
+                               if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+                                       struct pci_dev * bridge = dev->bus->self;
+
+                                       pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+                                       irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
+                                                       PCI_SLOT(bridge->devfn), pin);
+                                       if (irq >= 0)
+                                               printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
+                                                       pci_name(bridge), 'A' + pin, irq);
+                               }
+                               if (irq >= 0) {
+                                       printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+                                               pci_name(dev), 'A' + pin, irq);
+                                       dev->irq = irq;
+                               }
+                       }
+               }
+#endif
+               /*
+                * Still no IRQ? Try to lookup one...
+                */
+               if (pin && !dev->irq)
+                       pcibios_lookup_irq(dev, 0);
+       }
+}
+
+/*
+ * Work around broken HP Pavilion Notebooks which assign USB to
+ * IRQ 9 even though it is actually wired to IRQ 11
+ */
+static int __init fix_broken_hp_bios_irq9(struct dmi_system_id *d)
+{
+       if (!broken_hp_bios_irq9) {
+               broken_hp_bios_irq9 = 1;
+               printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
+       }
+       return 0;
+}
+
+/*
+ * Work around broken Acer TravelMate 360 Notebooks which assign
+ * Cardbus to IRQ 11 even though it is actually wired to IRQ 10
+ */
+static int __init fix_acer_tm360_irqrouting(struct dmi_system_id *d)
+{
+       if (!acer_tm360_irqrouting) {
+               acer_tm360_irqrouting = 1;
+               printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
+       }
+       return 0;
+}
+
+static struct dmi_system_id __initdata pciirq_dmi_table[] = {
+       {
+               .callback = fix_broken_hp_bios_irq9,
+               .ident = "HP Pavilion N5400 Series Laptop",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
+               },
+       },
+       {
+               .callback = fix_acer_tm360_irqrouting,
+               .ident = "Acer TravelMate 36x Laptop",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+               },
+       },
+       { }
+};
+
+static int __init pcibios_irq_init(void)
+{
+       DBG(KERN_DEBUG "PCI: IRQ init\n");
+
+       if (pcibios_enable_irq || raw_pci_ops == NULL)
+               return 0;
+
+       dmi_check_system(pciirq_dmi_table);
+
+       pirq_table = pirq_find_routing_table();
+
+#ifdef CONFIG_PCI_BIOS
+       if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
+               pirq_table = pcibios_get_irq_routing_table();
+#endif
+       if (pirq_table) {
+               pirq_peer_trick();
+               pirq_find_router(&pirq_router);
+               if (pirq_table->exclusive_irqs) {
+                       int i;
+                       for (i=0; i<16; i++)
+                               if (!(pirq_table->exclusive_irqs & (1 << i)))
+                                       pirq_penalty[i] += 100;
+               }
+               /* If we're using the I/O APIC, avoid using the PCI IRQ routing table */
+               if (io_apic_assign_pci_irqs)
+                       pirq_table = NULL;
+       }
+
+       pcibios_enable_irq = pirq_enable_irq;
+
+       pcibios_fixup_irqs();
+       return 0;
+}
+
+subsys_initcall(pcibios_irq_init);
+
+
+static void pirq_penalize_isa_irq(int irq, int active)
+{
+       /*
+        *  If any ISAPnP device reports an IRQ in its list of possible
+        *  IRQ's, we try to avoid assigning it to PCI devices.
+        */
+       if (irq < 16) {
+               if (active)
+                       pirq_penalty[irq] += 1000;
+               else
+                       pirq_penalty[irq] += 100;
+       }
+}
+
+void pcibios_penalize_isa_irq(int irq, int active)
+{
+#ifdef CONFIG_ACPI
+       if (!acpi_noirq)
+               acpi_penalize_isa_irq(irq, active);
+       else
+#endif
+               pirq_penalize_isa_irq(irq, active);
+}
+
+static int pirq_enable_irq(struct pci_dev *dev)
+{
+       u8 pin;
+       struct pci_dev *temp_dev;
+
+       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+       if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
+               char *msg = "";
+
+               pin--;          /* interrupt pins are numbered starting from 1 */
+
+               if (io_apic_assign_pci_irqs) {
+                       int irq;
+
+                       irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
+                       /*
+                        * Busses behind bridges are typically not listed in the MP-table.
+                        * In this case we have to look up the IRQ based on the parent bus,
+                        * parent slot, and pin number. The SMP code detects such bridged
+                        * busses itself so we should get into this branch reliably.
+                        */
+                       temp_dev = dev;
+                       while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+                               struct pci_dev * bridge = dev->bus->self;
+
+                               pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+                               irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
+                                               PCI_SLOT(bridge->devfn), pin);
+                               if (irq >= 0)
+                                       printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
+                                               pci_name(bridge), 'A' + pin, irq);
+                               dev = bridge;
+                       }
+                       dev = temp_dev;
+                       if (irq >= 0) {
+                               printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+                                       pci_name(dev), 'A' + pin, irq);
+                               dev->irq = irq;
+                               return 0;
+                       } else
+                               msg = " Probably buggy MP table.";
+               } else if (pci_probe & PCI_BIOS_IRQ_SCAN)
+                       msg = "";
+               else
+                       msg = " Please try using pci=biosirq.";
+
+               /* With IDE legacy devices the IRQ lookup failure is not a problem.. */
+               if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
+                       return 0;
+
+               printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
+                      'A' + pin, pci_name(dev), msg);
+       }
+       return 0;
+}
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
new file mode 100644 (file)
index 0000000..5565d70
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * legacy.c - traditional, old school PCI bus probing
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include "pci.h"
+
+/*
+ * Discover remaining PCI buses in case there are peer host bridges.
+ * We use the number of last PCI bus provided by the PCI BIOS.
+ */
+static void __devinit pcibios_fixup_peer_bridges(void)
+{
+       int n, devfn;
+
+       if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
+               return;
+       DBG("PCI: Peer bridge fixup\n");
+
+       for (n=0; n <= pcibios_last_bus; n++) {
+               u32 l;
+               if (pci_find_bus(0, n))
+                       continue;
+               for (devfn = 0; devfn < 256; devfn += 8) {
+                       if (!raw_pci_ops->read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
+                           l != 0x0000 && l != 0xffff) {
+                               DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
+                               printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
+                               pci_scan_bus_with_sysdata(n);
+                               break;
+                       }
+               }
+       }
+}
+
+static int __init pci_legacy_init(void)
+{
+       if (!raw_pci_ops) {
+               printk("PCI: System does not support PCI\n");
+               return 0;
+       }
+
+       if (pcibios_scanned++)
+               return 0;
+
+       printk("PCI: Probing PCI hardware\n");
+       pci_root_bus = pcibios_scan_root(0);
+       if (pci_root_bus)
+               pci_bus_add_devices(pci_root_bus);
+
+       pcibios_fixup_peer_bridges();
+
+       return 0;
+}
+
+subsys_initcall(pci_legacy_init);
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
new file mode 100644 (file)
index 0000000..4df637e
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * mmconfig-shared.c - Low-level direct PCI config space access via
+ *                     MMCONFIG - common code between i386 and x86-64.
+ *
+ * This code does:
+ * - known chipset handling
+ * - ACPI decoding and validation
+ *
+ * Per-architecture code takes care of the mappings and accesses
+ * themselves.
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/bitmap.h>
+#include <asm/e820.h>
+
+#include "pci.h"
+
+/* aperture is up to 256MB but BIOS may reserve less */
+#define MMCONFIG_APER_MIN      (2 * 1024*1024)
+#define MMCONFIG_APER_MAX      (256 * 1024*1024)
+
+DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
+
+/* Indicate if the mmcfg resources have been placed into the resource table. */
+static int __initdata pci_mmcfg_resources_inserted;
+
+/* K8 systems have some devices (typically in the builtin northbridge)
+   that are only accessible using type1
+   Normally this can be expressed in the MCFG by not listing them
+   and assigning suitable _SEGs, but this isn't implemented in some BIOS.
+   Instead try to discover all devices on bus 0 that are unreachable using MM
+   and fallback for them. */
+static void __init unreachable_devices(void)
+{
+       int i, bus;
+       /* Use the max bus number from ACPI here? */
+       for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
+               for (i = 0; i < 32; i++) {
+                       unsigned int devfn = PCI_DEVFN(i, 0);
+                       u32 val1, val2;
+
+                       pci_conf1_read(0, bus, devfn, 0, 4, &val1);
+                       if (val1 == 0xffffffff)
+                               continue;
+
+                       if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
+                               raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
+                               if (val1 == val2)
+                                       continue;
+                       }
+                       set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
+                       printk(KERN_NOTICE "PCI: No mmconfig possible on device"
+                              " %02x:%02x\n", bus, i);
+               }
+       }
+}
+
+static const char __init *pci_mmcfg_e7520(void)
+{
+       u32 win;
+       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
+
+       win = win & 0xf000;
+       if(win == 0x0000 || win == 0xf000)
+               pci_mmcfg_config_num = 0;
+       else {
+               pci_mmcfg_config_num = 1;
+               pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
+               if (!pci_mmcfg_config)
+                       return NULL;
+               pci_mmcfg_config[0].address = win << 16;
+               pci_mmcfg_config[0].pci_segment = 0;
+               pci_mmcfg_config[0].start_bus_number = 0;
+               pci_mmcfg_config[0].end_bus_number = 255;
+       }
+
+       return "Intel Corporation E7520 Memory Controller Hub";
+}
+
+static const char __init *pci_mmcfg_intel_945(void)
+{
+       u32 pciexbar, mask = 0, len = 0;
+
+       pci_mmcfg_config_num = 1;
+
+       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
+
+       /* Enable bit */
+       if (!(pciexbar & 1))
+               pci_mmcfg_config_num = 0;
+
+       /* Size bits */
+       switch ((pciexbar >> 1) & 3) {
+       case 0:
+               mask = 0xf0000000U;
+               len  = 0x10000000U;
+               break;
+       case 1:
+               mask = 0xf8000000U;
+               len  = 0x08000000U;
+               break;
+       case 2:
+               mask = 0xfc000000U;
+               len  = 0x04000000U;
+               break;
+       default:
+               pci_mmcfg_config_num = 0;
+       }
+
+       /* Errata #2, things break when not aligned on a 256Mb boundary */
+       /* Can only happen in 64M/128M mode */
+
+       if ((pciexbar & mask) & 0x0fffffffU)
+               pci_mmcfg_config_num = 0;
+
+       /* Don't hit the APIC registers and their friends */
+       if ((pciexbar & mask) >= 0xf0000000U)
+               pci_mmcfg_config_num = 0;
+
+       if (pci_mmcfg_config_num) {
+               pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
+               if (!pci_mmcfg_config)
+                       return NULL;
+               pci_mmcfg_config[0].address = pciexbar & mask;
+               pci_mmcfg_config[0].pci_segment = 0;
+               pci_mmcfg_config[0].start_bus_number = 0;
+               pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
+       }
+
+       return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
+}
+
+struct pci_mmcfg_hostbridge_probe {
+       u32 vendor;
+       u32 device;
+       const char *(*probe)(void);
+};
+
+static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
+};
+
+static int __init pci_mmcfg_check_hostbridge(void)
+{
+       u32 l;
+       u16 vendor, device;
+       int i;
+       const char *name;
+
+       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
+       vendor = l & 0xffff;
+       device = (l >> 16) & 0xffff;
+
+       pci_mmcfg_config_num = 0;
+       pci_mmcfg_config = NULL;
+       name = NULL;
+
+       for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
+               if (pci_mmcfg_probes[i].vendor == vendor &&
+                   pci_mmcfg_probes[i].device == device)
+                       name = pci_mmcfg_probes[i].probe();
+       }
+
+       if (name) {
+               printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
+                      name, pci_mmcfg_config_num ? "with" : "without");
+       }
+
+       return name != NULL;
+}
+
+static void __init pci_mmcfg_insert_resources(unsigned long resource_flags)
+{
+#define PCI_MMCFG_RESOURCE_NAME_LEN 19
+       int i;
+       struct resource *res;
+       char *names;
+       unsigned num_buses;
+
+       res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
+                       pci_mmcfg_config_num, GFP_KERNEL);
+       if (!res) {
+               printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
+               return;
+       }
+
+       names = (void *)&res[pci_mmcfg_config_num];
+       for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
+               struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
+               num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
+               res->name = names;
+               snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
+                        cfg->pci_segment);
+               res->start = cfg->address;
+               res->end = res->start + (num_buses << 20) - 1;
+               res->flags = IORESOURCE_MEM | resource_flags;
+               insert_resource(&iomem_resource, res);
+               names += PCI_MMCFG_RESOURCE_NAME_LEN;
+       }
+
+       /* Mark that the resources have been inserted. */
+       pci_mmcfg_resources_inserted = 1;
+}
+
+static void __init pci_mmcfg_reject_broken(int type)
+{
+       typeof(pci_mmcfg_config[0]) *cfg;
+
+       if ((pci_mmcfg_config_num == 0) ||
+           (pci_mmcfg_config == NULL) ||
+           (pci_mmcfg_config[0].address == 0))
+               return;
+
+       cfg = &pci_mmcfg_config[0];
+
+       /*
+        * Handle more broken MCFG tables on Asus etc.
+        * They only contain a single entry for bus 0-0.
+        */
+       if (pci_mmcfg_config_num == 1 &&
+           cfg->pci_segment == 0 &&
+           (cfg->start_bus_number | cfg->end_bus_number) == 0) {
+               printk(KERN_ERR "PCI: start and end of bus number is 0. "
+                      "Rejected as broken MCFG.\n");
+               goto reject;
+       }
+
+       /*
+        * Only do this check when type 1 works. If it doesn't work
+        * assume we run on a Mac and always use MCFG
+        */
+       if (type == 1 && !e820_all_mapped(cfg->address,
+                                         cfg->address + MMCONFIG_APER_MIN,
+                                         E820_RESERVED)) {
+               printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
+                      " E820-reserved\n", cfg->address);
+               goto reject;
+       }
+       return;
+
+reject:
+       printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+       kfree(pci_mmcfg_config);
+       pci_mmcfg_config = NULL;
+       pci_mmcfg_config_num = 0;
+}
+
+void __init pci_mmcfg_init(int type)
+{
+       int known_bridge = 0;
+
+       if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+               return;
+
+       if (type == 1 && pci_mmcfg_check_hostbridge())
+               known_bridge = 1;
+
+       if (!known_bridge) {
+               acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
+               pci_mmcfg_reject_broken(type);
+       }
+
+       if ((pci_mmcfg_config_num == 0) ||
+           (pci_mmcfg_config == NULL) ||
+           (pci_mmcfg_config[0].address == 0))
+               return;
+
+       if (pci_mmcfg_arch_init()) {
+               if (type == 1)
+                       unreachable_devices();
+               if (known_bridge)
+                       pci_mmcfg_insert_resources(IORESOURCE_BUSY);
+               pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+       } else {
+               /*
+                * Signal not to attempt to insert mmcfg resources because
+                * the architecture mmcfg setup could not initialize.
+                */
+               pci_mmcfg_resources_inserted = 1;
+       }
+}
+
+static int __init pci_mmcfg_late_insert_resources(void)
+{
+       /*
+        * If resources are already inserted or we are not using MMCONFIG,
+        * don't insert the resources.
+        */
+       if ((pci_mmcfg_resources_inserted == 1) ||
+           (pci_probe & PCI_PROBE_MMCONF) == 0 ||
+           (pci_mmcfg_config_num == 0) ||
+           (pci_mmcfg_config == NULL) ||
+           (pci_mmcfg_config[0].address == 0))
+               return 1;
+
+       /*
+        * Attempt to insert the mmcfg resources but not with the busy flag
+        * marked so it won't cause request errors when __request_region is
+        * called.
+        */
+       pci_mmcfg_insert_resources(0);
+
+       return 0;
+}
+
+/*
+ * Perform MMCONFIG resource insertion after PCI initialization to allow for
+ * misprogrammed MCFG tables that state larger sizes but actually conflict
+ * with other system resources.
+ */
+late_initcall(pci_mmcfg_late_insert_resources);
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
new file mode 100644 (file)
index 0000000..1bf5816
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx>
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This code is released under the GNU General Public License version 2.
+ */
+
+/*
+ * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <asm/e820.h>
+#include "pci.h"
+
+/* Assume systems with more busses have correct MCFG */
+#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
+
+/* The base address of the last MMCONFIG device accessed */
+static u32 mmcfg_last_accessed_device;
+static int mmcfg_last_accessed_cpu;
+
+/*
+ * Functions for accessing PCI configuration space with MMCONFIG accesses
+ */
+static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
+{
+       struct acpi_mcfg_allocation *cfg;
+       int cfg_num;
+
+       if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
+           test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
+               return 0;
+
+       for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
+               cfg = &pci_mmcfg_config[cfg_num];
+               if (cfg->pci_segment == seg &&
+                   (cfg->start_bus_number <= bus) &&
+                   (cfg->end_bus_number >= bus))
+                       return cfg->address;
+       }
+
+       /* Fall back to type 0 */
+       return 0;
+}
+
+/*
+ * This is always called under pci_config_lock
+ */
+static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
+{
+       u32 dev_base = base | (bus << 20) | (devfn << 12);
+       int cpu = smp_processor_id();
+       if (dev_base != mmcfg_last_accessed_device ||
+           cpu != mmcfg_last_accessed_cpu) {
+               mmcfg_last_accessed_device = dev_base;
+               mmcfg_last_accessed_cpu = cpu;
+               set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
+       }
+}
+
+static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
+                         unsigned int devfn, int reg, int len, u32 *value)
+{
+       unsigned long flags;
+       u32 base;
+
+       if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
+               *value = -1;
+               return -EINVAL;
+       }
+
+       base = get_base_addr(seg, bus, devfn);
+       if (!base)
+               return pci_conf1_read(seg,bus,devfn,reg,len,value);
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       pci_exp_set_dev_base(base, bus, devfn);
+
+       switch (len) {
+       case 1:
+               *value = mmio_config_readb(mmcfg_virt_addr + reg);
+               break;
+       case 2:
+               *value = mmio_config_readw(mmcfg_virt_addr + reg);
+               break;
+       case 4:
+               *value = mmio_config_readl(mmcfg_virt_addr + reg);
+               break;
+       }
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return 0;
+}
+
+static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
+                          unsigned int devfn, int reg, int len, u32 value)
+{
+       unsigned long flags;
+       u32 base;
+
+       if ((bus > 255) || (devfn > 255) || (reg > 4095))
+               return -EINVAL;
+
+       base = get_base_addr(seg, bus, devfn);
+       if (!base)
+               return pci_conf1_write(seg,bus,devfn,reg,len,value);
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       pci_exp_set_dev_base(base, bus, devfn);
+
+       switch (len) {
+       case 1:
+               mmio_config_writeb(mmcfg_virt_addr + reg, value);
+               break;
+       case 2:
+               mmio_config_writew(mmcfg_virt_addr + reg, value);
+               break;
+       case 4:
+               mmio_config_writel(mmcfg_virt_addr + reg, value);
+               break;
+       }
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return 0;
+}
+
+static struct pci_raw_ops pci_mmcfg = {
+       .read =         pci_mmcfg_read,
+       .write =        pci_mmcfg_write,
+};
+
+int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+                                   unsigned int devfn)
+{
+       return get_base_addr(seg, bus, devfn) != 0;
+}
+
+int __init pci_mmcfg_arch_init(void)
+{
+       printk(KERN_INFO "PCI: Using MMCONFIG\n");
+       raw_pci_ops = &pci_mmcfg;
+       return 1;
+}
diff --git a/arch/x86/pci/numa.c b/arch/x86/pci/numa.c
new file mode 100644 (file)
index 0000000..f5f165f
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * numa.c - Low-level PCI access for NUMA-Q machines
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/nodemask.h>
+#include "pci.h"
+
+#define BUS2QUAD(global) (mp_bus_id_to_node[global])
+#define BUS2LOCAL(global) (mp_bus_id_to_local[global])
+#define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
+
+#define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
+       (0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
+
+static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
+                            unsigned int devfn, int reg, int len, u32 *value)
+{
+       unsigned long flags;
+
+       if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
+               return -EINVAL;
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus));
+
+       switch (len) {
+       case 1:
+               *value = inb_quad(0xCFC + (reg & 3), BUS2QUAD(bus));
+               break;
+       case 2:
+               *value = inw_quad(0xCFC + (reg & 2), BUS2QUAD(bus));
+               break;
+       case 4:
+               *value = inl_quad(0xCFC, BUS2QUAD(bus));
+               break;
+       }
+
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return 0;
+}
+
+static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
+                             unsigned int devfn, int reg, int len, u32 value)
+{
+       unsigned long flags;
+
+       if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
+               return -EINVAL;
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus));
+
+       switch (len) {
+       case 1:
+               outb_quad((u8)value, 0xCFC + (reg & 3), BUS2QUAD(bus));
+               break;
+       case 2:
+               outw_quad((u16)value, 0xCFC + (reg & 2), BUS2QUAD(bus));
+               break;
+       case 4:
+               outl_quad((u32)value, 0xCFC, BUS2QUAD(bus));
+               break;
+       }
+
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return 0;
+}
+
+#undef PCI_CONF1_MQ_ADDRESS
+
+static struct pci_raw_ops pci_direct_conf1_mq = {
+       .read   = pci_conf1_mq_read,
+       .write  = pci_conf1_mq_write
+};
+
+
+static void __devinit pci_fixup_i450nx(struct pci_dev *d)
+{
+       /*
+        * i450NX -- Find and scan all secondary buses on all PXB's.
+        */
+       int pxb, reg;
+       u8 busno, suba, subb;
+       int quad = BUS2QUAD(d->bus->number);
+
+       printk("PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
+       reg = 0xd0;
+       for(pxb=0; pxb<2; pxb++) {
+               pci_read_config_byte(d, reg++, &busno);
+               pci_read_config_byte(d, reg++, &suba);
+               pci_read_config_byte(d, reg++, &subb);
+               DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
+               if (busno) {
+                       /* Bus A */
+                       pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
+               }
+               if (suba < subb) {
+                       /* Bus B */
+                       pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1));
+               }
+       }
+       pcibios_last_bus = -1;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
+
+static int __init pci_numa_init(void)
+{
+       int quad;
+
+       raw_pci_ops = &pci_direct_conf1_mq;
+
+       if (pcibios_scanned++)
+               return 0;
+
+       pci_root_bus = pcibios_scan_root(0);
+       if (pci_root_bus)
+               pci_bus_add_devices(pci_root_bus);
+       if (num_online_nodes() > 1)
+               for_each_online_node(quad) {
+                       if (quad == 0)
+                               continue;
+                       printk("Scanning PCI bus %d for quad %d\n", 
+                               QUADLOCAL2BUS(quad,0), quad);
+                       pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0));
+               }
+       return 0;
+}
+
+subsys_initcall(pci_numa_init);
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c
new file mode 100644 (file)
index 0000000..10ac8c3
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * BIOS32 and PCI BIOS handling.
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include "pci.h"
+#include "pci-functions.h"
+
+
+/* BIOS32 signature: "_32_" */
+#define BIOS32_SIGNATURE       (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
+
+/* PCI signature: "PCI " */
+#define PCI_SIGNATURE          (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
+
+/* PCI service signature: "$PCI" */
+#define PCI_SERVICE            (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
+
+/* PCI BIOS hardware mechanism flags */
+#define PCIBIOS_HW_TYPE1               0x01
+#define PCIBIOS_HW_TYPE2               0x02
+#define PCIBIOS_HW_TYPE1_SPEC          0x10
+#define PCIBIOS_HW_TYPE2_SPEC          0x20
+
+/*
+ * This is the standard structure used to identify the entry point
+ * to the BIOS32 Service Directory, as documented in
+ *     Standard BIOS 32-bit Service Directory Proposal
+ *     Revision 0.4 May 24, 1993
+ *     Phoenix Technologies Ltd.
+ *     Norwood, MA
+ * and the PCI BIOS specification.
+ */
+
+union bios32 {
+       struct {
+               unsigned long signature;        /* _32_ */
+               unsigned long entry;            /* 32 bit physical address */
+               unsigned char revision;         /* Revision level, 0 */
+               unsigned char length;           /* Length in paragraphs should be 01 */
+               unsigned char checksum;         /* All bytes must add up to zero */
+               unsigned char reserved[5];      /* Must be zero */
+       } fields;
+       char chars[16];
+};
+
+/*
+ * Physical address of the service directory.  I don't know if we're
+ * allowed to have more than one of these or not, so just in case
+ * we'll make pcibios_present() take a memory start parameter and store
+ * the array there.
+ */
+
+static struct {
+       unsigned long address;
+       unsigned short segment;
+} bios32_indirect = { 0, __KERNEL_CS };
+
+/*
+ * Returns the entry point for the given service, NULL on error
+ */
+
+static unsigned long bios32_service(unsigned long service)
+{
+       unsigned char return_code;      /* %al */
+       unsigned long address;          /* %ebx */
+       unsigned long length;           /* %ecx */
+       unsigned long entry;            /* %edx */
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __asm__("lcall *(%%edi); cld"
+               : "=a" (return_code),
+                 "=b" (address),
+                 "=c" (length),
+                 "=d" (entry)
+               : "0" (service),
+                 "1" (0),
+                 "D" (&bios32_indirect));
+       local_irq_restore(flags);
+
+       switch (return_code) {
+               case 0:
+                       return address + entry;
+               case 0x80:      /* Not present */
+                       printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service);
+                       return 0;
+               default: /* Shouldn't happen */
+                       printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n",
+                               service, return_code);
+                       return 0;
+       }
+}
+
+static struct {
+       unsigned long address;
+       unsigned short segment;
+} pci_indirect = { 0, __KERNEL_CS };
+
+static int pci_bios_present;
+
+static int __devinit check_pcibios(void)
+{
+       u32 signature, eax, ebx, ecx;
+       u8 status, major_ver, minor_ver, hw_mech;
+       unsigned long flags, pcibios_entry;
+
+       if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
+               pci_indirect.address = pcibios_entry + PAGE_OFFSET;
+
+               local_irq_save(flags);
+               __asm__(
+                       "lcall *(%%edi); cld\n\t"
+                       "jc 1f\n\t"
+                       "xor %%ah, %%ah\n"
+                       "1:"
+                       : "=d" (signature),
+                         "=a" (eax),
+                         "=b" (ebx),
+                         "=c" (ecx)
+                       : "1" (PCIBIOS_PCI_BIOS_PRESENT),
+                         "D" (&pci_indirect)
+                       : "memory");
+               local_irq_restore(flags);
+
+               status = (eax >> 8) & 0xff;
+               hw_mech = eax & 0xff;
+               major_ver = (ebx >> 8) & 0xff;
+               minor_ver = ebx & 0xff;
+               if (pcibios_last_bus < 0)
+                       pcibios_last_bus = ecx & 0xff;
+               DBG("PCI: BIOS probe returned s=%02x hw=%02x ver=%02x.%02x l=%02x\n",
+                       status, hw_mech, major_ver, minor_ver, pcibios_last_bus);
+               if (status || signature != PCI_SIGNATURE) {
+                       printk (KERN_ERR "PCI: BIOS BUG #%x[%08x] found\n",
+                               status, signature);
+                       return 0;
+               }
+               printk(KERN_INFO "PCI: PCI BIOS revision %x.%02x entry at 0x%lx, last bus=%d\n",
+                       major_ver, minor_ver, pcibios_entry, pcibios_last_bus);
+#ifdef CONFIG_PCI_DIRECT
+               if (!(hw_mech & PCIBIOS_HW_TYPE1))
+                       pci_probe &= ~PCI_PROBE_CONF1;
+               if (!(hw_mech & PCIBIOS_HW_TYPE2))
+                       pci_probe &= ~PCI_PROBE_CONF2;
+#endif
+               return 1;
+       }
+       return 0;
+}
+
+static int __devinit pci_bios_find_device (unsigned short vendor, unsigned short device_id,
+                                       unsigned short index, unsigned char *bus, unsigned char *device_fn)
+{
+       unsigned short bx;
+       unsigned short ret;
+
+       __asm__("lcall *(%%edi); cld\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=b" (bx),
+                 "=a" (ret)
+               : "1" (PCIBIOS_FIND_PCI_DEVICE),
+                 "c" (device_id),
+                 "d" (vendor),
+                 "S" ((int) index),
+                 "D" (&pci_indirect));
+       *bus = (bx >> 8) & 0xff;
+       *device_fn = bx & 0xff;
+       return (int) (ret & 0xff00) >> 8;
+}
+
+static int pci_bios_read(unsigned int seg, unsigned int bus,
+                        unsigned int devfn, int reg, int len, u32 *value)
+{
+       unsigned long result = 0;
+       unsigned long flags;
+       unsigned long bx = (bus << 8) | devfn;
+
+       if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
+               return -EINVAL;
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       switch (len) {
+       case 1:
+               __asm__("lcall *(%%esi); cld\n\t"
+                       "jc 1f\n\t"
+                       "xor %%ah, %%ah\n"
+                       "1:"
+                       : "=c" (*value),
+                         "=a" (result)
+                       : "1" (PCIBIOS_READ_CONFIG_BYTE),
+                         "b" (bx),
+                         "D" ((long)reg),
+                         "S" (&pci_indirect));
+               break;
+       case 2:
+               __asm__("lcall *(%%esi); cld\n\t"
+                       "jc 1f\n\t"
+                       "xor %%ah, %%ah\n"
+                       "1:"
+                       : "=c" (*value),
+                         "=a" (result)
+                       : "1" (PCIBIOS_READ_CONFIG_WORD),
+                         "b" (bx),
+                         "D" ((long)reg),
+                         "S" (&pci_indirect));
+               break;
+       case 4:
+               __asm__("lcall *(%%esi); cld\n\t"
+                       "jc 1f\n\t"
+                       "xor %%ah, %%ah\n"
+                       "1:"
+                       : "=c" (*value),
+                         "=a" (result)
+                       : "1" (PCIBIOS_READ_CONFIG_DWORD),
+                         "b" (bx),
+                         "D" ((long)reg),
+                         "S" (&pci_indirect));
+               break;
+       }
+
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return (int)((result & 0xff00) >> 8);
+}
+
+static int pci_bios_write(unsigned int seg, unsigned int bus,
+                         unsigned int devfn, int reg, int len, u32 value)
+{
+       unsigned long result = 0;
+       unsigned long flags;
+       unsigned long bx = (bus << 8) | devfn;
+
+       if ((bus > 255) || (devfn > 255) || (reg > 255)) 
+               return -EINVAL;
+
+       spin_lock_irqsave(&pci_config_lock, flags);
+
+       switch (len) {
+       case 1:
+               __asm__("lcall *(%%esi); cld\n\t"
+                       "jc 1f\n\t"
+                       "xor %%ah, %%ah\n"
+                       "1:"
+                       : "=a" (result)
+                       : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
+                         "c" (value),
+                         "b" (bx),
+                         "D" ((long)reg),
+                         "S" (&pci_indirect));
+               break;
+       case 2:
+               __asm__("lcall *(%%esi); cld\n\t"
+                       "jc 1f\n\t"
+                       "xor %%ah, %%ah\n"
+                       "1:"
+                       : "=a" (result)
+                       : "0" (PCIBIOS_WRITE_CONFIG_WORD),
+                         "c" (value),
+                         "b" (bx),
+                         "D" ((long)reg),
+                         "S" (&pci_indirect));
+               break;
+       case 4:
+               __asm__("lcall *(%%esi); cld\n\t"
+                       "jc 1f\n\t"
+                       "xor %%ah, %%ah\n"
+                       "1:"
+                       : "=a" (result)
+                       : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
+                         "c" (value),
+                         "b" (bx),
+                         "D" ((long)reg),
+                         "S" (&pci_indirect));
+               break;
+       }
+
+       spin_unlock_irqrestore(&pci_config_lock, flags);
+
+       return (int)((result & 0xff00) >> 8);
+}
+
+
+/*
+ * Function table for BIOS32 access
+ */
+
+static struct pci_raw_ops pci_bios_access = {
+       .read =         pci_bios_read,
+       .write =        pci_bios_write
+};
+
+/*
+ * Try to find PCI BIOS.
+ */
+
+static struct pci_raw_ops * __devinit pci_find_bios(void)
+{
+       union bios32 *check;
+       unsigned char sum;
+       int i, length;
+
+       /*
+        * Follow the standard procedure for locating the BIOS32 Service
+        * directory by scanning the permissible address range from
+        * 0xe0000 through 0xfffff for a valid BIOS32 structure.
+        */
+
+       for (check = (union bios32 *) __va(0xe0000);
+            check <= (union bios32 *) __va(0xffff0);
+            ++check) {
+               long sig;
+               if (probe_kernel_address(&check->fields.signature, sig))
+                       continue;
+
+               if (check->fields.signature != BIOS32_SIGNATURE)
+                       continue;
+               length = check->fields.length * 16;
+               if (!length)
+                       continue;
+               sum = 0;
+               for (i = 0; i < length ; ++i)
+                       sum += check->chars[i];
+               if (sum != 0)
+                       continue;
+               if (check->fields.revision != 0) {
+                       printk("PCI: unsupported BIOS32 revision %d at 0x%p\n",
+                               check->fields.revision, check);
+                       continue;
+               }
+               DBG("PCI: BIOS32 Service Directory structure at 0x%p\n", check);
+               if (check->fields.entry >= 0x100000) {
+                       printk("PCI: BIOS32 entry (0x%p) in high memory, "
+                                       "cannot use.\n", check);
+                       return NULL;
+               } else {
+                       unsigned long bios32_entry = check->fields.entry;
+                       DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n",
+                                       bios32_entry);
+                       bios32_indirect.address = bios32_entry + PAGE_OFFSET;
+                       if (check_pcibios())
+                               return &pci_bios_access;
+               }
+               break;  /* Hopefully more than one BIOS32 cannot happen... */
+       }
+
+       return NULL;
+}
+
+/*
+ * Sort the device list according to PCI BIOS. Nasty hack, but since some
+ * fool forgot to define the `correct' device order in the PCI BIOS specs
+ * and we want to be (possibly bug-to-bug ;-]) compatible with older kernels
+ * which used BIOS ordering, we are bound to do this...
+ */
+
+void __devinit pcibios_sort(void)
+{
+       LIST_HEAD(sorted_devices);
+       struct list_head *ln;
+       struct pci_dev *dev, *d;
+       int idx, found;
+       unsigned char bus, devfn;
+
+       DBG("PCI: Sorting device list...\n");
+       while (!list_empty(&pci_devices)) {
+               ln = pci_devices.next;
+               dev = pci_dev_g(ln);
+               idx = found = 0;
+               while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
+                       idx++;
+                       list_for_each(ln, &pci_devices) {
+                               d = pci_dev_g(ln);
+                               if (d->bus->number == bus && d->devfn == devfn) {
+                                       list_move_tail(&d->global_list, &sorted_devices);
+                                       if (d == dev)
+                                               found = 1;
+                                       break;
+                               }
+                       }
+                       if (ln == &pci_devices) {
+                               printk(KERN_WARNING "PCI: BIOS reporting unknown device %02x:%02x\n", bus, devfn);
+                               /*
+                                * We must not continue scanning as several buggy BIOSes
+                                * return garbage after the last device. Grr.
+                                */
+                               break;
+                       }
+               }
+               if (!found) {
+                       printk(KERN_WARNING "PCI: Device %s not found by BIOS\n",
+                               pci_name(dev));
+                       list_move_tail(&dev->global_list, &sorted_devices);
+               }
+       }
+       list_splice(&sorted_devices, &pci_devices);
+}
+
+/*
+ *  BIOS Functions for IRQ Routing
+ */
+
+struct irq_routing_options {
+       u16 size;
+       struct irq_info *table;
+       u16 segment;
+} __attribute__((packed));
+
+struct irq_routing_table * pcibios_get_irq_routing_table(void)
+{
+       struct irq_routing_options opt;
+       struct irq_routing_table *rt = NULL;
+       int ret, map;
+       unsigned long page;
+
+       if (!pci_bios_present)
+               return NULL;
+       page = __get_free_page(GFP_KERNEL);
+       if (!page)
+               return NULL;
+       opt.table = (struct irq_info *) page;
+       opt.size = PAGE_SIZE;
+       opt.segment = __KERNEL_DS;
+
+       DBG("PCI: Fetching IRQ routing table... ");
+       __asm__("push %%es\n\t"
+               "push %%ds\n\t"
+               "pop  %%es\n\t"
+               "lcall *(%%esi); cld\n\t"
+               "pop %%es\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=a" (ret),
+                 "=b" (map),
+                 "=m" (opt)
+               : "0" (PCIBIOS_GET_ROUTING_OPTIONS),
+                 "1" (0),
+                 "D" ((long) &opt),
+                 "S" (&pci_indirect),
+                 "m" (opt)
+               : "memory");
+       DBG("OK  ret=%d, size=%d, map=%x\n", ret, opt.size, map);
+       if (ret & 0xff00)
+               printk(KERN_ERR "PCI: Error %02x when fetching IRQ routing table.\n", (ret >> 8) & 0xff);
+       else if (opt.size) {
+               rt = kmalloc(sizeof(struct irq_routing_table) + opt.size, GFP_KERNEL);
+               if (rt) {
+                       memset(rt, 0, sizeof(struct irq_routing_table));
+                       rt->size = opt.size + sizeof(struct irq_routing_table);
+                       rt->exclusive_irqs = map;
+                       memcpy(rt->slots, (void *) page, opt.size);
+                       printk(KERN_INFO "PCI: Using BIOS Interrupt Routing Table\n");
+               }
+       }
+       free_page(page);
+       return rt;
+}
+EXPORT_SYMBOL(pcibios_get_irq_routing_table);
+
+int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
+{
+       int ret;
+
+       __asm__("lcall *(%%esi); cld\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=a" (ret)
+               : "0" (PCIBIOS_SET_PCI_HW_INT),
+                 "b" ((dev->bus->number << 8) | dev->devfn),
+                 "c" ((irq << 8) | (pin + 10)),
+                 "S" (&pci_indirect));
+       return !(ret & 0xff00);
+}
+EXPORT_SYMBOL(pcibios_set_irq_routing);
+
+void __init pci_pcbios_init(void)
+{
+       if ((pci_probe & PCI_PROBE_BIOS) 
+               && ((raw_pci_ops = pci_find_bios()))) {
+               pci_probe |= PCI_BIOS_SORT;
+               pci_bios_present = 1;
+       }
+}
+
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
new file mode 100644 (file)
index 0000000..8c66f27
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *     Low-Level PCI Access for i386 machines.
+ *
+ *     (c) 1999 Martin Mares <mj@ucw.cz>
+ */
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#define PCI_PROBE_BIOS         0x0001
+#define PCI_PROBE_CONF1                0x0002
+#define PCI_PROBE_CONF2                0x0004
+#define PCI_PROBE_MMCONF       0x0008
+#define PCI_PROBE_MASK         0x000f
+#define PCI_PROBE_NOEARLY      0x0010
+
+#define PCI_NO_SORT            0x0100
+#define PCI_BIOS_SORT          0x0200
+#define PCI_NO_CHECKS          0x0400
+#define PCI_USE_PIRQ_MASK      0x0800
+#define PCI_ASSIGN_ROMS                0x1000
+#define PCI_BIOS_IRQ_SCAN      0x2000
+#define PCI_ASSIGN_ALL_BUSSES  0x4000
+
+extern unsigned int pci_probe;
+extern unsigned long pirq_table_addr;
+
+enum pci_bf_sort_state {
+       pci_bf_sort_default,
+       pci_force_nobf,
+       pci_force_bf,
+       pci_dmi_bf,
+};
+
+/* pci-i386.c */
+
+extern unsigned int pcibios_max_latency;
+
+void pcibios_resource_survey(void);
+int pcibios_enable_resources(struct pci_dev *, int);
+
+/* pci-pc.c */
+
+extern int pcibios_last_bus;
+extern struct pci_bus *pci_root_bus;
+extern struct pci_ops pci_root_ops;
+
+/* pci-irq.c */
+
+struct irq_info {
+       u8 bus, devfn;                  /* Bus, device and function */
+       struct {
+               u8 link;                /* IRQ line ID, chipset dependent, 0=not routed */
+               u16 bitmap;             /* Available IRQs */
+       } __attribute__((packed)) irq[4];
+       u8 slot;                        /* Slot number, 0=onboard */
+       u8 rfu;
+} __attribute__((packed));
+
+struct irq_routing_table {
+       u32 signature;                  /* PIRQ_SIGNATURE should be here */
+       u16 version;                    /* PIRQ_VERSION */
+       u16 size;                       /* Table size in bytes */
+       u8 rtr_bus, rtr_devfn;          /* Where the interrupt router lies */
+       u16 exclusive_irqs;             /* IRQs devoted exclusively to PCI usage */
+       u16 rtr_vendor, rtr_device;     /* Vendor and device ID of interrupt router */
+       u32 miniport_data;              /* Crap */
+       u8 rfu[11];
+       u8 checksum;                    /* Modulo 256 checksum must give zero */
+       struct irq_info slots[0];
+} __attribute__((packed));
+
+extern unsigned int pcibios_irq_mask;
+
+extern int pcibios_scanned;
+extern spinlock_t pci_config_lock;
+
+extern int (*pcibios_enable_irq)(struct pci_dev *dev);
+extern void (*pcibios_disable_irq)(struct pci_dev *dev);
+
+extern int pci_conf1_write(unsigned int seg, unsigned int bus,
+                          unsigned int devfn, int reg, int len, u32 value);
+extern int pci_conf1_read(unsigned int seg, unsigned int bus,
+                         unsigned int devfn, int reg, int len, u32 *value);
+
+extern int pci_direct_probe(void);
+extern void pci_direct_init(int type);
+extern void pci_pcbios_init(void);
+extern void pci_mmcfg_init(int type);
+extern void pcibios_sort(void);
+
+/* pci-mmconfig.c */
+
+/* Verify the first 16 busses. We assume that systems with more busses
+   get MCFG right. */
+#define PCI_MMCFG_MAX_CHECK_BUS 16
+extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
+
+extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+                                          unsigned int devfn);
+extern int __init pci_mmcfg_arch_init(void);
+
+/*
+ * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
+ * on their northbrige except through the * %eax register. As such, you MUST
+ * NOT use normal IOMEM accesses, you need to only use the magic mmio-config
+ * accessor functions.
+ * In fact just use pci_config_*, nothing else please.
+ */
+static inline unsigned char mmio_config_readb(void __iomem *pos)
+{
+       u8 val;
+       asm volatile("movb (%1),%%al" : "=a" (val) : "r" (pos));
+       return val;
+}
+
+static inline unsigned short mmio_config_readw(void __iomem *pos)
+{
+       u16 val;
+       asm volatile("movw (%1),%%ax" : "=a" (val) : "r" (pos));
+       return val;
+}
+
+static inline unsigned int mmio_config_readl(void __iomem *pos)
+{
+       u32 val;
+       asm volatile("movl (%1),%%eax" : "=a" (val) : "r" (pos));
+       return val;
+}
+
+static inline void mmio_config_writeb(void __iomem *pos, u8 val)
+{
+       asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory");
+}
+
+static inline void mmio_config_writew(void __iomem *pos, u16 val)
+{
+       asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory");
+}
+
+static inline void mmio_config_writel(void __iomem *pos, u32 val)
+{
+       asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory");
+}
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
new file mode 100644 (file)
index 0000000..8ecb1c7
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *     Low-Level PCI Support for SGI Visual Workstation
+ *
+ *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include "cobalt.h"
+#include "lithium.h"
+
+#include "pci.h"
+
+
+extern struct pci_raw_ops pci_direct_conf1;
+
+static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
+static void pci_visws_disable_irq(struct pci_dev *dev) { }
+
+int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq;
+void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq;
+
+void __init pcibios_penalize_isa_irq(int irq, int active) {}
+
+
+unsigned int pci_bus0, pci_bus1;
+
+static inline u8 bridge_swizzle(u8 pin, u8 slot) 
+{
+       return (((pin - 1) + slot) % 4) + 1;
+}
+
+static u8 __init visws_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+       u8 pin = *pinp;
+
+       while (dev->bus->self) {        /* Move up the chain of bridges. */
+               pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+               dev = dev->bus->self;
+       }
+       *pinp = pin;
+
+       return PCI_SLOT(dev->devfn);
+}
+
+static int __init visws_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq, bus = dev->bus->number;
+
+       pin--;
+
+       /* Nothing useful at PIIX4 pin 1 */
+       if (bus == pci_bus0 && slot == 4 && pin == 0)
+               return -1;
+
+       /* PIIX4 USB is on Bus 0, Slot 4, Line 3 */
+       if (bus == pci_bus0 && slot == 4 && pin == 3) {
+               irq = CO_IRQ(CO_APIC_PIIX4_USB);
+               goto out;
+       }
+
+       /* First pin spread down 1 APIC entry per slot */
+       if (pin == 0) {
+               irq = CO_IRQ((bus == pci_bus0 ? CO_APIC_PCIB_BASE0 :
+                                               CO_APIC_PCIA_BASE0) + slot);
+               goto out;
+       }
+
+       /* lines 1,2,3 from any slot is shared in this twirly pattern */
+       if (bus == pci_bus1) {
+               /* lines 1-3 from devices 0 1 rotate over 2 apic entries */
+               irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((slot + (pin - 1)) % 2));
+       } else { /* bus == pci_bus0 */
+               /* lines 1-3 from devices 0-3 rotate over 3 apic entries */
+               if (slot == 0)
+                       slot = 3; /* same pattern */
+               irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((3 - slot) + (pin - 1) % 3));
+       }
+out:
+       printk(KERN_DEBUG "PCI: Bus %d Slot %d Line %d -> IRQ %d\n", bus, slot, pin, irq);
+       return irq;
+}
+
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+static int __init pcibios_init(void)
+{
+       /* The VISWS supports configuration access type 1 only */
+       pci_probe = (pci_probe | PCI_PROBE_CONF1) &
+                   ~(PCI_PROBE_BIOS | PCI_PROBE_CONF2);
+
+       pci_bus0 = li_pcib_read16(LI_PCI_BUSNUM) & 0xff;
+       pci_bus1 = li_pcia_read16(LI_PCI_BUSNUM) & 0xff;
+
+       printk(KERN_INFO "PCI: Lithium bridge A bus: %u, "
+               "bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0);
+
+       raw_pci_ops = &pci_direct_conf1;
+       pci_scan_bus_with_sysdata(pci_bus0);
+       pci_scan_bus_with_sysdata(pci_bus1);
+       pci_fixup_irqs(visws_swizzle, visws_map_irq);
+       pcibios_resource_survey();
+       return 0;
+}
+
+subsys_initcall(pcibios_init);
index d04d8f976d1c3179d4b49d79b2bb51461c4fce34..b3e54c45d408c91f4bbc650feb5f8c9c1a7273fd 100644 (file)
@@ -1,5 +1,5 @@
 ifeq ($(CONFIG_X86_32),y)
-include ${srctree}/arch/i386/pci/Makefile_32
+include ${srctree}/arch/x86/pci/Makefile_32
 else
 include ${srctree}/arch/x86_64/pci/Makefile_64
 endif
index 77b1b9abedc2822b743da2190da6d1b8b4e3c01f..79b618b9e9d47bf43d50f1997fa2d83368dbc2f3 100644 (file)
@@ -3,7 +3,7 @@
 #
 # Reuse the i386 PCI subsystem
 #
-EXTRA_CFLAGS += -Iarch/i386/pci
+EXTRA_CFLAGS += -Iarch/x86/pci
 
 obj-y          := i386.o
 obj-$(CONFIG_PCI_DIRECT)+= direct.o
@@ -15,13 +15,13 @@ obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_64.o direct.o mmconfig-shared.o
 
 obj-$(CONFIG_NUMA)     += k8-bus_64.o
 
-direct-y += ../../i386/pci/direct.o
-acpi-y   += ../../i386/pci/acpi.o
-legacy-y += ../../i386/pci/legacy.o
-irq-y    += ../../i386/pci/irq.o
-common-y += ../../i386/pci/common.o
-fixup-y  += ../../i386/pci/fixup.o
-i386-y  += ../../i386/pci/i386.o
-init-y += ../../i386/pci/init.o
-early-y += ../../i386/pci/early.o
-mmconfig-shared-y += ../../i386/pci/mmconfig-shared.o
+direct-y += ../../x86/pci/direct.o
+acpi-y   += ../../x86/pci/acpi.o
+legacy-y += ../../x86/pci/legacy.o
+irq-y    += ../../x86/pci/irq.o
+common-y += ../../x86/pci/common.o
+fixup-y  += ../../x86/pci/fixup.o
+i386-y  += ../../x86/pci/i386.o
+init-y += ../../x86/pci/init.o
+early-y += ../../x86/pci/early.o
+mmconfig-shared-y += ../../x86/pci/mmconfig-shared.o
index d590a99930fa5a762f2d327faca4d10ecb7373d3..2305cc450a4572da1d9dc0a57783a500db3a91a0 100644 (file)
@@ -45,7 +45,7 @@
 
 #include "cpqphp.h"
 #include "cpqphp_nvram.h"
-#include "../../../arch/i386/pci/pci.h"        /* horrible hack showing how processor dependent we are... */
+#include "../../../arch/x86/pci/pci.h" /* horrible hack showing how processor dependent we are... */
 
 
 /* Global variables */
index fc7c74d725955794141093e7a41217bd3964dd06..3f6cd20e95d2f187d2caaa9747a0d90f0c77f9b7 100644 (file)
@@ -37,7 +37,7 @@
 #include "../pci.h"
 #include "cpqphp.h"
 #include "cpqphp_nvram.h"
-#include "../../../arch/i386/pci/pci.h"        /* horrible hack showing how processor dependent we are... */
+#include "../../../arch/x86/pci/pci.h" /* horrible hack showing how processor dependent we are... */
 
 
 u8 cpqhp_nic_irq;
index 0316eeaaeb29cb288f45066dbf6e746610db66b1..a90c28d0c69df75c3cb62b2ca19d3073b49839d1 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include "../pci.h"
-#include "../../../arch/i386/pci/pci.h"        /* for struct irq_routing_table */
+#include "../../../arch/x86/pci/pci.h" /* for struct irq_routing_table */
 #include "ibmphp.h"
 
 #define attn_on(sl)  ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON)