1/* $NetBSD: acpi_pci_machdep.c,v 1.22 2022/08/13 20:07:13 jmcneill Exp $ */ 2 3/*- 4 * Copyright (c) 2018, 2020 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jared McNeill <jmcneill@invisible.ca>. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include "opt_pci.h" 33 34#define _INTR_PRIVATE 35 36#include <sys/cdefs.h> 37__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.22 2022/08/13 20:07:13 jmcneill Exp $"); 38 39#include <sys/param.h> 40#include <sys/bus.h> 41#include <sys/device.h> 42#include <sys/intr.h> 43#include <sys/systm.h> 44#include <sys/kernel.h> 45#include <sys/queue.h> 46#include <sys/mutex.h> 47#include <sys/kmem.h> 48#include <sys/cpu.h> 49 50#include <arm/cpufunc.h> 51 52#include <arm/pic/picvar.h> 53 54#include <dev/pci/pcireg.h> 55#include <dev/pci/pcivar.h> 56#include <dev/pci/pciconf.h> 57 58#include <dev/acpi/acpivar.h> 59#include <dev/acpi/acpi_mcfg.h> 60#include <dev/acpi/acpi_pci.h> 61 62#include <arm/acpi/acpi_iort.h> 63#include <arm/acpi/acpi_pci_machdep.h> 64 65#ifdef PCI_SMCCC 66#include <arm/pci/pci_smccc.h> 67#endif 68 69#include <arm/pci/pci_msi_machdep.h> 70 71struct acpi_pci_prt { 72 u_int prt_segment; 73 u_int prt_bus; 74 u_int prt_bridge_dev; 75 bool prt_derived; 76 ACPI_HANDLE prt_handle; 77 TAILQ_ENTRY(acpi_pci_prt) prt_list; 78}; 79 80static TAILQ_HEAD(, acpi_pci_prt) acpi_pci_irq_routes = 81 TAILQ_HEAD_INITIALIZER(acpi_pci_irq_routes); 82 83struct acpi_pci_pct { 84 struct acpi_pci_context pct_ap; 85 TAILQ_ENTRY(acpi_pci_pct) pct_list; 86}; 87 88static TAILQ_HEAD(, acpi_pci_pct) acpi_pci_chipset_tags = 89 TAILQ_HEAD_INITIALIZER(acpi_pci_chipset_tags); 90 91struct acpi_pci_intr { 92 struct pic_softc pi_pic; 93 int pi_irqbase; 94 int pi_irq; 95 uint32_t pi_unblocked; 96 void *pi_ih; 97 TAILQ_ENTRY(acpi_pci_intr) pi_list; 98}; 99 100static TAILQ_HEAD(, acpi_pci_intr) acpi_pci_intrs = 101 TAILQ_HEAD_INITIALIZER(acpi_pci_intrs); 102 103static const struct acpi_pci_quirk acpi_pci_mcfg_quirks[] = { 104 /* OEM ID OEM Table ID Revision Seg Func */ 105 { "AMAZON", "GRAVITON", 0, -1, acpi_pci_graviton_init }, 106 { "ARMLTD", "ARMN1SDP", 0x20181101, 0, acpi_pci_n1sdp_init }, 107 { "ARMLTD", "ARMN1SDP", 0x20181101, 1, acpi_pci_n1sdp_init }, 108 { "NXP ", "LX2160 ", 0, -1, acpi_pci_layerscape_gen4_init }, 109}; 110 111#ifdef PCI_SMCCC 112static const struct acpi_pci_quirk acpi_pci_smccc_quirk = { 113 .q_segment = -1, 114 .q_init = acpi_pci_smccc_init, 115}; 116#endif 117 118pci_chipset_tag_t acpi_pci_md_get_chipset_tag(struct acpi_softc *, int, int); 119 120static void acpi_pci_md_attach_hook(device_t, device_t, 121 struct pcibus_attach_args *); 122static int acpi_pci_md_bus_maxdevs(void *, int); 123static pcitag_t acpi_pci_md_make_tag(void *, int, int, int); 124static void acpi_pci_md_decompose_tag(void *, pcitag_t, int *, int *, int *); 125static u_int acpi_pci_md_get_segment(void *); 126static uint32_t acpi_pci_md_get_devid(void *, uint32_t); 127static uint32_t acpi_pci_md_get_frameid(void *, uint32_t); 128static pcireg_t acpi_pci_md_conf_read(void *, pcitag_t, int); 129static void acpi_pci_md_conf_write(void *, pcitag_t, int, pcireg_t); 130static int acpi_pci_md_conf_hook(void *, int, int, int, pcireg_t); 131static void acpi_pci_md_conf_interrupt(void *, int, int, int, int, int *); 132 133static int acpi_pci_md_intr_map(const struct pci_attach_args *, 134 pci_intr_handle_t *); 135static const char *acpi_pci_md_intr_string(void *, pci_intr_handle_t, 136 char *, size_t); 137static const struct evcnt *acpi_pci_md_intr_evcnt(void *, pci_intr_handle_t); 138static int acpi_pci_md_intr_setattr(void *, pci_intr_handle_t *, int, 139 uint64_t); 140static void * acpi_pci_md_intr_establish(void *, pci_intr_handle_t, 141 int, int (*)(void *), void *, 142 const char *); 143static void acpi_pci_md_intr_disestablish(void *, void *); 144 145struct arm32_pci_chipset arm_acpi_pci_chipset = { 146 .pc_attach_hook = acpi_pci_md_attach_hook, 147 .pc_bus_maxdevs = acpi_pci_md_bus_maxdevs, 148 .pc_make_tag = acpi_pci_md_make_tag, 149 .pc_decompose_tag = acpi_pci_md_decompose_tag, 150 .pc_get_segment = acpi_pci_md_get_segment, 151 .pc_get_devid = acpi_pci_md_get_devid, 152 .pc_get_frameid = acpi_pci_md_get_frameid, 153 .pc_conf_read = acpi_pci_md_conf_read, 154 .pc_conf_write = acpi_pci_md_conf_write, 155 .pc_conf_hook = acpi_pci_md_conf_hook, 156 .pc_conf_interrupt = acpi_pci_md_conf_interrupt, 157 158 .pc_intr_map = acpi_pci_md_intr_map, 159 .pc_intr_string = acpi_pci_md_intr_string, 160 .pc_intr_evcnt = acpi_pci_md_intr_evcnt, 161 .pc_intr_setattr = acpi_pci_md_intr_setattr, 162 .pc_intr_establish = acpi_pci_md_intr_establish, 163 .pc_intr_disestablish = acpi_pci_md_intr_disestablish, 164}; 165 166static ACPI_STATUS 167acpi_pci_md_pci_link(ACPI_HANDLE handle, pci_chipset_tag_t pc, int bus) 168{ 169 ACPI_PCI_ROUTING_TABLE *prt; 170 ACPI_HANDLE linksrc; 171 ACPI_BUFFER buf; 172 ACPI_STATUS rv; 173 void *linkdev; 174 175 rv = acpi_get(handle, &buf, AcpiGetIrqRoutingTable); 176 if (ACPI_FAILURE(rv)) 177 return rv; 178 179 for (char *p = buf.Pointer; ; p += prt->Length) { 180 prt = (ACPI_PCI_ROUTING_TABLE *)p; 181 if (prt->Length == 0) 182 break; 183 184 const u_int dev = ACPI_HIWORD(prt->Address); 185 if (prt->Source[0] != 0) { 186 aprint_debug("ACPI: %s dev %u INT%c on lnkdev %s\n", 187 acpi_name(handle), dev, 'A' + (prt->Pin & 3), prt->Source); 188 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, prt->Source, &linksrc); 189 if (ACPI_FAILURE(rv)) { 190 aprint_debug("ACPI: AcpiGetHandle failed for '%s': %s\n", 191 prt->Source, AcpiFormatException(rv)); 192 continue; 193 } 194 195 linkdev = acpi_pci_link_devbyhandle(linksrc); 196 acpi_pci_link_add_reference(linkdev, pc, 0, bus, dev, prt->Pin & 3); 197 } else { 198 aprint_debug("ACPI: %s dev %u INT%c on globint %d\n", 199 acpi_name(handle), dev, 'A' + (prt->Pin & 3), prt->SourceIndex); 200 } 201 } 202 203 return AE_OK; 204} 205 206static void 207acpi_pci_md_attach_hook(device_t parent, device_t self, 208 struct pcibus_attach_args *pba) 209{ 210 struct acpi_pci_context *ap = pba->pba_pc->pc_conf_v; 211 struct acpi_pci_prt *prt, *prtp; 212 struct acpi_devnode *ad; 213 ACPI_HANDLE handle; 214 int seg, bus, dev, func; 215 u_int bridge_dev = 0; 216 bool derived = false; 217 218 seg = ap->ap_seg; 219 handle = NULL; 220 221 if (pba->pba_bridgetag) { 222 /* 223 * Find the PCI address of our parent bridge and look for the 224 * corresponding ACPI device node. If there is no node for this 225 * bus, use the parent bridge routing information. 226 */ 227 acpi_pci_md_decompose_tag(NULL, *pba->pba_bridgetag, &bus, &dev, &func); 228 ad = acpi_pcidev_find(seg, bus, dev, func); 229 if (ad != NULL) { 230 handle = ad->ad_handle; 231 } else { 232 /* No routes defined for this bus, derive from parent */ 233 TAILQ_FOREACH(prtp, &acpi_pci_irq_routes, prt_list) 234 if (prtp->prt_bus == bus && 235 prtp->prt_segment == seg) { 236 handle = prtp->prt_handle; 237 bridge_dev = dev; 238 derived = true; 239 break; 240 } 241 } 242 } else { 243 /* 244 * Lookup the ACPI device node for the root bus. 245 */ 246 ad = acpi_pciroot_find(seg, 0); 247 if (ad != NULL) 248 handle = ad->ad_handle; 249 } 250 251 if (handle != NULL) { 252 prt = kmem_alloc(sizeof(*prt), KM_SLEEP); 253 prt->prt_bus = pba->pba_bus; 254 prt->prt_segment = seg; 255 prt->prt_handle = handle; 256 prt->prt_bridge_dev = bridge_dev; 257 prt->prt_derived = derived; 258 TAILQ_INSERT_TAIL(&acpi_pci_irq_routes, prt, prt_list); 259 } 260 261 acpimcfg_map_bus(self, pba->pba_pc, pba->pba_bus); 262 263 if (ad != NULL) { 264 /* 265 * This is a new ACPI managed bus. Add PCI link references. 266 */ 267 acpi_pci_md_pci_link(ad->ad_handle, pba->pba_pc, pba->pba_bus); 268 } 269} 270 271static int 272acpi_pci_md_bus_maxdevs(void *v, int busno) 273{ 274 return 32; 275} 276 277static pcitag_t 278acpi_pci_md_make_tag(void *v, int b, int d, int f) 279{ 280 return (b << 16) | (d << 11) | (f << 8); 281} 282 283static void 284acpi_pci_md_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 285{ 286 if (bp) 287 *bp = (tag >> 16) & 0xff; 288 if (dp) 289 *dp = (tag >> 11) & 0x1f; 290 if (fp) 291 *fp = (tag >> 8) & 0x7; 292} 293 294static u_int 295acpi_pci_md_get_segment(void *v) 296{ 297 struct acpi_pci_context * const ap = v; 298 299 return ap->ap_seg; 300} 301 302static uint32_t 303acpi_pci_md_get_devid(void *v, uint32_t devid) 304{ 305 struct acpi_pci_context * const ap = v; 306 307 return acpi_iort_pci_root_map(ap->ap_seg, devid); 308} 309 310static uint32_t 311acpi_pci_md_get_frameid(void *v, uint32_t devid) 312{ 313 struct acpi_pci_context * const ap = v; 314 315 return acpi_iort_its_id_map(ap->ap_seg, devid); 316} 317 318static pcireg_t 319acpi_pci_md_conf_read(void *v, pcitag_t tag, int offset) 320{ 321 struct acpi_pci_context * const ap = v; 322 pcireg_t val; 323 324 if (offset < 0 || offset >= PCI_EXTCONF_SIZE) 325 return (pcireg_t) -1; 326 327 if (ap->ap_conf_read != NULL) 328 ap->ap_conf_read(&ap->ap_pc, tag, offset, &val); 329 else 330 acpimcfg_conf_read(&ap->ap_pc, tag, offset, &val); 331 332 return val; 333} 334 335static void 336acpi_pci_md_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) 337{ 338 struct acpi_pci_context * const ap = v; 339 340 if (offset < 0 || offset >= PCI_EXTCONF_SIZE) 341 return; 342 343 if (ap->ap_conf_write != NULL) 344 ap->ap_conf_write(&ap->ap_pc, tag, offset, val); 345 else 346 acpimcfg_conf_write(&ap->ap_pc, tag, offset, val); 347} 348 349static int 350acpi_pci_md_conf_hook(void *v, int b, int d, int f, pcireg_t id) 351{ 352 return PCI_CONF_DEFAULT; 353} 354 355static void 356acpi_pci_md_conf_interrupt(void *v, int bus, int dev, int ipin, int sqiz, int *ilinep) 357{ 358} 359 360static struct acpi_pci_prt * 361acpi_pci_md_intr_find_prt(pci_chipset_tag_t pc, u_int bus) 362{ 363 struct acpi_pci_prt *prt, *prtp; 364 u_int segment; 365 366 segment = pci_get_segment(pc); 367 368 prt = NULL; 369 TAILQ_FOREACH(prtp, &acpi_pci_irq_routes, prt_list) 370 if (prtp->prt_segment == segment && prtp->prt_bus == bus) { 371 prt = prtp; 372 break; 373 } 374 375 return prt; 376} 377 378static int 379acpi_pci_md_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih) 380{ 381 struct acpi_pci_prt *prt; 382 ACPI_PCI_ROUTING_TABLE *tab; 383 int line, pol, trig, error; 384 ACPI_HANDLE linksrc; 385 ACPI_BUFFER buf; 386 void *linkdev; 387 u_int pin; 388 389 if (pa->pa_intrpin == PCI_INTERRUPT_PIN_NONE) 390 return EINVAL; 391 392 prt = acpi_pci_md_intr_find_prt(pa->pa_pc, pa->pa_bus); 393 if (prt == NULL) 394 return ENXIO; 395 396 if (ACPI_FAILURE(acpi_get(prt->prt_handle, &buf, AcpiGetIrqRoutingTable))) 397 return EIO; 398 399 /* 400 * For busses with no direct _PRT entry, derive the pin from the 401 * parent bridge. 402 */ 403 if (prt->prt_derived) { 404 pin = (((pa->pa_rawintrpin + prt->prt_bridge_dev) - 1) % 4) + 1; 405 } else { 406 pin = pa->pa_intrpin; 407 } 408 409 aprint_debug("%s: bus=%u pin=%u pa_rawintrpin=%u pa_intrpin=%u " 410 "pa_intrswiz=%u prt_bridge_dev=%u\n", 411 __func__, pa->pa_bus, pin, pa->pa_rawintrpin, 412 pa->pa_intrpin, pa->pa_intrswiz, prt->prt_bridge_dev); 413 414 error = ENOENT; 415 for (char *p = buf.Pointer; ; p += tab->Length) { 416 tab = (ACPI_PCI_ROUTING_TABLE *)p; 417 if (tab->Length == 0) 418 break; 419 420 if (pa->pa_device == ACPI_HIWORD(tab->Address) && 421 (pin - 1) == (tab->Pin & 3)) { 422 if (tab->Source[0] != 0) { 423 if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, tab->Source, &linksrc))) 424 goto done; 425 linkdev = acpi_pci_link_devbyhandle(linksrc); 426 *ih = acpi_pci_link_route_interrupt(linkdev, 427 pa->pa_pc, tab->SourceIndex, 428 &line, &pol, &trig); 429 error = 0; 430 goto done; 431 } else { 432 *ih = tab->SourceIndex; 433 error = 0; 434 goto done; 435 } 436 } 437 } 438 439done: 440 ACPI_FREE(buf.Pointer); 441 return error; 442} 443 444static const char * 445acpi_pci_md_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len) 446{ 447 const int irq = __SHIFTOUT(ih, ARM_PCI_INTR_IRQ); 448 const int vec = __SHIFTOUT(ih, ARM_PCI_INTR_MSI_VEC); 449 450 if (ih & ARM_PCI_INTR_MSIX) 451 snprintf(buf, len, "irq %d (MSI-X vec %d)", irq, vec); 452 else if (ih & ARM_PCI_INTR_MSI) 453 snprintf(buf, len, "irq %d (MSI vec %d)", irq, vec); 454 else 455 snprintf(buf, len, "irq %d", irq); 456 457 return buf; 458} 459 460static const struct evcnt * 461acpi_pci_md_intr_evcnt(void *v, pci_intr_handle_t ih) 462{ 463 return NULL; 464} 465 466static int 467acpi_pci_md_intr_setattr(void *v, pci_intr_handle_t *ih, int attr, uint64_t data) 468{ 469 switch (attr) { 470 case PCI_INTR_MPSAFE: 471 if (data) 472 *ih |= ARM_PCI_INTR_MPSAFE; 473 else 474 *ih &= ~ARM_PCI_INTR_MPSAFE; 475 return 0; 476 default: 477 return ENODEV; 478 } 479} 480 481static struct acpi_pci_intr * 482acpi_pci_md_intr_lookup(int irq) 483{ 484 struct acpi_pci_intr *pi; 485 486 TAILQ_FOREACH(pi, &acpi_pci_intrs, pi_list) 487 if (pi->pi_irq == irq) 488 return pi; 489 490 return NULL; 491} 492 493static void 494acpi_pci_md_unblock_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irqmask) 495{ 496 struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic; 497 498 pi->pi_unblocked |= irqmask; 499} 500 501static void 502acpi_pci_md_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irqmask) 503{ 504 struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic; 505 506 pi->pi_unblocked &= ~irqmask; 507} 508 509static int 510acpi_pci_md_find_pending_irqs(struct pic_softc *pic) 511{ 512 struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic; 513 514 pic_mark_pending_sources(pic, 0, pi->pi_unblocked); 515 516 return 1; 517} 518 519static void 520acpi_pci_md_establish_irq(struct pic_softc *pic, struct intrsource *is) 521{ 522} 523 524static void 525acpi_pci_md_source_name(struct pic_softc *pic, int irq, char *buf, size_t len) 526{ 527 snprintf(buf, len, "slot %d", irq); 528} 529 530static struct pic_ops acpi_pci_pic_ops = { 531 .pic_unblock_irqs = acpi_pci_md_unblock_irqs, 532 .pic_block_irqs = acpi_pci_md_block_irqs, 533 .pic_find_pending_irqs = acpi_pci_md_find_pending_irqs, 534 .pic_establish_irq = acpi_pci_md_establish_irq, 535 .pic_source_name = acpi_pci_md_source_name, 536}; 537 538static void * 539acpi_pci_md_intr_establish(void *v, pci_intr_handle_t ih, int ipl, 540 int (*callback)(void *), void *arg, const char *xname) 541{ 542 struct acpi_pci_context * const ap = v; 543 struct acpi_pci_intr *pi; 544 int slot; 545 546 if ((ih & (ARM_PCI_INTR_MSI | ARM_PCI_INTR_MSIX)) != 0) 547 return arm_pci_msi_intr_establish(&ap->ap_pc, ih, ipl, callback, arg, xname); 548 549 const int irq = (int)__SHIFTOUT(ih, ARM_PCI_INTR_IRQ); 550 const int mpsafe = (ih & ARM_PCI_INTR_MPSAFE) ? IST_MPSAFE : 0; 551 552 pi = acpi_pci_md_intr_lookup(irq); 553 if (pi == NULL) { 554 pi = kmem_zalloc(sizeof(*pi), KM_SLEEP); 555 pi->pi_irq = irq; 556 snprintf(pi->pi_pic.pic_name, sizeof(pi->pi_pic.pic_name), 557 "PCI irq %d", irq); 558 pi->pi_pic.pic_maxsources = 32; 559 pi->pi_pic.pic_ops = &acpi_pci_pic_ops; 560 pi->pi_irqbase = pic_add(&pi->pi_pic, PIC_IRQBASE_ALLOC); 561 TAILQ_INSERT_TAIL(&acpi_pci_intrs, pi, pi_list); 562 pi->pi_ih = intr_establish_xname(irq, IPL_VM, IST_LEVEL | IST_MPSAFE, 563 pic_handle_intr, &pi->pi_pic, device_xname(ap->ap_dev)); 564 } 565 if (pi->pi_ih == NULL) 566 return NULL; 567 568 /* Find a free slot */ 569 for (slot = 0; slot < pi->pi_pic.pic_maxsources; slot++) 570 if (pi->pi_pic.pic_sources[slot] == NULL) 571 break; 572 if (slot == pi->pi_pic.pic_maxsources) 573 return NULL; 574 575 return intr_establish_xname(pi->pi_irqbase + slot, ipl, IST_LEVEL | mpsafe, 576 callback, arg, xname); 577} 578 579static void 580acpi_pci_md_intr_disestablish(void *v, void *vih) 581{ 582 intr_disestablish(vih); 583} 584 585const struct acpi_pci_quirk * 586acpi_pci_md_find_quirk(int seg) 587{ 588 ACPI_STATUS rv; 589 ACPI_TABLE_MCFG *mcfg; 590 u_int n; 591 592 rv = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); 593 if (ACPI_FAILURE(rv)) { 594#ifdef PCI_SMCCC 595 uint32_t ver = pci_smccc_version(); 596 aprint_debug("%s: SMCCC version %#x\n", __func__, ver); 597 if (PCI_SMCCC_SUCCESS(ver)) { 598 return &acpi_pci_smccc_quirk; 599 } 600#endif 601 return NULL; 602 } 603 604 for (n = 0; n < __arraycount(acpi_pci_mcfg_quirks); n++) { 605 const struct acpi_pci_quirk *q = &acpi_pci_mcfg_quirks[n]; 606 if (memcmp(q->q_oemid, mcfg->Header.OemId, ACPI_OEM_ID_SIZE) == 0 && 607 memcmp(q->q_oemtableid, mcfg->Header.OemTableId, ACPI_OEM_TABLE_ID_SIZE) == 0 && 608 q->q_oemrevision == mcfg->Header.OemRevision && 609 (q->q_segment == -1 || q->q_segment == seg)) 610 return q; 611 } 612 613 return NULL; 614} 615 616pci_chipset_tag_t 617acpi_pci_md_get_chipset_tag(struct acpi_softc *sc, int seg, int bbn) 618{ 619 struct acpi_pci_pct *pct = NULL, *pctp; 620 const struct acpi_pci_quirk *q; 621 622 TAILQ_FOREACH(pctp, &acpi_pci_chipset_tags, pct_list) 623 if (pctp->pct_ap.ap_seg == seg) { 624 pct = pctp; 625 break; 626 } 627 628 if (pct == NULL) { 629 pct = kmem_zalloc(sizeof(*pct), KM_SLEEP); 630 pct->pct_ap.ap_dev = sc->sc_dev; 631 pct->pct_ap.ap_pc = arm_acpi_pci_chipset; 632 pct->pct_ap.ap_pc.pc_conf_v = &pct->pct_ap; 633 pct->pct_ap.ap_pc.pc_intr_v = &pct->pct_ap; 634 pct->pct_ap.ap_seg = seg; 635 pct->pct_ap.ap_bus = bbn; 636 pct->pct_ap.ap_maxbus = -1; 637 pct->pct_ap.ap_bst = acpi_softc->sc_memt; 638 639 q = acpi_pci_md_find_quirk(seg); 640 if (q != NULL) 641 q->q_init(&pct->pct_ap); 642 643 TAILQ_INSERT_TAIL(&acpi_pci_chipset_tags, pct, pct_list); 644 } 645 646 return &pct->pct_ap.ap_pc; 647} 648__strong_alias(acpi_get_pci_chipset_tag,acpi_pci_md_get_chipset_tag); 649