#include <console/console.h>
+#include <device/path.h>
+#include <device/pci_ids.h>
#include <cpu/cpu.h>
-#include <smp/start_stop.h>
#include <arch/smp/mpspec.h>
#include <string.h>
-#include <cpu/p5/cpuid.h>
-#include <cpu/p6/apic.h>
+#include <arch/cpu.h>
+#include <cpu/x86/lapic.h>
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)
* Having the proper apicid's in the table so the non-bootstrap
* processors can be woken up should be enough.
*/
-void smp_write_processors(struct mp_config_table *mc,
- unsigned long *processor_map)
+void smp_write_processors(struct mp_config_table *mc)
{
- int i;
- int processor_id;
+ int boot_apic_id;
unsigned apic_version;
unsigned cpu_features;
unsigned cpu_feature_flags;
- int eax, ebx, ecx, edx;
- processor_id = this_processors_id();
- apic_version = apic_read(APIC_LVR) & 0xff;
- cpuid(1, &eax, &ebx, &ecx, &edx);
- cpu_features = eax;
- cpu_feature_flags = edx;
- for(i = 0; i < CONFIG_MAX_CPUS; i++) {
- unsigned long cpu_apicid = initial_apicid[i];
+ 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 = all_devices; cpu; cpu = cpu->next) {
unsigned long cpu_flag;
- if(initial_apicid[i]==-1)
+ 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 (processor_map[i] & CPU_BOOTPROCESSOR) {
- cpu_flag |= MPC_CPU_BOOTPROCESSOR;
+ if (boot_apic_id == cpu->path.apic.apic_id) {
+ cpu_flag = MPC_CPU_ENABLED | MPC_CPU_BOOTPROCESSOR;
}
- smp_write_processor(mc, cpu_apicid, apic_version,
+ smp_write_processor(mc,
+ 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);
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,