1 /*- 2 * Copyright (c) 2011 Nathan Whitehorn 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/param.h> 28 #include <sys/systm.h> 29 #include <sys/module.h> 30 #include <sys/bus.h> 31 #include <sys/conf.h> 32 #include <sys/kernel.h> 33 #include <sys/rman.h> 34 35 #include <dev/ofw/openfirm.h> 36 #include <dev/ofw/ofw_pci.h> 37 #include <dev/ofw/ofw_bus.h> 38 #include <dev/ofw/ofw_bus_subr.h> 39 #include <dev/ofw/ofwpci.h> 40 41 #include <dev/pci/pcivar.h> 42 #include <dev/pci/pcireg.h> 43 #include <dev/pci/pcib_private.h> 44 45 #include <machine/bus.h> 46 #include <machine/md_var.h> 47 #include <machine/resource.h> 48 49 #include <vm/vm.h> 50 #include <vm/pmap.h> 51 52 #include "pcib_if.h" 53 54 /* 55 * If it is necessary to set another value of this for 56 * some platforms it should be set at fdt.h file 57 */ 58 #ifndef PCI_MAP_INTR 59 #define PCI_MAP_INTR 4 60 #endif 61 62 #define PCI_INTR_PINS 4 63 64 /* 65 * bus interface. 66 */ 67 static struct resource * ofw_pcib_alloc_resource(device_t, device_t, 68 int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); 69 static int ofw_pcib_release_resource(device_t, device_t, int, int, 70 struct resource *); 71 static int ofw_pcib_activate_resource(device_t, device_t, int, int, 72 struct resource *); 73 static int ofw_pcib_deactivate_resource(device_t, device_t, int, int, 74 struct resource *); 75 static int ofw_pcib_adjust_resource(device_t, device_t, int, 76 struct resource *, rman_res_t, rman_res_t); 77 static int ofw_pcib_translate_resource(device_t bus, int type, 78 rman_res_t start, rman_res_t *newstart); 79 80 #ifdef __powerpc__ 81 static bus_space_tag_t ofw_pcib_bus_get_bus_tag(device_t, device_t); 82 #endif 83 84 /* 85 * pcib interface 86 */ 87 static int ofw_pcib_maxslots(device_t); 88 89 /* 90 * ofw_bus interface 91 */ 92 static phandle_t ofw_pcib_get_node(device_t, device_t); 93 94 /* 95 * local methods 96 */ 97 static int ofw_pcib_fill_ranges(phandle_t, struct ofw_pci_range *); 98 static struct rman *ofw_pcib_get_rman(struct ofw_pci_softc *, int, u_int); 99 100 /* 101 * Driver methods. 102 */ 103 static device_method_t ofw_pcib_methods[] = { 104 /* Device interface */ 105 DEVMETHOD(device_attach, ofw_pcib_attach), 106 107 /* Bus interface */ 108 DEVMETHOD(bus_print_child, bus_generic_print_child), 109 DEVMETHOD(bus_read_ivar, ofw_pcib_read_ivar), 110 DEVMETHOD(bus_write_ivar, ofw_pcib_write_ivar), 111 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 112 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 113 DEVMETHOD(bus_alloc_resource, ofw_pcib_alloc_resource), 114 DEVMETHOD(bus_release_resource, ofw_pcib_release_resource), 115 DEVMETHOD(bus_activate_resource, ofw_pcib_activate_resource), 116 DEVMETHOD(bus_deactivate_resource, ofw_pcib_deactivate_resource), 117 DEVMETHOD(bus_adjust_resource, ofw_pcib_adjust_resource), 118 DEVMETHOD(bus_translate_resource, ofw_pcib_translate_resource), 119 #ifdef __powerpc__ 120 DEVMETHOD(bus_get_bus_tag, ofw_pcib_bus_get_bus_tag), 121 #endif 122 123 /* pcib interface */ 124 DEVMETHOD(pcib_maxslots, ofw_pcib_maxslots), 125 DEVMETHOD(pcib_route_interrupt, ofw_pcib_route_interrupt), 126 DEVMETHOD(pcib_request_feature, pcib_request_feature_allow), 127 128 /* ofw_bus interface */ 129 DEVMETHOD(ofw_bus_get_node, ofw_pcib_get_node), 130 131 DEVMETHOD_END 132 }; 133 134 DEFINE_CLASS_0(ofw_pcib, ofw_pcib_driver, ofw_pcib_methods, 0); 135 136 int 137 ofw_pcib_init(device_t dev) 138 { 139 struct ofw_pci_softc *sc; 140 phandle_t node; 141 u_int32_t busrange[2]; 142 struct ofw_pci_range *rp; 143 int i, error; 144 struct ofw_pci_cell_info *cell_info; 145 146 node = ofw_bus_get_node(dev); 147 sc = device_get_softc(dev); 148 sc->sc_initialized = 1; 149 sc->sc_range = NULL; 150 sc->sc_pci_domain = device_get_unit(dev); 151 152 cell_info = (struct ofw_pci_cell_info *)malloc(sizeof(*cell_info), 153 M_DEVBUF, M_WAITOK | M_ZERO); 154 155 sc->sc_cell_info = cell_info; 156 157 if (OF_getencprop(node, "bus-range", busrange, sizeof(busrange)) != 8) 158 busrange[0] = 0; 159 160 sc->sc_dev = dev; 161 sc->sc_node = node; 162 sc->sc_bus = busrange[0]; 163 164 if (sc->sc_quirks & OFW_PCI_QUIRK_RANGES_ON_CHILDREN) { 165 phandle_t c; 166 int n, i; 167 168 sc->sc_nrange = 0; 169 for (c = OF_child(node); c != 0; c = OF_peer(c)) { 170 n = ofw_pcib_nranges(c, cell_info); 171 if (n > 0) 172 sc->sc_nrange += n; 173 } 174 if (sc->sc_nrange == 0) { 175 error = ENXIO; 176 goto out; 177 } 178 sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]), 179 M_DEVBUF, M_WAITOK); 180 i = 0; 181 for (c = OF_child(node); c != 0; c = OF_peer(c)) { 182 n = ofw_pcib_fill_ranges(c, &sc->sc_range[i]); 183 if (n > 0) 184 i += n; 185 } 186 KASSERT(i == sc->sc_nrange, ("range count mismatch")); 187 } else { 188 sc->sc_nrange = ofw_pcib_nranges(node, cell_info); 189 if (sc->sc_nrange <= 0) { 190 device_printf(dev, "could not getranges\n"); 191 error = ENXIO; 192 goto out; 193 } 194 sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]), 195 M_DEVBUF, M_WAITOK); 196 ofw_pcib_fill_ranges(node, sc->sc_range); 197 } 198 199 sc->sc_io_rman.rm_type = RMAN_ARRAY; 200 sc->sc_io_rman.rm_descr = "PCI I/O Ports"; 201 error = rman_init(&sc->sc_io_rman); 202 if (error != 0) { 203 device_printf(dev, "rman_init() failed. error = %d\n", error); 204 goto out; 205 } 206 207 sc->sc_mem_rman.rm_type = RMAN_ARRAY; 208 sc->sc_mem_rman.rm_descr = "PCI Non Prefetchable Memory"; 209 error = rman_init(&sc->sc_mem_rman); 210 if (error != 0) { 211 device_printf(dev, "rman_init() failed. error = %d\n", error); 212 goto out_mem_rman; 213 } 214 215 sc->sc_pmem_rman.rm_type = RMAN_ARRAY; 216 sc->sc_pmem_rman.rm_descr = "PCI Prefetchable Memory"; 217 error = rman_init(&sc->sc_pmem_rman); 218 if (error != 0) { 219 device_printf(dev, "rman_init() failed. error = %d\n", error); 220 goto out_pmem_rman; 221 } 222 223 for (i = 0; i < sc->sc_nrange; i++) { 224 error = 0; 225 rp = sc->sc_range + i; 226 227 if (sc->sc_range_mask & ((uint64_t)1 << i)) 228 continue; 229 switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { 230 case OFW_PCI_PHYS_HI_SPACE_CONFIG: 231 break; 232 case OFW_PCI_PHYS_HI_SPACE_IO: 233 error = rman_manage_region(&sc->sc_io_rman, rp->pci, 234 rp->pci + rp->size - 1); 235 break; 236 case OFW_PCI_PHYS_HI_SPACE_MEM32: 237 case OFW_PCI_PHYS_HI_SPACE_MEM64: 238 if (rp->pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) { 239 sc->sc_have_pmem = 1; 240 error = rman_manage_region(&sc->sc_pmem_rman, 241 rp->pci, rp->pci + rp->size - 1); 242 } else { 243 error = rman_manage_region(&sc->sc_mem_rman, 244 rp->pci, rp->pci + rp->size - 1); 245 } 246 break; 247 } 248 249 if (error != 0) { 250 device_printf(dev, 251 "rman_manage_region(%x, %#jx, %#jx) failed. " 252 "error = %d\n", rp->pci_hi & 253 OFW_PCI_PHYS_HI_SPACEMASK, rp->pci, 254 rp->pci + rp->size - 1, error); 255 goto out_full; 256 } 257 } 258 259 ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t)); 260 return (0); 261 262 out_full: 263 rman_fini(&sc->sc_pmem_rman); 264 out_pmem_rman: 265 rman_fini(&sc->sc_mem_rman); 266 out_mem_rman: 267 rman_fini(&sc->sc_io_rman); 268 out: 269 free(sc->sc_cell_info, M_DEVBUF); 270 free(sc->sc_range, M_DEVBUF); 271 272 return (error); 273 } 274 275 void 276 ofw_pcib_fini(device_t dev) 277 { 278 struct ofw_pci_softc *sc; 279 280 sc = device_get_softc(dev); 281 free(sc->sc_cell_info, M_DEVBUF); 282 free(sc->sc_range, M_DEVBUF); 283 rman_fini(&sc->sc_io_rman); 284 rman_fini(&sc->sc_mem_rman); 285 rman_fini(&sc->sc_pmem_rman); 286 } 287 288 int 289 ofw_pcib_attach(device_t dev) 290 { 291 struct ofw_pci_softc *sc; 292 int error; 293 294 sc = device_get_softc(dev); 295 if (!sc->sc_initialized) { 296 error = ofw_pcib_init(dev); 297 if (error != 0) 298 return (error); 299 } 300 301 device_add_child(dev, "pci", -1); 302 return (bus_generic_attach(dev)); 303 } 304 305 static int 306 ofw_pcib_maxslots(device_t dev) 307 { 308 309 return (PCI_SLOTMAX); 310 } 311 312 int 313 ofw_pcib_route_interrupt(device_t bus, device_t dev, int pin) 314 { 315 struct ofw_pci_softc *sc; 316 struct ofw_pci_register reg; 317 uint32_t pintr, mintr[PCI_MAP_INTR]; 318 int intrcells; 319 phandle_t iparent; 320 321 sc = device_get_softc(bus); 322 pintr = pin; 323 324 /* Fabricate imap information in case this isn't an OFW device */ 325 bzero(®, sizeof(reg)); 326 reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) | 327 (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) | 328 (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT); 329 330 intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), 331 &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), 332 mintr, sizeof(mintr), &iparent); 333 if (intrcells != 0) { 334 pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr); 335 return (pintr); 336 } 337 338 /* 339 * Maybe it's a real interrupt, not an intpin 340 */ 341 if (pin > PCI_INTR_PINS) 342 return (pin); 343 344 device_printf(bus, "could not route pin %d for device %d.%d\n", 345 pin, pci_get_slot(dev), pci_get_function(dev)); 346 return (PCI_INVALID_IRQ); 347 } 348 349 int 350 ofw_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 351 { 352 struct ofw_pci_softc *sc; 353 354 sc = device_get_softc(dev); 355 356 switch (which) { 357 case PCIB_IVAR_DOMAIN: 358 *result = sc->sc_pci_domain; 359 return (0); 360 case PCIB_IVAR_BUS: 361 *result = sc->sc_bus; 362 return (0); 363 default: 364 break; 365 } 366 367 return (ENOENT); 368 } 369 370 int 371 ofw_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 372 { 373 struct ofw_pci_softc *sc; 374 375 sc = device_get_softc(dev); 376 377 switch (which) { 378 case PCIB_IVAR_BUS: 379 sc->sc_bus = value; 380 return (0); 381 default: 382 break; 383 } 384 385 return (ENOENT); 386 } 387 388 int 389 ofw_pcib_nranges(phandle_t node, struct ofw_pci_cell_info *info) 390 { 391 ssize_t nbase_ranges; 392 393 if (info == NULL) 394 return (-1); 395 396 info->host_address_cells = 1; 397 info->size_cells = 2; 398 info->pci_address_cell = 3; 399 400 OF_getencprop(OF_parent(node), "#address-cells", 401 &(info->host_address_cells), sizeof(info->host_address_cells)); 402 OF_getencprop(node, "#address-cells", 403 &(info->pci_address_cell), sizeof(info->pci_address_cell)); 404 OF_getencprop(node, "#size-cells", &(info->size_cells), 405 sizeof(info->size_cells)); 406 407 nbase_ranges = OF_getproplen(node, "ranges"); 408 if (nbase_ranges <= 0) 409 return (-1); 410 411 return (nbase_ranges / sizeof(cell_t) / 412 (info->pci_address_cell + info->host_address_cells + 413 info->size_cells)); 414 } 415 416 static struct resource * 417 ofw_pcib_alloc_resource(device_t bus, device_t child, int type, int *rid, 418 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 419 { 420 struct ofw_pci_softc *sc; 421 struct resource *rv; 422 struct rman *rm; 423 int needactivate; 424 425 needactivate = flags & RF_ACTIVE; 426 flags &= ~RF_ACTIVE; 427 428 sc = device_get_softc(bus); 429 430 #if defined(NEW_PCIB) && defined(PCI_RES_BUS) 431 if (type == PCI_RES_BUS) { 432 return (pci_domain_alloc_bus(sc->sc_pci_domain, child, rid, 433 start, end, count, flags | needactivate)); 434 } 435 #endif 436 437 rm = ofw_pcib_get_rman(sc, type, flags); 438 if (rm == NULL) { 439 return (bus_generic_alloc_resource(bus, child, type, rid, 440 start, end, count, flags | needactivate)); 441 } 442 443 rv = rman_reserve_resource(rm, start, end, count, flags, child); 444 if (rv == NULL) { 445 device_printf(bus, "failed to reserve resource for %s\n", 446 device_get_nameunit(child)); 447 return (NULL); 448 } 449 450 rman_set_rid(rv, *rid); 451 452 if (needactivate) { 453 if (bus_activate_resource(child, type, *rid, rv) != 0) { 454 device_printf(bus, 455 "failed to activate resource for %s\n", 456 device_get_nameunit(child)); 457 rman_release_resource(rv); 458 return (NULL); 459 } 460 } 461 462 return (rv); 463 } 464 465 static int 466 ofw_pcib_release_resource(device_t bus, device_t child, int type, int rid, 467 struct resource *res) 468 { 469 struct ofw_pci_softc *sc; 470 struct rman *rm; 471 int error; 472 473 sc = device_get_softc(bus); 474 475 #if defined(NEW_PCIB) && defined(PCI_RES_BUS) 476 if (type == PCI_RES_BUS) 477 return (pci_domain_release_bus(sc->sc_pci_domain, child, rid, 478 res)); 479 #endif 480 481 rm = ofw_pcib_get_rman(sc, type, rman_get_flags(res)); 482 if (rm == NULL) { 483 return (bus_generic_release_resource(bus, child, type, rid, 484 res)); 485 } 486 KASSERT(rman_is_region_manager(res, rm), ("rman mismatch")); 487 488 if (rman_get_flags(res) & RF_ACTIVE) { 489 error = bus_deactivate_resource(child, type, rid, res); 490 if (error != 0) 491 return (error); 492 } 493 return (rman_release_resource(res)); 494 } 495 496 static int 497 ofw_pcib_translate_resource(device_t bus, int type, rman_res_t start, 498 rman_res_t *newstart) 499 { 500 struct ofw_pci_softc *sc; 501 struct ofw_pci_range *rp; 502 int space; 503 504 sc = device_get_softc(bus); 505 506 /* 507 * Map this through the ranges list 508 */ 509 for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && 510 rp->pci_hi != 0; rp++) { 511 if (start < rp->pci || start >= rp->pci + rp->size) 512 continue; 513 514 switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { 515 case OFW_PCI_PHYS_HI_SPACE_IO: 516 space = SYS_RES_IOPORT; 517 break; 518 case OFW_PCI_PHYS_HI_SPACE_MEM32: 519 case OFW_PCI_PHYS_HI_SPACE_MEM64: 520 space = SYS_RES_MEMORY; 521 break; 522 default: 523 space = -1; 524 } 525 526 if (type == space) { 527 start += (rp->host - rp->pci); 528 *newstart = start; 529 return (0); 530 } 531 } 532 return (ENOENT); 533 } 534 535 static int 536 ofw_pcib_activate_resource(device_t bus, device_t child, int type, int rid, 537 struct resource *res) 538 { 539 struct ofw_pci_softc *sc; 540 bus_space_handle_t handle; 541 bus_space_tag_t tag; 542 struct ofw_pci_range *rp; 543 vm_paddr_t start; 544 int space; 545 int rv; 546 547 sc = device_get_softc(bus); 548 549 if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) { 550 return (bus_generic_activate_resource(bus, child, type, rid, 551 res)); 552 } 553 554 start = (vm_paddr_t)rman_get_start(res); 555 556 /* 557 * Map this through the ranges list 558 */ 559 for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && 560 rp->pci_hi != 0; rp++) { 561 if (start < rp->pci || start >= rp->pci + rp->size) 562 continue; 563 564 switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { 565 case OFW_PCI_PHYS_HI_SPACE_IO: 566 space = SYS_RES_IOPORT; 567 break; 568 case OFW_PCI_PHYS_HI_SPACE_MEM32: 569 case OFW_PCI_PHYS_HI_SPACE_MEM64: 570 space = SYS_RES_MEMORY; 571 break; 572 default: 573 space = -1; 574 } 575 576 if (type == space) { 577 start += (rp->host - rp->pci); 578 break; 579 } 580 } 581 582 if (bootverbose) 583 printf("ofw_pci mapdev: start %jx, len %jd\n", 584 (rman_res_t)start, rman_get_size(res)); 585 586 tag = BUS_GET_BUS_TAG(child, child); 587 if (tag == NULL) 588 return (ENOMEM); 589 590 rman_set_bustag(res, tag); 591 rv = bus_space_map(tag, start, 592 rman_get_size(res), 0, &handle); 593 if (rv != 0) 594 return (ENOMEM); 595 596 rman_set_bushandle(res, handle); 597 rman_set_virtual(res, (void *)handle); /* XXX for powerpc only ? */ 598 599 return (rman_activate_resource(res)); 600 } 601 602 #ifdef __powerpc__ 603 static bus_space_tag_t 604 ofw_pcib_bus_get_bus_tag(device_t bus, device_t child) 605 { 606 607 return (&bs_le_tag); 608 } 609 #endif 610 611 static int 612 ofw_pcib_deactivate_resource(device_t bus, device_t child, int type, int rid, 613 struct resource *res) 614 { 615 vm_size_t psize; 616 617 if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) { 618 return (bus_generic_deactivate_resource(bus, child, type, rid, 619 res)); 620 } 621 622 psize = rman_get_size(res); 623 pmap_unmapdev(rman_get_virtual(res), psize); 624 625 return (rman_deactivate_resource(res)); 626 } 627 628 static int 629 ofw_pcib_adjust_resource(device_t bus, device_t child, int type, 630 struct resource *res, rman_res_t start, rman_res_t end) 631 { 632 struct rman *rm; 633 struct ofw_pci_softc *sc; 634 635 sc = device_get_softc(bus); 636 #if defined(NEW_PCIB) && defined(PCI_RES_BUS) 637 if (type == PCI_RES_BUS) 638 return (pci_domain_adjust_bus(sc->sc_pci_domain, child, res, 639 start, end)); 640 #endif 641 642 rm = ofw_pcib_get_rman(sc, type, rman_get_flags(res)); 643 if (rm == NULL) { 644 return (bus_generic_adjust_resource(bus, child, type, res, 645 start, end)); 646 } 647 KASSERT(rman_is_region_manager(res, rm), ("rman mismatch")); 648 KASSERT(!(rman_get_flags(res) & RF_ACTIVE), 649 ("active resources cannot be adjusted")); 650 651 return (rman_adjust_resource(res, start, end)); 652 } 653 654 static phandle_t 655 ofw_pcib_get_node(device_t bus, device_t dev) 656 { 657 struct ofw_pci_softc *sc; 658 659 sc = device_get_softc(bus); 660 /* We only have one child, the PCI bus, which needs our own node. */ 661 662 return (sc->sc_node); 663 } 664 665 static int 666 ofw_pcib_fill_ranges(phandle_t node, struct ofw_pci_range *ranges) 667 { 668 int host_address_cells = 1, pci_address_cells = 3, size_cells = 2; 669 cell_t *base_ranges; 670 ssize_t nbase_ranges; 671 int nranges; 672 int i, j, k; 673 674 OF_getencprop(OF_parent(node), "#address-cells", &host_address_cells, 675 sizeof(host_address_cells)); 676 OF_getencprop(node, "#address-cells", &pci_address_cells, 677 sizeof(pci_address_cells)); 678 OF_getencprop(node, "#size-cells", &size_cells, sizeof(size_cells)); 679 680 nbase_ranges = OF_getproplen(node, "ranges"); 681 if (nbase_ranges <= 0) 682 return (-1); 683 nranges = nbase_ranges / sizeof(cell_t) / 684 (pci_address_cells + host_address_cells + size_cells); 685 686 base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); 687 OF_getencprop(node, "ranges", base_ranges, nbase_ranges); 688 689 for (i = 0, j = 0; i < nranges; i++) { 690 ranges[i].pci_hi = base_ranges[j++]; 691 ranges[i].pci = 0; 692 for (k = 0; k < pci_address_cells - 1; k++) { 693 ranges[i].pci <<= 32; 694 ranges[i].pci |= base_ranges[j++]; 695 } 696 ranges[i].host = 0; 697 for (k = 0; k < host_address_cells; k++) { 698 ranges[i].host <<= 32; 699 ranges[i].host |= base_ranges[j++]; 700 } 701 ranges[i].size = 0; 702 for (k = 0; k < size_cells; k++) { 703 ranges[i].size <<= 32; 704 ranges[i].size |= base_ranges[j++]; 705 } 706 } 707 708 free(base_ranges, M_DEVBUF); 709 return (nranges); 710 } 711 712 static struct rman * 713 ofw_pcib_get_rman(struct ofw_pci_softc *sc, int type, u_int flags) 714 { 715 716 switch (type) { 717 case SYS_RES_IOPORT: 718 return (&sc->sc_io_rman); 719 case SYS_RES_MEMORY: 720 if (sc->sc_have_pmem && (flags & RF_PREFETCHABLE)) 721 return (&sc->sc_pmem_rman); 722 else 723 return (&sc->sc_mem_rman); 724 default: 725 break; 726 } 727 728 return (NULL); 729 } 730