1/* $NetBSD: mpacpi.c,v 1.92.8.1 2012/11/22 00:39:00 riz Exp $ */ 2 3/* 4 * Copyright (c) 2003 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Frank van der Linden for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include <sys/cdefs.h> 39__KERNEL_RCSID(0, "$NetBSD: mpacpi.c,v 1.92.8.1 2012/11/22 00:39:00 riz Exp $"); 40 41#include "acpica.h" 42#include "opt_acpi.h" 43#include "opt_mpbios.h" 44#include "opt_multiprocessor.h" 45#include "pchb.h" 46 47#include <sys/param.h> 48#include <sys/systm.h> 49#include <sys/kernel.h> 50#include <sys/device.h> 51#include <sys/kmem.h> 52#include <sys/queue.h> 53 54#include <uvm/uvm_extern.h> 55 56#include <machine/specialreg.h> 57#include <machine/cpuvar.h> 58#include <sys/bus.h> 59#include <machine/mpacpi.h> 60#include <machine/mpbiosvar.h> 61 62#include <machine/i82093reg.h> 63#include <machine/i82093var.h> 64#include <machine/i82489reg.h> 65#include <machine/i82489var.h> 66#include <dev/isa/isareg.h> 67#include <dev/pci/pcivar.h> 68#include <dev/pci/pcidevs.h> 69#include <dev/pci/ppbreg.h> 70 71#include <dev/acpi/acpica.h> 72#include <dev/acpi/acpireg.h> 73#include <dev/acpi/acpivar.h> 74 75#include <dev/cons.h> 76 77#define _COMPONENT ACPI_RESOURCE_COMPONENT 78ACPI_MODULE_NAME ("mpacpi") 79 80#include "pci.h" 81#include "ioapic.h" 82#include "lapic.h" 83 84#include "locators.h" 85 86/* XXX room for PCI-to-PCI bus */ 87#define BUS_BUFFER (16) 88 89#if NPCI > 0 90struct mpacpi_pcibus { 91 TAILQ_ENTRY(mpacpi_pcibus) mpr_list; 92 ACPI_HANDLE mpr_handle; /* Same thing really, but.. */ 93 ACPI_BUFFER mpr_buf; /* preserve _PRT */ 94 int mpr_seg; /* PCI segment number */ 95 int mpr_bus; /* PCI bus number */ 96}; 97 98static TAILQ_HEAD(, mpacpi_pcibus) mpacpi_pcibusses; 99 100#endif 101 102static int mpacpi_cpuprint(void *, const char *); 103static int mpacpi_ioapicprint(void *, const char *); 104 105/* acpi_madt_walk callbacks */ 106static ACPI_STATUS mpacpi_count(ACPI_SUBTABLE_HEADER *, void *); 107static ACPI_STATUS mpacpi_config_cpu(ACPI_SUBTABLE_HEADER *, void *); 108static ACPI_STATUS mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *, void *); 109static ACPI_STATUS mpacpi_nonpci_intr(ACPI_SUBTABLE_HEADER *, void *); 110 111#if NPCI > 0 112static int mpacpi_pcircount(struct mpacpi_pcibus *); 113static int mpacpi_pciroute(struct mpacpi_pcibus *); 114static int mpacpi_find_pcibusses(struct acpi_softc *); 115 116static void mpacpi_print_pci_intr(int); 117#endif 118 119static void mpacpi_config_irouting(struct acpi_softc *); 120 121static void mpacpi_print_intr(struct mp_intr_map *); 122static void mpacpi_print_isa_intr(int); 123 124static void mpacpi_user_continue(const char *fmt, ...); 125 126int mpacpi_nioapic; /* number of ioapics */ 127int mpacpi_ncpu; /* number of cpus */ 128int mpacpi_nintsrc; /* number of non-device interrupts */ 129 130#if NPCI > 0 131static int mpacpi_npci; 132static int mpacpi_maxpci; 133static int mpacpi_npciroots; 134#endif 135 136static int mpacpi_intr_index; 137static paddr_t mpacpi_lapic_base = LAPIC_BASE; 138 139int mpacpi_step; 140int mpacpi_force; 141 142static int 143mpacpi_cpuprint(void *aux, const char *pnp) 144{ 145 struct cpu_attach_args *caa = aux; 146 147 if (pnp) 148 aprint_normal("cpu at %s", pnp); 149 aprint_normal(" apid %d", caa->cpu_number); 150 return (UNCONF); 151} 152 153static int 154mpacpi_ioapicprint(void *aux, const char *pnp) 155{ 156 struct apic_attach_args *aaa = aux; 157 158 if (pnp) 159 aprint_normal("ioapic at %s", pnp); 160 aprint_normal(" apid %d", aaa->apic_id); 161 return (UNCONF); 162} 163 164/* 165 * Handle special interrupt sources and overrides from the MADT. 166 * This is a callback function for acpi_madt_walk() (see acpi.c). 167 */ 168static ACPI_STATUS 169mpacpi_nonpci_intr(ACPI_SUBTABLE_HEADER *hdrp, void *aux) 170{ 171 int *index = aux, pin, lindex; 172 struct mp_intr_map *mpi; 173 ACPI_MADT_NMI_SOURCE *ioapic_nmi; 174 ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi; 175 ACPI_MADT_INTERRUPT_OVERRIDE *isa_ovr; 176 ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi; 177 struct pic *pic; 178 extern struct acpi_softc *acpi_softc; /* XXX */ 179 180 switch (hdrp->Type) { 181 case ACPI_MADT_TYPE_NMI_SOURCE: 182 ioapic_nmi = (ACPI_MADT_NMI_SOURCE *)hdrp; 183 pic = intr_findpic(ioapic_nmi->GlobalIrq); 184 if (pic == NULL) 185 break; 186#if NIOAPIC == 0 187 if (pic->pic_type == PIC_IOAPIC) 188 break; 189#endif 190 mpi = &mp_intrs[*index]; 191 (*index)++; 192 mpi->next = NULL; 193 mpi->bus = NULL; 194 mpi->type = MPS_INTTYPE_NMI; 195 mpi->ioapic = pic; 196 pin = ioapic_nmi->GlobalIrq - pic->pic_vecbase; 197 mpi->ioapic_pin = pin; 198 mpi->bus_pin = -1; 199 mpi->redir = (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT); 200#if NIOAPIC > 0 201 if (pic->pic_type == PIC_IOAPIC) { 202 pic->pic_ioapic->sc_pins[pin].ip_map = mpi; 203 mpi->ioapic_ih = APIC_INT_VIA_APIC | 204 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 205 (pin << APIC_INT_PIN_SHIFT); 206 } else 207#endif 208 mpi->ioapic_ih = pin; 209 mpi->flags = ioapic_nmi->IntiFlags; 210 mpi->global_int = ioapic_nmi->GlobalIrq; 211 break; 212 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 213 lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)hdrp; 214 mpi = &mp_intrs[*index]; 215 (*index)++; 216 mpi->next = NULL; 217 mpi->bus = NULL; 218 mpi->ioapic = NULL; 219 mpi->type = MPS_INTTYPE_NMI; 220 mpi->ioapic_pin = lapic_nmi->Lint; 221 mpi->cpu_id = lapic_nmi->ProcessorId; 222 mpi->redir = (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT); 223 mpi->global_int = -1; 224 break; 225 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 226 isa_ovr = (ACPI_MADT_INTERRUPT_OVERRIDE *)hdrp; 227 if (mp_verbose) { 228 printf("mpacpi: ISA interrupt override %d -> %d (%d/%d)\n", 229 isa_ovr->SourceIrq, isa_ovr->GlobalIrq, 230 isa_ovr->IntiFlags & ACPI_MADT_POLARITY_MASK, 231 (isa_ovr->IntiFlags & ACPI_MADT_TRIGGER_MASK) >> 2); 232 } 233 if (isa_ovr->SourceIrq > 15 || isa_ovr->SourceIrq == 2 || 234 (isa_ovr->SourceIrq == 0 && isa_ovr->GlobalIrq == 2 && 235 (acpi_softc->sc_quirks & ACPI_QUIRK_IRQ0))) 236 break; 237 pic = intr_findpic(isa_ovr->GlobalIrq); 238 if (pic == NULL) 239 break; 240#if NIOAPIC == 0 241 if (pic->pic_type == PIC_IOAPIC) 242 break; 243#endif 244 pin = isa_ovr->GlobalIrq - pic->pic_vecbase; 245 lindex = isa_ovr->SourceIrq; 246 /* 247 * IRQ 2 was skipped in the default setup. 248 */ 249 if (lindex > 2) 250 lindex--; 251 mpi = &mp_intrs[lindex]; 252#if NIOAPIC > 0 253 if (pic->pic_type == PIC_IOAPIC) { 254 mpi->ioapic_ih = APIC_INT_VIA_APIC | 255 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 256 (pin << APIC_INT_PIN_SHIFT); 257 } else 258#endif 259 mpi->ioapic_ih = pin; 260 mpi->bus_pin = isa_ovr->SourceIrq; 261 mpi->ioapic = (struct pic *)pic; 262 mpi->ioapic_pin = pin; 263 mpi->sflags |= MPI_OVR; 264 mpi->redir = 0; 265 mpi->global_int = isa_ovr->GlobalIrq; 266 switch (isa_ovr->IntiFlags & ACPI_MADT_POLARITY_MASK) { 267 case ACPI_MADT_POLARITY_ACTIVE_HIGH: 268 mpi->redir &= ~IOAPIC_REDLO_ACTLO; 269 break; 270 case ACPI_MADT_POLARITY_ACTIVE_LOW: 271 mpi->redir |= IOAPIC_REDLO_ACTLO; 272 break; 273 case ACPI_MADT_POLARITY_CONFORMS: 274 if (isa_ovr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 275 mpi->redir |= IOAPIC_REDLO_ACTLO; 276 else 277 mpi->redir &= ~IOAPIC_REDLO_ACTLO; 278 break; 279 } 280 mpi->redir |= (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT); 281 switch (isa_ovr->IntiFlags & ACPI_MADT_TRIGGER_MASK) { 282 case ACPI_MADT_TRIGGER_LEVEL: 283 mpi->redir |= IOAPIC_REDLO_LEVEL; 284 break; 285 case ACPI_MADT_TRIGGER_EDGE: 286 mpi->redir &= ~IOAPIC_REDLO_LEVEL; 287 break; 288 case ACPI_MADT_TRIGGER_CONFORMS: 289 if (isa_ovr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 290 mpi->redir |= IOAPIC_REDLO_LEVEL; 291 else 292 mpi->redir &= ~IOAPIC_REDLO_LEVEL; 293 break; 294 } 295 mpi->flags = isa_ovr->IntiFlags; 296#if NIOAPIC > 0 297 if (pic->pic_type == PIC_IOAPIC) 298 pic->pic_ioapic->sc_pins[pin].ip_map = mpi; 299#endif 300 break; 301 302 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 303 x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)hdrp; 304 305 mpi = &mp_intrs[*index]; 306 (*index)++; 307 mpi->next = NULL; 308 mpi->bus = NULL; 309 mpi->ioapic = NULL; 310 mpi->type = MPS_INTTYPE_NMI; 311 mpi->ioapic_pin = x2apic_nmi->Lint; 312 mpi->cpu_id = x2apic_nmi->Uid; 313 mpi->redir = (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT); 314 mpi->global_int = -1; 315 break; 316 317 default: 318 break; 319 } 320 return AE_OK; 321} 322 323/* 324 * Count various MP resources present in the MADT. 325 * This is a callback function for acpi_madt_walk(). 326 */ 327static ACPI_STATUS 328mpacpi_count(ACPI_SUBTABLE_HEADER *hdrp, void *aux) 329{ 330 ACPI_MADT_LOCAL_APIC_OVERRIDE *lop; 331 332 switch (hdrp->Type) { 333 case ACPI_MADT_TYPE_LOCAL_APIC: 334 case ACPI_MADT_TYPE_LOCAL_X2APIC: 335 mpacpi_ncpu++; 336 break; 337 case ACPI_MADT_TYPE_IO_APIC: 338 mpacpi_nioapic++; 339 break; 340 case ACPI_MADT_TYPE_NMI_SOURCE: 341 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 342 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 343 mpacpi_nintsrc++; 344 break; 345 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: 346 lop = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)hdrp; 347 mpacpi_lapic_base = lop->Address; 348 default: 349 break; 350 } 351 return AE_OK; 352} 353 354static ACPI_STATUS 355mpacpi_config_cpu(ACPI_SUBTABLE_HEADER *hdrp, void *aux) 356{ 357 device_t parent = aux; 358 ACPI_MADT_LOCAL_APIC *lapic; 359 ACPI_MADT_LOCAL_X2APIC *x2apic; 360 struct cpu_attach_args caa; 361 int cpunum = 0; 362 int locs[CPUBUSCF_NLOCS]; 363 364#if defined(MULTIPROCESSOR) || defined(IOAPIC) 365 if (mpacpi_ncpu > 1) 366 cpunum = lapic_cpu_number(); 367#endif 368 369 switch (hdrp->Type) { 370 case ACPI_MADT_TYPE_LOCAL_APIC: 371 lapic = (ACPI_MADT_LOCAL_APIC *)hdrp; 372 if (lapic->LapicFlags & ACPI_MADT_ENABLED) { 373 if (lapic->Id != cpunum) 374 caa.cpu_role = CPU_ROLE_AP; 375 else 376 caa.cpu_role = CPU_ROLE_BP; 377 caa.cpu_id = lapic->ProcessorId; 378 caa.cpu_number = lapic->Id; 379 caa.cpu_func = &mp_cpu_funcs; 380 locs[CPUBUSCF_APID] = caa.cpu_number; 381 config_found_sm_loc(parent, "cpubus", locs, 382 &caa, mpacpi_cpuprint, config_stdsubmatch); 383 } 384 break; 385 386 case ACPI_MADT_TYPE_LOCAL_X2APIC: 387 x2apic = (ACPI_MADT_LOCAL_X2APIC *)hdrp; 388 389 /* ACPI spec: "Logical processors with APIC ID values 390 * less than 255 must use the Processor Local APIC 391 * structure to convey their APIC information to OSPM." 392 */ 393 if (x2apic->LocalApicId <= 0xff) { 394 printf("bogus MADT X2APIC entry (id = 0x%"PRIx32")\n", 395 x2apic->LocalApicId); 396 break; 397 } 398 399 if (x2apic->LapicFlags & ACPI_MADT_ENABLED) { 400 if (x2apic->LocalApicId != cpunum) 401 caa.cpu_role = CPU_ROLE_AP; 402 else 403 caa.cpu_role = CPU_ROLE_BP; 404 caa.cpu_id = x2apic->Uid; 405 caa.cpu_number = x2apic->LocalApicId; 406 caa.cpu_func = &mp_cpu_funcs; 407 locs[CPUBUSCF_APID] = caa.cpu_number; 408 config_found_sm_loc(parent, "cpubus", locs, 409 &caa, mpacpi_cpuprint, config_stdsubmatch); 410 } 411 break; 412 413 } 414 return AE_OK; 415} 416 417static ACPI_STATUS 418mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *hdrp, void *aux) 419{ 420 device_t parent = aux; 421 struct apic_attach_args aaa; 422 ACPI_MADT_IO_APIC *p; 423 int locs[IOAPICBUSCF_NLOCS]; 424 425 if (hdrp->Type == ACPI_MADT_TYPE_IO_APIC) { 426 p = (ACPI_MADT_IO_APIC *)hdrp; 427 aaa.apic_id = p->Id; 428 aaa.apic_address = p->Address; 429 aaa.apic_version = -1; 430 aaa.flags = IOAPIC_VWIRE; 431 aaa.apic_vecbase = p->GlobalIrqBase; 432 locs[IOAPICBUSCF_APID] = aaa.apic_id; 433 config_found_sm_loc(parent, "ioapicbus", locs, &aaa, 434 mpacpi_ioapicprint, config_stdsubmatch); 435 } 436 return AE_OK; 437} 438 439int 440mpacpi_scan_apics(device_t self, int *ncpup) 441{ 442 int rv = 0; 443 444 if (acpi_madt_map() != AE_OK) 445 return 0; 446 447 mpacpi_ncpu = mpacpi_nintsrc = mpacpi_nioapic = 0; 448 acpi_madt_walk(mpacpi_count, self); 449 450#if NLAPIC > 0 451 lapic_boot_init(mpacpi_lapic_base); 452#endif 453 454 acpi_madt_walk(mpacpi_config_cpu, self); 455 456 if (mpacpi_ncpu == 0) 457 goto done; 458 459 acpi_madt_walk(mpacpi_config_ioapic, self); 460 461#if NPCI > 0 462 /* 463 * If PCI routing tables can't be built we report failure 464 * and let MPBIOS do the work. 465 */ 466 if (!mpacpi_force && 467 (acpi_find_quirks() & (ACPI_QUIRK_BADPCI)) != 0) 468 goto done; 469#endif 470 rv = 1; 471done: 472 *ncpup = mpacpi_ncpu; 473 acpi_madt_unmap(); 474 return rv; 475} 476 477#if NPCI > 0 478 479static void 480mpacpi_pci_foundbus(struct acpi_devnode *ad) 481{ 482 struct mpacpi_pcibus *mpr; 483 ACPI_BUFFER buf; 484 int rv; 485 486 /* 487 * set mpr_buf from _PRT (if it exists). 488 * set mpr_seg and mpr_bus from previously cached info. 489 */ 490 491 rv = acpi_get(ad->ad_handle, &buf, AcpiGetIrqRoutingTable); 492 if (ACPI_FAILURE(rv)) { 493 buf.Length = 0; 494 buf.Pointer = NULL; 495 } 496 497 mpr = kmem_zalloc(sizeof(struct mpacpi_pcibus), KM_SLEEP); 498 if ((ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) { 499 if (mp_verbose) 500 printf("mpacpi: found root PCI bus %d\n", 501 mpr->mpr_bus); 502 mpacpi_npciroots++; 503 } else { 504 if (mp_verbose) 505 printf("mpacpi: found subordinate bus %d\n", 506 mpr->mpr_bus); 507 } 508 509 mpr->mpr_handle = ad->ad_handle; 510 mpr->mpr_buf = buf; 511 mpr->mpr_seg = ad->ad_pciinfo->ap_segment; 512 mpr->mpr_bus = ad->ad_pciinfo->ap_downbus; 513 TAILQ_INSERT_TAIL(&mpacpi_pcibusses, mpr, mpr_list); 514 515 /* 516 * XXX this wrongly assumes that bus numbers are unique 517 * even between segments. 518 */ 519 if (mpr->mpr_bus > mpacpi_maxpci) 520 mpacpi_maxpci = mpr->mpr_bus; 521 522 mpacpi_npci++; 523} 524 525 526static void 527mpacpi_pci_walk(struct acpi_devnode *ad) 528{ 529 struct acpi_devnode *child; 530 531 if (ad->ad_pciinfo && 532 (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) != 0) { 533 mpacpi_pci_foundbus(ad); 534 } 535 SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list) { 536 mpacpi_pci_walk(child); 537 } 538} 539 540static int 541mpacpi_find_pcibusses(struct acpi_softc *sc) 542{ 543 544 TAILQ_INIT(&mpacpi_pcibusses); 545 mpacpi_pci_walk(sc->sc_root); 546 return 0; 547} 548 549/* 550 * Find all static PRT entries for a PCI bus. 551 */ 552static int 553mpacpi_pciroute(struct mpacpi_pcibus *mpr) 554{ 555 ACPI_PCI_ROUTING_TABLE *ptrp; 556 ACPI_HANDLE linkdev; 557 char *p; 558 struct mp_intr_map *mpi, *iter; 559 struct mp_bus *mpb; 560 struct pic *pic; 561 unsigned dev; 562 int pin; 563 564 if (mp_verbose) 565 printf("mpacpi: configuring PCI bus %d int routing\n", 566 mpr->mpr_bus); 567 568 mpb = &mp_busses[mpr->mpr_bus]; 569 570 if (mpb->mb_name != NULL) 571 printf("mpacpi: PCI bus %d int routing already done!\n", 572 mpr->mpr_bus); 573 574 mpb->mb_intrs = NULL; 575 mpb->mb_name = "pci"; 576 mpb->mb_idx = mpr->mpr_bus; 577 mpb->mb_intr_print = mpacpi_print_pci_intr; 578 mpb->mb_intr_cfg = NULL; 579 mpb->mb_data = 0; 580 581 if (mpr->mpr_buf.Length == 0) { 582 goto out; 583 } 584 585 for (p = mpr->mpr_buf.Pointer; ; p += ptrp->Length) { 586 ptrp = (ACPI_PCI_ROUTING_TABLE *)p; 587 if (ptrp->Length == 0) 588 break; 589 dev = ACPI_HIWORD(ptrp->Address); 590 591 if (ptrp->Source[0] == 0 && 592 (ptrp->SourceIndex == 14 || ptrp->SourceIndex == 15)) { 593 printf("Skipping PCI routing entry for PCI IDE compat IRQ"); 594 continue; 595 } 596 597 mpi = &mp_intrs[mpacpi_intr_index]; 598 mpi->bus_pin = (dev << 2) | (ptrp->Pin & 3); 599 mpi->bus = mpb; 600 mpi->type = MPS_INTTYPE_INT; 601 602 /* 603 * First check if an entry for this device/pin combination 604 * was already found. Some DSDTs have more than one entry 605 * and it seems that the first is generally the right one. 606 */ 607 for (iter = mpb->mb_intrs; iter != NULL; iter = iter->next) { 608 if (iter->bus_pin == mpi->bus_pin) 609 break; 610 } 611 if (iter != NULL) 612 continue; 613 614 ++mpacpi_intr_index; 615 616 if (ptrp->Source[0] != 0) { 617 if (mp_verbose > 1) 618 printf("pciroute: dev %d INT%c on lnkdev %s\n", 619 dev, 'A' + (ptrp->Pin & 3), ptrp->Source); 620 mpi->global_int = -1; 621 mpi->sourceindex = ptrp->SourceIndex; 622 if (AcpiGetHandle(ACPI_ROOT_OBJECT, ptrp->Source, 623 &linkdev) != AE_OK) { 624 printf("AcpiGetHandle failed for '%s'\n", 625 ptrp->Source); 626 continue; 627 } 628 /* acpi_allocate_resources(linkdev); */ 629 mpi->ioapic_pin = -1; 630 mpi->linkdev = acpi_pci_link_devbyhandle(linkdev); 631 acpi_pci_link_add_reference(mpi->linkdev, 0, 632 mpr->mpr_bus, dev, ptrp->Pin & 3); 633 mpi->ioapic = NULL; 634 mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2); 635 if (mp_verbose > 1) 636 printf("pciroute: done adding entry\n"); 637 } else { 638 if (mp_verbose > 1) 639 printf("pciroute: dev %d INT%c on globint %d\n", 640 dev, 'A' + (ptrp->Pin & 3), 641 ptrp->SourceIndex); 642 mpi->sourceindex = 0; 643 mpi->global_int = ptrp->SourceIndex; 644 pic = intr_findpic(ptrp->SourceIndex); 645 if (pic == NULL) 646 continue; 647 /* Defaults for PCI (active low, level triggered) */ 648 mpi->redir = 649 (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT) | 650 IOAPIC_REDLO_LEVEL | IOAPIC_REDLO_ACTLO; 651 mpi->ioapic = pic; 652 pin = ptrp->SourceIndex - pic->pic_vecbase; 653 if (pic->pic_type == PIC_I8259 && pin > 15) 654 panic("bad pin %d for legacy IRQ", pin); 655 mpi->ioapic_pin = pin; 656#if NIOAPIC > 0 657 if (pic->pic_type == PIC_IOAPIC) { 658 pic->pic_ioapic->sc_pins[pin].ip_map = mpi; 659 mpi->ioapic_ih = APIC_INT_VIA_APIC | 660 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 661 (pin << APIC_INT_PIN_SHIFT); 662 } else 663#endif 664 mpi->ioapic_ih = pin; 665 mpi->linkdev = NULL; 666 mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2); 667 if (mp_verbose > 1) 668 printf("pciroute: done adding entry\n"); 669 } 670 671 mpi->cpu_id = 0; 672 673 mpi->next = mpb->mb_intrs; 674 mpb->mb_intrs = mpi; 675 } 676 677 ACPI_FREE(mpr->mpr_buf.Pointer); 678 mpr->mpr_buf.Pointer = NULL; /* be preventive to bugs */ 679 680out: 681 if (mp_verbose > 1) 682 printf("pciroute: done\n"); 683 684 return 0; 685} 686 687/* 688 * Count number of elements in _PRT 689 */ 690static int 691mpacpi_pcircount(struct mpacpi_pcibus *mpr) 692{ 693 int count = 0; 694 ACPI_PCI_ROUTING_TABLE *PrtElement; 695 uint8_t *Buffer; 696 697 if (mpr->mpr_buf.Length == 0) { 698 return 0; 699 } 700 701 for (Buffer = mpr->mpr_buf.Pointer;; Buffer += PrtElement->Length) { 702 PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer; 703 if (PrtElement->Length == 0) 704 break; 705 count++; 706 } 707 708 return count; 709} 710#endif 711 712/* 713 * Set up the interrupt config lists, in the same format as the mpbios does. 714 */ 715static void 716mpacpi_config_irouting(struct acpi_softc *acpi) 717{ 718#if NPCI > 0 719 struct mpacpi_pcibus *mpr; 720#endif 721 int nintr; 722 int i; 723 struct mp_bus *mbp; 724 struct mp_intr_map *mpi; 725 struct pic *pic; 726 727 nintr = mpacpi_nintsrc + NUM_LEGACY_IRQS - 1; 728#if NPCI > 0 729 TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) { 730 nintr += mpacpi_pcircount(mpr); 731 } 732 733 mp_isa_bus = mpacpi_maxpci + BUS_BUFFER; /* XXX */ 734#else 735 mp_isa_bus = 0; 736#endif 737 mp_nbus = mp_isa_bus + 1; 738 mp_nintr = nintr; 739 740 mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus, KM_SLEEP); 741 if (mp_busses == NULL) 742 panic("can't allocate mp_busses"); 743 744 mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * mp_nintr, KM_SLEEP); 745 if (mp_intrs == NULL) 746 panic("can't allocate mp_intrs"); 747 748 mbp = &mp_busses[mp_isa_bus]; 749 mbp->mb_name = "isa"; 750 mbp->mb_idx = 0; 751 mbp->mb_intr_print = mpacpi_print_isa_intr; 752 mbp->mb_intr_cfg = NULL; 753 mbp->mb_intrs = &mp_intrs[0]; 754 mbp->mb_data = 0; 755 756 pic = intr_findpic(0); 757 if (pic == NULL) 758 panic("mpacpi: can't find first PIC"); 759#if NIOAPIC == 0 760 if (pic->pic_type == PIC_IOAPIC) 761 panic("mpacpi: ioapic but no i8259?"); 762#endif 763 764 /* 765 * Set up default identity mapping for ISA irqs to first ioapic. 766 */ 767 for (i = mpacpi_intr_index = 0; i < NUM_LEGACY_IRQS; i++) { 768 if (i == 2) 769 continue; 770 mpi = &mp_intrs[mpacpi_intr_index]; 771 if (mpacpi_intr_index < (NUM_LEGACY_IRQS - 2)) 772 mpi->next = &mp_intrs[mpacpi_intr_index + 1]; 773 else 774 mpi->next = NULL; 775 mpi->bus = mbp; 776 mpi->bus_pin = i; 777 mpi->ioapic_pin = i; 778 mpi->ioapic = pic; 779 mpi->type = MPS_INTTYPE_INT; 780 mpi->cpu_id = 0; 781 mpi->redir = 0; 782#if NIOAPIC > 0 783 if (pic->pic_type == PIC_IOAPIC) { 784 mpi->ioapic_ih = APIC_INT_VIA_APIC | 785 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 786 (i << APIC_INT_PIN_SHIFT); 787 mpi->redir = 788 (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT); 789 pic->pic_ioapic->sc_pins[i].ip_map = mpi; 790 } else 791#endif 792 mpi->ioapic_ih = i; 793 794 mpi->flags = MPS_INTPO_DEF | (MPS_INTTR_DEF << 2); 795 mpi->global_int = i; 796 mpacpi_intr_index++; 797 } 798 799 mpacpi_user_continue("done setting up mp_bus array and ISA maps"); 800 801 if (acpi_madt_map() == AE_OK) { 802 acpi_madt_walk(mpacpi_nonpci_intr, &mpacpi_intr_index); 803 acpi_madt_unmap(); 804 } 805 806 mpacpi_user_continue("done with non-PCI interrupts"); 807 808#if NPCI > 0 809 TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) { 810 mpacpi_pciroute(mpr); 811 } 812#endif 813 814 mpacpi_user_continue("done routing PCI interrupts"); 815 816 mp_nintr = mpacpi_intr_index; 817} 818 819/* 820 * XXX code duplication with mpbios.c 821 */ 822 823#if NPCI > 0 824static void 825mpacpi_print_pci_intr(int intr) 826{ 827 printf(" device %d INT_%c", (intr>>2)&0x1f, 'A' + (intr & 0x3)); 828} 829#endif 830 831static void 832mpacpi_print_isa_intr(int intr) 833{ 834 printf(" irq %d", intr); 835} 836 837static const char inttype_fmt[] = "\177\020" 838 "f\0\2type\0" "=\1NMI\0" "=\2SMI\0" "=\3ExtINT\0"; 839 840static const char flagtype_fmt[] = "\177\020" 841 "f\0\2pol\0" "=\1Act Hi\0" "=\3Act Lo\0" 842 "f\2\2trig\0" "=\1Edge\0" "=\3Level\0"; 843 844static void 845mpacpi_print_intr(struct mp_intr_map *mpi) 846{ 847 char buf[256]; 848 int pin; 849 struct pic *sc; 850 const char *busname; 851 852 sc = mpi->ioapic; 853 pin = mpi->ioapic_pin; 854 if (mpi->bus != NULL) 855 busname = mpi->bus->mb_name; 856 else { 857 switch (mpi->type) { 858 case MPS_INTTYPE_NMI: 859 busname = "NMI"; 860 break; 861 case MPS_INTTYPE_SMI: 862 busname = "SMI"; 863 break; 864 case MPS_INTTYPE_ExtINT: 865 busname = "ExtINT"; 866 break; 867 default: 868 busname = "<unknown>"; 869 break; 870 } 871 } 872 873 if (mpi->linkdev != NULL) 874 printf("linkdev %s attached to %s", 875 acpi_pci_link_name(mpi->linkdev), busname); 876 else 877 printf("%s: pin %d attached to %s", 878 sc ? sc->pic_name : "local apic", 879 pin, busname); 880 881 if (mpi->bus != NULL) { 882 if (mpi->bus->mb_idx != -1) 883 printf("%d", mpi->bus->mb_idx); 884 (*(mpi->bus->mb_intr_print))(mpi->bus_pin); 885 } 886 snprintb(buf, sizeof(buf), inttype_fmt, mpi->type); 887 printf(" (type %s", buf); 888 889 snprintb(buf, sizeof(buf), flagtype_fmt, mpi->flags); 890 printf(" flags %s)\n", buf); 891 892} 893 894 895int 896mpacpi_find_interrupts(void *self) 897{ 898#if NIOAPIC > 0 899 ACPI_STATUS rv; 900#endif 901 struct acpi_softc *acpi = self; 902 int i; 903 904#ifdef MPBIOS 905 /* 906 * If MPBIOS was enabled, and did the work (because the initial 907 * MADT scan failed for some reason), there's nothing left to 908 * do here. Same goes for the case where no I/O APICS were found. 909 */ 910 if (mpbios_scanned) 911 return 0; 912#endif 913 914#if NIOAPIC > 0 915 if (mpacpi_nioapic != 0) { 916 /* 917 * Switch us into APIC mode by evaluating _PIC(1). 918 * Needs to be done now, since it has an effect on 919 * the interrupt information we're about to retrieve. 920 * 921 * ACPI 3.0 (section 5.8.1): 922 * 0 = PIC mode, 1 = APIC mode, 2 = SAPIC mode. 923 */ 924 rv = acpi_eval_set_integer(NULL, "\\_PIC", 1); 925 if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) { 926 if (mp_verbose) 927 printf("mpacpi: switch to APIC mode failed\n"); 928 return 0; 929 } 930 } 931#endif 932 933#if NPCI > 0 934 mpacpi_user_continue("finding PCI busses "); 935 mpacpi_find_pcibusses(acpi); 936 if (mp_verbose) 937 printf("mpacpi: %d PCI busses\n", mpacpi_npci); 938#endif 939 mpacpi_config_irouting(acpi); 940 if (mp_verbose) 941 for (i = 0; i < mp_nintr; i++) 942 mpacpi_print_intr(&mp_intrs[i]); 943 return 0; 944} 945 946#if NPCI > 0 947 948int 949mpacpi_pci_attach_hook(device_t parent, device_t self, 950 struct pcibus_attach_args *pba) 951{ 952 struct mp_bus *mpb; 953 954#ifdef MPBIOS 955 if (mpbios_scanned != 0) 956 return ENOENT; 957#endif 958 959 if (TAILQ_EMPTY(&mpacpi_pcibusses)) 960 return 0; 961 962 /* 963 * If this bus is not found in mpacpi_find_pcibusses 964 * (i.e. behind PCI-to-PCI bridge), register as an extra bus. 965 * 966 * at this point, mp_busses[] are as follows: 967 * mp_busses[0 .. mpacpi_maxpci] : PCI 968 * mp_busses[mpacpi_maxpci + BUS_BUFFER] : ISA 969 */ 970 if (pba->pba_bus >= mp_isa_bus) { 971 intr_add_pcibus(pba); 972 return 0; 973 } 974 975 mpb = &mp_busses[pba->pba_bus]; 976 if (mpb->mb_name != NULL) { 977 if (strcmp(mpb->mb_name, "pci")) 978 return EINVAL; 979 } else 980 /* 981 * As we cannot find all PCI-to-PCI bridge in 982 * mpacpi_find_pcibusses, some of the MP_busses may remain 983 * uninitialized. 984 */ 985 mpb->mb_name = "pci"; 986 987 mpb->mb_dev = self; 988 mpb->mb_pci_bridge_tag = pba->pba_bridgetag; 989 mpb->mb_pci_chipset_tag = pba->pba_pc; 990 991 if (mp_verbose) 992 printf("\n%s: added to list as bus %d", device_xname(parent), 993 pba->pba_bus); 994 995 996 if (pba->pba_bus > mpacpi_maxpci) 997 mpacpi_maxpci = pba->pba_bus; 998 999 return 0; 1000} 1001#endif 1002 1003int 1004mpacpi_findintr_linkdev(struct mp_intr_map *mip) 1005{ 1006 int irq, line, pol, trig; 1007 struct pic *pic; 1008 int pin; 1009 1010 if (mip->linkdev == NULL) 1011 return ENOENT; 1012 1013 irq = acpi_pci_link_route_interrupt(mip->linkdev, mip->sourceindex, 1014 &line, &pol, &trig); 1015 if (mp_verbose) 1016 printf("linkdev %s returned ACPI global irq %d, line %d\n", 1017 acpi_pci_link_name(mip->linkdev), irq, line); 1018 if (irq == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) 1019 return ENOENT; 1020 if (irq != line) { 1021 aprint_error("%s: mpacpi_findintr_linkdev:" 1022 " irq mismatch (%d vs %d)\n", 1023 acpi_pci_link_name(mip->linkdev), irq, line); 1024 return ENOENT; 1025 } 1026 1027 /* 1028 * Convert ACPICA values to MPS values 1029 */ 1030 if (pol == ACPI_ACTIVE_LOW) 1031 pol = MPS_INTPO_ACTLO; 1032 else 1033 pol = MPS_INTPO_ACTHI; 1034 1035 if (trig == ACPI_EDGE_SENSITIVE) 1036 trig = MPS_INTTR_EDGE; 1037 else 1038 trig = MPS_INTTR_LEVEL; 1039 1040 mip->flags = pol | (trig << 2); 1041 mip->global_int = irq; 1042 pic = intr_findpic(irq); 1043 if (pic == NULL) 1044 return ENOENT; 1045 mip->ioapic = pic; 1046 pin = irq - pic->pic_vecbase; 1047 1048 if (pic->pic_type == PIC_IOAPIC) { 1049#if NIOAPIC > 0 1050 mip->redir = (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT); 1051 if (pol == MPS_INTPO_ACTLO) 1052 mip->redir |= IOAPIC_REDLO_ACTLO; 1053 if (trig == MPS_INTTR_LEVEL) 1054 mip->redir |= IOAPIC_REDLO_LEVEL; 1055 mip->ioapic_ih = APIC_INT_VIA_APIC | 1056 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 1057 (pin << APIC_INT_PIN_SHIFT); 1058 pic->pic_ioapic->sc_pins[pin].ip_map = mip; 1059 mip->ioapic_pin = pin; 1060#else 1061 return ENOENT; 1062#endif 1063 } else 1064 mip->ioapic_ih = pin; 1065 return 0; 1066} 1067 1068static void 1069mpacpi_user_continue(const char *fmt, ...) 1070{ 1071 va_list ap; 1072 1073 if (!mpacpi_step) 1074 return; 1075 1076 printf("mpacpi: "); 1077 va_start(ap, fmt); 1078 vprintf(fmt, ap); 1079 va_end(ap); 1080 printf("<press any key to continue>\n>"); 1081 cngetc(); 1082} 1083