acpipci.c revision 1.25
1/* $OpenBSD: acpipci.c,v 1.25 2021/02/25 23:07:48 patrick Exp $ */ 2/* 3 * Copyright (c) 2018 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <sys/param.h> 19#include <sys/device.h> 20#include <sys/extent.h> 21#include <sys/malloc.h> 22#include <sys/systm.h> 23 24#include <machine/bus.h> 25 26#include <dev/acpi/acpireg.h> 27#include <dev/acpi/acpivar.h> 28#include <dev/acpi/acpidev.h> 29#include <dev/acpi/amltypes.h> 30#include <dev/acpi/dsdt.h> 31 32#include <dev/pci/pcidevs.h> 33#include <dev/pci/pcireg.h> 34#include <dev/pci/pcivar.h> 35#include <dev/pci/ppbreg.h> 36 37struct acpipci_mcfg { 38 SLIST_ENTRY(acpipci_mcfg) am_list; 39 40 uint16_t am_segment; 41 uint8_t am_min_bus; 42 uint8_t am_max_bus; 43 44 bus_space_tag_t am_iot; 45 bus_space_handle_t am_ioh; 46 47 struct arm64_pci_chipset am_pc; 48}; 49 50struct acpipci_trans { 51 struct acpipci_trans *at_next; 52 bus_space_tag_t at_iot; 53 bus_addr_t at_base; 54 bus_size_t at_size; 55 bus_size_t at_offset; 56}; 57 58struct acpipci_softc { 59 struct device sc_dev; 60 struct acpi_softc *sc_acpi; 61 struct aml_node *sc_node; 62 bus_space_tag_t sc_iot; 63 pci_chipset_tag_t sc_pc; 64 65 struct bus_space sc_bus_iot; 66 struct bus_space sc_bus_memt; 67 struct acpipci_trans *sc_io_trans; 68 struct acpipci_trans *sc_mem_trans; 69 70 struct extent *sc_busex; 71 struct extent *sc_memex; 72 struct extent *sc_ioex; 73 char sc_busex_name[32]; 74 char sc_ioex_name[32]; 75 char sc_memex_name[32]; 76 int sc_bus; 77 uint32_t sc_seg; 78}; 79 80int acpipci_match(struct device *, void *, void *); 81void acpipci_attach(struct device *, struct device *, void *); 82 83struct cfattach acpipci_ca = { 84 sizeof(struct acpipci_softc), acpipci_match, acpipci_attach 85}; 86 87struct cfdriver acpipci_cd = { 88 NULL, "acpipci", DV_DULL 89}; 90 91const char *acpipci_hids[] = { 92 "PNP0A08", 93 NULL 94}; 95 96int acpipci_parse_resources(int, union acpi_resource *, void *); 97int acpipci_bs_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, 98 bus_space_handle_t *); 99paddr_t acpipci_bs_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); 100 101void acpipci_attach_hook(struct device *, struct device *, 102 struct pcibus_attach_args *); 103int acpipci_bus_maxdevs(void *, int); 104pcitag_t acpipci_make_tag(void *, int, int, int); 105void acpipci_decompose_tag(void *, pcitag_t, int *, int *, int *); 106int acpipci_conf_size(void *, pcitag_t); 107pcireg_t acpipci_conf_read(void *, pcitag_t, int); 108void acpipci_conf_write(void *, pcitag_t, int, pcireg_t); 109int acpipci_probe_device_hook(void *, struct pci_attach_args *); 110 111int acpipci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 112const char *acpipci_intr_string(void *, pci_intr_handle_t); 113void *acpipci_intr_establish(void *, pci_intr_handle_t, int, 114 struct cpu_info *, int (*)(void *), void *, char *); 115void acpipci_intr_disestablish(void *, void *); 116 117uint32_t acpipci_iort_map_msi(pci_chipset_tag_t, pcitag_t); 118 119int 120acpipci_match(struct device *parent, void *match, void *aux) 121{ 122 struct acpi_attach_args *aaa = aux; 123 struct cfdata *cf = match; 124 125 return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name); 126} 127 128void 129acpipci_attach(struct device *parent, struct device *self, void *aux) 130{ 131 struct acpi_attach_args *aaa = aux; 132 struct acpipci_softc *sc = (struct acpipci_softc *)self; 133 struct pcibus_attach_args pba; 134 struct aml_value res; 135 uint64_t bbn = 0; 136 uint64_t seg = 0; 137 138 sc->sc_acpi = (struct acpi_softc *)parent; 139 sc->sc_node = aaa->aaa_node; 140 printf(" %s", sc->sc_node->name); 141 142 if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { 143 printf(": can't find resources\n"); 144 return; 145 } 146 147 aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn); 148 sc->sc_bus = bbn; 149 150 aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL, &seg); 151 sc->sc_seg = seg; 152 153 sc->sc_iot = aaa->aaa_memt; 154 155 printf("\n"); 156 157 /* Create extents for our address spaces. */ 158 snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name), 159 "%s pcibus", sc->sc_dev.dv_xname); 160 snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name), 161 "%s pciio", sc->sc_dev.dv_xname); 162 snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name), 163 "%s pcimem", sc->sc_dev.dv_xname); 164 sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255, 165 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 166 sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff, 167 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 168 sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1, 169 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 170 171 aml_parse_resource(&res, acpipci_parse_resources, sc); 172 173 memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot)); 174 sc->sc_bus_iot.bus_private = sc->sc_io_trans; 175 sc->sc_bus_iot._space_map = acpipci_bs_map; 176 sc->sc_bus_iot._space_mmap = acpipci_bs_mmap; 177 memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt)); 178 sc->sc_bus_memt.bus_private = sc->sc_mem_trans; 179 sc->sc_bus_memt._space_map = acpipci_bs_map; 180 sc->sc_bus_memt._space_mmap = acpipci_bs_mmap; 181 182 sc->sc_pc = pci_lookup_segment(seg); 183 KASSERT(sc->sc_pc->pc_intr_v == NULL); 184 185 sc->sc_pc->pc_probe_device_hook = acpipci_probe_device_hook; 186 187 sc->sc_pc->pc_intr_v = sc; 188 sc->sc_pc->pc_intr_map = acpipci_intr_map; 189 sc->sc_pc->pc_intr_map_msi = _pci_intr_map_msi; 190 sc->sc_pc->pc_intr_map_msix = _pci_intr_map_msix; 191 sc->sc_pc->pc_intr_string = acpipci_intr_string; 192 sc->sc_pc->pc_intr_establish = acpipci_intr_establish; 193 sc->sc_pc->pc_intr_disestablish = acpipci_intr_disestablish; 194 195 memset(&pba, 0, sizeof(pba)); 196 pba.pba_busname = "pci"; 197 pba.pba_iot = &sc->sc_bus_iot; 198 pba.pba_memt = &sc->sc_bus_memt; 199 pba.pba_dmat = aaa->aaa_dmat; 200 pba.pba_pc = sc->sc_pc; 201 pba.pba_busex = sc->sc_busex; 202 pba.pba_ioex = sc->sc_ioex; 203 pba.pba_memex = sc->sc_memex; 204 pba.pba_pmemex = sc->sc_memex; 205 pba.pba_domain = pci_ndomains++; 206 pba.pba_bus = sc->sc_bus; 207 pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; 208 209 config_found(self, &pba, NULL); 210} 211 212int 213acpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg) 214{ 215 struct acpipci_softc *sc = arg; 216 struct acpipci_trans *at; 217 int type = AML_CRSTYPE(crs); 218 int restype, tflags; 219 u_long min, len = 0, tra; 220 221 switch (type) { 222 case LR_WORD: 223 restype = crs->lr_word.type; 224 tflags = crs->lr_word.tflags; 225 min = crs->lr_word._min; 226 len = crs->lr_word._len; 227 tra = crs->lr_word._tra; 228 break; 229 case LR_DWORD: 230 restype = crs->lr_dword.type; 231 tflags = crs->lr_dword.tflags; 232 min = crs->lr_dword._min; 233 len = crs->lr_dword._len; 234 tra = crs->lr_dword._tra; 235 break; 236 case LR_QWORD: 237 restype = crs->lr_qword.type; 238 tflags = crs->lr_qword.tflags; 239 min = crs->lr_qword._min; 240 len = crs->lr_qword._len; 241 tra = crs->lr_qword._tra; 242 break; 243 } 244 245 if (len == 0) 246 return 0; 247 248 switch (restype) { 249 case LR_TYPE_MEMORY: 250 if (tflags & LR_MEMORY_TTP) 251 return 0; 252 extent_free(sc->sc_memex, min, len, EX_WAITOK); 253 at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK); 254 at->at_iot = sc->sc_iot; 255 at->at_base = min; 256 at->at_size = len; 257 at->at_offset = tra; 258 at->at_next = sc->sc_mem_trans; 259 sc->sc_mem_trans = at; 260 break; 261 case LR_TYPE_IO: 262 /* 263 * Don't check _TTP as various firmwares don't set it, 264 * even though they should!! 265 */ 266 extent_free(sc->sc_ioex, min, len, EX_WAITOK); 267 at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK); 268 at->at_iot = sc->sc_iot; 269 at->at_base = min; 270 at->at_size = len; 271 at->at_offset = tra; 272 at->at_next = sc->sc_io_trans; 273 sc->sc_io_trans = at; 274 break; 275 case LR_TYPE_BUS: 276 extent_free(sc->sc_busex, min, len, EX_WAITOK); 277 /* 278 * Let _CRS minimum bus number override _BBN. 279 */ 280 sc->sc_bus = min; 281 break; 282 } 283 284 return 0; 285} 286 287void 288acpipci_attach_hook(struct device *parent, struct device *self, 289 struct pcibus_attach_args *pba) 290{ 291} 292 293int 294acpipci_bus_maxdevs(void *v, int bus) 295{ 296 return 32; 297} 298 299pcitag_t 300acpipci_make_tag(void *v, int bus, int device, int function) 301{ 302 return ((bus << 20) | (device << 15) | (function << 12)); 303} 304 305void 306acpipci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 307{ 308 if (bp != NULL) 309 *bp = (tag >> 20) & 0xff; 310 if (dp != NULL) 311 *dp = (tag >> 15) & 0x1f; 312 if (fp != NULL) 313 *fp = (tag >> 12) & 0x7; 314} 315 316int 317acpipci_conf_size(void *v, pcitag_t tag) 318{ 319 return PCIE_CONFIG_SPACE_SIZE; 320} 321 322pcireg_t 323acpipci_conf_read(void *v, pcitag_t tag, int reg) 324{ 325 struct acpipci_mcfg *am = v; 326 327 if (tag < (am->am_min_bus << 20) || 328 tag >= ((am->am_max_bus + 1) << 20)) 329 return 0xffffffff; 330 331 return bus_space_read_4(am->am_iot, am->am_ioh, tag | reg); 332} 333 334void 335acpipci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 336{ 337 struct acpipci_mcfg *am = v; 338 339 if (tag < (am->am_min_bus << 20) || 340 tag >= ((am->am_max_bus + 1) << 20)) 341 return; 342 343 bus_space_write_4(am->am_iot, am->am_ioh, tag | reg, data); 344} 345 346int 347acpipci_probe_device_hook(void *v, struct pci_attach_args *pa) 348{ 349 return 0; 350} 351 352int 353acpipci_intr_swizzle(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 354{ 355 int dev, swizpin; 356 357 if (pa->pa_bridgeih == NULL) 358 return -1; 359 360 pci_decompose_tag(pa->pa_pc, pa->pa_tag, NULL, &dev, NULL); 361 swizpin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin, dev); 362 if (pa->pa_bridgeih[swizpin - 1].ih_type == PCI_NONE) 363 return -1; 364 365 *ihp = pa->pa_bridgeih[swizpin - 1]; 366 return 0; 367} 368 369int 370acpipci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 371{ 372 struct acpipci_softc *sc = pa->pa_pc->pc_intr_v; 373 struct aml_node *node = sc->sc_node; 374 struct aml_value res; 375 uint64_t addr, pin, source, index; 376 int i; 377 378 /* 379 * If we're behind a bridge, we need to look for a _PRT for 380 * it. If we don't find a _PRT, we need to swizzle. If we're 381 * not behind a bridge we need to look for a _PRT on the host 382 * bridge node itself. 383 */ 384 if (pa->pa_bridgetag) { 385 node = acpi_find_pci(pa->pa_pc, *pa->pa_bridgetag); 386 if (node == NULL) 387 return acpipci_intr_swizzle(pa, ihp); 388 } 389 390 if (aml_evalname(sc->sc_acpi, node, "_PRT", 0, NULL, &res)) 391 return acpipci_intr_swizzle(pa, ihp); 392 393 if (res.type != AML_OBJTYPE_PACKAGE) 394 return -1; 395 396 for (i = 0; i < res.length; i++) { 397 struct aml_value *val = res.v_package[i]; 398 399 if (val->type != AML_OBJTYPE_PACKAGE) 400 continue; 401 if (val->length != 4) 402 continue; 403 if (val->v_package[0]->type != AML_OBJTYPE_INTEGER || 404 val->v_package[1]->type != AML_OBJTYPE_INTEGER || 405 val->v_package[2]->type != AML_OBJTYPE_INTEGER || 406 val->v_package[3]->type != AML_OBJTYPE_INTEGER) 407 continue; 408 409 addr = val->v_package[0]->v_integer; 410 pin = val->v_package[1]->v_integer; 411 source = val->v_package[2]->v_integer; 412 index = val->v_package[3]->v_integer; 413 if (ACPI_ADR_PCIDEV(addr) != pa->pa_device || 414 ACPI_ADR_PCIFUN(addr) != 0xffff || 415 pin != pa->pa_intrpin - 1 || source != 0) 416 continue; 417 418 ihp->ih_pc = pa->pa_pc; 419 ihp->ih_tag = pa->pa_tag; 420 ihp->ih_intrpin = index; 421 ihp->ih_type = PCI_INTX; 422 423 return 0; 424 } 425 426 return -1; 427} 428 429const char * 430acpipci_intr_string(void *v, pci_intr_handle_t ih) 431{ 432 static char irqstr[32]; 433 434 switch (ih.ih_type) { 435 case PCI_MSI: 436 return "msi"; 437 case PCI_MSIX: 438 return "msix"; 439 } 440 441 snprintf(irqstr, sizeof(irqstr), "irq %d", ih.ih_intrpin); 442 return irqstr; 443} 444 445void * 446acpipci_intr_establish(void *v, pci_intr_handle_t ih, int level, 447 struct cpu_info *ci, int (*func)(void *), void *arg, char *name) 448{ 449 struct acpipci_softc *sc = v; 450 struct interrupt_controller *ic; 451 struct arm_intr_handle *aih; 452 void *cookie; 453 454 extern LIST_HEAD(, interrupt_controller) interrupt_controllers; 455 LIST_FOREACH(ic, &interrupt_controllers, ic_list) { 456 if (ic->ic_establish_msi) 457 break; 458 } 459 if (ic == NULL) 460 return NULL; 461 462 KASSERT(ih.ih_type != PCI_NONE); 463 464 if (ih.ih_type != PCI_INTX) { 465 uint64_t addr, data; 466 467 /* Map Requester ID through IORT to get sideband data. */ 468 data = acpipci_iort_map_msi(ih.ih_pc, ih.ih_tag); 469 cookie = ic->ic_establish_msi(ic->ic_cookie, &addr, 470 &data, level, ci, func, arg, name); 471 if (cookie == NULL) 472 return NULL; 473 474 /* TODO: translate address to the PCI device's view */ 475 476 if (ih.ih_type == PCI_MSIX) { 477 pci_msix_enable(ih.ih_pc, ih.ih_tag, 478 &sc->sc_bus_memt, ih.ih_intrpin, addr, data); 479 } else 480 pci_msi_enable(ih.ih_pc, ih.ih_tag, addr, data); 481 482 aih = malloc(sizeof(*aih), M_DEVBUF, M_WAITOK); 483 aih->ih_ic = ic; 484 aih->ih_ih = cookie; 485 cookie = aih; 486 } else { 487 if (ci != NULL && !CPU_IS_PRIMARY(ci)) 488 return NULL; 489 cookie = acpi_intr_establish(ih.ih_intrpin, 0, level, 490 func, arg, name); 491 } 492 493 return cookie; 494} 495 496void 497acpipci_intr_disestablish(void *v, void *cookie) 498{ 499 struct arm_intr_handle *aih = cookie; 500 struct interrupt_controller *ic = aih->ih_ic; 501 502 if (ic->ic_establish_msi) 503 ic->ic_disestablish(aih->ih_ih); 504 else 505 acpi_intr_disestablish(cookie); 506} 507 508/* 509 * Translate memory address if needed. 510 */ 511int 512acpipci_bs_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 513 int flags, bus_space_handle_t *bshp) 514{ 515 struct acpipci_trans *at; 516 517 for (at = t->bus_private; at; at = at->at_next) { 518 if (addr >= at->at_base && addr < at->at_base + at->at_size) { 519 return bus_space_map(at->at_iot, 520 addr + at->at_offset, size, flags, bshp); 521 } 522 } 523 524 return ENXIO; 525} 526 527paddr_t 528acpipci_bs_mmap(bus_space_tag_t t, bus_addr_t addr, off_t off, 529 int prot, int flags) 530{ 531 struct acpipci_trans *at; 532 533 for (at = t->bus_private; at; at = at->at_next) { 534 if (addr >= at->at_base && addr < at->at_base + at->at_size) { 535 return bus_space_mmap(at->at_iot, 536 addr + at->at_offset, off, prot, flags); 537 } 538 } 539 540 return -1; 541} 542 543SLIST_HEAD(,acpipci_mcfg) acpipci_mcfgs = 544 SLIST_HEAD_INITIALIZER(acpipci_mcfgs); 545 546void 547pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int segment, 548 int min_bus, int max_bus) 549{ 550 struct acpipci_mcfg *am; 551 552 am = malloc(sizeof(struct acpipci_mcfg), M_DEVBUF, M_WAITOK | M_ZERO); 553 am->am_segment = segment; 554 am->am_min_bus = min_bus; 555 am->am_max_bus = max_bus; 556 557 am->am_iot = iot; 558 if (bus_space_map(iot, addr, (max_bus + 1) << 20, 0, &am->am_ioh)) 559 panic("%s: can't map config space", __func__); 560 561 am->am_pc.pc_conf_v = am; 562 am->am_pc.pc_attach_hook = acpipci_attach_hook; 563 am->am_pc.pc_bus_maxdevs = acpipci_bus_maxdevs; 564 am->am_pc.pc_make_tag = acpipci_make_tag; 565 am->am_pc.pc_decompose_tag = acpipci_decompose_tag; 566 am->am_pc.pc_conf_size = acpipci_conf_size; 567 am->am_pc.pc_conf_read = acpipci_conf_read; 568 am->am_pc.pc_conf_write = acpipci_conf_write; 569 SLIST_INSERT_HEAD(&acpipci_mcfgs, am, am_list); 570} 571 572pcireg_t 573acpipci_dummy_conf_read(void *v, pcitag_t tag, int reg) 574{ 575 return 0xffffffff; 576} 577 578void 579acpipci_dummy_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 580{ 581} 582 583struct arm64_pci_chipset acpipci_dummy_chipset = { 584 .pc_attach_hook = acpipci_attach_hook, 585 .pc_bus_maxdevs = acpipci_bus_maxdevs, 586 .pc_make_tag = acpipci_make_tag, 587 .pc_decompose_tag = acpipci_decompose_tag, 588 .pc_conf_size = acpipci_conf_size, 589 .pc_conf_read = acpipci_dummy_conf_read, 590 .pc_conf_write = acpipci_dummy_conf_write, 591}; 592 593pci_chipset_tag_t 594pci_lookup_segment(int segment) 595{ 596 struct acpipci_mcfg *am; 597 598 SLIST_FOREACH(am, &acpipci_mcfgs, am_list) { 599 if (am->am_segment == segment) 600 return &am->am_pc; 601 } 602 603 return &acpipci_dummy_chipset; 604} 605 606/* 607 * IORT support. 608 */ 609 610uint32_t acpipci_iort_map(struct acpi_iort *, uint32_t, uint32_t); 611 612uint32_t 613acpipci_iort_map_node(struct acpi_iort *iort, 614 struct acpi_iort_node *node, uint32_t id) 615{ 616 struct acpi_iort_mapping *map = 617 (struct acpi_iort_mapping *)((char *)node + node->mapping_offset); 618 int i; 619 620 for (i = 0; i < node->number_of_mappings; i++) { 621 uint32_t offset = map[i].output_reference; 622 623 if (map[i].flags & ACPI_IORT_MAPPING_SINGLE) { 624 id = map[i].output_base; 625 return acpipci_iort_map(iort, offset, id); 626 } 627 628 /* Mapping encodes number of IDs in the range minus one. */ 629 if (map[i].input_base <= id && 630 id <= map[i].input_base + map[i].number_of_ids) { 631 id = map[i].output_base + (id - map[i].input_base); 632 return acpipci_iort_map(iort, offset, id); 633 } 634 } 635 636 return id; 637} 638 639uint32_t 640acpipci_iort_map(struct acpi_iort *iort, uint32_t offset, uint32_t id) 641{ 642 struct acpi_iort_node *node = 643 (struct acpi_iort_node *)((char *)iort + offset); 644 645 switch (node->type) { 646 case ACPI_IORT_ITS: 647 return id; 648 case ACPI_IORT_SMMU: 649 return acpipci_iort_map_node(iort, node, id); 650 } 651 652 return id; 653} 654 655uint32_t 656acpipci_iort_map_msi(pci_chipset_tag_t pc, pcitag_t tag) 657{ 658 struct acpipci_softc *sc = pc->pc_intr_v; 659 struct acpi_table_header *hdr; 660 struct acpi_iort *iort = NULL; 661 struct acpi_iort_node *node; 662 struct acpi_iort_rc_node *rc; 663 struct acpi_q *entry; 664 uint32_t rid, offset; 665 int i; 666 667 rid = pci_requester_id(pc, tag); 668 669 /* Look for IORT table. */ 670 SIMPLEQ_FOREACH(entry, &sc->sc_acpi->sc_tables, q_next) { 671 hdr = entry->q_table; 672 if (strncmp(hdr->signature, IORT_SIG, 673 sizeof(hdr->signature)) == 0) { 674 iort = entry->q_table; 675 break; 676 } 677 } 678 if (iort == NULL) 679 return rid; 680 681 /* Find our root complex and map. */ 682 offset = iort->offset; 683 for (i = 0; i < iort->number_of_nodes; i++) { 684 node = (struct acpi_iort_node *)((char *)iort + offset); 685 switch (node->type) { 686 case ACPI_IORT_ROOT_COMPLEX: 687 rc = (struct acpi_iort_rc_node *)&node[1]; 688 if (rc->segment == sc->sc_seg) 689 return acpipci_iort_map_node(iort, node, rid); 690 break; 691 } 692 offset += node->length; 693 } 694 695 return rid; 696} 697