patch-2.3.43 linux/arch/ia64/kernel/acpi.c
Next file: linux/arch/ia64/kernel/efi.c
Previous file: linux/arch/ia64/kernel/Makefile
Back to the patch index
Back to the overall index
- Lines: 309
- Date:
Tue Feb 8 12:01:59 2000
- Orig file:
v2.3.42/linux/arch/ia64/kernel/acpi.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/acpi.c linux/arch/ia64/kernel/acpi.c
@@ -0,0 +1,308 @@
+/*
+ * Advanced Configuration and Power Interface
+ *
+ * Based on 'ACPI Specification 1.0b' February 2, 1999 and
+ * 'IA-64 Extensions to ACPI Specification' Revision 0.6
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
+ */
+
+#include <linux/config.h>
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/acpi-ext.h>
+#include <asm/page.h>
+#include <asm/efi.h>
+#include <asm/io.h>
+#include <asm/iosapic.h>
+#include <asm/irq.h>
+
+#undef ACPI_DEBUG /* Guess what this does? */
+
+#ifdef CONFIG_SMP
+extern unsigned long ipi_base_addr;
+#endif
+
+/* These are ugly but will be reclaimed by the kernel */
+int __initdata acpi_cpus = 0;
+int __initdata acpi_apic_map[32];
+int __initdata cpu_cnt = 0;
+
+void (*pm_idle) (void);
+
+/*
+ * Identify usable CPU's and remember them for SMP bringup later.
+ */
+static void __init
+acpi_lsapic(char *p)
+{
+ int add = 1;
+
+ acpi_entry_lsapic_t *lsapic = (acpi_entry_lsapic_t *) p;
+
+ if ((lsapic->flags & LSAPIC_PRESENT) == 0)
+ return;
+
+ printk(" CPU %d (%.04x:%.04x): ", cpu_cnt, lsapic->eid, lsapic->id);
+
+ if ((lsapic->flags & LSAPIC_ENABLED) == 0) {
+ printk("Disabled.\n");
+ add = 0;
+ } else if (lsapic->flags & LSAPIC_PERFORMANCE_RESTRICTED) {
+ printk("Performance Restricted; ignoring.\n");
+ add = 0;
+ }
+
+ if (add) {
+ printk("Available.\n");
+ acpi_cpus++;
+ acpi_apic_map[cpu_cnt] = (lsapic->id << 8) | lsapic->eid;
+ }
+
+ cpu_cnt++;
+}
+
+/*
+ * Find all IOSAPICs and tag the iosapic_vector structure with the appropriate
+ * base addresses.
+ */
+static void __init
+acpi_iosapic(char *p)
+{
+ /*
+ * This is not good. ACPI is not necessarily limited to CONFIG_IA64_SV, yet
+ * ACPI does not necessarily imply IOSAPIC either. Perhaps there should be
+ * a means for platform_setup() to register ACPI handlers?
+ */
+#ifdef CONFIG_IA64_DIG
+ acpi_entry_iosapic_t *iosapic = (acpi_entry_iosapic_t *) p;
+ unsigned int ver;
+ int l, v, pins;
+
+ ver = iosapic_version(iosapic->address);
+ pins = (ver >> 16) & 0xff;
+
+ printk("IOSAPIC Version %x.%x: address 0x%lx IRQs 0x%x - 0x%x\n",
+ (ver & 0xf0) >> 4, (ver & 0x0f), iosapic->address,
+ iosapic->irq_base, iosapic->irq_base + pins);
+
+ for (l = 0; l < pins; l++) {
+ v = map_legacy_irq(iosapic->irq_base + l);
+ if (v > IA64_MAX_VECTORED_IRQ) {
+ printk(" !!! IRQ %d > 255\n", v);
+ continue;
+ }
+ /* XXX Check for IOSAPIC collisions */
+ iosapic_addr(v) = (unsigned long) ioremap(iosapic->address, 0);
+ iosapic_baseirq(v) = iosapic->irq_base;
+ }
+ iosapic_init(iosapic->address);
+#endif
+}
+
+
+/*
+ * Configure legacy IRQ information in iosapic_vector
+ */
+static void __init
+acpi_legacy_irq(char *p)
+{
+ /*
+ * This is not good. ACPI is not necessarily limited to CONFIG_IA64_SV, yet
+ * ACPI does not necessarily imply IOSAPIC either. Perhaps there should be
+ * a means for platform_setup() to register ACPI handlers?
+ */
+#ifdef CONFIG_IA64_IRQ_ACPI
+ acpi_entry_int_override_t *legacy = (acpi_entry_int_override_t *) p;
+ unsigned char vector;
+ int i;
+
+ vector = map_legacy_irq(legacy->isa_irq);
+
+ /*
+ * Clobber any old pin mapping. It may be that it gets replaced later on
+ */
+ for (i = 0; i < IA64_MAX_VECTORED_IRQ; i++) {
+ if (i == vector)
+ continue;
+ if (iosapic_pin(i) == iosapic_pin(vector))
+ iosapic_pin(i) = 0xff;
+ }
+
+ iosapic_pin(vector) = legacy->pin;
+ iosapic_bus(vector) = BUS_ISA; /* This table only overrides the ISA devices */
+ iosapic_busdata(vector) = 0;
+
+ /*
+ * External timer tick is special...
+ */
+ if (vector != TIMER_IRQ)
+ iosapic_dmode(vector) = IO_SAPIC_LOWEST_PRIORITY;
+ else
+ iosapic_dmode(vector) = IO_SAPIC_FIXED;
+
+ /* See MPS 1.4 section 4.3.4 */
+ switch (legacy->flags) {
+ case 0x5:
+ iosapic_polarity(vector) = IO_SAPIC_POL_HIGH;
+ iosapic_trigger(vector) = IO_SAPIC_EDGE;
+ break;
+ case 0x8:
+ iosapic_polarity(vector) = IO_SAPIC_POL_LOW;
+ iosapic_trigger(vector) = IO_SAPIC_EDGE;
+ break;
+ case 0xd:
+ iosapic_polarity(vector) = IO_SAPIC_POL_HIGH;
+ iosapic_trigger(vector) = IO_SAPIC_LEVEL;
+ break;
+ case 0xf:
+ iosapic_polarity(vector) = IO_SAPIC_POL_LOW;
+ iosapic_trigger(vector) = IO_SAPIC_LEVEL;
+ break;
+ default:
+ printk(" ACPI Legacy IRQ 0x%02x: Unknown flags 0x%x\n", legacy->isa_irq,
+ legacy->flags);
+ break;
+ }
+
+#ifdef ACPI_DEBUG
+ printk("Legacy ISA IRQ %x -> IA64 Vector %x IOSAPIC Pin %x Active %s %s Trigger\n",
+ legacy->isa_irq, vector, iosapic_pin(vector),
+ ((iosapic_polarity(vector) == IO_SAPIC_POL_LOW) ? "Low" : "High"),
+ ((iosapic_trigger(vector) == IO_SAPIC_LEVEL) ? "Level" : "Edge"));
+#endif /* ACPI_DEBUG */
+
+#endif /* CONFIG_IA64_IRQ_ACPI */
+}
+
+/*
+ * Info on platform interrupt sources: NMI. PMI, INIT, etc.
+ */
+static void __init
+acpi_platform(char *p)
+{
+ acpi_entry_platform_src_t *plat = (acpi_entry_platform_src_t *) p;
+
+ printk("PLATFORM: IOSAPIC %x -> Vector %lx on CPU %.04u:%.04u\n",
+ plat->iosapic_vector, plat->global_vector, plat->eid, plat->id);
+}
+
+/*
+ * Parse the ACPI Multiple SAPIC Table
+ */
+static void __init
+acpi_parse_msapic(acpi_sapic_t *msapic)
+{
+ char *p, *end;
+
+ memset(&acpi_apic_map, -1, sizeof(acpi_apic_map));
+
+#ifdef CONFIG_SMP
+ /* Base address of IPI Message Block */
+ ipi_base_addr = ioremap(msapic->interrupt_block, 0);
+#endif
+
+ p = (char *) (msapic + 1);
+ end = p + (msapic->header.length - sizeof(acpi_sapic_t));
+
+ while (p < end) {
+
+ switch (*p) {
+ case ACPI_ENTRY_LOCAL_SAPIC:
+ acpi_lsapic(p);
+ break;
+
+ case ACPI_ENTRY_IO_SAPIC:
+ acpi_iosapic(p);
+ break;
+
+ case ACPI_ENTRY_INT_SRC_OVERRIDE:
+ acpi_legacy_irq(p);
+ break;
+
+ case ACPI_ENTRY_PLATFORM_INT_SOURCE:
+ acpi_platform(p);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Move to next table entry. */
+ p += *(p + 1);
+ }
+
+ /* Make bootup pretty */
+ printk(" %d CPUs available, %d CPUs total\n", acpi_cpus, cpu_cnt);
+}
+
+int __init
+acpi_parse(acpi_rsdp_t *rsdp)
+{
+ acpi_rsdt_t *rsdt;
+ acpi_desc_table_hdr_t *hdrp;
+ long tables, i;
+
+ if (!rsdp) {
+ printk("Uh-oh, no ACPI Root System Description Pointer table!\n");
+ return 0;
+ }
+
+ if (strncmp(rsdp->signature, ACPI_RSDP_SIG, ACPI_RSDP_SIG_LEN)) {
+ printk("Uh-oh, ACPI RSDP signature incorrect!\n");
+ return 0;
+ }
+
+ rsdp->rsdt = __va(rsdp->rsdt);
+ rsdt = rsdp->rsdt;
+ if (strncmp(rsdt->header.signature, ACPI_RSDT_SIG, ACPI_RSDT_SIG_LEN)) {
+ printk("Uh-oh, ACPI RDST signature incorrect!\n");
+ return 0;
+ }
+
+ printk("ACPI: %.6s %.8s %d.%d\n", rsdt->header.oem_id, rsdt->header.oem_table_id,
+ rsdt->header.oem_revision >> 16, rsdt->header.oem_revision & 0xffff);
+
+ tables = (rsdt->header.length - sizeof(acpi_desc_table_hdr_t)) / 8;
+ for (i = 0; i < tables; i++) {
+ hdrp = (acpi_desc_table_hdr_t *) __va(rsdt->entry_ptrs[i]);
+
+ /* Only interested int the MSAPIC table for now ... */
+ if (strncmp(hdrp->signature, ACPI_SAPIC_SIG, ACPI_SAPIC_SIG_LEN) != 0)
+ continue;
+
+ acpi_parse_msapic((acpi_sapic_t *) hdrp);
+ } /* while() */
+
+ if (acpi_cpus == 0) {
+ printk("ACPI: Found 0 CPUS; assuming 1\n");
+ acpi_cpus = 1; /* We've got at least one of these, no? */
+ }
+ return 1;
+}
+
+const char *
+acpi_get_sysname (void)
+{
+ /* the following should go away once we have an ACPI parser: */
+#ifdef CONFIG_IA64_GENERIC
+ return "hpsim";
+#else
+# if defined (CONFIG_IA64_HP_SIM)
+ return "hpsim";
+# elif defined (CONFIG_IA64_SGI_SN1_SIM)
+ return "sn1";
+# elif defined (CONFIG_IA64_DIG)
+ return "dig";
+# else
+# error Unknown platform. Fix acpi.c.
+# endif
+#endif
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)