1 /* $OpenBSD: bcm2711_pcie.c,v 1.13 2024/03/27 15:15:00 patrick Exp $ */ 2 /* 3 * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> 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/systm.h> 20 #include <sys/device.h> 21 #include <sys/extent.h> 22 #include <sys/malloc.h> 23 24 #include <machine/intr.h> 25 #include <machine/bus.h> 26 #include <machine/fdt.h> 27 #include <machine/simplebusvar.h> 28 29 #include <dev/pci/pcidevs.h> 30 #include <dev/pci/pcireg.h> 31 #include <dev/pci/pcivar.h> 32 #include <dev/pci/ppbreg.h> 33 34 #include <dev/ofw/openfirm.h> 35 #include <dev/ofw/fdt.h> 36 37 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c 38 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010 39 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070 40 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080 41 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084 42 #define PCIE_EXT_CFG_DATA 0x8000 43 #define PCIE_EXT_CFG_INDEX 0x9000 44 #define PCIE_RGR1_SW_INIT_1 0x9210 45 #define PCIE_RGR1_SW_INIT_1_PERST_MASK (1 << 0) 46 #define PCIE_RGR1_SW_INIT_1_INIT_MASK (1 << 1) 47 48 #define HREAD4(sc, reg) \ 49 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 50 #define HWRITE4(sc, reg, val) \ 51 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 52 53 struct bcmpcie_range { 54 uint32_t flags; 55 uint64_t pci_base; 56 uint64_t phys_base; 57 uint64_t size; 58 }; 59 60 struct bcmpcie_softc { 61 struct simplebus_softc sc_sbus; 62 bus_space_tag_t sc_iot; 63 bus_space_handle_t sc_ioh; 64 bus_dma_tag_t sc_dmat; 65 66 int sc_node; 67 int sc_acells; 68 int sc_scells; 69 int sc_pacells; 70 int sc_pscells; 71 struct bcmpcie_range *sc_ranges; 72 int sc_nranges; 73 struct bcmpcie_range *sc_dmaranges; 74 int sc_ndmaranges; 75 76 struct bus_space sc_bus_iot; 77 struct bus_space sc_bus_memt; 78 79 struct machine_bus_dma_tag sc_dma; 80 81 struct machine_pci_chipset sc_pc; 82 int sc_bus; 83 }; 84 85 int bcmpcie_match(struct device *, void *, void *); 86 void bcmpcie_attach(struct device *, struct device *, void *); 87 88 const struct cfattach bcmpcie_ca = { 89 sizeof (struct bcmpcie_softc), bcmpcie_match, bcmpcie_attach 90 }; 91 92 struct cfdriver bcmpcie_cd = { 93 NULL, "bcmpcie", DV_DULL 94 }; 95 96 int 97 bcmpcie_match(struct device *parent, void *match, void *aux) 98 { 99 struct fdt_attach_args *faa = aux; 100 101 return OF_is_compatible(faa->fa_node, "brcm,bcm2711-pcie") || 102 OF_is_compatible(faa->fa_node, "brcm,bcm2712-pcie"); 103 } 104 105 int bcmpcie_submatch(struct device *, void *, void *); 106 void bcmpcie_attach_hook(struct device *, struct device *, 107 struct pcibus_attach_args *); 108 int bcmpcie_bus_maxdevs(void *, int); 109 pcitag_t bcmpcie_make_tag(void *, int, int, int); 110 void bcmpcie_decompose_tag(void *, pcitag_t, int *, int *, int *); 111 int bcmpcie_conf_size(void *, pcitag_t); 112 pcireg_t bcmpcie_conf_read(void *, pcitag_t, int); 113 void bcmpcie_conf_write(void *, pcitag_t, int, pcireg_t); 114 int bcmpcie_probe_device_hook(void *, struct pci_attach_args *); 115 116 int bcmpcie_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 117 const char *bcmpcie_intr_string(void *, pci_intr_handle_t); 118 void *bcmpcie_intr_establish(void *, pci_intr_handle_t, int, 119 struct cpu_info *, int (*)(void *), void *, char *); 120 void bcmpcie_intr_disestablish(void *, void *); 121 122 int bcmpcie_bs_iomap(bus_space_tag_t, bus_addr_t, bus_size_t, int, 123 bus_space_handle_t *); 124 int bcmpcie_bs_memmap(bus_space_tag_t, bus_addr_t, bus_size_t, int, 125 bus_space_handle_t *); 126 int bcmpcie_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, 127 bus_size_t, struct proc *, int, paddr_t *, int *, int); 128 int bcmpcie_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, 129 bus_dma_segment_t *, int, bus_size_t, int); 130 131 void 132 bcmpcie_attach(struct device *parent, struct device *self, void *aux) 133 { 134 struct bcmpcie_softc *sc = (struct bcmpcie_softc *)self; 135 struct fdt_attach_args *faa = aux; 136 struct pcibus_attach_args pba; 137 uint32_t *ranges; 138 int i, j, nranges, rangeslen; 139 uint32_t reg; 140 141 if (faa->fa_nreg < 1) { 142 printf(": no registers\n"); 143 return; 144 } 145 146 sc->sc_iot = faa->fa_iot; 147 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 148 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 149 printf(": can't map registers\n"); 150 return; 151 } 152 153 reg = HREAD4(sc, PCIE_RGR1_SW_INIT_1); 154 if (reg & PCIE_RGR1_SW_INIT_1_INIT_MASK) { 155 printf(": disabled\n"); 156 return; 157 } 158 159 sc->sc_node = faa->fa_node; 160 sc->sc_dmat = faa->fa_dmat; 161 162 sc->sc_acells = OF_getpropint(sc->sc_node, "#address-cells", 163 faa->fa_acells); 164 sc->sc_scells = OF_getpropint(sc->sc_node, "#size-cells", 165 faa->fa_scells); 166 sc->sc_pacells = faa->fa_acells; 167 sc->sc_pscells = faa->fa_scells; 168 169 /* Memory and IO space translations. */ 170 rangeslen = OF_getproplen(sc->sc_node, "ranges"); 171 if (rangeslen <= 0 || (rangeslen % sizeof(uint32_t)) || 172 (rangeslen / sizeof(uint32_t)) % (sc->sc_acells + 173 sc->sc_pacells + sc->sc_scells)) { 174 printf(": invalid ranges property\n"); 175 return; 176 } 177 178 ranges = malloc(rangeslen, M_TEMP, M_WAITOK); 179 OF_getpropintarray(sc->sc_node, "ranges", ranges, 180 rangeslen); 181 182 nranges = (rangeslen / sizeof(uint32_t)) / 183 (sc->sc_acells + sc->sc_pacells + sc->sc_scells); 184 sc->sc_ranges = mallocarray(nranges, 185 sizeof(struct bcmpcie_range), M_DEVBUF, M_WAITOK); 186 sc->sc_nranges = nranges; 187 188 for (i = 0, j = 0; i < sc->sc_nranges; i++) { 189 sc->sc_ranges[i].flags = ranges[j++]; 190 sc->sc_ranges[i].pci_base = ranges[j++]; 191 if (sc->sc_acells - 1 == 2) { 192 sc->sc_ranges[i].pci_base <<= 32; 193 sc->sc_ranges[i].pci_base |= ranges[j++]; 194 } 195 sc->sc_ranges[i].phys_base = ranges[j++]; 196 if (sc->sc_pacells == 2) { 197 sc->sc_ranges[i].phys_base <<= 32; 198 sc->sc_ranges[i].phys_base |= ranges[j++]; 199 } 200 sc->sc_ranges[i].size = ranges[j++]; 201 if (sc->sc_scells == 2) { 202 sc->sc_ranges[i].size <<= 32; 203 sc->sc_ranges[i].size |= ranges[j++]; 204 } 205 } 206 207 free(ranges, M_TEMP, rangeslen); 208 209 /* DMA translations */ 210 rangeslen = OF_getproplen(sc->sc_node, "dma-ranges"); 211 if (rangeslen > 0) { 212 if ((rangeslen % sizeof(uint32_t)) || 213 (rangeslen / sizeof(uint32_t)) % (sc->sc_acells + 214 sc->sc_pacells + sc->sc_scells)) { 215 printf(": invalid dma-ranges property\n"); 216 free(sc->sc_ranges, M_DEVBUF, 217 sc->sc_nranges * sizeof(struct bcmpcie_range)); 218 return; 219 } 220 221 ranges = malloc(rangeslen, M_TEMP, M_WAITOK); 222 OF_getpropintarray(sc->sc_node, "dma-ranges", ranges, 223 rangeslen); 224 225 nranges = (rangeslen / sizeof(uint32_t)) / 226 (sc->sc_acells + sc->sc_pacells + sc->sc_scells); 227 sc->sc_dmaranges = mallocarray(nranges, 228 sizeof(struct bcmpcie_range), M_DEVBUF, M_WAITOK); 229 sc->sc_ndmaranges = nranges; 230 231 for (i = 0, j = 0; i < sc->sc_ndmaranges; i++) { 232 sc->sc_dmaranges[i].flags = ranges[j++]; 233 sc->sc_dmaranges[i].pci_base = ranges[j++]; 234 if (sc->sc_acells - 1 == 2) { 235 sc->sc_dmaranges[i].pci_base <<= 32; 236 sc->sc_dmaranges[i].pci_base |= ranges[j++]; 237 } 238 sc->sc_dmaranges[i].phys_base = ranges[j++]; 239 if (sc->sc_pacells == 2) { 240 sc->sc_dmaranges[i].phys_base <<= 32; 241 sc->sc_dmaranges[i].phys_base |= ranges[j++]; 242 } 243 sc->sc_dmaranges[i].size = ranges[j++]; 244 if (sc->sc_scells == 2) { 245 sc->sc_dmaranges[i].size <<= 32; 246 sc->sc_dmaranges[i].size |= ranges[j++]; 247 } 248 } 249 250 free(ranges, M_TEMP, rangeslen); 251 } 252 253 /* 254 * Reprogram the outbound window to match the configuration in 255 * the device tree. This is necessary since the EDK2-based 256 * UEFI firmware reprograms the window. 257 */ 258 for (i = 0; i < sc->sc_nranges; i++) { 259 if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000) { 260 uint64_t cpu_base = sc->sc_ranges[i].phys_base; 261 uint64_t cpu_limit = sc->sc_ranges[i].phys_base + 262 sc->sc_ranges[i].size - 1; 263 264 HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO, 265 sc->sc_ranges[i].pci_base); 266 HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI, 267 sc->sc_ranges[i].pci_base >> 32); 268 HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT, 269 (cpu_base & PPB_MEM_MASK) >> PPB_MEM_SHIFT | 270 (cpu_limit & PPB_MEM_MASK)); 271 HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI, 272 cpu_base >> 32); 273 HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI, 274 cpu_limit >> 32); 275 } 276 } 277 278 memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot)); 279 sc->sc_bus_iot.bus_private = sc; 280 sc->sc_bus_iot._space_map = bcmpcie_bs_iomap; 281 memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt)); 282 sc->sc_bus_memt.bus_private = sc; 283 sc->sc_bus_memt._space_map = bcmpcie_bs_memmap; 284 285 memcpy(&sc->sc_dma, sc->sc_dmat, sizeof(sc->sc_dma)); 286 sc->sc_dma._dmamap_load_buffer = bcmpcie_dmamap_load_buffer; 287 sc->sc_dma._dmamap_load_raw = bcmpcie_dmamap_load_raw; 288 sc->sc_dma._cookie = sc; 289 290 sc->sc_pc.pc_conf_v = sc; 291 sc->sc_pc.pc_attach_hook = bcmpcie_attach_hook; 292 sc->sc_pc.pc_bus_maxdevs = bcmpcie_bus_maxdevs; 293 sc->sc_pc.pc_make_tag = bcmpcie_make_tag; 294 sc->sc_pc.pc_decompose_tag = bcmpcie_decompose_tag; 295 sc->sc_pc.pc_conf_size = bcmpcie_conf_size; 296 sc->sc_pc.pc_conf_read = bcmpcie_conf_read; 297 sc->sc_pc.pc_conf_write = bcmpcie_conf_write; 298 sc->sc_pc.pc_probe_device_hook = bcmpcie_probe_device_hook; 299 300 sc->sc_pc.pc_intr_v = sc; 301 sc->sc_pc.pc_intr_map = bcmpcie_intr_map; 302 sc->sc_pc.pc_intr_map_msi = _pci_intr_map_msi; 303 sc->sc_pc.pc_intr_map_msivec = _pci_intr_map_msivec; 304 sc->sc_pc.pc_intr_map_msix = _pci_intr_map_msix; 305 sc->sc_pc.pc_intr_string = bcmpcie_intr_string; 306 sc->sc_pc.pc_intr_establish = bcmpcie_intr_establish; 307 sc->sc_pc.pc_intr_disestablish = bcmpcie_intr_disestablish; 308 309 memset(&pba, 0, sizeof(pba)); 310 pba.pba_busname = "pci"; 311 pba.pba_iot = &sc->sc_bus_iot; 312 pba.pba_memt = &sc->sc_bus_memt; 313 pba.pba_dmat = &sc->sc_dma; 314 pba.pba_pc = &sc->sc_pc; 315 pba.pba_domain = pci_ndomains++; 316 pba.pba_bus = 0; 317 318 /* Attach device tree nodes enumerating PCIe bus */ 319 simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa); 320 321 config_found_sm(self, &pba, NULL, bcmpcie_submatch); 322 } 323 324 int 325 bcmpcie_submatch(struct device *self, void *match, void *aux) 326 { 327 struct cfdata *cf = match; 328 struct pcibus_attach_args *pba = aux; 329 330 if (strcmp(pba->pba_busname, cf->cf_driver->cd_name) != 0) 331 return 0; 332 333 return (*cf->cf_attach->ca_match)(self, match, aux); 334 } 335 336 void 337 bcmpcie_attach_hook(struct device *parent, struct device *self, 338 struct pcibus_attach_args *pba) 339 { 340 } 341 342 int 343 bcmpcie_bus_maxdevs(void *v, int bus) 344 { 345 struct bcmpcie_softc *sc = v; 346 347 if (bus == sc->sc_bus || bus == sc->sc_bus + 1) 348 return 1; 349 return 32; 350 } 351 352 pcitag_t 353 bcmpcie_make_tag(void *v, int bus, int device, int function) 354 { 355 /* Return ECAM address. */ 356 return ((bus << 20) | (device << 15) | (function << 12)); 357 } 358 359 void 360 bcmpcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 361 { 362 if (bp != NULL) 363 *bp = (tag >> 20) & 0xff; 364 if (dp != NULL) 365 *dp = (tag >> 15) & 0x1f; 366 if (fp != NULL) 367 *fp = (tag >> 12) & 0x7; 368 } 369 370 int 371 bcmpcie_conf_size(void *v, pcitag_t tag) 372 { 373 return PCIE_CONFIG_SPACE_SIZE; 374 } 375 376 pcireg_t 377 bcmpcie_conf_read(void *v, pcitag_t tag, int reg) 378 { 379 struct bcmpcie_softc *sc = v; 380 int bus, dev, fn; 381 382 bcmpcie_decompose_tag(sc, tag, &bus, &dev, &fn); 383 if (bus == 0) { 384 KASSERT(dev == 0); 385 return HREAD4(sc, tag | reg); 386 } 387 388 HWRITE4(sc, PCIE_EXT_CFG_INDEX, tag); 389 return HREAD4(sc, PCIE_EXT_CFG_DATA + reg); 390 } 391 392 void 393 bcmpcie_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 394 { 395 struct bcmpcie_softc *sc = v; 396 int bus, dev, fn; 397 398 bcmpcie_decompose_tag(sc, tag, &bus, &dev, &fn); 399 if (bus == 0) { 400 KASSERT(dev == 0); 401 HWRITE4(sc, tag | reg, data); 402 return; 403 } 404 405 HWRITE4(sc, PCIE_EXT_CFG_INDEX, tag); 406 HWRITE4(sc, PCIE_EXT_CFG_DATA + reg, data); 407 } 408 409 int 410 bcmpcie_probe_device_hook(void *v, struct pci_attach_args *pa) 411 { 412 return 0; 413 } 414 415 int 416 bcmpcie_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 417 { 418 int pin = pa->pa_rawintrpin; 419 420 if (pin == 0 || pin > PCI_INTERRUPT_PIN_MAX) 421 return -1; 422 423 if (pa->pa_tag == 0) 424 return -1; 425 426 ihp->ih_pc = pa->pa_pc; 427 ihp->ih_tag = pa->pa_intrtag; 428 ihp->ih_intrpin = pa->pa_intrpin; 429 ihp->ih_type = PCI_INTX; 430 431 return 0; 432 } 433 434 const char * 435 bcmpcie_intr_string(void *v, pci_intr_handle_t ih) 436 { 437 switch (ih.ih_type) { 438 case PCI_MSI: 439 return "msi"; 440 case PCI_MSIX: 441 return "msix"; 442 } 443 444 return "intx"; 445 } 446 447 void * 448 bcmpcie_intr_establish(void *v, pci_intr_handle_t ih, int level, 449 struct cpu_info *ci, int (*func)(void *), void *arg, char *name) 450 { 451 struct bcmpcie_softc *sc = v; 452 int bus, dev, fn; 453 uint32_t reg[4]; 454 455 KASSERT(ih.ih_type == PCI_INTX); 456 bcmpcie_decompose_tag(sc, ih.ih_tag, &bus, &dev, &fn); 457 458 reg[0] = bus << 16 | dev << 11 | fn << 8; 459 reg[1] = reg[2] = 0; 460 reg[3] = ih.ih_intrpin; 461 462 return fdt_intr_establish_imap_cpu(sc->sc_node, reg, sizeof(reg), 463 level, ci, func, arg, name); 464 } 465 466 void 467 bcmpcie_intr_disestablish(void *v, void *cookie) 468 { 469 } 470 471 int 472 bcmpcie_bs_iomap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 473 int flags, bus_space_handle_t *bshp) 474 { 475 struct bcmpcie_softc *sc = t->bus_private; 476 int i; 477 478 for (i = 0; i < sc->sc_nranges; i++) { 479 uint64_t pci_start = sc->sc_ranges[i].pci_base; 480 uint64_t pci_end = pci_start + sc->sc_ranges[i].size; 481 uint64_t phys_start = sc->sc_ranges[i].phys_base; 482 483 if ((sc->sc_ranges[i].flags & 0x03000000) == 0x01000000 && 484 addr >= pci_start && addr + size <= pci_end) { 485 return bus_space_map(sc->sc_iot, 486 addr - pci_start + phys_start, size, flags, bshp); 487 } 488 } 489 490 return ENXIO; 491 } 492 493 int 494 bcmpcie_bs_memmap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 495 int flags, bus_space_handle_t *bshp) 496 { 497 struct bcmpcie_softc *sc = t->bus_private; 498 int i; 499 500 for (i = 0; i < sc->sc_nranges; i++) { 501 uint64_t pci_start = sc->sc_ranges[i].pci_base; 502 uint64_t pci_end = pci_start + sc->sc_ranges[i].size; 503 uint64_t phys_start = sc->sc_ranges[i].phys_base; 504 505 if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000 && 506 addr >= pci_start && addr + size <= pci_end) { 507 return bus_space_map(sc->sc_iot, 508 addr - pci_start + phys_start, size, flags, bshp); 509 } 510 } 511 512 return ENXIO; 513 } 514 515 int 516 bcmpcie_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, 517 bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp, 518 int *segp, int first) 519 { 520 struct bcmpcie_softc *sc = t->_cookie; 521 int seg, firstseg = *segp; 522 int error; 523 524 error = sc->sc_dmat->_dmamap_load_buffer(sc->sc_dmat, map, buf, buflen, 525 p, flags, lastaddrp, segp, first); 526 if (error) 527 return error; 528 529 if (sc->sc_dmaranges == NULL) 530 return 0; 531 532 /* For each segment. */ 533 for (seg = firstseg; seg <= *segp; seg++) { 534 uint64_t addr = map->dm_segs[seg].ds_addr; 535 uint64_t size = map->dm_segs[seg].ds_len; 536 int i; 537 538 /* For each range. */ 539 for (i = 0; i < sc->sc_ndmaranges; i++) { 540 uint64_t pci_start = sc->sc_dmaranges[i].pci_base; 541 uint64_t phys_start = sc->sc_dmaranges[i].phys_base; 542 uint64_t phys_end = phys_start + 543 sc->sc_dmaranges[i].size; 544 545 if (addr >= phys_start && addr + size <= phys_end) { 546 map->dm_segs[seg].ds_addr -= phys_start; 547 map->dm_segs[seg].ds_addr += pci_start; 548 break; 549 } 550 } 551 552 if (i == sc->sc_ndmaranges) 553 return EINVAL; 554 } 555 556 return 0; 557 } 558 559 int 560 bcmpcie_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, 561 bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) 562 { 563 struct bcmpcie_softc *sc = t->_cookie; 564 int seg, error; 565 566 error = sc->sc_dmat->_dmamap_load_raw(sc->sc_dmat, map, 567 segs, nsegs, size, flags); 568 if (error) 569 return error; 570 571 if (sc->sc_dmaranges == NULL) 572 return 0; 573 574 /* For each segment. */ 575 for (seg = 0; seg < map->dm_nsegs; seg++) { 576 uint64_t addr = map->dm_segs[seg].ds_addr; 577 uint64_t size = map->dm_segs[seg].ds_len; 578 int i; 579 580 /* For each range. */ 581 for (i = 0; i < sc->sc_ndmaranges; i++) { 582 uint64_t pci_start = sc->sc_dmaranges[i].pci_base; 583 uint64_t phys_start = sc->sc_dmaranges[i].phys_base; 584 uint64_t phys_end = phys_start + 585 sc->sc_dmaranges[i].size; 586 587 if (addr >= phys_start && addr + size <= phys_end) { 588 map->dm_segs[seg].ds_addr -= phys_start; 589 map->dm_segs[seg].ds_addr += pci_start; 590 break; 591 } 592 } 593 594 if (i == sc->sc_ndmaranges) 595 return EINVAL; 596 } 597 598 return 0; 599 } 600