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