1 /* $NetBSD: acpi_pci_machdep.c,v 1.16 2020/02/13 00:02:21 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2018 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 #define _INTR_PRIVATE 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.16 2020/02/13 00:02:21 jmcneill Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/bus.h> 39 #include <sys/device.h> 40 #include <sys/intr.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/extent.h> 44 #include <sys/queue.h> 45 #include <sys/mutex.h> 46 #include <sys/kmem.h> 47 48 #include <machine/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 #include <arm/pci/pci_msi_machdep.h> 66 67 struct acpi_pci_prt { 68 u_int prt_segment; 69 u_int prt_bus; 70 ACPI_HANDLE prt_handle; 71 TAILQ_ENTRY(acpi_pci_prt) prt_list; 72 }; 73 74 static TAILQ_HEAD(, acpi_pci_prt) acpi_pci_irq_routes = 75 TAILQ_HEAD_INITIALIZER(acpi_pci_irq_routes); 76 77 struct acpi_pci_pct { 78 struct acpi_pci_context pct_ap; 79 TAILQ_ENTRY(acpi_pci_pct) pct_list; 80 }; 81 82 static TAILQ_HEAD(, acpi_pci_pct) acpi_pci_chipset_tags = 83 TAILQ_HEAD_INITIALIZER(acpi_pci_chipset_tags); 84 85 struct acpi_pci_intr; 86 87 struct acpi_pci_intr { 88 struct pic_softc pi_pic; 89 int pi_irqbase; 90 int pi_irq; 91 uint32_t pi_unblocked; 92 void *pi_ih; 93 TAILQ_ENTRY(acpi_pci_intr) pi_list; 94 }; 95 96 static TAILQ_HEAD(, acpi_pci_intr) acpi_pci_intrs = 97 TAILQ_HEAD_INITIALIZER(acpi_pci_intrs); 98 99 static const struct acpi_pci_quirk acpi_pci_quirks[] = { 100 /* OEM ID OEM Table ID Revision Seg Func */ 101 { "AMAZON", "GRAVITON", 0, -1, acpi_pci_graviton_init }, 102 { "ARMLTD", "ARMN1SDP", 0x20181101, 0, acpi_pci_n1sdp_init }, 103 { "ARMLTD", "ARMN1SDP", 0x20181101, 1, acpi_pci_n1sdp_init }, 104 { "NXP ", "LX2160 ", 0, -1, acpi_pci_layerscape_gen4_init }, 105 }; 106 107 pci_chipset_tag_t acpi_pci_md_get_chipset_tag(struct acpi_softc *, int, int); 108 109 static void acpi_pci_md_attach_hook(device_t, device_t, 110 struct pcibus_attach_args *); 111 static int acpi_pci_md_bus_maxdevs(void *, int); 112 static pcitag_t acpi_pci_md_make_tag(void *, int, int, int); 113 static void acpi_pci_md_decompose_tag(void *, pcitag_t, int *, int *, int *); 114 static u_int acpi_pci_md_get_segment(void *); 115 static uint32_t acpi_pci_md_get_devid(void *, uint32_t); 116 static uint32_t acpi_pci_md_get_frameid(void *, uint32_t); 117 static pcireg_t acpi_pci_md_conf_read(void *, pcitag_t, int); 118 static void acpi_pci_md_conf_write(void *, pcitag_t, int, pcireg_t); 119 static int acpi_pci_md_conf_hook(void *, int, int, int, pcireg_t); 120 static void acpi_pci_md_conf_interrupt(void *, int, int, int, int, int *); 121 122 static int acpi_pci_md_intr_map(const struct pci_attach_args *, 123 pci_intr_handle_t *); 124 static const char *acpi_pci_md_intr_string(void *, pci_intr_handle_t, 125 char *, size_t); 126 static const struct evcnt *acpi_pci_md_intr_evcnt(void *, pci_intr_handle_t); 127 static int acpi_pci_md_intr_setattr(void *, pci_intr_handle_t *, int, 128 uint64_t); 129 static void * acpi_pci_md_intr_establish(void *, pci_intr_handle_t, 130 int, int (*)(void *), void *, 131 const char *); 132 static void acpi_pci_md_intr_disestablish(void *, void *); 133 134 struct arm32_pci_chipset arm_acpi_pci_chipset = { 135 .pc_attach_hook = acpi_pci_md_attach_hook, 136 .pc_bus_maxdevs = acpi_pci_md_bus_maxdevs, 137 .pc_make_tag = acpi_pci_md_make_tag, 138 .pc_decompose_tag = acpi_pci_md_decompose_tag, 139 .pc_get_segment = acpi_pci_md_get_segment, 140 .pc_get_devid = acpi_pci_md_get_devid, 141 .pc_get_frameid = acpi_pci_md_get_frameid, 142 .pc_conf_read = acpi_pci_md_conf_read, 143 .pc_conf_write = acpi_pci_md_conf_write, 144 .pc_conf_hook = acpi_pci_md_conf_hook, 145 .pc_conf_interrupt = acpi_pci_md_conf_interrupt, 146 147 .pc_intr_map = acpi_pci_md_intr_map, 148 .pc_intr_string = acpi_pci_md_intr_string, 149 .pc_intr_evcnt = acpi_pci_md_intr_evcnt, 150 .pc_intr_setattr = acpi_pci_md_intr_setattr, 151 .pc_intr_establish = acpi_pci_md_intr_establish, 152 .pc_intr_disestablish = acpi_pci_md_intr_disestablish, 153 }; 154 155 static ACPI_STATUS 156 acpi_pci_md_pci_link(ACPI_HANDLE handle, pci_chipset_tag_t pc, int bus) 157 { 158 ACPI_PCI_ROUTING_TABLE *prt; 159 ACPI_HANDLE linksrc; 160 ACPI_BUFFER buf; 161 ACPI_STATUS rv; 162 void *linkdev; 163 164 rv = acpi_get(handle, &buf, AcpiGetIrqRoutingTable); 165 if (ACPI_FAILURE(rv)) 166 return rv; 167 168 for (char *p = buf.Pointer; ; p += prt->Length) { 169 prt = (ACPI_PCI_ROUTING_TABLE *)p; 170 if (prt->Length == 0) 171 break; 172 173 const u_int dev = ACPI_HIWORD(prt->Address); 174 if (prt->Source[0] != 0) { 175 aprint_debug("ACPI: %s dev %u INT%c on lnkdev %s\n", 176 acpi_name(handle), dev, 'A' + (prt->Pin & 3), prt->Source); 177 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, prt->Source, &linksrc); 178 if (ACPI_FAILURE(rv)) { 179 aprint_debug("ACPI: AcpiGetHandle failed for '%s': %s\n", 180 prt->Source, AcpiFormatException(rv)); 181 continue; 182 } 183 184 linkdev = acpi_pci_link_devbyhandle(linksrc); 185 acpi_pci_link_add_reference(linkdev, pc, 0, bus, dev, prt->Pin & 3); 186 } else { 187 aprint_debug("ACPI: %s dev %u INT%c on globint %d\n", 188 acpi_name(handle), dev, 'A' + (prt->Pin & 3), prt->SourceIndex); 189 } 190 } 191 192 return AE_OK; 193 } 194 195 static void 196 acpi_pci_md_attach_hook(device_t parent, device_t self, 197 struct pcibus_attach_args *pba) 198 { 199 struct acpi_pci_context *ap = pba->pba_pc->pc_conf_v; 200 struct acpi_pci_prt *prt, *prtp; 201 struct acpi_devnode *ad; 202 ACPI_HANDLE handle; 203 int seg, bus, dev, func; 204 205 seg = ap->ap_seg; 206 handle = NULL; 207 208 if (pba->pba_bridgetag) { 209 /* 210 * Find the PCI address of our parent bridge and look for the 211 * corresponding ACPI device node. If there is no node for this 212 * bus, use the parent bridge routing information. 213 */ 214 acpi_pci_md_decompose_tag(NULL, *pba->pba_bridgetag, &bus, &dev, &func); 215 ad = acpi_pcidev_find(seg, bus, dev, func); 216 if (ad != NULL) { 217 handle = ad->ad_handle; 218 } else { 219 /* No routes defined for this bus, copy from parent */ 220 TAILQ_FOREACH(prtp, &acpi_pci_irq_routes, prt_list) 221 if (prtp->prt_bus == bus) { 222 handle = prtp->prt_handle; 223 break; 224 } 225 } 226 } else { 227 /* 228 * Lookup the ACPI device node for the root bus. 229 */ 230 ad = acpi_pciroot_find(seg, 0); 231 if (ad != NULL) 232 handle = ad->ad_handle; 233 } 234 235 if (handle != NULL) { 236 prt = kmem_alloc(sizeof(*prt), KM_SLEEP); 237 prt->prt_bus = pba->pba_bus; 238 prt->prt_segment = ap->ap_seg; 239 prt->prt_handle = handle; 240 TAILQ_INSERT_TAIL(&acpi_pci_irq_routes, prt, prt_list); 241 } 242 243 acpimcfg_map_bus(self, pba->pba_pc, pba->pba_bus); 244 245 if (ad != NULL) { 246 /* 247 * This is a new ACPI managed bus. Add PCI link references. 248 */ 249 acpi_pci_md_pci_link(ad->ad_handle, pba->pba_pc, pba->pba_bus); 250 } 251 } 252 253 static int 254 acpi_pci_md_bus_maxdevs(void *v, int busno) 255 { 256 return 32; 257 } 258 259 static pcitag_t 260 acpi_pci_md_make_tag(void *v, int b, int d, int f) 261 { 262 return (b << 16) | (d << 11) | (f << 8); 263 } 264 265 static void 266 acpi_pci_md_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 267 { 268 if (bp) 269 *bp = (tag >> 16) & 0xff; 270 if (dp) 271 *dp = (tag >> 11) & 0x1f; 272 if (fp) 273 *fp = (tag >> 8) & 0x7; 274 } 275 276 static u_int 277 acpi_pci_md_get_segment(void *v) 278 { 279 struct acpi_pci_context * const ap = v; 280 281 return ap->ap_seg; 282 } 283 284 static uint32_t 285 acpi_pci_md_get_devid(void *v, uint32_t devid) 286 { 287 struct acpi_pci_context * const ap = v; 288 289 return acpi_iort_pci_root_map(ap->ap_seg, devid); 290 } 291 292 static uint32_t 293 acpi_pci_md_get_frameid(void *v, uint32_t devid) 294 { 295 struct acpi_pci_context * const ap = v; 296 297 return acpi_iort_its_id_map(ap->ap_seg, devid); 298 } 299 300 static pcireg_t 301 acpi_pci_md_conf_read(void *v, pcitag_t tag, int offset) 302 { 303 struct acpi_pci_context * const ap = v; 304 pcireg_t val; 305 306 if (offset < 0 || offset >= PCI_EXTCONF_SIZE) 307 return (pcireg_t) -1; 308 309 if (ap->ap_conf_read != NULL) 310 ap->ap_conf_read(&ap->ap_pc, tag, offset, &val); 311 else 312 acpimcfg_conf_read(&ap->ap_pc, tag, offset, &val); 313 314 return val; 315 } 316 317 static void 318 acpi_pci_md_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) 319 { 320 struct acpi_pci_context * const ap = v; 321 322 if (offset < 0 || offset >= PCI_EXTCONF_SIZE) 323 return; 324 325 if (ap->ap_conf_write != NULL) 326 ap->ap_conf_write(&ap->ap_pc, tag, offset, val); 327 else 328 acpimcfg_conf_write(&ap->ap_pc, tag, offset, val); 329 } 330 331 static int 332 acpi_pci_md_conf_hook(void *v, int b, int d, int f, pcireg_t id) 333 { 334 return PCI_CONF_DEFAULT; 335 } 336 337 static void 338 acpi_pci_md_conf_interrupt(void *v, int bus, int dev, int ipin, int sqiz, int *ilinep) 339 { 340 } 341 342 static struct acpi_pci_prt * 343 acpi_pci_md_intr_find_prt(pci_chipset_tag_t pc, u_int bus) 344 { 345 struct acpi_pci_prt *prt, *prtp; 346 u_int segment; 347 348 segment = pci_get_segment(pc); 349 350 prt = NULL; 351 TAILQ_FOREACH(prtp, &acpi_pci_irq_routes, prt_list) 352 if (prtp->prt_segment == segment && prtp->prt_bus == bus) { 353 prt = prtp; 354 break; 355 } 356 357 return prt; 358 } 359 360 static int 361 acpi_pci_md_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih) 362 { 363 struct acpi_pci_prt *prt; 364 ACPI_PCI_ROUTING_TABLE *tab; 365 int line, pol, trig, error; 366 ACPI_HANDLE linksrc; 367 ACPI_BUFFER buf; 368 void *linkdev; 369 370 if (pa->pa_intrpin == PCI_INTERRUPT_PIN_NONE) 371 return EINVAL; 372 373 prt = acpi_pci_md_intr_find_prt(pa->pa_pc, pa->pa_bus); 374 if (prt == NULL) 375 return ENXIO; 376 377 if (ACPI_FAILURE(acpi_get(prt->prt_handle, &buf, AcpiGetIrqRoutingTable))) 378 return EIO; 379 380 error = ENOENT; 381 for (char *p = buf.Pointer; ; p += tab->Length) { 382 tab = (ACPI_PCI_ROUTING_TABLE *)p; 383 if (tab->Length == 0) 384 break; 385 386 if (pa->pa_device == ACPI_HIWORD(tab->Address) && 387 (pa->pa_intrpin - 1) == (tab->Pin & 3)) { 388 if (tab->Source[0] != 0) { 389 if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, tab->Source, &linksrc))) 390 goto done; 391 linkdev = acpi_pci_link_devbyhandle(linksrc); 392 *ih = acpi_pci_link_route_interrupt(linkdev, 393 pa->pa_pc, tab->SourceIndex, 394 &line, &pol, &trig); 395 error = 0; 396 goto done; 397 } else { 398 *ih = tab->SourceIndex; 399 error = 0; 400 goto done; 401 } 402 } 403 } 404 405 done: 406 ACPI_FREE(buf.Pointer); 407 return error; 408 } 409 410 static const char * 411 acpi_pci_md_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len) 412 { 413 const int irq = __SHIFTOUT(ih, ARM_PCI_INTR_IRQ); 414 const int vec = __SHIFTOUT(ih, ARM_PCI_INTR_MSI_VEC); 415 416 if (ih & ARM_PCI_INTR_MSIX) 417 snprintf(buf, len, "irq %d (MSI-X vec %d)", irq, vec); 418 else if (ih & ARM_PCI_INTR_MSI) 419 snprintf(buf, len, "irq %d (MSI vec %d)", irq, vec); 420 else 421 snprintf(buf, len, "irq %d", irq); 422 423 return buf; 424 } 425 426 static const struct evcnt * 427 acpi_pci_md_intr_evcnt(void *v, pci_intr_handle_t ih) 428 { 429 return NULL; 430 } 431 432 static int 433 acpi_pci_md_intr_setattr(void *v, pci_intr_handle_t *ih, int attr, uint64_t data) 434 { 435 switch (attr) { 436 case PCI_INTR_MPSAFE: 437 if (data) 438 *ih |= ARM_PCI_INTR_MPSAFE; 439 else 440 *ih &= ~ARM_PCI_INTR_MPSAFE; 441 return 0; 442 default: 443 return ENODEV; 444 } 445 } 446 447 static struct acpi_pci_intr * 448 acpi_pci_md_intr_lookup(int irq) 449 { 450 struct acpi_pci_intr *pi; 451 452 TAILQ_FOREACH(pi, &acpi_pci_intrs, pi_list) 453 if (pi->pi_irq == irq) 454 return pi; 455 456 return NULL; 457 } 458 459 static void 460 acpi_pci_md_unblock_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irqmask) 461 { 462 struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic; 463 464 pi->pi_unblocked |= irqmask; 465 } 466 467 static void 468 acpi_pci_md_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irqmask) 469 { 470 struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic; 471 472 pi->pi_unblocked &= ~irqmask; 473 } 474 475 static int 476 acpi_pci_md_find_pending_irqs(struct pic_softc *pic) 477 { 478 struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic; 479 480 pic_mark_pending_sources(pic, 0, pi->pi_unblocked); 481 482 return 1; 483 } 484 485 static void 486 acpi_pci_md_establish_irq(struct pic_softc *pic, struct intrsource *is) 487 { 488 } 489 490 static void 491 acpi_pci_md_source_name(struct pic_softc *pic, int irq, char *buf, size_t len) 492 { 493 snprintf(buf, len, "slot %d", irq); 494 } 495 496 static struct pic_ops acpi_pci_pic_ops = { 497 .pic_unblock_irqs = acpi_pci_md_unblock_irqs, 498 .pic_block_irqs = acpi_pci_md_block_irqs, 499 .pic_find_pending_irqs = acpi_pci_md_find_pending_irqs, 500 .pic_establish_irq = acpi_pci_md_establish_irq, 501 .pic_source_name = acpi_pci_md_source_name, 502 }; 503 504 static void * 505 acpi_pci_md_intr_establish(void *v, pci_intr_handle_t ih, int ipl, 506 int (*callback)(void *), void *arg, const char *xname) 507 { 508 struct acpi_pci_context * const ap = v; 509 struct acpi_pci_intr *pi; 510 int slot; 511 512 if ((ih & (ARM_PCI_INTR_MSI | ARM_PCI_INTR_MSIX)) != 0) 513 return arm_pci_msi_intr_establish(&ap->ap_pc, ih, ipl, callback, arg, xname); 514 515 const int irq = (int)__SHIFTOUT(ih, ARM_PCI_INTR_IRQ); 516 const int mpsafe = (ih & ARM_PCI_INTR_MPSAFE) ? IST_MPSAFE : 0; 517 518 pi = acpi_pci_md_intr_lookup(irq); 519 if (pi == NULL) { 520 pi = kmem_zalloc(sizeof(*pi), KM_SLEEP); 521 pi->pi_irq = irq; 522 snprintf(pi->pi_pic.pic_name, sizeof(pi->pi_pic.pic_name), 523 "PCI irq %d", irq); 524 pi->pi_pic.pic_maxsources = 32; 525 pi->pi_pic.pic_ops = &acpi_pci_pic_ops; 526 pi->pi_irqbase = pic_add(&pi->pi_pic, PIC_IRQBASE_ALLOC); 527 TAILQ_INSERT_TAIL(&acpi_pci_intrs, pi, pi_list); 528 pi->pi_ih = intr_establish_xname(irq, IPL_SCHED, IST_LEVEL | IST_MPSAFE, 529 pic_handle_intr, &pi->pi_pic, device_xname(ap->ap_dev)); 530 } 531 if (pi->pi_ih == NULL) 532 return NULL; 533 534 /* Find a free slot */ 535 for (slot = 0; slot < pi->pi_pic.pic_maxsources; slot++) 536 if (pi->pi_pic.pic_sources[slot] == NULL) 537 break; 538 if (slot == pi->pi_pic.pic_maxsources) 539 return NULL; 540 541 return intr_establish_xname(pi->pi_irqbase + slot, ipl, IST_LEVEL | mpsafe, 542 callback, arg, xname); 543 } 544 545 static void 546 acpi_pci_md_intr_disestablish(void *v, void *vih) 547 { 548 intr_disestablish(vih); 549 } 550 551 const struct acpi_pci_quirk * 552 acpi_pci_md_find_quirk(int seg) 553 { 554 ACPI_STATUS rv; 555 ACPI_TABLE_MCFG *mcfg; 556 u_int n; 557 558 rv = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); 559 if (ACPI_FAILURE(rv)) 560 return NULL; 561 562 for (n = 0; n < __arraycount(acpi_pci_quirks); n++) { 563 const struct acpi_pci_quirk *q = &acpi_pci_quirks[n]; 564 if (memcmp(q->q_oemid, mcfg->Header.OemId, ACPI_OEM_ID_SIZE) == 0 && 565 memcmp(q->q_oemtableid, mcfg->Header.OemTableId, ACPI_OEM_TABLE_ID_SIZE) == 0 && 566 q->q_oemrevision == mcfg->Header.OemRevision && 567 (q->q_segment == -1 || q->q_segment == seg)) 568 return q; 569 } 570 571 return NULL; 572 } 573 574 pci_chipset_tag_t 575 acpi_pci_md_get_chipset_tag(struct acpi_softc *sc, int seg, int bbn) 576 { 577 struct acpi_pci_pct *pct = NULL, *pctp; 578 const struct acpi_pci_quirk *q; 579 580 TAILQ_FOREACH(pctp, &acpi_pci_chipset_tags, pct_list) 581 if (pctp->pct_ap.ap_seg == seg) { 582 pct = pctp; 583 break; 584 } 585 586 if (pct == NULL) { 587 pct = kmem_zalloc(sizeof(*pct), KM_SLEEP); 588 pct->pct_ap.ap_dev = sc->sc_dev; 589 pct->pct_ap.ap_pc = arm_acpi_pci_chipset; 590 pct->pct_ap.ap_pc.pc_conf_v = &pct->pct_ap; 591 pct->pct_ap.ap_pc.pc_intr_v = &pct->pct_ap; 592 pct->pct_ap.ap_seg = seg; 593 pct->pct_ap.ap_bus = bbn; 594 pct->pct_ap.ap_bst = acpi_softc->sc_memt; 595 596 q = acpi_pci_md_find_quirk(seg); 597 if (q != NULL) 598 q->q_init(&pct->pct_ap); 599 600 TAILQ_INSERT_TAIL(&acpi_pci_chipset_tags, pct, pct_list); 601 } 602 603 return &pct->pct_ap.ap_pc; 604 } 605 __strong_alias(acpi_get_pci_chipset_tag,acpi_pci_md_get_chipset_tag); 606