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