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 return (bus_generic_attach(dev)); 307 } 308 309 static int 310 ofw_pcib_maxslots(device_t dev) 311 { 312 313 return (PCI_SLOTMAX); 314 } 315 316 int 317 ofw_pcib_route_interrupt(device_t bus, device_t dev, int pin) 318 { 319 struct ofw_pci_softc *sc; 320 struct ofw_pci_register reg; 321 uint32_t pintr, mintr[PCI_MAP_INTR]; 322 int intrcells; 323 phandle_t iparent; 324 325 sc = device_get_softc(bus); 326 pintr = pin; 327 328 /* Fabricate imap information in case this isn't an OFW device */ 329 bzero(®, sizeof(reg)); 330 reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) | 331 (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) | 332 (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT); 333 334 intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), 335 &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), 336 mintr, sizeof(mintr), &iparent); 337 if (intrcells != 0) { 338 pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr); 339 return (pintr); 340 } 341 342 /* 343 * Maybe it's a real interrupt, not an intpin 344 */ 345 if (pin > PCI_INTR_PINS) 346 return (pin); 347 348 device_printf(bus, "could not route pin %d for device %d.%d\n", 349 pin, pci_get_slot(dev), pci_get_function(dev)); 350 return (PCI_INVALID_IRQ); 351 } 352 353 int 354 ofw_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 355 { 356 struct ofw_pci_softc *sc; 357 358 sc = device_get_softc(dev); 359 360 switch (which) { 361 case PCIB_IVAR_DOMAIN: 362 *result = sc->sc_pci_domain; 363 return (0); 364 case PCIB_IVAR_BUS: 365 *result = sc->sc_bus; 366 return (0); 367 default: 368 break; 369 } 370 371 return (ENOENT); 372 } 373 374 int 375 ofw_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 376 { 377 struct ofw_pci_softc *sc; 378 379 sc = device_get_softc(dev); 380 381 switch (which) { 382 case PCIB_IVAR_BUS: 383 sc->sc_bus = value; 384 return (0); 385 default: 386 break; 387 } 388 389 return (ENOENT); 390 } 391 392 int 393 ofw_pcib_nranges(phandle_t node, struct ofw_pci_cell_info *info) 394 { 395 ssize_t nbase_ranges; 396 397 if (info == NULL) 398 return (-1); 399 400 info->host_address_cells = 1; 401 info->size_cells = 2; 402 info->pci_address_cell = 3; 403 404 OF_getencprop(OF_parent(node), "#address-cells", 405 &(info->host_address_cells), sizeof(info->host_address_cells)); 406 OF_getencprop(node, "#address-cells", 407 &(info->pci_address_cell), sizeof(info->pci_address_cell)); 408 OF_getencprop(node, "#size-cells", &(info->size_cells), 409 sizeof(info->size_cells)); 410 411 nbase_ranges = OF_getproplen(node, "ranges"); 412 if (nbase_ranges <= 0) 413 return (-1); 414 415 return (nbase_ranges / sizeof(cell_t) / 416 (info->pci_address_cell + info->host_address_cells + 417 info->size_cells)); 418 } 419 420 static struct resource * 421 ofw_pcib_alloc_resource(device_t bus, device_t child, int type, int *rid, 422 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 423 { 424 struct ofw_pci_softc *sc; 425 426 sc = device_get_softc(bus); 427 switch (type) { 428 case PCI_RES_BUS: 429 return (pci_domain_alloc_bus(sc->sc_pci_domain, child, rid, 430 start, end, count, flags)); 431 case SYS_RES_MEMORY: 432 case SYS_RES_IOPORT: 433 return (bus_generic_rman_alloc_resource(bus, child, type, rid, 434 start, end, count, flags)); 435 default: 436 return (bus_generic_alloc_resource(bus, child, type, rid, 437 start, end, count, flags)); 438 } 439 } 440 441 static int 442 ofw_pcib_release_resource(device_t bus, device_t child, struct resource *res) 443 { 444 struct ofw_pci_softc *sc; 445 446 sc = device_get_softc(bus); 447 switch (rman_get_type(res)) { 448 case PCI_RES_BUS: 449 return (pci_domain_release_bus(sc->sc_pci_domain, child, res)); 450 case SYS_RES_MEMORY: 451 case SYS_RES_IOPORT: 452 return (bus_generic_rman_release_resource(bus, child, res)); 453 default: 454 return (bus_generic_release_resource(bus, child, res)); 455 } 456 } 457 458 static int 459 ofw_pcib_translate_resource(device_t bus, int type, rman_res_t start, 460 rman_res_t *newstart) 461 { 462 struct ofw_pci_softc *sc; 463 struct ofw_pci_range *rp; 464 int space; 465 466 sc = device_get_softc(bus); 467 468 /* 469 * Map this through the ranges list 470 */ 471 for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && 472 rp->pci_hi != 0; rp++) { 473 if (start < rp->pci || start >= rp->pci + rp->size) 474 continue; 475 476 switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { 477 case OFW_PCI_PHYS_HI_SPACE_IO: 478 space = SYS_RES_IOPORT; 479 break; 480 case OFW_PCI_PHYS_HI_SPACE_MEM32: 481 case OFW_PCI_PHYS_HI_SPACE_MEM64: 482 space = SYS_RES_MEMORY; 483 break; 484 default: 485 space = -1; 486 } 487 488 if (type == space) { 489 start += (rp->host - rp->pci); 490 *newstart = start; 491 return (0); 492 } 493 } 494 return (ENOENT); 495 } 496 497 static int 498 ofw_pcib_activate_resource(device_t bus, device_t child, struct resource *res) 499 { 500 struct ofw_pci_softc *sc; 501 502 sc = device_get_softc(bus); 503 switch (rman_get_type(res)) { 504 case PCI_RES_BUS: 505 return (pci_domain_activate_bus(sc->sc_pci_domain, child, res)); 506 case SYS_RES_MEMORY: 507 case SYS_RES_IOPORT: 508 return (bus_generic_rman_activate_resource(bus, child, res)); 509 default: 510 return (bus_generic_activate_resource(bus, child, res)); 511 } 512 } 513 514 static int 515 ofw_pcib_map_resource(device_t dev, device_t child, struct resource *r, 516 struct resource_map_request *argsp, struct resource_map *map) 517 { 518 struct resource_map_request args; 519 struct ofw_pci_softc *sc; 520 struct ofw_pci_range *rp; 521 rman_res_t length, start; 522 int error, space; 523 524 /* Resources must be active to be mapped. */ 525 if (!(rman_get_flags(r) & RF_ACTIVE)) 526 return (ENXIO); 527 528 switch (rman_get_type(r)) { 529 case SYS_RES_MEMORY: 530 case SYS_RES_IOPORT: 531 break; 532 default: 533 return (EINVAL); 534 } 535 536 resource_init_map_request(&args); 537 error = resource_validate_map_request(r, argsp, &args, &start, &length); 538 if (error) 539 return (error); 540 541 /* 542 * Map this through the ranges list 543 */ 544 sc = device_get_softc(dev); 545 for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && 546 rp->pci_hi != 0; rp++) { 547 if (start < rp->pci || start >= rp->pci + rp->size) 548 continue; 549 550 switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { 551 case OFW_PCI_PHYS_HI_SPACE_IO: 552 space = SYS_RES_IOPORT; 553 break; 554 case OFW_PCI_PHYS_HI_SPACE_MEM32: 555 case OFW_PCI_PHYS_HI_SPACE_MEM64: 556 space = SYS_RES_MEMORY; 557 break; 558 default: 559 space = -1; 560 } 561 562 if (rman_get_type(r) == space) { 563 start += (rp->host - rp->pci); 564 break; 565 } 566 } 567 568 if (bootverbose) 569 printf("ofw_pci mapdev: start %jx, len %jd\n", start, length); 570 571 map->r_bustag = BUS_GET_BUS_TAG(child, child); 572 if (map->r_bustag == NULL) 573 return (ENOMEM); 574 575 error = bus_space_map(map->r_bustag, start, length, 0, 576 &map->r_bushandle); 577 if (error != 0) 578 return (error); 579 580 /* XXX for powerpc only? */ 581 map->r_vaddr = (void *)map->r_bushandle; 582 map->r_size = length; 583 return (0); 584 } 585 586 static int 587 ofw_pcib_unmap_resource(device_t dev, device_t child, struct resource *r, 588 struct resource_map *map) 589 { 590 switch (rman_get_type(r)) { 591 case SYS_RES_MEMORY: 592 case SYS_RES_IOPORT: 593 bus_space_unmap(map->r_bustag, map->r_bushandle, map->r_size); 594 return (0); 595 default: 596 return (EINVAL); 597 } 598 } 599 600 #ifdef __powerpc__ 601 static bus_space_tag_t 602 ofw_pcib_bus_get_bus_tag(device_t bus, device_t child) 603 { 604 605 return (&bs_le_tag); 606 } 607 #endif 608 609 static int 610 ofw_pcib_deactivate_resource(device_t bus, device_t child, struct resource *res) 611 { 612 struct ofw_pci_softc *sc; 613 614 sc = device_get_softc(bus); 615 switch (rman_get_type(res)) { 616 case PCI_RES_BUS: 617 return (pci_domain_deactivate_bus(sc->sc_pci_domain, child, 618 res)); 619 case SYS_RES_MEMORY: 620 case SYS_RES_IOPORT: 621 return (bus_generic_rman_deactivate_resource(bus, child, res)); 622 default: 623 return (bus_generic_deactivate_resource(bus, child, res)); 624 } 625 } 626 627 static int 628 ofw_pcib_adjust_resource(device_t bus, device_t child, 629 struct resource *res, rman_res_t start, rman_res_t end) 630 { 631 struct ofw_pci_softc *sc; 632 633 sc = device_get_softc(bus); 634 switch (rman_get_type(res)) { 635 case PCI_RES_BUS: 636 return (pci_domain_adjust_bus(sc->sc_pci_domain, child, res, 637 start, end)); 638 case SYS_RES_MEMORY: 639 case SYS_RES_IOPORT: 640 return (bus_generic_rman_adjust_resource(bus, child, res, 641 start, end)); 642 default: 643 return (bus_generic_adjust_resource(bus, child, res, start, 644 end)); 645 } 646 } 647 648 static phandle_t 649 ofw_pcib_get_node(device_t bus, device_t dev) 650 { 651 struct ofw_pci_softc *sc; 652 653 sc = device_get_softc(bus); 654 /* We only have one child, the PCI bus, which needs our own node. */ 655 656 return (sc->sc_node); 657 } 658 659 static int 660 ofw_pcib_fill_ranges(phandle_t node, struct ofw_pci_range *ranges) 661 { 662 int host_address_cells = 1, pci_address_cells = 3, size_cells = 2; 663 cell_t *base_ranges; 664 ssize_t nbase_ranges; 665 int nranges; 666 int i, j, k; 667 668 OF_getencprop(OF_parent(node), "#address-cells", &host_address_cells, 669 sizeof(host_address_cells)); 670 OF_getencprop(node, "#address-cells", &pci_address_cells, 671 sizeof(pci_address_cells)); 672 OF_getencprop(node, "#size-cells", &size_cells, sizeof(size_cells)); 673 674 nbase_ranges = OF_getproplen(node, "ranges"); 675 if (nbase_ranges <= 0) 676 return (-1); 677 nranges = nbase_ranges / sizeof(cell_t) / 678 (pci_address_cells + host_address_cells + size_cells); 679 680 base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); 681 OF_getencprop(node, "ranges", base_ranges, nbase_ranges); 682 683 for (i = 0, j = 0; i < nranges; i++) { 684 ranges[i].pci_hi = base_ranges[j++]; 685 ranges[i].pci = 0; 686 for (k = 0; k < pci_address_cells - 1; k++) { 687 ranges[i].pci <<= 32; 688 ranges[i].pci |= base_ranges[j++]; 689 } 690 ranges[i].host = 0; 691 for (k = 0; k < host_address_cells; k++) { 692 ranges[i].host <<= 32; 693 ranges[i].host |= base_ranges[j++]; 694 } 695 ranges[i].size = 0; 696 for (k = 0; k < size_cells; k++) { 697 ranges[i].size <<= 32; 698 ranges[i].size |= base_ranges[j++]; 699 } 700 } 701 702 free(base_ranges, M_DEVBUF); 703 return (nranges); 704 } 705 706 static struct rman * 707 ofw_pcib_get_rman(device_t bus, int type, u_int flags) 708 { 709 struct ofw_pci_softc *sc; 710 711 sc = device_get_softc(bus); 712 switch (type) { 713 case SYS_RES_IOPORT: 714 return (&sc->sc_io_rman); 715 case SYS_RES_MEMORY: 716 if (sc->sc_have_pmem && (flags & RF_PREFETCHABLE)) 717 return (&sc->sc_pmem_rman); 718 else 719 return (&sc->sc_mem_rman); 720 default: 721 break; 722 } 723 724 return (NULL); 725 } 726