diff options
author | Yinghai Lu <yinghailu@gmail.com> | 2008-02-20 17:41:38 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2008-02-20 17:41:38 +0000 |
commit | f327d9f9540971518e1661e1f50d30ffa6b74173 (patch) | |
tree | 51e84712bcaf920a99413e46dd9d255d4278d5c9 /src/arch/i386/smp | |
parent | 8eff1e3d0419f42684fc8a63e1dd0a84eb7e9b50 (diff) |
Route device IRQ through PCI bridge instead in mptable.
Don't enable pin0 for ioapic of io-4.
1. apic error in kernel for MB with mcp55+io55
2. some pcie-cards could have pci bridge there, so need to put entries
for device under them in mptable.
Signed-off-by: Yinghai Lu <yinghailu@gmail.com>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3112 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch/i386/smp')
-rw-r--r-- | src/arch/i386/smp/mpspec.c | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/src/arch/i386/smp/mpspec.c b/src/arch/i386/smp/mpspec.c index 797dab43c6..3aedd21088 100644 --- a/src/arch/i386/smp/mpspec.c +++ b/src/arch/i386/smp/mpspec.c @@ -1,6 +1,7 @@ #include <console/console.h> #include <device/device.h> #include <device/path.h> +#include <device/pci_ids.h> #include <cpu/cpu.h> #include <arch/smp/mpspec.h> #include <string.h> @@ -26,8 +27,7 @@ void *smp_write_floating_table(unsigned long addr) void *v; /* 16 byte align the table address */ - addr += 15; - addr &= ~15; + addr = (addr + 0xf) & (~0xf); v = (void *)addr; mf = v; @@ -52,8 +52,8 @@ void *smp_write_floating_table_physaddr(unsigned long addr, unsigned long mpf_ph { struct intel_mp_floating *mf; void *v; - - v = (void *)addr; + + v = (void *)addr; mf = v; mf->mpf_signature[0] = '_'; mf->mpf_signature[1] = 'M'; @@ -204,6 +204,58 @@ void smp_write_intsrc(struct mp_config_table *mc, #endif } +void smp_write_intsrc_pci_bridge(struct mp_config_table *mc, + unsigned char irqtype, unsigned short irqflag, + struct device *dev, + unsigned char dstapic, unsigned char *dstirq) +{ + struct device *child; + + int linkn; + int i; + int srcbus; + int slot; + + struct bus *link; + unsigned char dstirq_x[4]; + + for (linkn = 0; linkn < dev->links; linkn++) { + + link = &dev->link[linkn]; + child = link->children; + srcbus = link->secondary; + + while (child) { + if (child->path.type != DEVICE_PATH_PCI) + goto next; + + slot = (child->path.u.pci.devfn >> 3); + /* round pins */ + for (i = 0; i < 4; i++) + dstirq_x[i] = dstirq[(i + slot) % 4]; + + if ((child->class >> 16) != PCI_BASE_CLASS_BRIDGE) { + /* pci device */ + printk_debug("route irq: %s %04x\n", dev_path(child)); + for (i = 0; i < 4; i++) + smp_write_intsrc(mc, irqtype, irqflag, srcbus, (slot<<2)|i, dstapic, dstirq_x[i]); + goto next; + } + + switch (child->class>>8) { + case PCI_CLASS_BRIDGE_PCI: + case PCI_CLASS_BRIDGE_PCMCIA: + case PCI_CLASS_BRIDGE_CARDBUS: + printk_debug("route irq bridge: %s %04x\n", dev_path(child)); + smp_write_intsrc_pci_bridge(mc, irqtype, irqflag, child, dstapic, dstirq_x); + } + + next: + child = child->sibling; + } + + } +} void smp_write_lintsrc(struct mp_config_table *mc, unsigned char irqtype, unsigned short irqflag, |