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