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