printk_foo -> printk(BIOS_FOO, ...)
[coreboot.git] / src / arch / i386 / smp / mpspec.c
index babfcbdca2fb2439564218efc1570dd867d65ff9..1beba873ccbb86e8452a94d70bf4b67a6197dce4 100644 (file)
@@ -1,4 +1,6 @@
 #include <console/console.h>
+#include <device/path.h>
+#include <device/pci_ids.h>
 #include <cpu/cpu.h>
 #include <arch/smp/mpspec.h>
 #include <string.h>
@@ -20,30 +22,33 @@ unsigned char smp_compute_checksum(void *v, int len)
 
 void *smp_write_floating_table(unsigned long addr)
 {
-       struct intel_mp_floating *mf;
-       void *v;
-       
        /* 16 byte align the table address */
-       addr += 15;
-       addr &= ~15;
-       v = (void *)addr;
+       addr = (addr + 0xf) & (~0xf);
+       return smp_write_floating_table_physaddr(addr, addr + SMP_FLOATING_TABLE_LEN);
+}
 
-       mf = v;
-       mf->mpf_signature[0] = '_';
-       mf->mpf_signature[1] = 'M';
-       mf->mpf_signature[2] = 'P';
-       mf->mpf_signature[3] = '_';
-       mf->mpf_physptr = (unsigned long)(((char *)v) + SMP_FLOATING_TABLE_LEN);
-       mf->mpf_length = 1;
-       mf->mpf_specification = 4;
-       mf->mpf_checksum = 0;
-       mf->mpf_feature1 = 0;
-       mf->mpf_feature2 = 0;
-       mf->mpf_feature3 = 0;
-       mf->mpf_feature4 = 0;
-       mf->mpf_feature5 = 0;
-       mf->mpf_checksum = smp_compute_checksum(mf, mf->mpf_length*16);
-       return v;
+void *smp_write_floating_table_physaddr(unsigned long addr, unsigned long mpf_physptr)
+{
+        struct intel_mp_floating *mf;
+        void *v;
+       
+       v = (void *)addr;
+        mf = v;
+        mf->mpf_signature[0] = '_';
+        mf->mpf_signature[1] = 'M';
+        mf->mpf_signature[2] = 'P';
+        mf->mpf_signature[3] = '_';
+        mf->mpf_physptr = mpf_physptr;
+        mf->mpf_length = 1;
+        mf->mpf_specification = 4;
+        mf->mpf_checksum = 0;
+        mf->mpf_feature1 = 0;
+        mf->mpf_feature2 = 0;
+        mf->mpf_feature3 = 0;
+        mf->mpf_feature4 = 0;
+        mf->mpf_feature5 = 0;
+        mf->mpf_checksum = smp_compute_checksum(mf, mf->mpf_length*16);
+        return v;
 }
 
 void *smp_next_mpc_entry(struct mp_config_table *mc)
@@ -101,32 +106,35 @@ void smp_write_processors(struct mp_config_table *mc)
        unsigned cpu_feature_flags;
        struct cpuid_result result;
        device_t cpu;
+       
        boot_apic_id = lapicid();
        apic_version = lapic_read(LAPIC_LVR) & 0xff;
        result = cpuid(1);
        cpu_features = result.eax;
        cpu_feature_flags = result.edx;
-       for(cpu = dev_root.link[1].children; cpu; cpu = cpu->sibling) {
+       for(cpu = all_devices; cpu; cpu = cpu->next) {
                unsigned long cpu_flag;
-               if (cpu->path.type != DEVICE_PATH_APIC) {
+               if ((cpu->path.type != DEVICE_PATH_APIC) || 
+                       (cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER))
+               {
                        continue;
                }
                if (!cpu->enabled) {
                        continue;
                }
                cpu_flag = MPC_CPU_ENABLED;
-               if (boot_apic_id == cpu->path.u.apic.apic_id) {
-                       cpu_flag = MPC_CPU_ENABLED;
+               if (boot_apic_id == cpu->path.apic.apic_id) {
+                       cpu_flag = MPC_CPU_ENABLED | MPC_CPU_BOOTPROCESSOR;
                }
                smp_write_processor(mc, 
-                       cpu->path.u.apic.apic_id, apic_version,
+                       cpu->path.apic.apic_id, apic_version,
                        cpu_flag, cpu_features, cpu_feature_flags
                );
        }
 }
 
 void smp_write_bus(struct mp_config_table *mc,
-       unsigned char id, unsigned char *bustype)
+       unsigned char id, const char *bustype)
 {
        struct mpc_config_bus *mpc;
        mpc = smp_next_mpc_entry(mc);
@@ -168,13 +176,65 @@ void smp_write_intsrc(struct mp_config_table *mc,
        mpc->mpc_dstapic = dstapic;
        mpc->mpc_dstirq = dstirq;
        smp_add_mpc_entry(mc, sizeof(*mpc));
-#if CONFIG_DEBUG_MPTABLE == 1
-       printk_info("add intsrc srcbus 0x%x srcbusirq 0x%x, dstapic 0x%x, dstirq 0x%x\n",
+#ifdef DEBUG_MPTABLE
+       printk(BIOS_DEBUG, "add intsrc srcbus 0x%x srcbusirq 0x%x, dstapic 0x%x, dstirq 0x%x\n",
                                srcbus, srcbusirq, dstapic, dstirq);
-       hexdump(__FUNCTION__, mpc, sizeof(*mpc));
+       hexdump(__func__, mpc, sizeof(*mpc));
 #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.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(BIOS_DEBUG, "route irq: %s\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(BIOS_DEBUG, "route irq bridge: %s\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,