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