acpipci.c revision 1.6
1/* $OpenBSD: acpipci.c,v 1.6 2018/08/11 22:47:27 kettenis 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 37bus_addr_t pci_mcfg_addr; 38int pci_mcfg_min_bus, pci_mcfg_max_bus; 39bus_space_tag_t pci_mcfgt; 40bus_space_handle_t pci_mcfgh; 41 42struct acpipci_trans { 43 struct acpipci_trans *at_next; 44 bus_space_tag_t at_iot; 45 bus_addr_t at_base; 46 bus_size_t at_size; 47 bus_size_t at_offset; 48}; 49 50struct acpipci_softc { 51 struct device sc_dev; 52 struct acpi_softc *sc_acpi; 53 struct aml_node *sc_node; 54 55 bus_space_tag_t sc_iot; 56 bus_space_handle_t sc_ioh; 57 58 struct bus_space sc_bus_iot; 59 struct bus_space sc_bus_memt; 60 struct acpipci_trans *sc_io_trans; 61 struct acpipci_trans *sc_mem_trans; 62 63 struct arm64_pci_chipset sc_pc; 64 struct extent *sc_busex; 65 struct extent *sc_memex; 66 struct extent *sc_ioex; 67 char sc_busex_name[32]; 68 char sc_ioex_name[32]; 69 char sc_memex_name[32]; 70 int sc_bus; 71 uint32_t sc_seg; 72}; 73 74int acpipci_match(struct device *, void *, void *); 75void acpipci_attach(struct device *, struct device *, void *); 76 77struct cfattach acpipci_ca = { 78 sizeof(struct acpipci_softc), acpipci_match, acpipci_attach 79}; 80 81struct cfdriver acpipci_cd = { 82 NULL, "acpipci", DV_DULL 83}; 84 85const char *acpipci_hids[] = { 86 "PNP0A08", 87 NULL 88}; 89 90int acpipci_parse_resources(int, union acpi_resource *, void *); 91int acpipci_bs_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, 92 bus_space_handle_t *); 93 94void acpipci_attach_hook(struct device *, struct device *, 95 struct pcibus_attach_args *); 96int acpipci_bus_maxdevs(void *, int); 97pcitag_t acpipci_make_tag(void *, int, int, int); 98void acpipci_decompose_tag(void *, pcitag_t, int *, int *, int *); 99int acpipci_conf_size(void *, pcitag_t); 100pcireg_t acpipci_conf_read(void *, pcitag_t, int); 101void acpipci_conf_write(void *, pcitag_t, int, pcireg_t); 102 103int acpipci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 104int acpipci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); 105int acpipci_intr_map_msix(struct pci_attach_args *, int, 106 pci_intr_handle_t *); 107const char *acpipci_intr_string(void *, pci_intr_handle_t); 108void *acpipci_intr_establish(void *, pci_intr_handle_t, int, 109 int (*)(void *), void *, char *); 110void acpipci_intr_disestablish(void *, void *); 111 112uint32_t acpipci_iort_map_msi(pci_chipset_tag_t, pcitag_t); 113 114int 115acpipci_match(struct device *parent, void *match, void *aux) 116{ 117 struct acpi_attach_args *aaa = aux; 118 struct cfdata *cf = match; 119 120 return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name); 121} 122 123void 124acpipci_attach(struct device *parent, struct device *self, void *aux) 125{ 126 struct acpi_attach_args *aaa = aux; 127 struct acpipci_softc *sc = (struct acpipci_softc *)self; 128 struct pcibus_attach_args pba; 129 struct aml_value res; 130 uint64_t bbn = 0; 131 uint64_t seg = 0; 132 133 /* Bail out early if we don't have a valid MCFG table. */ 134 if (pci_mcfg_addr == 0 || pci_mcfg_max_bus <= pci_mcfg_min_bus) { 135 printf(": no registers\n"); 136 return; 137 } 138 139 sc->sc_acpi = (struct acpi_softc *)parent; 140 sc->sc_node = aaa->aaa_node; 141 printf(" %s", sc->sc_node->name); 142 143 if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { 144 printf(": can't find resources\n"); 145 return; 146 } 147 148 aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn); 149 sc->sc_bus = bbn; 150 151 aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL, &seg); 152 sc->sc_seg = seg; 153 154 sc->sc_iot = pci_mcfgt; 155 sc->sc_ioh = pci_mcfgh; 156 157 printf("\n"); 158 159 /* XXX We only support segment 0 for now. */ 160 if (seg != 0) 161 return; 162 163 /* Create extents for our address spaces. */ 164 snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name), 165 "%s pcibus", sc->sc_dev.dv_xname); 166 snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name), 167 "%s pciio", sc->sc_dev.dv_xname); 168 snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name), 169 "%s pcimem", sc->sc_dev.dv_xname); 170 sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255, 171 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 172 sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff, 173 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 174 sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1, 175 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 176 177 aml_parse_resource(&res, acpipci_parse_resources, sc); 178 179 memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot)); 180 sc->sc_bus_iot.bus_private = sc->sc_io_trans; 181 sc->sc_bus_iot._space_map = acpipci_bs_map; 182 memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt)); 183 sc->sc_bus_memt.bus_private = sc->sc_mem_trans; 184 sc->sc_bus_memt._space_map = acpipci_bs_map; 185 186 sc->sc_pc.pc_conf_v = sc; 187 sc->sc_pc.pc_attach_hook = acpipci_attach_hook; 188 sc->sc_pc.pc_bus_maxdevs = acpipci_bus_maxdevs; 189 sc->sc_pc.pc_make_tag = acpipci_make_tag; 190 sc->sc_pc.pc_decompose_tag = acpipci_decompose_tag; 191 sc->sc_pc.pc_conf_size = acpipci_conf_size; 192 sc->sc_pc.pc_conf_read = acpipci_conf_read; 193 sc->sc_pc.pc_conf_write = acpipci_conf_write; 194 195 sc->sc_pc.pc_intr_v = sc; 196 sc->sc_pc.pc_intr_map = acpipci_intr_map; 197 sc->sc_pc.pc_intr_map_msi = acpipci_intr_map_msi; 198 sc->sc_pc.pc_intr_map_msix = acpipci_intr_map_msix; 199 sc->sc_pc.pc_intr_string = acpipci_intr_string; 200 sc->sc_pc.pc_intr_establish = acpipci_intr_establish; 201 sc->sc_pc.pc_intr_disestablish = acpipci_intr_disestablish; 202 203 memset(&pba, 0, sizeof(pba)); 204 pba.pba_busname = "pci"; 205 pba.pba_iot = &sc->sc_bus_iot; 206 pba.pba_memt = &sc->sc_bus_memt; 207 pba.pba_dmat = aaa->aaa_dmat; 208 pba.pba_pc = &sc->sc_pc; 209 pba.pba_busex = sc->sc_busex; 210 pba.pba_ioex = sc->sc_ioex; 211 pba.pba_memex = sc->sc_memex; 212 pba.pba_domain = pci_ndomains++; 213 pba.pba_bus = sc->sc_bus; 214 pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; 215 216 config_found(self, &pba, NULL); 217} 218 219int 220acpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg) 221{ 222 struct acpipci_softc *sc = arg; 223 struct acpipci_trans *at; 224 int type = AML_CRSTYPE(crs); 225 int restype, tflags; 226 u_long min, len = 0, tra; 227 228 switch (type) { 229 case LR_WORD: 230 restype = crs->lr_word.type; 231 tflags = crs->lr_word.tflags; 232 min = crs->lr_word._min; 233 len = crs->lr_word._len; 234 tra = crs->lr_word._tra; 235 break; 236 case LR_DWORD: 237 restype = crs->lr_dword.type; 238 tflags = crs->lr_dword.tflags; 239 min = crs->lr_dword._min; 240 len = crs->lr_dword._len; 241 tra = crs->lr_dword._tra; 242 break; 243 case LR_QWORD: 244 restype = crs->lr_qword.type; 245 tflags = crs->lr_qword.tflags; 246 min = crs->lr_qword._min; 247 len = crs->lr_qword._len; 248 tra = crs->lr_qword._tra; 249 break; 250 } 251 252 if (len == 0) 253 return 0; 254 255 switch (restype) { 256 case LR_TYPE_MEMORY: 257 if (tflags & LR_MEMORY_TTP) 258 return 0; 259 extent_free(sc->sc_memex, min, len, EX_WAITOK); 260 at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK); 261 at->at_iot = sc->sc_iot; 262 at->at_base = min; 263 at->at_size = len; 264 at->at_offset = tra; 265 at->at_next = sc->sc_mem_trans; 266 sc->sc_mem_trans = at; 267 break; 268 case LR_TYPE_IO: 269 if ((tflags & LR_IO_TTP) == 0) 270 return 0; 271 extent_free(sc->sc_ioex, min, len, EX_WAITOK); 272 at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK); 273 at->at_iot = sc->sc_iot; 274 at->at_base = min; 275 at->at_size = len; 276 at->at_offset = tra; 277 at->at_next = sc->sc_io_trans; 278 sc->sc_io_trans = at; 279 break; 280 case LR_TYPE_BUS: 281 extent_free(sc->sc_busex, min, len, EX_WAITOK); 282 break; 283 } 284 285 return 0; 286} 287 288void 289acpipci_attach_hook(struct device *parent, struct device *self, 290 struct pcibus_attach_args *pba) 291{ 292} 293 294int 295acpipci_bus_maxdevs(void *v, int bus) 296{ 297 return 32; 298} 299 300pcitag_t 301acpipci_make_tag(void *v, int bus, int device, int function) 302{ 303 return ((bus << 20) | (device << 15) | (function << 12)); 304} 305 306void 307acpipci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 308{ 309 if (bp != NULL) 310 *bp = (tag >> 20) & 0xff; 311 if (dp != NULL) 312 *dp = (tag >> 15) & 0x1f; 313 if (fp != NULL) 314 *fp = (tag >> 12) & 0x7; 315} 316 317int 318acpipci_conf_size(void *v, pcitag_t tag) 319{ 320 return PCIE_CONFIG_SPACE_SIZE; 321} 322 323pcireg_t 324acpipci_conf_read(void *v, pcitag_t tag, int reg) 325{ 326 struct acpipci_softc *sc = v; 327 328 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, tag | reg); 329} 330 331void 332acpipci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 333{ 334 struct acpipci_softc *sc = v; 335 336 bus_space_write_4(sc->sc_iot, sc->sc_ioh, tag | reg, data); 337} 338 339struct acpipci_intr_handle { 340 pci_chipset_tag_t ih_pc; 341 pcitag_t ih_tag; 342 int ih_intrpin; 343 int ih_msi; 344}; 345 346int 347acpipci_intr_swizzle(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 348{ 349 struct acpipci_intr_handle *ih; 350 int dev, swizpin; 351 352 if (pa->pa_bridgetag == NULL) 353 return -1; 354 355 pci_decompose_tag(pa->pa_pc, pa->pa_tag, NULL, &dev, NULL); 356 swizpin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin, dev); 357 if ((void *)pa->pa_bridgeih[swizpin - 1] == NULL) 358 return -1; 359 360 ih = malloc(sizeof(struct acpipci_intr_handle), M_DEVBUF, M_WAITOK); 361 memcpy(ih, (void *)pa->pa_bridgeih[swizpin - 1], 362 sizeof(struct acpipci_intr_handle)); 363 *ihp = (pci_intr_handle_t)ih; 364 365 return 0; 366} 367 368int 369acpipci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 370{ 371 struct acpipci_softc *sc = pa->pa_pc->pc_intr_v; 372 struct aml_node *node = sc->sc_node; 373 struct aml_value res; 374 uint64_t addr, pin, source, index; 375 struct acpipci_intr_handle *ih; 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 ih = malloc(sizeof(struct acpipci_intr_handle), 419 M_DEVBUF, M_WAITOK); 420 ih->ih_pc = pa->pa_pc; 421 ih->ih_tag = pa->pa_tag; 422 ih->ih_intrpin = index; 423 ih->ih_msi = 0; 424 *ihp = (pci_intr_handle_t)ih; 425 426 return 0; 427 } 428 429 return -1; 430} 431 432int 433acpipci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 434{ 435 pci_chipset_tag_t pc = pa->pa_pc; 436 pcitag_t tag = pa->pa_tag; 437 struct acpipci_intr_handle *ih; 438 439 if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 || 440 pci_get_capability(pc, tag, PCI_CAP_MSI, NULL, NULL) == 0) 441 return -1; 442 443 ih = malloc(sizeof(struct acpipci_intr_handle), M_DEVBUF, M_WAITOK); 444 ih->ih_pc = pa->pa_pc; 445 ih->ih_tag = pa->pa_tag; 446 ih->ih_intrpin = pa->pa_intrpin; 447 ih->ih_msi = 1; 448 *ihp = (pci_intr_handle_t)ih; 449 450 return 0; 451} 452 453int 454acpipci_intr_map_msix(struct pci_attach_args *pa, int vec, 455 pci_intr_handle_t *ihp) 456{ 457 return -1; 458} 459 460const char * 461acpipci_intr_string(void *v, pci_intr_handle_t ihp) 462{ 463 struct acpipci_intr_handle *ih = (struct acpipci_intr_handle *)ihp; 464 static char irqstr[32]; 465 466 if (ih->ih_msi) 467 return "msi"; 468 469 snprintf(irqstr, sizeof(irqstr), "irq %d", ih->ih_intrpin); 470 return irqstr; 471} 472 473void * 474acpipci_intr_establish(void *v, pci_intr_handle_t ihp, int level, 475 int (*func)(void *), void *arg, char *name) 476{ 477 struct acpipci_intr_handle *ih = (struct acpipci_intr_handle *)ihp; 478 struct interrupt_controller *ic; 479 void *cookie; 480 481 extern LIST_HEAD(, interrupt_controller) interrupt_controllers; 482 LIST_FOREACH(ic, &interrupt_controllers, ic_list) { 483 if (ic->ic_establish_msi) 484 break; 485 } 486 if (ic == NULL) 487 return NULL; 488 489 if (ih->ih_msi) { 490 uint64_t addr, data; 491 pcireg_t reg; 492 int off; 493 494 /* Map Requester ID through IORT to get sideband data. */ 495 data = acpipci_iort_map_msi(ih->ih_pc, ih->ih_tag); 496 cookie = ic->ic_establish_msi(ic->ic_cookie, &addr, 497 &data, level, func, arg, name); 498 if (cookie == NULL) 499 return NULL; 500 501 /* TODO: translate address to the PCI device's view */ 502 503 if (pci_get_capability(ih->ih_pc, ih->ih_tag, PCI_CAP_MSI, 504 &off, ®) == 0) 505 panic("%s: no msi capability", __func__); 506 507 if (reg & PCI_MSI_MC_C64) { 508 pci_conf_write(ih->ih_pc, ih->ih_tag, 509 off + PCI_MSI_MA, addr); 510 pci_conf_write(ih->ih_pc, ih->ih_tag, 511 off + PCI_MSI_MAU32, addr >> 32); 512 pci_conf_write(ih->ih_pc, ih->ih_tag, 513 off + PCI_MSI_MD64, data); 514 } else { 515 pci_conf_write(ih->ih_pc, ih->ih_tag, 516 off + PCI_MSI_MA, addr); 517 pci_conf_write(ih->ih_pc, ih->ih_tag, 518 off + PCI_MSI_MD32, data); 519 } 520 pci_conf_write(ih->ih_pc, ih->ih_tag, 521 off, reg | PCI_MSI_MC_MSIE); 522 } else { 523 cookie = acpi_intr_establish(ih->ih_intrpin, 0, level, 524 func, arg, name); 525 } 526 527 free(ih, M_DEVBUF, sizeof(struct acpipci_intr_handle)); 528 return cookie; 529} 530 531void 532acpipci_intr_disestablish(void *v, void *cookie) 533{ 534 panic("%s", __func__); 535} 536 537/* 538 * Translate memory address if needed. 539 */ 540int 541acpipci_bs_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 542 int flags, bus_space_handle_t *bshp) 543{ 544 struct acpipci_trans *at; 545 546 for (at = t->bus_private; at; at = at->at_next) { 547 if (addr >= at->at_base && addr < at->at_base + at->at_size) { 548 return bus_space_map(at->at_iot, 549 addr + at->at_offset, size, flags, bshp); 550 } 551 } 552 553 return ENXIO; 554} 555 556struct arm64_pci_chipset pci_mcfg_chipset; 557 558pcireg_t 559pci_mcfg_conf_read(void *v, pcitag_t tag, int reg) 560{ 561 return bus_space_read_4(pci_mcfgt, pci_mcfgh, tag | reg); 562} 563 564void 565pci_mcfg_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 566{ 567 bus_space_write_4(pci_mcfgt, pci_mcfgh, tag | reg, data); 568} 569 570pci_chipset_tag_t 571pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int min_bus, int max_bus) 572{ 573 pci_chipset_tag_t pc = &pci_mcfg_chipset; 574 575 pci_mcfgt = iot; 576 pci_mcfg_addr = addr; 577 pci_mcfg_min_bus = min_bus; 578 pci_mcfg_max_bus = max_bus; 579 580 if (bus_space_map(iot, addr, (pci_mcfg_max_bus + 1) << 20, 0, 581 &pci_mcfgh)) 582 panic("%s: can't map config space", __func__); 583 584 memset(pc, 0, sizeof(*pc)); 585 pc->pc_bus_maxdevs = acpipci_bus_maxdevs; 586 pc->pc_make_tag = acpipci_make_tag; 587 pc->pc_decompose_tag = acpipci_decompose_tag; 588 pc->pc_conf_size = acpipci_conf_size; 589 pc->pc_conf_read = pci_mcfg_conf_read; 590 pc->pc_conf_write = pci_mcfg_conf_write; 591 592 return pc; 593} 594 595/* 596 * IORT support. 597 */ 598 599struct acpi_iort { 600 struct acpi_table_header hdr; 601#define IORT_SIG "IORT" 602 uint32_t number_of_nodes; 603 uint32_t offset; 604 uint32_t reserved; 605} __packed; 606 607struct acpi_iort_node { 608 uint8_t type; 609#define ACPI_IORT_ITS 0 610#define ACPI_IORT_ROOT_COMPLEX 2 611 uint16_t length; 612 uint8_t revision; 613 uint32_t reserved1; 614 uint32_t number_of_mappings; 615 uint32_t mapping_offset; 616 uint64_t memory_access_properties; 617 uint32_t atf_attributes; 618 uint32_t segment; 619 uint8_t memory_address_size_limit; 620 uint8_t reserved2[3]; 621} __packed; 622 623struct acpi_iort_mapping { 624 uint32_t input_base; 625 uint32_t length; 626 uint32_t output_base; 627 uint32_t output_reference; 628 uint32_t flags; 629#define ACPI_IORT_MAPPING_SINGLE 0x00000001 630} __packed; 631 632uint32_t 633acpipci_iort_map_node(struct acpi_iort_node *node, uint32_t id, uint32_t reference) 634{ 635 struct acpi_iort_mapping *map = 636 (struct acpi_iort_mapping *)((char *)node + node->mapping_offset); 637 int i; 638 639 for (i = 0; i < node->number_of_mappings; i++) { 640 if (map[i].output_reference != reference) 641 continue; 642 643 if (map[i].flags & ACPI_IORT_MAPPING_SINGLE) 644 return map[i].output_base; 645 646 if (map[i].input_base <= id && 647 id < map[i].input_base + map[i].length) 648 return map[i].output_base + (id - map[i].input_base); 649 } 650 651 return id; 652} 653 654uint32_t 655acpipci_iort_map_msi(pci_chipset_tag_t pc, pcitag_t tag) 656{ 657 struct acpipci_softc *sc = pc->pc_intr_v; 658 struct acpi_table_header *hdr; 659 struct acpi_iort *iort = NULL; 660 struct acpi_iort_node *node; 661 struct acpi_q *entry; 662 uint32_t rid, its = 0; 663 uint32_t offset; 664 int i; 665 666 rid = pci_requester_id(pc, tag); 667 668 /* Look for IORT table. */ 669 SIMPLEQ_FOREACH(entry, &sc->sc_acpi->sc_tables, q_next) { 670 hdr = entry->q_table; 671 if (strncmp(hdr->signature, IORT_SIG, 672 sizeof(hdr->signature)) == 0) { 673 iort = entry->q_table; 674 break; 675 } 676 } 677 if (iort == NULL) 678 return rid; 679 680 /* Find reference to ITS group. */ 681 offset = iort->offset; 682 for (i = 0; i < iort->number_of_nodes; i++) { 683 node = (struct acpi_iort_node *)((char *)iort + offset); 684 switch (node->type) { 685 case ACPI_IORT_ITS: 686 its = offset; 687 break; 688 } 689 offset += node->length; 690 } 691 if (its == 0) 692 return rid; 693 694 /* Find our root complex and map. */ 695 offset = iort->offset; 696 for (i = 0; i < iort->number_of_nodes; i++) { 697 node = (struct acpi_iort_node *)((char *)iort + offset); 698 switch (node->type) { 699 case ACPI_IORT_ROOT_COMPLEX: 700 if (node->segment == sc->sc_seg) 701 return acpipci_iort_map_node(node, rid, its); 702 break; 703 } 704 offset += node->length; 705 } 706 707 return rid; 708} 709