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