📄 acpi.c
字号:
return -ENODEV; p = (char *) (acpi_madt + 1); end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt)); while (p < end) { if (*p == ACPI_MADT_IOSAPIC) { iosapic = (struct acpi_table_iosapic *) p; *gsi_base = iosapic->global_irq_base; *iosapic_address = ioremap(iosapic->address, 0); ver = iosapic_version(*iosapic_address); max_pin = (ver >> 16) & 0xff; if ((gsi - *gsi_base) <= max_pin) return 0; /* Found it! */ } p += p[1]; } return -ENODEV;}static int __initacpi_parse_iosapic (acpi_table_entry_header *header){ struct acpi_table_iosapic *iosapic; iosapic = (struct acpi_table_iosapic *) header; if (!iosapic) return -EINVAL; acpi_table_print_madt_entry(header); if (iosapic_init) {#ifndef CONFIG_ITANIUM /* PCAT_COMPAT flag indicates dual-8259 setup */ iosapic_init(iosapic->address, iosapic->global_irq_base, acpi_madt->flags.pcat_compat);#else /* Firmware on old Itanium systems is broken */ iosapic_init(iosapic->address, iosapic->global_irq_base, 1);#endif } return 0;}static int __initacpi_parse_plat_int_src (acpi_table_entry_header *header){ struct acpi_table_plat_int_src *plintsrc; int vector; u32 gsi_base; char *iosapic_address; plintsrc = (struct acpi_table_plat_int_src *) header; if (!plintsrc) return -EINVAL; acpi_table_print_madt_entry(header); if (!iosapic_register_platform_intr) { printk(KERN_WARNING PREFIX "No ACPI platform interrupt support\n"); return -ENODEV; } if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) { printk(KERN_WARNING PREFIX "IOSAPIC not found\n"); return -ENODEV; } /* * Get vector assignment for this interrupt, set attributes, * and program the IOSAPIC routing table. */ vector = iosapic_register_platform_intr(plintsrc->type, plintsrc->global_irq, plintsrc->iosapic_vector, plintsrc->eid, plintsrc->id, (plintsrc->flags.polarity == 1) ? 1 : 0, (plintsrc->flags.trigger == 1) ? 1 : 0, gsi_base, iosapic_address); platform_intr_list[plintsrc->type] = vector; return 0;}static int __initacpi_parse_int_src_ovr (acpi_table_entry_header *header){ struct acpi_table_int_src_ovr *p; p = (struct acpi_table_int_src_ovr *) header; if (!p) return -EINVAL; acpi_table_print_madt_entry(header); /* Ignore if the platform doesn't support overrides */ if (!iosapic_override_isa_irq) return 0; iosapic_override_isa_irq(p->bus_irq, p->global_irq, (p->flags.polarity == 1) ? 1 : 0, (p->flags.trigger == 1) ? 1 : 0); return 0;}static int __initacpi_parse_nmi_src (acpi_table_entry_header *header){ struct acpi_table_nmi_src *nmi_src; nmi_src = (struct acpi_table_nmi_src*) header; if (!nmi_src) return -EINVAL; acpi_table_print_madt_entry(header); /* TBD: Support nimsrc entries */ return 0;}static int __initacpi_parse_madt (unsigned long phys_addr, unsigned long size){ if (!phys_addr || !size) return -EINVAL; acpi_madt = (struct acpi_table_madt *) __va(phys_addr); /* remember the value for reference after free_initmem() */ has_8259 = acpi_madt->flags.pcat_compat; /* Get base address of IPI Message Block */ if (acpi_madt->lapic_address) ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0); printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr); return 0;}static int __initacpi_parse_fadt (unsigned long phys_addr, unsigned long size){ struct acpi_table_header *fadt_header; fadt_descriptor_rev2 *fadt; u32 sci_irq, gsi_base; char *iosapic_address; if (!phys_addr || !size) return -EINVAL; fadt_header = (struct acpi_table_header *) __va(phys_addr); if (fadt_header->revision != 3) return -ENODEV; /* Only deal with ACPI 2.0 FADT */ fadt = (fadt_descriptor_rev2 *) fadt_header; if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER)) acpi_kbd_controller_present = 0; sci_irq = fadt->sci_int; if (has_8259 && sci_irq < 16) return 0; /* legacy, no setup required */ if (!iosapic_register_intr) return -ENODEV; if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address)) iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address); return 0;}#ifdef CONFIG_SERIAL_ACPI#include <linux/acpi_serial.h>static int __initacpi_parse_spcr (unsigned long phys_addr, unsigned long size){ acpi_ser_t *spcr; u32 gsi, gsi_base; char *iosapic_address; if (!phys_addr || !size) return -EINVAL; if (!iosapic_register_intr) return -ENODEV; /* * ACPI is able to describe serial ports that live at non-standard * memory addresses and use non-standard interrupts, either via * direct SAPIC mappings or via PCI interrupts. We handle interrupt * routing for SAPIC-based (non-PCI) devices here. Interrupt routing * for PCI devices will be handled when processing the PCI Interrupt * Routing Table (PRT). */ spcr = (acpi_ser_t *) __va(phys_addr); setup_serial_acpi(spcr); if (spcr->length < sizeof(acpi_ser_t)) /* Table not long enough for full info, thus no interrupt */ return -ENODEV; if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) && (spcr->int_type == ACPI_SERIAL_INT_SAPIC)) { /* We have a UART in memory space with an SAPIC interrupt */ gsi = (spcr->global_int[3] << 24) | (spcr->global_int[2] << 16) | (spcr->global_int[1] << 8) | (spcr->global_int[0]); if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address)) iosapic_register_intr(gsi, 1, 1, gsi_base, iosapic_address); } return 0;}#endif /*CONFIG_SERIAL_ACPI*/unsigned long __initacpi_find_rsdp (void){ unsigned long rsdp_phys = 0; if (efi.acpi20) rsdp_phys = __pa(efi.acpi20); else if (efi.acpi) printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n"); return rsdp_phys;}int __initacpi_boot_init (char *cmdline){ int result; /* Initialize the ACPI boot-time table parser */ result = acpi_table_init(cmdline); if (result) return result; /* * MADT * ---- * Parse the Multiple APIC Description Table (MADT), if exists. * Note that this table provides platform SMP configuration * information -- the successor to MPS tables. */ if (acpi_table_parse(ACPI_APIC, acpi_parse_madt) < 1) { printk(KERN_ERR PREFIX "Can't find MADT\n"); goto skip_madt; } /* Local APIC */ if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr) < 0) printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic) < 1) printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n"); if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi) < 0) printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); /* I/O APIC */ if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC, acpi_parse_iosapic) < 1) printk(KERN_ERR PREFIX "Error parsing MADT - no IOAPIC entries\n"); /* System-Level Interrupt Routing */ if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src) < 0) printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n"); if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr) < 0) printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src) < 0) printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");skip_madt: /* * The FADT table contains an SCI_INT line, by which the system * gets interrupts such as power and sleep buttons. If it's not * on a Legacy interrupt, it needs to be setup. */ if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1) printk(KERN_ERR PREFIX "Can't find FADT\n");#ifdef CONFIG_SERIAL_ACPI acpi_table_parse(ACPI_SPCR, acpi_parse_spcr);#endif#ifdef CONFIG_SMP if (available_cpus == 0) { printk("ACPI: Found 0 CPUS; assuming 1\n"); available_cpus = 1; /* We've got at least one of these, no? */ } smp_boot_data.cpu_count = total_cpus;#endif /* Make boot-up look pretty */ printk("%d CPUs available, %d CPUs total\n", available_cpus, total_cpus); return 0;}/* -------------------------------------------------------------------------- PCI Interrupt Routing -------------------------------------------------------------------------- */int __initacpi_get_prt (struct pci_vector_struct **vectors, int *count){ struct pci_vector_struct *vector; struct list_head *node; struct acpi_prt_entry *entry; int i = 0; if (!vectors || !count) return -EINVAL; *vectors = NULL; *count = 0; if (acpi_prt.count < 0) { printk(KERN_ERR PREFIX "No PCI interrupt routing entries\n"); return -ENODEV; } /* Allocate vectors */ *vectors = kmalloc(sizeof(struct pci_vector_struct) * acpi_prt.count, GFP_KERNEL); if (!(*vectors)) return -ENOMEM; /* Convert PRT entries to IOSAPIC PCI vectors */ vector = *vectors; list_for_each(node, &acpi_prt.entries) { entry = (struct acpi_prt_entry *)node; vector[i].segment = entry->id.segment; vector[i].bus = entry->id.bus; vector[i].pci_id = ((u32) entry->id.device << 16) | 0xffff; vector[i].pin = entry->pin; vector[i].irq = entry->link.index; i++; } *count = acpi_prt.count; return 0;}/* Assume IA64 always use I/O SAPIC */int __initacpi_get_interrupt_model (int *type){ if (!type) return -EINVAL; *type = ACPI_IRQ_MODEL_IOSAPIC; return 0;}intacpi_irq_to_vector (u32 irq){ if (has_8259 && irq < 16) return isa_irq_to_vector(irq); return gsi_to_vector(irq);}#endif /* CONFIG_ACPI_BOOT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -