1/* 2 * acpi.c - Architecture-Specific Low-Level ACPI Support 3 * 4 * Copyright (C) 1999 VA Linux Systems 5 * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com> 6 * Copyright (C) 2000, 2002 Hewlett-Packard Co. 7 * David Mosberger-Tang <davidm@hpl.hp.com> 8 * Copyright (C) 2000 Intel Corp. 9 * Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com> 10 * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 11 * 12 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; either version 2 of the License, or 17 * (at your option) any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, write to the Free Software 26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 * 28 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29 */ 30 31#include <linux/config.h> 32#include <linux/init.h> 33#include <linux/kernel.h> 34#include <linux/sched.h> 35#include <linux/smp.h> 36#include <linux/string.h> 37#include <linux/types.h> 38#include <linux/irq.h> 39#include <linux/acpi.h> 40#include <linux/efi.h> 41#include <asm/io.h> 42#include <asm/iosapic.h> 43#include <asm/machvec.h> 44#include <asm/page.h> 45#include <asm/system.h> 46 47 48#define PREFIX "ACPI: " 49 50asm (".weak iosapic_register_intr"); 51asm (".weak iosapic_override_isa_irq"); 52asm (".weak iosapic_register_platform_intr"); 53asm (".weak iosapic_init"); 54asm (".weak iosapic_version"); 55 56void (*pm_idle) (void); 57void (*pm_power_off) (void); 58 59unsigned char acpi_kbd_controller_present = 1; 60 61const char * 62acpi_get_sysname (void) 63{ 64#ifdef CONFIG_IA64_GENERIC 65 unsigned long rsdp_phys; 66 struct acpi20_table_rsdp *rsdp; 67 struct acpi_table_xsdt *xsdt; 68 struct acpi_table_header *hdr; 69 70 rsdp_phys = acpi_find_rsdp(); 71 if (!rsdp_phys) { 72 printk("ACPI 2.0 RSDP not found, default to \"dig\"\n"); 73 return "dig"; 74 } 75 76 rsdp = (struct acpi20_table_rsdp *) __va(rsdp_phys); 77 if (strncmp(rsdp->signature, RSDP_SIG, sizeof(RSDP_SIG) - 1)) { 78 printk("ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n"); 79 return "dig"; 80 } 81 82 xsdt = (struct acpi_table_xsdt *) __va(rsdp->xsdt_address); 83 hdr = &xsdt->header; 84 if (strncmp(hdr->signature, XSDT_SIG, sizeof(XSDT_SIG) - 1)) { 85 printk("ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n"); 86 return "dig"; 87 } 88 89 if (!strcmp(hdr->oem_id, "HP")) { 90 return "hpzx1"; 91 } 92 93 return "dig"; 94#else 95# if defined (CONFIG_IA64_HP_SIM) 96 return "hpsim"; 97# elif defined (CONFIG_IA64_HP_ZX1) 98 return "hpzx1"; 99# elif defined (CONFIG_IA64_SGI_SN1) 100 return "sn1"; 101# elif defined (CONFIG_IA64_SGI_SN2) 102 return "sn2"; 103# elif defined (CONFIG_IA64_DIG) 104 return "dig"; 105# elif defined (CONFIG_IA64_HP_ZX1) 106 return "hpzx1"; 107# else 108# error Unknown platform. Fix acpi.c. 109# endif 110#endif 111} 112 113#ifdef CONFIG_ACPI 114 115/** 116 * acpi_get_crs - Return the current resource settings for a device 117 * obj: A handle for this device 118 * buf: A buffer to be populated by this call. 119 * 120 * Pass a valid handle, typically obtained by walking the namespace and a 121 * pointer to an allocated buffer, and this function will fill in the buffer 122 * with a list of acpi_resource structures. 123 */ 124acpi_status 125acpi_get_crs (acpi_handle obj, acpi_buffer *buf) 126{ 127 acpi_status result; 128 buf->length = 0; 129 buf->pointer = NULL; 130 131 result = acpi_get_current_resources(obj, buf); 132 if (result != AE_BUFFER_OVERFLOW) 133 return result; 134 buf->pointer = kmalloc(buf->length, GFP_KERNEL); 135 if (!buf->pointer) 136 return -ENOMEM; 137 138 return acpi_get_current_resources(obj, buf); 139} 140 141acpi_resource * 142acpi_get_crs_next (acpi_buffer *buf, int *offset) 143{ 144 acpi_resource *res; 145 146 if (*offset >= buf->length) 147 return NULL; 148 149 res = buf->pointer + *offset; 150 *offset += res->length; 151 return res; 152} 153 154acpi_resource_data * 155acpi_get_crs_type (acpi_buffer *buf, int *offset, int type) 156{ 157 for (;;) { 158 acpi_resource *res = acpi_get_crs_next(buf, offset); 159 if (!res) 160 return NULL; 161 if (res->id == type) 162 return &res->data; 163 } 164} 165 166void 167acpi_dispose_crs (acpi_buffer *buf) 168{ 169 kfree(buf->pointer); 170} 171 172static void 173acpi_get_crs_addr (acpi_buffer *buf, int type, u64 *base, u64 *length, u64 *tra) 174{ 175 int offset = 0; 176 acpi_resource_address16 *addr16; 177 acpi_resource_address32 *addr32; 178 acpi_resource_address64 *addr64; 179 180 for (;;) { 181 acpi_resource *res = acpi_get_crs_next(buf, &offset); 182 if (!res) 183 return; 184 switch (res->id) { 185 case ACPI_RSTYPE_ADDRESS16: 186 addr16 = (acpi_resource_address16 *) &res->data; 187 188 if (type == addr16->resource_type) { 189 *base = addr16->min_address_range; 190 *length = addr16->address_length; 191 *tra = addr16->address_translation_offset; 192 return; 193 } 194 break; 195 case ACPI_RSTYPE_ADDRESS32: 196 addr32 = (acpi_resource_address32 *) &res->data; 197 if (type == addr32->resource_type) { 198 *base = addr32->min_address_range; 199 *length = addr32->address_length; 200 *tra = addr32->address_translation_offset; 201 return; 202 } 203 break; 204 case ACPI_RSTYPE_ADDRESS64: 205 addr64 = (acpi_resource_address64 *) &res->data; 206 if (type == addr64->resource_type) { 207 *base = addr64->min_address_range; 208 *length = addr64->address_length; 209 *tra = addr64->address_translation_offset; 210 return; 211 } 212 break; 213 } 214 } 215} 216 217acpi_status 218acpi_get_addr_space(acpi_handle obj, u8 type, u64 *base, u64 *length, u64 *tra) 219{ 220 acpi_status status; 221 acpi_buffer buf; 222 223 *base = 0; 224 *length = 0; 225 *tra = 0; 226 227 status = acpi_get_crs(obj, &buf); 228 if (ACPI_FAILURE(status)) { 229 printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); 230 return status; 231 } 232 233 acpi_get_crs_addr(&buf, type, base, length, tra); 234 235 acpi_dispose_crs(&buf); 236 237 return AE_OK; 238} 239 240typedef struct { 241 u8 guid_id; 242 u8 guid[16]; 243 u8 csr_base[8]; 244 u8 csr_length[8]; 245} acpi_hp_vendor_long; 246 247#define HP_CCSR_LENGTH 0x21 248#define HP_CCSR_TYPE 0x2 249#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \ 250 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad) 251 252acpi_status 253acpi_hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length) 254{ 255 int i, offset = 0; 256 acpi_status status; 257 acpi_buffer buf; 258 acpi_resource_vendor *res; 259 acpi_hp_vendor_long *hp_res; 260 efi_guid_t vendor_guid; 261 262 *csr_base = 0; 263 *csr_length = 0; 264 265 status = acpi_get_crs(obj, &buf); 266 if (ACPI_FAILURE(status)) { 267 printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); 268 return status; 269 } 270 271 res = (acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR); 272 if (!res) { 273 printk(KERN_ERR PREFIX "Failed to find config space for device\n"); 274 acpi_dispose_crs(&buf); 275 return AE_NOT_FOUND; 276 } 277 278 hp_res = (acpi_hp_vendor_long *)(res->reserved); 279 280 if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) { 281 printk(KERN_ERR PREFIX "Unknown Vendor data\n"); 282 acpi_dispose_crs(&buf); 283 return AE_TYPE; /* Revisit error? */ 284 } 285 286 memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t)); 287 if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) { 288 printk(KERN_ERR PREFIX "Vendor GUID does not match\n"); 289 acpi_dispose_crs(&buf); 290 return AE_TYPE; /* Revisit error? */ 291 } 292 293 for (i = 0 ; i < 8 ; i++) { 294 *csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8)); 295 *csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8)); 296 } 297 298 acpi_dispose_crs(&buf); 299 300 return AE_OK; 301} 302#endif /* CONFIG_ACPI */ 303 304#ifdef CONFIG_ACPI_BOOT 305 306#define ACPI_MAX_PLATFORM_INTERRUPTS 256 307 308/* Array to record platform interrupt vectors for generic interrupt routing. */ 309int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 }; 310 311enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC; 312 313/* 314 * Interrupt routing API for device drivers. Provides interrupt vector for 315 * a generic platform event. Currently only CPEI is implemented. 316 */ 317int 318acpi_request_vector (u32 int_type) 319{ 320 int vector = -1; 321 322 if (int_type < ACPI_MAX_PLATFORM_INTERRUPTS) { 323 /* correctable platform error interrupt */ 324 vector = platform_intr_list[int_type]; 325 } else 326 printk("acpi_request_vector(): invalid interrupt type\n"); 327 328 return vector; 329} 330 331char * 332__acpi_map_table (unsigned long phys_addr, unsigned long size) 333{ 334 return __va(phys_addr); 335} 336 337/* -------------------------------------------------------------------------- 338 Boot-time Table Parsing 339 -------------------------------------------------------------------------- */ 340 341static int total_cpus __initdata; 342static int available_cpus __initdata; 343struct acpi_table_madt * acpi_madt __initdata; 344static u8 has_8259; 345 346 347static int __init 348acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header) 349{ 350 struct acpi_table_lapic_addr_ovr *lapic; 351 352 lapic = (struct acpi_table_lapic_addr_ovr *) header; 353 if (!lapic) 354 return -EINVAL; 355 356 acpi_table_print_madt_entry(header); 357 358 if (lapic->address) { 359 iounmap((void *) ipi_base_addr); 360 ipi_base_addr = (unsigned long) ioremap(lapic->address, 0); 361 } 362 363 return 0; 364} 365 366 367static int __init 368acpi_parse_lsapic (acpi_table_entry_header *header) 369{ 370 struct acpi_table_lsapic *lsapic; 371 372 lsapic = (struct acpi_table_lsapic *) header; 373 if (!lsapic) 374 return -EINVAL; 375 376 acpi_table_print_madt_entry(header); 377 378 printk("CPU %d (0x%04x)", total_cpus, (lsapic->id << 8) | lsapic->eid); 379 380 if (lsapic->flags.enabled) { 381 available_cpus++; 382 printk(" enabled"); 383#ifdef CONFIG_SMP 384 smp_boot_data.cpu_phys_id[total_cpus] = (lsapic->id << 8) | lsapic->eid; 385 if (hard_smp_processor_id() == smp_boot_data.cpu_phys_id[total_cpus]) 386 printk(" (BSP)"); 387#endif 388 } 389 else { 390 printk(" disabled"); 391#ifdef CONFIG_SMP 392 smp_boot_data.cpu_phys_id[total_cpus] = -1; 393#endif 394 } 395 396 printk("\n"); 397 398 total_cpus++; 399 return 0; 400} 401 402 403static int __init 404acpi_parse_lapic_nmi (acpi_table_entry_header *header) 405{ 406 struct acpi_table_lapic_nmi *lacpi_nmi; 407 408 lacpi_nmi = (struct acpi_table_lapic_nmi*) header; 409 if (!lacpi_nmi) 410 return -EINVAL; 411 412 acpi_table_print_madt_entry(header); 413 414 /* TBD: Support lapic_nmi entries */ 415 416 return 0; 417} 418 419 420static int __init 421acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address) 422{ 423 struct acpi_table_iosapic *iosapic; 424 int ver; 425 int max_pin; 426 char *p; 427 char *end; 428 429 if (!gsi_base || !iosapic_address) 430 return -ENODEV; 431 432 p = (char *) (acpi_madt + 1); 433 end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt)); 434 435 while (p < end) { 436 if (*p == ACPI_MADT_IOSAPIC) { 437 iosapic = (struct acpi_table_iosapic *) p; 438 439 *gsi_base = iosapic->global_irq_base; 440 *iosapic_address = ioremap(iosapic->address, 0); 441 442 ver = iosapic_version(*iosapic_address); 443 max_pin = (ver >> 16) & 0xff; 444 445 if ((gsi - *gsi_base) <= max_pin) 446 return 0; /* Found it! */ 447 } 448 p += p[1]; 449 } 450 return -ENODEV; 451} 452 453 454static int __init 455acpi_parse_iosapic (acpi_table_entry_header *header) 456{ 457 struct acpi_table_iosapic *iosapic; 458 459 iosapic = (struct acpi_table_iosapic *) header; 460 if (!iosapic) 461 return -EINVAL; 462 463 acpi_table_print_madt_entry(header); 464 465 if (iosapic_init) { 466#ifndef CONFIG_ITANIUM 467 /* PCAT_COMPAT flag indicates dual-8259 setup */ 468 iosapic_init(iosapic->address, iosapic->global_irq_base, 469 acpi_madt->flags.pcat_compat); 470#else 471 /* Firmware on old Itanium systems is broken */ 472 iosapic_init(iosapic->address, iosapic->global_irq_base, 1); 473#endif 474 } 475 return 0; 476} 477 478 479static int __init 480acpi_parse_plat_int_src (acpi_table_entry_header *header) 481{ 482 struct acpi_table_plat_int_src *plintsrc; 483 int vector; 484 u32 gsi_base; 485 char *iosapic_address; 486 487 plintsrc = (struct acpi_table_plat_int_src *) header; 488 if (!plintsrc) 489 return -EINVAL; 490 491 acpi_table_print_madt_entry(header); 492 493 if (!iosapic_register_platform_intr) { 494 printk(KERN_WARNING PREFIX "No ACPI platform interrupt support\n"); 495 return -ENODEV; 496 } 497 498 if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) { 499 printk(KERN_WARNING PREFIX "IOSAPIC not found\n"); 500 return -ENODEV; 501 } 502 503 /* 504 * Get vector assignment for this interrupt, set attributes, 505 * and program the IOSAPIC routing table. 506 */ 507 vector = iosapic_register_platform_intr(plintsrc->type, 508 plintsrc->global_irq, 509 plintsrc->iosapic_vector, 510 plintsrc->eid, 511 plintsrc->id, 512 (plintsrc->flags.polarity == 1) ? 1 : 0, 513 (plintsrc->flags.trigger == 1) ? 1 : 0, 514 gsi_base, 515 iosapic_address); 516 517 platform_intr_list[plintsrc->type] = vector; 518 return 0; 519} 520 521 522static int __init 523acpi_parse_int_src_ovr (acpi_table_entry_header *header) 524{ 525 struct acpi_table_int_src_ovr *p; 526 527 p = (struct acpi_table_int_src_ovr *) header; 528 if (!p) 529 return -EINVAL; 530 531 acpi_table_print_madt_entry(header); 532 533 /* Ignore if the platform doesn't support overrides */ 534 if (!iosapic_override_isa_irq) 535 return 0; 536 537 iosapic_override_isa_irq(p->bus_irq, p->global_irq, 538 (p->flags.polarity == 1) ? 1 : 0, 539 (p->flags.trigger == 1) ? 1 : 0); 540 541 return 0; 542} 543 544 545static int __init 546acpi_parse_nmi_src (acpi_table_entry_header *header) 547{ 548 struct acpi_table_nmi_src *nmi_src; 549 550 nmi_src = (struct acpi_table_nmi_src*) header; 551 if (!nmi_src) 552 return -EINVAL; 553 554 acpi_table_print_madt_entry(header); 555 556 /* TBD: Support nimsrc entries */ 557 558 return 0; 559} 560 561 562static int __init 563acpi_parse_madt (unsigned long phys_addr, unsigned long size) 564{ 565 if (!phys_addr || !size) 566 return -EINVAL; 567 568 acpi_madt = (struct acpi_table_madt *) __va(phys_addr); 569 570 /* remember the value for reference after free_initmem() */ 571 has_8259 = acpi_madt->flags.pcat_compat; 572 573 /* Get base address of IPI Message Block */ 574 575 if (acpi_madt->lapic_address) 576 ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0); 577 578 printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr); 579 return 0; 580} 581 582 583static int __init 584acpi_parse_fadt (unsigned long phys_addr, unsigned long size) 585{ 586 struct acpi_table_header *fadt_header; 587 fadt_descriptor_rev2 *fadt; 588 u32 sci_irq, gsi_base; 589 char *iosapic_address; 590 591 if (!phys_addr || !size) 592 return -EINVAL; 593 594 fadt_header = (struct acpi_table_header *) __va(phys_addr); 595 596 if (fadt_header->revision != 3) 597 return -ENODEV; /* Only deal with ACPI 2.0 FADT */ 598 599 fadt = (fadt_descriptor_rev2 *) fadt_header; 600 601 if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER)) 602 acpi_kbd_controller_present = 0; 603 604 sci_irq = fadt->sci_int; 605 606 if (has_8259 && sci_irq < 16) 607 return 0; /* legacy, no setup required */ 608 609 if (!iosapic_register_intr) 610 return -ENODEV; 611 612 if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address)) 613 iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address); 614 615 return 0; 616} 617 618 619#ifdef CONFIG_SERIAL_ACPI 620 621#include <linux/acpi_serial.h> 622 623static int __init 624acpi_parse_spcr (unsigned long phys_addr, unsigned long size) 625{ 626 acpi_ser_t *spcr; 627 u32 gsi, gsi_base; 628 char *iosapic_address; 629 630 if (!phys_addr || !size) 631 return -EINVAL; 632 633 if (!iosapic_register_intr) 634 return -ENODEV; 635 636 /* 637 * ACPI is able to describe serial ports that live at non-standard 638 * memory addresses and use non-standard interrupts, either via 639 * direct SAPIC mappings or via PCI interrupts. We handle interrupt 640 * routing for SAPIC-based (non-PCI) devices here. Interrupt routing 641 * for PCI devices will be handled when processing the PCI Interrupt 642 * Routing Table (PRT). 643 */ 644 645 spcr = (acpi_ser_t *) __va(phys_addr); 646 setup_serial_acpi(spcr); 647 648 if (spcr->length < sizeof(acpi_ser_t)) 649 /* Table not long enough for full info, thus no interrupt */ 650 return -ENODEV; 651 652 if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) && 653 (spcr->int_type == ACPI_SERIAL_INT_SAPIC)) { 654 655 /* We have a UART in memory space with an SAPIC interrupt */ 656 657 gsi = (spcr->global_int[3] << 24) | 658 (spcr->global_int[2] << 16) | 659 (spcr->global_int[1] << 8) | 660 (spcr->global_int[0]); 661 662 if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address)) 663 iosapic_register_intr(gsi, 1, 1, 664 gsi_base, iosapic_address); 665 } 666 return 0; 667} 668 669#endif /*CONFIG_SERIAL_ACPI*/ 670 671 672unsigned long __init 673acpi_find_rsdp (void) 674{ 675 unsigned long rsdp_phys = 0; 676 677 if (efi.acpi20) 678 rsdp_phys = __pa(efi.acpi20); 679 else if (efi.acpi) 680 printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n"); 681 682 return rsdp_phys; 683} 684 685 686int __init 687acpi_boot_init (char *cmdline) 688{ 689 int result; 690 691 /* Initialize the ACPI boot-time table parser */ 692 result = acpi_table_init(cmdline); 693 if (result) 694 return result; 695 696 /* 697 * MADT 698 * ---- 699 * Parse the Multiple APIC Description Table (MADT), if exists. 700 * Note that this table provides platform SMP configuration 701 * information -- the successor to MPS tables. 702 */ 703 704 if (acpi_table_parse(ACPI_APIC, acpi_parse_madt) < 1) { 705 printk(KERN_ERR PREFIX "Can't find MADT\n"); 706 goto skip_madt; 707 } 708 709 /* Local APIC */ 710 711 if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, 712 acpi_parse_lapic_addr_ovr) < 0) 713 printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); 714 715 if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, 716 acpi_parse_lsapic) < 1) 717 printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n"); 718 719 if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, 720 acpi_parse_lapic_nmi) < 0) 721 printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); 722 723 /* I/O APIC */ 724 725 if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC, 726 acpi_parse_iosapic) < 1) 727 printk(KERN_ERR PREFIX "Error parsing MADT - no IOAPIC entries\n"); 728 729 /* System-Level Interrupt Routing */ 730 731 if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, 732 acpi_parse_plat_int_src) < 0) 733 printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n"); 734 735 if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, 736 acpi_parse_int_src_ovr) < 0) 737 printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); 738 739 if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, 740 acpi_parse_nmi_src) < 0) 741 printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); 742skip_madt: 743 744 /* 745 * The FADT table contains an SCI_INT line, by which the system 746 * gets interrupts such as power and sleep buttons. If it's not 747 * on a Legacy interrupt, it needs to be setup. 748 */ 749 if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1) 750 printk(KERN_ERR PREFIX "Can't find FADT\n"); 751 752#ifdef CONFIG_SERIAL_ACPI 753 acpi_table_parse(ACPI_SPCR, acpi_parse_spcr); 754#endif 755 756#ifdef CONFIG_SMP 757 if (available_cpus == 0) { 758 printk("ACPI: Found 0 CPUS; assuming 1\n"); 759 available_cpus = 1; /* We've got at least one of these, no? */ 760 } 761 smp_boot_data.cpu_count = total_cpus; 762#endif 763 /* Make boot-up look pretty */ 764 printk("%d CPUs available, %d CPUs total\n", available_cpus, total_cpus); 765 return 0; 766} 767 768 769/* -------------------------------------------------------------------------- 770 PCI Interrupt Routing 771 -------------------------------------------------------------------------- */ 772 773int __init 774acpi_get_prt (struct pci_vector_struct **vectors, int *count) 775{ 776 struct pci_vector_struct *vector; 777 struct list_head *node; 778 struct acpi_prt_entry *entry; 779 int i = 0; 780 781 if (!vectors || !count) 782 return -EINVAL; 783 784 *vectors = NULL; 785 *count = 0; 786 787 if (acpi_prt.count < 0) { 788 printk(KERN_ERR PREFIX "No PCI interrupt routing entries\n"); 789 return -ENODEV; 790 } 791 792 /* Allocate vectors */ 793 794 *vectors = kmalloc(sizeof(struct pci_vector_struct) * acpi_prt.count, GFP_KERNEL); 795 if (!(*vectors)) 796 return -ENOMEM; 797 798 /* Convert PRT entries to IOSAPIC PCI vectors */ 799 800 vector = *vectors; 801 802 list_for_each(node, &acpi_prt.entries) { 803 entry = (struct acpi_prt_entry *)node; 804 vector[i].segment = entry->id.segment; 805 vector[i].bus = entry->id.bus; 806 vector[i].pci_id = ((u32) entry->id.device << 16) | 0xffff; 807 vector[i].pin = entry->pin; 808 vector[i].irq = entry->link.index; 809 i++; 810 } 811 *count = acpi_prt.count; 812 return 0; 813} 814 815/* Assume IA64 always use I/O SAPIC */ 816 817int __init 818acpi_get_interrupt_model (int *type) 819{ 820 if (!type) 821 return -EINVAL; 822 823 *type = ACPI_IRQ_MODEL_IOSAPIC; 824 return 0; 825} 826 827int 828acpi_irq_to_vector (u32 irq) 829{ 830 if (has_8259 && irq < 16) 831 return isa_irq_to_vector(irq); 832 833 return gsi_to_vector(irq); 834} 835 836#endif /* CONFIG_ACPI_BOOT */ 837