1 /*- 2 * Copyright (c) 2015 Landon Fuller <landon@landonf.org> 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 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 /* 34 * Abstract BHND Bridge Device Driver 35 * 36 * Provides generic support for bridging from a parent bus (such as PCI) to 37 * a BHND-compatible bus (e.g. bcma or siba). 38 */ 39 40 #include <sys/param.h> 41 #include <sys/kernel.h> 42 #include <sys/bus.h> 43 #include <sys/module.h> 44 #include <sys/systm.h> 45 46 #include <machine/bus.h> 47 #include <sys/rman.h> 48 #include <machine/resource.h> 49 50 #include <dev/bhnd/bhndvar.h> 51 #include <dev/bhnd/bhndreg.h> 52 53 #include <dev/bhnd/cores/chipc/chipcreg.h> 54 #include <dev/bhnd/nvram/bhnd_nvram.h> 55 56 #include "bhnd_chipc_if.h" 57 #include "bhnd_nvram_if.h" 58 59 #include "bhndbvar.h" 60 #include "bhndb_bus_if.h" 61 #include "bhndb_hwdata.h" 62 #include "bhndb_private.h" 63 64 /* Debugging flags */ 65 static u_long bhndb_debug = 0; 66 TUNABLE_ULONG("hw.bhndb.debug", &bhndb_debug); 67 68 enum { 69 BHNDB_DEBUG_PRIO = 1 << 0, 70 }; 71 72 #define BHNDB_DEBUG(_type) (BHNDB_DEBUG_ ## _type & bhndb_debug) 73 74 static bool bhndb_hw_matches(device_t *devlist, 75 int num_devs, 76 const struct bhndb_hw *hw); 77 78 static int bhndb_initialize_region_cfg( 79 struct bhndb_softc *sc, device_t *devs, 80 int ndevs, 81 const struct bhndb_hw_priority *table, 82 struct bhndb_resources *r); 83 84 static int bhndb_find_hwspec(struct bhndb_softc *sc, 85 device_t *devs, int ndevs, 86 const struct bhndb_hw **hw); 87 88 static int bhndb_read_chipid(struct bhndb_softc *sc, 89 const struct bhndb_hwcfg *cfg, 90 struct bhnd_chipid *result); 91 92 bhndb_addrspace bhndb_get_addrspace(struct bhndb_softc *sc, 93 device_t child); 94 95 static struct rman *bhndb_get_rman(struct bhndb_softc *sc, 96 device_t child, int type); 97 98 static int bhndb_init_child_resource(struct resource *r, 99 struct resource *parent, 100 bhnd_size_t offset, 101 bhnd_size_t size); 102 103 static int bhndb_activate_static_region( 104 struct bhndb_softc *sc, 105 struct bhndb_region *region, 106 device_t child, int type, int rid, 107 struct resource *r); 108 109 static int bhndb_try_activate_resource( 110 struct bhndb_softc *sc, device_t child, 111 int type, int rid, struct resource *r, 112 bool *indirect); 113 114 115 /** 116 * Default bhndb(4) implementation of DEVICE_PROBE(). 117 * 118 * This function provides the default bhndb implementation of DEVICE_PROBE(), 119 * and is compatible with bhndb(4) bridges attached via bhndb_attach_bridge(). 120 */ 121 int 122 bhndb_generic_probe(device_t dev) 123 { 124 return (BUS_PROBE_NOWILDCARD); 125 } 126 127 static void 128 bhndb_probe_nomatch(device_t dev, device_t child) 129 { 130 const char *name; 131 132 name = device_get_name(child); 133 if (name == NULL) 134 name = "unknown device"; 135 136 device_printf(dev, "<%s> (no driver attached)\n", name); 137 } 138 139 static int 140 bhndb_print_child(device_t dev, device_t child) 141 { 142 struct bhndb_softc *sc; 143 struct resource_list *rl; 144 int retval = 0; 145 146 sc = device_get_softc(dev); 147 148 retval += bus_print_child_header(dev, child); 149 150 rl = BUS_GET_RESOURCE_LIST(dev, child); 151 if (rl != NULL) { 152 retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, 153 "%#jx"); 154 retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, 155 "%jd"); 156 } 157 158 retval += bus_print_child_domain(dev, child); 159 retval += bus_print_child_footer(dev, child); 160 161 return (retval); 162 } 163 164 static int 165 bhndb_child_pnpinfo_str(device_t bus, device_t child, char *buf, 166 size_t buflen) 167 { 168 *buf = '\0'; 169 return (0); 170 } 171 172 static int 173 bhndb_child_location_str(device_t dev, device_t child, char *buf, 174 size_t buflen) 175 { 176 struct bhndb_softc *sc; 177 178 sc = device_get_softc(dev); 179 180 snprintf(buf, buflen, "base=0x%llx", 181 (unsigned long long) sc->chipid.enum_addr); 182 return (0); 183 } 184 185 /** 186 * Return true if @p devlist matches the @p hw specification. 187 * 188 * @param devlist A device table to match against. 189 * @param num_devs The number of devices in @p devlist. 190 * @param hw The hardware description to be matched against. 191 */ 192 static bool 193 bhndb_hw_matches(device_t *devlist, int num_devs, const struct bhndb_hw *hw) 194 { 195 for (u_int i = 0; i < hw->num_hw_reqs; i++) { 196 const struct bhnd_core_match *match; 197 struct bhnd_core_info ci; 198 bool found; 199 200 match = &hw->hw_reqs[i]; 201 found = false; 202 203 for (int d = 0; d < num_devs; d++) { 204 ci = bhnd_get_core_info(devlist[d]); 205 if (!bhnd_core_matches(&ci, match)) 206 continue; 207 208 found = true; 209 break; 210 } 211 212 if (!found) 213 return (false); 214 } 215 216 return (true); 217 } 218 219 /** 220 * Initialize the region maps and priority configuration in @p r using 221 * the provided priority @p table and the set of devices attached to 222 * the bridged @p bus_dev . 223 * 224 * @param sc The bhndb device state. 225 * @param devs All devices enumerated on the bridged bhnd bus. 226 * @param ndevs The length of @p devs. 227 * @param table Hardware priority table to be used to determine the relative 228 * priorities of per-core port resources. 229 * @param r The resource state to be configured. 230 */ 231 static int 232 bhndb_initialize_region_cfg(struct bhndb_softc *sc, device_t *devs, int ndevs, 233 const struct bhndb_hw_priority *table, struct bhndb_resources *r) 234 { 235 const struct bhndb_hw_priority *hp; 236 bhnd_addr_t addr; 237 bhnd_size_t size; 238 size_t prio_low, prio_default, prio_high; 239 int error; 240 241 /* The number of port regions per priority band that must be accessible 242 * via dynamic register windows */ 243 prio_low = 0; 244 prio_default = 0; 245 prio_high = 0; 246 247 /* 248 * Register bridge regions covering all statically mapped ports. 249 */ 250 for (int i = 0; i < ndevs; i++) { 251 const struct bhndb_regwin *regw; 252 device_t child; 253 254 child = devs[i]; 255 256 for (regw = r->cfg->register_windows; 257 regw->win_type != BHNDB_REGWIN_T_INVALID; regw++) 258 { 259 /* Only core windows are supported */ 260 if (regw->win_type != BHNDB_REGWIN_T_CORE) 261 continue; 262 263 /* Skip non-applicable register windows. */ 264 if (!bhndb_regwin_matches_device(regw, child)) 265 continue; 266 267 /* Fetch the base address of the mapped port. */ 268 error = bhnd_get_region_addr(child, 269 regw->d.core.port_type, regw->d.core.port, 270 regw->d.core.region, &addr, &size); 271 if (error) 272 return (error); 273 274 /* 275 * Always defer to the register window's size. 276 * 277 * If the port size is smaller than the window size, 278 * this ensures that we fully utilize register windows 279 * larger than the referenced port. 280 * 281 * If the port size is larger than the window size, this 282 * ensures that we do not directly map the allocations 283 * within the region to a too-small window. 284 */ 285 size = regw->win_size; 286 287 /* 288 * Add to the bus region list. 289 * 290 * The window priority for a statically mapped 291 * region is always HIGH. 292 */ 293 error = bhndb_add_resource_region(r, addr, size, 294 BHNDB_PRIORITY_HIGH, regw); 295 if (error) 296 return (error); 297 } 298 } 299 300 /* 301 * Perform priority accounting and register bridge regions for all 302 * ports defined in the priority table 303 */ 304 for (int i = 0; i < ndevs; i++) { 305 struct bhndb_region *region; 306 device_t child; 307 308 child = devs[i]; 309 310 /* 311 * Skip priority accounting for cores that ... 312 */ 313 314 /* ... do not require bridge resources */ 315 if (bhnd_is_hw_disabled(child) || !device_is_enabled(child)) 316 continue; 317 318 /* ... do not have a priority table entry */ 319 hp = bhndb_hw_priority_find_device(table, child); 320 if (hp == NULL) 321 continue; 322 323 /* ... are explicitly disabled in the priority table. */ 324 if (hp->priority == BHNDB_PRIORITY_NONE) 325 continue; 326 327 /* Determine the number of dynamic windows required and 328 * register their bus_region entries. */ 329 for (u_int i = 0; i < hp->num_ports; i++) { 330 const struct bhndb_port_priority *pp; 331 332 pp = &hp->ports[i]; 333 334 /* Skip ports not defined on this device */ 335 if (!bhnd_is_region_valid(child, pp->type, pp->port, 336 pp->region)) 337 { 338 continue; 339 } 340 341 /* Fetch the address+size of the mapped port. */ 342 error = bhnd_get_region_addr(child, pp->type, pp->port, 343 pp->region, &addr, &size); 344 if (error) 345 return (error); 346 347 /* Skip ports with an existing static mapping */ 348 region = bhndb_find_resource_region(r, addr, size); 349 if (region != NULL && region->static_regwin != NULL) 350 continue; 351 352 /* Define a dynamic region for this port */ 353 error = bhndb_add_resource_region(r, addr, size, 354 pp->priority, NULL); 355 if (error) 356 return (error); 357 358 /* Update port mapping counts */ 359 switch (pp->priority) { 360 case BHNDB_PRIORITY_NONE: 361 break; 362 case BHNDB_PRIORITY_LOW: 363 prio_low++; 364 break; 365 case BHNDB_PRIORITY_DEFAULT: 366 prio_default++; 367 break; 368 case BHNDB_PRIORITY_HIGH: 369 prio_high++; 370 break; 371 } 372 } 373 } 374 375 /* Determine the minimum priority at which we'll allocate direct 376 * register windows from our dynamic pool */ 377 size_t prio_total = prio_low + prio_default + prio_high; 378 if (prio_total <= r->dwa_count) { 379 /* low+default+high priority regions get windows */ 380 r->min_prio = BHNDB_PRIORITY_LOW; 381 382 } else if (prio_default + prio_high <= r->dwa_count) { 383 /* default+high priority regions get windows */ 384 r->min_prio = BHNDB_PRIORITY_DEFAULT; 385 386 } else { 387 /* high priority regions get windows */ 388 r->min_prio = BHNDB_PRIORITY_HIGH; 389 } 390 391 if (BHNDB_DEBUG(PRIO)) { 392 struct bhndb_region *region; 393 const char *direct_msg, *type_msg; 394 bhndb_priority_t prio, prio_min; 395 396 prio_min = r->min_prio; 397 device_printf(sc->dev, "min_prio: %d\n", prio_min); 398 399 STAILQ_FOREACH(region, &r->bus_regions, link) { 400 prio = region->priority; 401 402 direct_msg = prio >= prio_min ? "direct" : "indirect"; 403 type_msg = region->static_regwin ? "static" : "dynamic"; 404 405 device_printf(sc->dev, "region 0x%llx+0x%llx priority " 406 "%u %s/%s\n", 407 (unsigned long long) region->addr, 408 (unsigned long long) region->size, 409 region->priority, 410 direct_msg, type_msg); 411 } 412 } 413 414 return (0); 415 } 416 417 /** 418 * Find a hardware specification for @p dev. 419 * 420 * @param sc The bhndb device state. 421 * @param devs All devices enumerated on the bridged bhnd bus. 422 * @param ndevs The length of @p devs. 423 * @param[out] hw On success, the matched hardware specification. 424 * with @p dev. 425 * 426 * @retval 0 success 427 * @retval non-zero if an error occurs fetching device info for comparison. 428 */ 429 static int 430 bhndb_find_hwspec(struct bhndb_softc *sc, device_t *devs, int ndevs, 431 const struct bhndb_hw **hw) 432 { 433 const struct bhndb_hw *next, *hw_table; 434 435 /* Search for the first matching hardware config. */ 436 hw_table = BHNDB_BUS_GET_HARDWARE_TABLE(sc->parent_dev, sc->dev); 437 for (next = hw_table; next->hw_reqs != NULL; next++) { 438 if (!bhndb_hw_matches(devs, ndevs, next)) 439 continue; 440 441 /* Found */ 442 *hw = next; 443 return (0); 444 } 445 446 return (ENOENT); 447 } 448 449 /** 450 * Read the ChipCommon identification data for this device. 451 * 452 * @param sc bhndb device state. 453 * @param cfg The hardware configuration to use when mapping the ChipCommon 454 * registers. 455 * @param[out] result the chip identification data. 456 * 457 * @retval 0 success 458 * @retval non-zero if the ChipCommon identification data could not be read. 459 */ 460 static int 461 bhndb_read_chipid(struct bhndb_softc *sc, const struct bhndb_hwcfg *cfg, 462 struct bhnd_chipid *result) 463 { 464 const struct bhnd_chipid *parent_cid; 465 const struct bhndb_regwin *cc_win; 466 struct resource_spec rs; 467 int error; 468 469 /* Let our parent device override the discovery process */ 470 parent_cid = BHNDB_BUS_GET_CHIPID(sc->parent_dev, sc->dev); 471 if (parent_cid != NULL) { 472 *result = *parent_cid; 473 return (0); 474 } 475 476 /* Find a register window we can use to map the first CHIPC_CHIPID_SIZE 477 * of ChipCommon registers. */ 478 cc_win = bhndb_regwin_find_best(cfg->register_windows, 479 BHND_DEVCLASS_CC, 0, BHND_PORT_DEVICE, 0, 0, CHIPC_CHIPID_SIZE); 480 if (cc_win == NULL) { 481 device_printf(sc->dev, "no chipcommon register window\n"); 482 return (0); 483 } 484 485 /* We can assume a device without a static ChipCommon window uses the 486 * default ChipCommon address. */ 487 if (cc_win->win_type == BHNDB_REGWIN_T_DYN) { 488 error = BHNDB_SET_WINDOW_ADDR(sc->dev, cc_win, 489 BHND_DEFAULT_CHIPC_ADDR); 490 491 if (error) { 492 device_printf(sc->dev, "failed to set chipcommon " 493 "register window\n"); 494 return (error); 495 } 496 } 497 498 /* Let the default bhnd implemenation alloc/release the resource and 499 * perform the read */ 500 rs.type = cc_win->res.type; 501 rs.rid = cc_win->res.rid; 502 rs.flags = RF_ACTIVE; 503 504 return (bhnd_read_chipid(sc->parent_dev, &rs, cc_win->win_offset, 505 result)); 506 } 507 508 /** 509 * Helper function that must be called by subclass bhndb(4) drivers 510 * when implementing DEVICE_ATTACH() before calling any bhnd(4) or bhndb(4) 511 * APIs on the bridge device. 512 * 513 * @param dev The bridge device to attach. 514 * @param bridge_devclass The device class of the bridging core. This is used 515 * to automatically detect the bridge core, and to disable additional bridge 516 * cores (e.g. PCMCIA on a PCIe device). 517 */ 518 int 519 bhndb_attach(device_t dev, bhnd_devclass_t bridge_devclass) 520 { 521 struct bhndb_devinfo *dinfo; 522 struct bhndb_softc *sc; 523 const struct bhndb_hwcfg *cfg; 524 int error; 525 526 sc = device_get_softc(dev); 527 sc->dev = dev; 528 sc->parent_dev = device_get_parent(dev); 529 sc->bridge_class = bridge_devclass; 530 531 BHNDB_LOCK_INIT(sc); 532 533 /* Read our chip identification data */ 534 cfg = BHNDB_BUS_GET_GENERIC_HWCFG(sc->parent_dev, sc->dev); 535 if ((error = bhndb_read_chipid(sc, cfg, &sc->chipid))) 536 return (error); 537 538 /* Populate generic resource allocation state. */ 539 sc->bus_res = bhndb_alloc_resources(dev, sc->parent_dev, cfg); 540 if (sc->bus_res == NULL) { 541 return (ENXIO); 542 } 543 544 /* Attach our bridged bus device */ 545 sc->bus_dev = BUS_ADD_CHILD(dev, 0, "bhnd", -1); 546 if (sc->bus_dev == NULL) { 547 error = ENXIO; 548 goto failed; 549 } 550 551 /* Configure address space */ 552 dinfo = device_get_ivars(sc->bus_dev); 553 dinfo->addrspace = BHNDB_ADDRSPACE_BRIDGED; 554 555 /* Finish attach */ 556 return (bus_generic_attach(dev)); 557 558 failed: 559 BHNDB_LOCK_DESTROY(sc); 560 561 if (sc->bus_res != NULL) 562 bhndb_free_resources(sc->bus_res); 563 564 return (error); 565 } 566 567 /** 568 * Default bhndb(4) implementation of BHNDB_INIT_FULL_CONFIG(). 569 * 570 * This function provides the default bhndb implementation of 571 * BHNDB_INIT_FULL_CONFIG(), and must be called by any subclass driver 572 * overriding BHNDB_INIT_FULL_CONFIG(). 573 * 574 * As documented by BHNDB_INIT_FULL_CONFIG, this function performs final 575 * bridge configuration based on the hardware information enumerated by the 576 * child bus, and will reset all resource allocation state on the bridge. 577 * 578 * When calling this method: 579 * - Any bus resources previously allocated by @p child must be deallocated. 580 * - The @p child bus must have performed initial enumeration -- but not 581 * probe or attachment -- of its children. 582 */ 583 int 584 bhndb_generic_init_full_config(device_t dev, device_t child, 585 const struct bhndb_hw_priority *hw_prio_table) 586 { 587 struct bhndb_softc *sc; 588 const struct bhndb_hw *hw; 589 struct bhndb_resources *r; 590 device_t *devs; 591 device_t hostb; 592 int ndevs; 593 int error; 594 595 sc = device_get_softc(dev); 596 hostb = NULL; 597 598 /* Fetch the full set of bhnd-attached cores */ 599 if ((error = device_get_children(sc->bus_dev, &devs, &ndevs))) 600 return (error); 601 602 /* Find our host bridge device */ 603 hostb = BHNDB_FIND_HOSTB_DEVICE(dev, child); 604 if (hostb == NULL) { 605 device_printf(sc->dev, "no host bridge core found\n"); 606 error = ENODEV; 607 goto cleanup; 608 } 609 610 /* Find our full register window configuration */ 611 if ((error = bhndb_find_hwspec(sc, devs, ndevs, &hw))) { 612 device_printf(sc->dev, "unable to identify device, " 613 " using generic bridge resource definitions\n"); 614 error = 0; 615 goto cleanup; 616 } 617 618 if (bootverbose || BHNDB_DEBUG(PRIO)) 619 device_printf(sc->dev, "%s resource configuration\n", hw->name); 620 621 /* Release existing resource state */ 622 BHNDB_LOCK(sc); 623 bhndb_free_resources(sc->bus_res); 624 sc->bus_res = NULL; 625 BHNDB_UNLOCK(sc); 626 627 /* Allocate new resource state */ 628 r = bhndb_alloc_resources(dev, sc->parent_dev, hw->cfg); 629 if (r == NULL) { 630 error = ENXIO; 631 goto cleanup; 632 } 633 634 /* Initialize our resource priority configuration */ 635 error = bhndb_initialize_region_cfg(sc, devs, ndevs, hw_prio_table, r); 636 if (error) { 637 bhndb_free_resources(r); 638 goto cleanup; 639 } 640 641 /* Update our bridge state */ 642 BHNDB_LOCK(sc); 643 sc->bus_res = r; 644 sc->hostb_dev = hostb; 645 BHNDB_UNLOCK(sc); 646 647 cleanup: 648 free(devs, M_TEMP); 649 return (error); 650 } 651 652 /** 653 * Default bhndb(4) implementation of DEVICE_DETACH(). 654 * 655 * This function detaches any child devices, and if successful, releases all 656 * resources held by the bridge device. 657 */ 658 int 659 bhndb_generic_detach(device_t dev) 660 { 661 struct bhndb_softc *sc; 662 int error; 663 664 sc = device_get_softc(dev); 665 666 /* Detach children */ 667 if ((error = bus_generic_detach(dev))) 668 return (error); 669 670 /* Clean up our driver state. */ 671 bhndb_free_resources(sc->bus_res); 672 673 BHNDB_LOCK_DESTROY(sc); 674 675 return (0); 676 } 677 678 /** 679 * Default bhndb(4) implementation of DEVICE_SUSPEND(). 680 * 681 * This function calls bus_generic_suspend() (or implements equivalent 682 * behavior). 683 */ 684 int 685 bhndb_generic_suspend(device_t dev) 686 { 687 return (bus_generic_suspend(dev)); 688 } 689 690 /** 691 * Default bhndb(4) implementation of DEVICE_RESUME(). 692 * 693 * This function calls bus_generic_resume() (or implements equivalent 694 * behavior). 695 */ 696 int 697 bhndb_generic_resume(device_t dev) 698 { 699 struct bhndb_softc *sc; 700 struct bhndb_resources *bus_res; 701 struct bhndb_dw_alloc *dwa; 702 int error; 703 704 sc = device_get_softc(dev); 705 bus_res = sc->bus_res; 706 707 /* Guarantee that all in-use dynamic register windows are mapped to 708 * their previously configured target address. */ 709 BHNDB_LOCK(sc); 710 for (size_t i = 0; i < bus_res->dwa_count; i++) { 711 dwa = &bus_res->dw_alloc[i]; 712 713 /* Skip regions that were not previously used */ 714 if (bhndb_dw_is_free(bus_res, dwa) && dwa->target == 0x0) 715 continue; 716 717 /* Otherwise, ensure the register window is correct before 718 * any children attempt MMIO */ 719 error = BHNDB_SET_WINDOW_ADDR(dev, dwa->win, dwa->target); 720 if (error) 721 break; 722 } 723 BHNDB_UNLOCK(sc); 724 725 /* Error restoring hardware state; children cannot be safely resumed */ 726 if (error) { 727 device_printf(dev, "Unable to restore hardware configuration; " 728 "cannot resume: %d\n", error); 729 return (error); 730 } 731 732 return (bus_generic_resume(dev)); 733 } 734 735 /** 736 * Default implementation of BHNDB_SUSPEND_RESOURCE. 737 */ 738 static void 739 bhndb_suspend_resource(device_t dev, device_t child, int type, 740 struct resource *r) 741 { 742 struct bhndb_softc *sc; 743 struct bhndb_dw_alloc *dwa; 744 745 sc = device_get_softc(dev); 746 747 // TODO: IRQs? 748 if (type != SYS_RES_MEMORY) 749 return; 750 751 BHNDB_LOCK(sc); 752 dwa = bhndb_dw_find_resource(sc->bus_res, r); 753 if (dwa == NULL) { 754 BHNDB_UNLOCK(sc); 755 return; 756 } 757 758 if (BHNDB_DEBUG(PRIO)) 759 device_printf(child, "suspend resource type=%d 0x%jx+0x%jx\n", 760 type, rman_get_start(r), rman_get_size(r)); 761 762 /* Release the resource's window reference */ 763 bhndb_dw_release(sc->bus_res, dwa, r); 764 BHNDB_UNLOCK(sc); 765 } 766 767 /** 768 * Default implementation of BHNDB_RESUME_RESOURCE. 769 */ 770 static int 771 bhndb_resume_resource(device_t dev, device_t child, int type, 772 struct resource *r) 773 { 774 struct bhndb_softc *sc; 775 776 sc = device_get_softc(dev); 777 778 // TODO: IRQs? 779 if (type != SYS_RES_MEMORY) 780 return (0); 781 782 /* Inactive resources don't require reallocation of bridge resources */ 783 if (!(rman_get_flags(r) & RF_ACTIVE)) 784 return (0); 785 786 if (BHNDB_DEBUG(PRIO)) 787 device_printf(child, "resume resource type=%d 0x%jx+0x%jx\n", 788 type, rman_get_start(r), rman_get_size(r)); 789 790 return (bhndb_try_activate_resource(sc, rman_get_device(r), type, 791 rman_get_rid(r), r, NULL)); 792 } 793 794 795 /** 796 * Default bhndb(4) implementation of BUS_READ_IVAR(). 797 */ 798 static int 799 bhndb_read_ivar(device_t dev, device_t child, int index, 800 uintptr_t *result) 801 { 802 return (ENOENT); 803 } 804 805 /** 806 * Default bhndb(4) implementation of BUS_WRITE_IVAR(). 807 */ 808 static int 809 bhndb_write_ivar(device_t dev, device_t child, int index, 810 uintptr_t value) 811 { 812 return (ENOENT); 813 } 814 815 /** 816 * Return the address space for the given @p child device. 817 */ 818 bhndb_addrspace 819 bhndb_get_addrspace(struct bhndb_softc *sc, device_t child) 820 { 821 struct bhndb_devinfo *dinfo; 822 device_t imd_dev; 823 824 /* Find the directly attached parent of the requesting device */ 825 imd_dev = child; 826 while (imd_dev != NULL && device_get_parent(imd_dev) != sc->dev) 827 imd_dev = device_get_parent(imd_dev); 828 829 if (imd_dev == NULL) 830 panic("bhndb address space request for non-child device %s\n", 831 device_get_nameunit(child)); 832 833 dinfo = device_get_ivars(imd_dev); 834 return (dinfo->addrspace); 835 } 836 837 /** 838 * Return the rman instance for a given resource @p type, if any. 839 * 840 * @param sc The bhndb device state. 841 * @param child The requesting child. 842 * @param type The resource type (e.g. SYS_RES_MEMORY, SYS_RES_IRQ, ...) 843 */ 844 static struct rman * 845 bhndb_get_rman(struct bhndb_softc *sc, device_t child, int type) 846 { 847 switch (bhndb_get_addrspace(sc, child)) { 848 case BHNDB_ADDRSPACE_NATIVE: 849 switch (type) { 850 case SYS_RES_MEMORY: 851 return (&sc->bus_res->ht_mem_rman); 852 case SYS_RES_IRQ: 853 return (NULL); 854 default: 855 return (NULL); 856 }; 857 858 case BHNDB_ADDRSPACE_BRIDGED: 859 switch (type) { 860 case SYS_RES_MEMORY: 861 return (&sc->bus_res->br_mem_rman); 862 case SYS_RES_IRQ: 863 // TODO 864 // return &sc->irq_rman; 865 return (NULL); 866 default: 867 return (NULL); 868 }; 869 } 870 871 /* Quieten gcc */ 872 return (NULL); 873 } 874 875 /** 876 * Default implementation of BUS_ADD_CHILD() 877 */ 878 static device_t 879 bhndb_add_child(device_t dev, u_int order, const char *name, int unit) 880 { 881 struct bhndb_devinfo *dinfo; 882 device_t child; 883 884 child = device_add_child_ordered(dev, order, name, unit); 885 if (child == NULL) 886 return (NULL); 887 888 dinfo = malloc(sizeof(struct bhndb_devinfo), M_BHND, M_NOWAIT); 889 if (dinfo == NULL) { 890 device_delete_child(dev, child); 891 return (NULL); 892 } 893 894 dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE; 895 resource_list_init(&dinfo->resources); 896 897 device_set_ivars(child, dinfo); 898 899 return (child); 900 } 901 902 /** 903 * Default implementation of BUS_CHILD_DELETED(). 904 */ 905 static void 906 bhndb_child_deleted(device_t dev, device_t child) 907 { 908 struct bhndb_devinfo *dinfo = device_get_ivars(child); 909 if (dinfo != NULL) { 910 resource_list_free(&dinfo->resources); 911 free(dinfo, M_BHND); 912 } 913 914 device_set_ivars(child, NULL); 915 } 916 917 /** 918 * Default implementation of BHNDB_GET_CHIPID(). 919 */ 920 static const struct bhnd_chipid * 921 bhndb_get_chipid(device_t dev, device_t child) 922 { 923 struct bhndb_softc *sc = device_get_softc(dev); 924 return (&sc->chipid); 925 } 926 927 928 /** 929 * Default implementation of BHNDB_IS_HW_DISABLED(). 930 */ 931 static bool 932 bhndb_is_hw_disabled(device_t dev, device_t child) { 933 struct bhndb_softc *sc; 934 struct bhnd_core_info core; 935 936 sc = device_get_softc(dev); 937 938 /* Requestor must be attached to the bhnd bus */ 939 if (device_get_parent(child) != sc->bus_dev) { 940 return (BHND_BUS_IS_HW_DISABLED(device_get_parent(dev), child)); 941 } 942 943 /* Fetch core info */ 944 core = bhnd_get_core_info(child); 945 946 /* Try to defer to the bhndb bus parent */ 947 if (BHNDB_BUS_IS_CORE_DISABLED(sc->parent_dev, dev, &core)) 948 return (true); 949 950 /* Otherwise, we treat bridge-capable cores as unpopulated if they're 951 * not the configured host bridge */ 952 if (BHND_DEVCLASS_SUPPORTS_HOSTB(bhnd_core_class(&core))) 953 return (BHNDB_FIND_HOSTB_DEVICE(dev, sc->bus_dev) != child); 954 955 /* Otherwise, assume the core is populated */ 956 return (false); 957 } 958 959 /* ascending core index comparison used by bhndb_find_hostb_device() */ 960 static int 961 compare_core_index(const void *lhs, const void *rhs) 962 { 963 u_int left = bhnd_get_core_index(*(const device_t *) lhs); 964 u_int right = bhnd_get_core_index(*(const device_t *) rhs); 965 966 if (left < right) 967 return (-1); 968 else if (left > right) 969 return (1); 970 else 971 return (0); 972 } 973 974 /** 975 * Default bhndb(4) implementation of BHND_BUS_FIND_HOSTB_DEVICE(). 976 * 977 * This function uses a heuristic valid on all known PCI/PCIe/PCMCIA-bridged 978 * bhnd(4) devices to determine the hostb core: 979 * 980 * - The core must have a Broadcom vendor ID. 981 * - The core devclass must match the bridge type. 982 * - The core must be the first device on the bus with the bridged device 983 * class. 984 * 985 * @param dev The bhndb device 986 * @param child The requesting bhnd bus. 987 */ 988 static device_t 989 bhndb_find_hostb_device(device_t dev, device_t child) 990 { 991 struct bhndb_softc *sc; 992 struct bhnd_device_match md; 993 device_t hostb_dev, *devlist; 994 int devcnt, error; 995 996 sc = device_get_softc(dev); 997 998 /* Set up a match descriptor for the required device class. */ 999 md = (struct bhnd_device_match) { 1000 BHND_MATCH_CORE_CLASS(sc->bridge_class), 1001 BHND_MATCH_CORE_UNIT(0) 1002 }; 1003 1004 /* Must be the absolute first matching device on the bus. */ 1005 if ((error = device_get_children(child, &devlist, &devcnt))) 1006 return (false); 1007 1008 /* Sort by core index value, ascending */ 1009 qsort(devlist, devcnt, sizeof(*devlist), compare_core_index); 1010 1011 /* Find the hostb device */ 1012 hostb_dev = NULL; 1013 for (int i = 0; i < devcnt; i++) { 1014 if (bhnd_device_matches(devlist[i], &md)) { 1015 hostb_dev = devlist[i]; 1016 break; 1017 } 1018 } 1019 1020 /* Clean up */ 1021 free(devlist, M_TEMP); 1022 1023 return (hostb_dev); 1024 } 1025 1026 /** 1027 * Default bhndb(4) implementation of BUS_ALLOC_RESOURCE(). 1028 */ 1029 static struct resource * 1030 bhndb_alloc_resource(device_t dev, device_t child, int type, 1031 int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 1032 { 1033 struct bhndb_softc *sc; 1034 struct resource_list_entry *rle; 1035 struct resource *rv; 1036 struct rman *rm; 1037 int error; 1038 bool passthrough, isdefault; 1039 1040 sc = device_get_softc(dev); 1041 passthrough = (device_get_parent(child) != dev); 1042 isdefault = RMAN_IS_DEFAULT_RANGE(start, end); 1043 rle = NULL; 1044 1045 /* Populate defaults */ 1046 if (!passthrough && isdefault) { 1047 /* Fetch the resource list entry. */ 1048 rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child), 1049 type, *rid); 1050 if (rle == NULL) { 1051 device_printf(dev, 1052 "default resource %#x type %d for child %s " 1053 "not found\n", *rid, type, 1054 device_get_nameunit(child)); 1055 1056 return (NULL); 1057 } 1058 1059 if (rle->res != NULL) { 1060 device_printf(dev, 1061 "resource entry %#x type %d for child %s is busy\n", 1062 *rid, type, device_get_nameunit(child)); 1063 1064 return (NULL); 1065 } 1066 1067 start = rle->start; 1068 end = rle->end; 1069 count = ulmax(count, rle->count); 1070 } 1071 1072 /* Validate resource addresses */ 1073 if (start > end || count > ((end - start) + 1)) 1074 return (NULL); 1075 1076 /* Fetch the resource manager */ 1077 rm = bhndb_get_rman(sc, child, type); 1078 if (rm == NULL) 1079 return (NULL); 1080 1081 /* Make our reservation */ 1082 rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, 1083 child); 1084 if (rv == NULL) 1085 return (NULL); 1086 1087 rman_set_rid(rv, *rid); 1088 1089 /* Activate */ 1090 if (flags & RF_ACTIVE) { 1091 error = bus_activate_resource(child, type, *rid, rv); 1092 if (error) { 1093 device_printf(dev, 1094 "failed to activate entry %#x type %d for " 1095 "child %s: %d\n", 1096 *rid, type, device_get_nameunit(child), error); 1097 1098 rman_release_resource(rv); 1099 1100 return (NULL); 1101 } 1102 } 1103 1104 /* Update child's resource list entry */ 1105 if (rle != NULL) { 1106 rle->res = rv; 1107 rle->start = rman_get_start(rv); 1108 rle->end = rman_get_end(rv); 1109 rle->count = rman_get_size(rv); 1110 } 1111 1112 return (rv); 1113 } 1114 1115 /** 1116 * Default bhndb(4) implementation of BUS_RELEASE_RESOURCE(). 1117 */ 1118 static int 1119 bhndb_release_resource(device_t dev, device_t child, int type, int rid, 1120 struct resource *r) 1121 { 1122 int error; 1123 1124 /* Deactivate resources */ 1125 if (rman_get_flags(r) & RF_ACTIVE) { 1126 error = BUS_DEACTIVATE_RESOURCE(dev, child, type, rid, r); 1127 if (error) 1128 return (error); 1129 } 1130 1131 if ((error = rman_release_resource(r))) 1132 return (error); 1133 1134 return (0); 1135 } 1136 1137 /** 1138 * Default bhndb(4) implementation of BUS_ADJUST_RESOURCE(). 1139 */ 1140 static int 1141 bhndb_adjust_resource(device_t dev, device_t child, int type, 1142 struct resource *r, rman_res_t start, rman_res_t end) 1143 { 1144 struct bhndb_softc *sc; 1145 struct rman *rm; 1146 rman_res_t mstart, mend; 1147 int error; 1148 1149 sc = device_get_softc(dev); 1150 error = 0; 1151 1152 /* Verify basic constraints */ 1153 if (end <= start) 1154 return (EINVAL); 1155 1156 /* Fetch resource manager */ 1157 rm = bhndb_get_rman(sc, child, type); 1158 if (rm == NULL) 1159 return (ENXIO); 1160 1161 if (!rman_is_region_manager(r, rm)) 1162 return (ENXIO); 1163 1164 BHNDB_LOCK(sc); 1165 1166 /* If not active, allow any range permitted by the resource manager */ 1167 if (!(rman_get_flags(r) & RF_ACTIVE)) 1168 goto done; 1169 1170 /* Otherwise, the range is limited to the existing register window 1171 * mapping */ 1172 error = bhndb_find_resource_limits(sc->bus_res, r, &mstart, &mend); 1173 if (error) 1174 goto done; 1175 1176 if (start < mstart || end > mend) { 1177 error = EINVAL; 1178 goto done; 1179 } 1180 1181 /* Fall through */ 1182 done: 1183 if (!error) 1184 error = rman_adjust_resource(r, start, end); 1185 1186 BHNDB_UNLOCK(sc); 1187 return (error); 1188 } 1189 1190 /** 1191 * Initialize child resource @p r with a virtual address, tag, and handle 1192 * copied from @p parent, adjusted to contain only the range defined by 1193 * @p offsize and @p size. 1194 * 1195 * @param r The register to be initialized. 1196 * @param parent The parent bus resource that fully contains the subregion. 1197 * @param offset The subregion offset within @p parent. 1198 * @param size The subregion size. 1199 * @p r. 1200 */ 1201 static int 1202 bhndb_init_child_resource(struct resource *r, 1203 struct resource *parent, bhnd_size_t offset, bhnd_size_t size) 1204 { 1205 bus_space_handle_t bh, child_bh; 1206 bus_space_tag_t bt; 1207 uintptr_t vaddr; 1208 int error; 1209 1210 /* Fetch the parent resource's real bus values */ 1211 vaddr = (uintptr_t) rman_get_virtual(parent); 1212 bt = rman_get_bustag(parent); 1213 bh = rman_get_bushandle(parent); 1214 1215 /* Configure child resource with window-adjusted real bus values */ 1216 vaddr += offset; 1217 error = bus_space_subregion(bt, bh, offset, size, &child_bh); 1218 if (error) 1219 return (error); 1220 1221 rman_set_virtual(r, (void *) vaddr); 1222 rman_set_bustag(r, bt); 1223 rman_set_bushandle(r, child_bh); 1224 1225 return (0); 1226 } 1227 1228 /** 1229 * Attempt activation of a fixed register window mapping for @p child. 1230 * 1231 * @param sc BHNDB device state. 1232 * @param region The static region definition capable of mapping @p r. 1233 * @param child A child requesting resource activation. 1234 * @param type Resource type. 1235 * @param rid Resource identifier. 1236 * @param r Resource to be activated. 1237 * 1238 * @retval 0 if @p r was activated successfully 1239 * @retval ENOENT if no fixed register window was found. 1240 * @retval non-zero if @p r could not be activated. 1241 */ 1242 static int 1243 bhndb_activate_static_region(struct bhndb_softc *sc, 1244 struct bhndb_region *region, device_t child, int type, int rid, 1245 struct resource *r) 1246 { 1247 struct resource *bridge_res; 1248 const struct bhndb_regwin *win; 1249 bhnd_size_t parent_offset; 1250 rman_res_t r_start, r_size; 1251 int error; 1252 1253 win = region->static_regwin; 1254 1255 KASSERT(win != NULL && BHNDB_REGWIN_T_IS_STATIC(win->win_type), 1256 ("can't activate non-static region")); 1257 1258 r_start = rman_get_start(r); 1259 r_size = rman_get_size(r); 1260 1261 /* Find the corresponding bridge resource */ 1262 bridge_res = bhndb_find_regwin_resource(sc->bus_res, win); 1263 if (bridge_res == NULL) 1264 return (ENXIO); 1265 1266 /* Calculate subregion offset within the parent resource */ 1267 parent_offset = r_start - region->addr; 1268 parent_offset += win->win_offset; 1269 1270 /* Configure resource with its real bus values. */ 1271 error = bhndb_init_child_resource(r, bridge_res, parent_offset, r_size); 1272 if (error) 1273 return (error); 1274 1275 /* Mark active */ 1276 if ((error = rman_activate_resource(r))) 1277 return (error); 1278 1279 return (0); 1280 } 1281 1282 /** 1283 * Attempt to allocate/retain a dynamic register window for @p r, returning 1284 * the retained window. 1285 * 1286 * @param sc The bhndb driver state. 1287 * @param r The resource for which a window will be retained. 1288 */ 1289 static struct bhndb_dw_alloc * 1290 bhndb_retain_dynamic_window(struct bhndb_softc *sc, struct resource *r) 1291 { 1292 struct bhndb_dw_alloc *dwa; 1293 rman_res_t r_start, r_size; 1294 int error; 1295 1296 BHNDB_LOCK_ASSERT(sc, MA_OWNED); 1297 1298 r_start = rman_get_start(r); 1299 r_size = rman_get_size(r); 1300 1301 /* Look for an existing dynamic window we can reference */ 1302 dwa = bhndb_dw_find_mapping(sc->bus_res, r_start, r_size); 1303 if (dwa != NULL) { 1304 if (bhndb_dw_retain(sc->bus_res, dwa, r) == 0) 1305 return (dwa); 1306 1307 return (NULL); 1308 } 1309 1310 /* Otherwise, try to reserve a free window */ 1311 dwa = bhndb_dw_next_free(sc->bus_res); 1312 if (dwa == NULL) { 1313 /* No free windows */ 1314 return (NULL); 1315 } 1316 1317 /* Set the window target */ 1318 error = bhndb_dw_set_addr(sc->dev, sc->bus_res, dwa, rman_get_start(r), 1319 rman_get_size(r)); 1320 if (error) { 1321 device_printf(sc->dev, "dynamic window initialization " 1322 "for 0x%llx-0x%llx failed: %d\n", 1323 (unsigned long long) r_start, 1324 (unsigned long long) r_start + r_size - 1, 1325 error); 1326 return (NULL); 1327 } 1328 1329 /* Add our reservation */ 1330 if (bhndb_dw_retain(sc->bus_res, dwa, r)) 1331 return (NULL); 1332 1333 return (dwa); 1334 } 1335 1336 /** 1337 * Activate a resource using any viable static or dynamic register window. 1338 * 1339 * @param sc The bhndb driver state. 1340 * @param child The child holding ownership of @p r. 1341 * @param type The type of the resource to be activated. 1342 * @param rid The resource ID of @p r. 1343 * @param r The resource to be activated 1344 * @param[out] indirect On error and if not NULL, will be set to 'true' if 1345 * the caller should instead use an indirect resource mapping. 1346 * 1347 * @retval 0 success 1348 * @retval non-zero activation failed. 1349 */ 1350 static int 1351 bhndb_try_activate_resource(struct bhndb_softc *sc, device_t child, int type, 1352 int rid, struct resource *r, bool *indirect) 1353 { 1354 struct bhndb_region *region; 1355 struct bhndb_dw_alloc *dwa; 1356 bhndb_priority_t dw_priority; 1357 rman_res_t r_start, r_size; 1358 rman_res_t parent_offset; 1359 int error; 1360 1361 BHNDB_LOCK_ASSERT(sc, MA_NOTOWNED); 1362 1363 // TODO - IRQs 1364 if (type != SYS_RES_MEMORY) 1365 return (ENXIO); 1366 1367 if (indirect) 1368 *indirect = false; 1369 1370 r_start = rman_get_start(r); 1371 r_size = rman_get_size(r); 1372 1373 /* Activate native addrspace resources using the host address space */ 1374 if (bhndb_get_addrspace(sc, child) == BHNDB_ADDRSPACE_NATIVE) { 1375 struct resource *parent; 1376 1377 /* Find the bridge resource referenced by the child */ 1378 parent = bhndb_find_resource_range(sc->bus_res, r_start, 1379 r_size); 1380 if (parent == NULL) { 1381 device_printf(sc->dev, "host resource not found " 1382 "for 0x%llx-0x%llx\n", 1383 (unsigned long long) r_start, 1384 (unsigned long long) r_start + r_size - 1); 1385 return (ENOENT); 1386 } 1387 1388 /* Initialize child resource with the real bus values */ 1389 error = bhndb_init_child_resource(r, parent, 1390 r_start - rman_get_start(parent), r_size); 1391 if (error) 1392 return (error); 1393 1394 /* Try to activate child resource */ 1395 return (rman_activate_resource(r)); 1396 } 1397 1398 /* Default to low priority */ 1399 dw_priority = BHNDB_PRIORITY_LOW; 1400 1401 /* Look for a bus region matching the resource's address range */ 1402 region = bhndb_find_resource_region(sc->bus_res, r_start, r_size); 1403 if (region != NULL) 1404 dw_priority = region->priority; 1405 1406 /* Prefer static mappings over consuming a dynamic windows. */ 1407 if (region && region->static_regwin) { 1408 error = bhndb_activate_static_region(sc, region, child, type, 1409 rid, r); 1410 if (error) 1411 device_printf(sc->dev, "static window allocation " 1412 "for 0x%llx-0x%llx failed\n", 1413 (unsigned long long) r_start, 1414 (unsigned long long) r_start + r_size - 1); 1415 return (error); 1416 } 1417 1418 /* A dynamic window will be required; is this resource high enough 1419 * priority to be reserved a dynamic window? */ 1420 if (dw_priority < sc->bus_res->min_prio) { 1421 if (indirect) 1422 *indirect = true; 1423 1424 return (ENOMEM); 1425 } 1426 1427 /* Find and retain a usable window */ 1428 BHNDB_LOCK(sc); { 1429 dwa = bhndb_retain_dynamic_window(sc, r); 1430 } BHNDB_UNLOCK(sc); 1431 1432 if (dwa == NULL) { 1433 if (indirect) 1434 *indirect = true; 1435 return (ENOMEM); 1436 } 1437 1438 /* Configure resource with its real bus values. */ 1439 parent_offset = dwa->win->win_offset; 1440 parent_offset += r_start - dwa->target; 1441 1442 error = bhndb_init_child_resource(r, dwa->parent_res, parent_offset, 1443 dwa->win->win_size); 1444 if (error) 1445 goto failed; 1446 1447 /* Mark active */ 1448 if ((error = rman_activate_resource(r))) 1449 goto failed; 1450 1451 return (0); 1452 1453 failed: 1454 /* Release our region allocation. */ 1455 BHNDB_LOCK(sc); 1456 bhndb_dw_release(sc->bus_res, dwa, r); 1457 BHNDB_UNLOCK(sc); 1458 1459 return (error); 1460 } 1461 1462 /** 1463 * Default bhndb(4) implementation of BUS_ACTIVATE_RESOURCE(). 1464 * 1465 * Maps resource activation requests to a viable static or dynamic 1466 * register window, if any. 1467 */ 1468 static int 1469 bhndb_activate_resource(device_t dev, device_t child, int type, int rid, 1470 struct resource *r) 1471 { 1472 struct bhndb_softc *sc = device_get_softc(dev); 1473 1474 return (bhndb_try_activate_resource(sc, child, type, rid, r, NULL)); 1475 } 1476 1477 /** 1478 * Default bhndb(4) implementation of BUS_DEACTIVATE_RESOURCE(). 1479 */ 1480 static int 1481 bhndb_deactivate_resource(device_t dev, device_t child, int type, 1482 int rid, struct resource *r) 1483 { 1484 struct bhndb_dw_alloc *dwa; 1485 struct bhndb_softc *sc; 1486 struct rman *rm; 1487 int error; 1488 1489 sc = device_get_softc(dev); 1490 1491 if ((rm = bhndb_get_rman(sc, child, type)) == NULL) 1492 return (EINVAL); 1493 1494 /* Mark inactive */ 1495 if ((error = rman_deactivate_resource(r))) 1496 return (error); 1497 1498 /* Free any dynamic window allocation. */ 1499 if (bhndb_get_addrspace(sc, child) == BHNDB_ADDRSPACE_BRIDGED) { 1500 BHNDB_LOCK(sc); 1501 dwa = bhndb_dw_find_resource(sc->bus_res, r); 1502 if (dwa != NULL) 1503 bhndb_dw_release(sc->bus_res, dwa, r); 1504 BHNDB_UNLOCK(sc); 1505 } 1506 1507 return (0); 1508 } 1509 1510 /** 1511 * Default bhndb(4) implementation of BUS_GET_RESOURCE_LIST(). 1512 */ 1513 static struct resource_list * 1514 bhndb_get_resource_list(device_t dev, device_t child) 1515 { 1516 struct bhndb_devinfo *dinfo = device_get_ivars(child); 1517 return (&dinfo->resources); 1518 } 1519 1520 /** 1521 * Default bhndb(4) implementation of BHND_BUS_ACTIVATE_RESOURCE(). 1522 * 1523 * For BHNDB_ADDRSPACE_NATIVE children, all resources may be assumed to 1524 * be activated by the bridge. 1525 * 1526 * For BHNDB_ADDRSPACE_BRIDGED children, attempts to activate a static register 1527 * window, a dynamic register window, or configures @p r as an indirect 1528 * resource -- in that order. 1529 */ 1530 static int 1531 bhndb_activate_bhnd_resource(device_t dev, device_t child, 1532 int type, int rid, struct bhnd_resource *r) 1533 { 1534 struct bhndb_softc *sc; 1535 struct bhndb_region *region; 1536 rman_res_t r_start, r_size; 1537 int error; 1538 bool indirect; 1539 1540 KASSERT(!r->direct, 1541 ("direct flag set on inactive resource")); 1542 1543 KASSERT(!(rman_get_flags(r->res) & RF_ACTIVE), 1544 ("RF_ACTIVE set on inactive resource")); 1545 1546 sc = device_get_softc(dev); 1547 1548 r_start = rman_get_start(r->res); 1549 r_size = rman_get_size(r->res); 1550 1551 /* Verify bridged address range's resource priority, and skip direct 1552 * allocation if the priority is too low. */ 1553 if (bhndb_get_addrspace(sc, child) == BHNDB_ADDRSPACE_BRIDGED) { 1554 bhndb_priority_t r_prio; 1555 1556 region = bhndb_find_resource_region(sc->bus_res, r_start, 1557 r_size); 1558 if (region != NULL) 1559 r_prio = region->priority; 1560 else 1561 r_prio = BHNDB_PRIORITY_NONE; 1562 1563 /* If less than the minimum dynamic window priority, this 1564 * resource should always be indirect. */ 1565 if (r_prio < sc->bus_res->min_prio) 1566 return (0); 1567 } 1568 1569 /* Attempt direct activation */ 1570 error = bhndb_try_activate_resource(sc, child, type, rid, r->res, 1571 &indirect); 1572 if (!error) { 1573 r->direct = true; 1574 } else if (indirect) { 1575 /* The request was valid, but no viable register window is 1576 * available; indirection must be employed. */ 1577 error = 0; 1578 r->direct = false; 1579 } 1580 1581 if (BHNDB_DEBUG(PRIO) && 1582 bhndb_get_addrspace(sc, child) == BHNDB_ADDRSPACE_BRIDGED) 1583 { 1584 device_printf(child, "activated 0x%llx-0x%llx as %s " 1585 "resource\n", 1586 (unsigned long long) r_start, 1587 (unsigned long long) r_start + r_size - 1, 1588 r->direct ? "direct" : "indirect"); 1589 } 1590 1591 return (error); 1592 }; 1593 1594 /** 1595 * Default bhndb(4) implementation of BHND_BUS_DEACTIVATE_RESOURCE(). 1596 */ 1597 static int 1598 bhndb_deactivate_bhnd_resource(device_t dev, device_t child, 1599 int type, int rid, struct bhnd_resource *r) 1600 { 1601 int error; 1602 1603 /* Indirect resources don't require activation */ 1604 if (!r->direct) 1605 return (0); 1606 1607 KASSERT(rman_get_flags(r->res) & RF_ACTIVE, 1608 ("RF_ACTIVE not set on direct resource")); 1609 1610 /* Perform deactivation */ 1611 error = bus_deactivate_resource(child, type, rid, r->res); 1612 if (!error) 1613 r->direct = false; 1614 1615 return (error); 1616 }; 1617 1618 /** 1619 * Slow path for bhndb_io_resource(). 1620 * 1621 * Iterates over the existing allocated dynamic windows looking for a viable 1622 * in-use region; the first matching region is returned. 1623 */ 1624 static struct bhndb_dw_alloc * 1625 bhndb_io_resource_slow(struct bhndb_softc *sc, bus_addr_t addr, 1626 bus_size_t size, bus_size_t *offset) 1627 { 1628 struct bhndb_resources *br; 1629 struct bhndb_dw_alloc *dwa; 1630 1631 BHNDB_LOCK_ASSERT(sc, MA_OWNED); 1632 1633 br = sc->bus_res; 1634 1635 /* Search for an existing dynamic mapping of this address range. 1636 * Static regions are not searched, as a statically mapped 1637 * region would never be allocated as an indirect resource. */ 1638 for (size_t i = 0; i < br->dwa_count; i++) { 1639 const struct bhndb_regwin *win; 1640 1641 dwa = &br->dw_alloc[i]; 1642 win = dwa->win; 1643 1644 KASSERT(win->win_type == BHNDB_REGWIN_T_DYN, 1645 ("invalid register window type")); 1646 1647 /* Verify the range */ 1648 if (addr < dwa->target) 1649 continue; 1650 1651 if (addr + size > dwa->target + win->win_size) 1652 continue; 1653 1654 /* Found */ 1655 *offset = dwa->win->win_offset; 1656 *offset += addr - dwa->target; 1657 1658 return (dwa); 1659 } 1660 1661 /* not found */ 1662 return (NULL); 1663 } 1664 1665 /** 1666 * Find the bridge resource to be used for I/O requests. 1667 * 1668 * @param sc Bridge driver state. 1669 * @param addr The I/O target address. 1670 * @param size The size of the I/O operation to be performed at @p addr. 1671 * @param[out] offset The offset within the returned resource at which 1672 * to perform the I/O request. 1673 */ 1674 static inline struct bhndb_dw_alloc * 1675 bhndb_io_resource(struct bhndb_softc *sc, bus_addr_t addr, bus_size_t size, 1676 bus_size_t *offset) 1677 { 1678 struct bhndb_resources *br; 1679 struct bhndb_dw_alloc *dwa; 1680 int error; 1681 1682 BHNDB_LOCK_ASSERT(sc, MA_OWNED); 1683 1684 br = sc->bus_res; 1685 1686 /* Try to fetch a free window */ 1687 dwa = bhndb_dw_next_free(br); 1688 1689 /* 1690 * If no dynamic windows are available, look for an existing 1691 * region that maps the target range. 1692 * 1693 * If none are found, this is a child driver bug -- our window 1694 * over-commit should only fail in the case where a child driver leaks 1695 * resources, or perform operations out-of-order. 1696 * 1697 * Broadcom HND chipsets are designed to not require register window 1698 * swapping during execution; as long as the child devices are 1699 * attached/detached correctly, using the hardware's required order 1700 * of operations, there should always be a window available for the 1701 * current operation. 1702 */ 1703 if (dwa == NULL) { 1704 dwa = bhndb_io_resource_slow(sc, addr, size, offset); 1705 if (dwa == NULL) { 1706 panic("register windows exhausted attempting to map " 1707 "0x%llx-0x%llx\n", 1708 (unsigned long long) addr, 1709 (unsigned long long) addr+size-1); 1710 } 1711 1712 return (dwa); 1713 } 1714 1715 /* Adjust the window if the I/O request won't fit in the current 1716 * target range. */ 1717 if (addr < dwa->target || 1718 (dwa->target + dwa->win->win_size) - addr < size) 1719 { 1720 error = bhndb_dw_set_addr(sc->dev, sc->bus_res, dwa, addr, 1721 size); 1722 if (error) { 1723 panic("failed to set register window target mapping " 1724 "0x%llx-0x%llx\n", 1725 (unsigned long long) addr, 1726 (unsigned long long) addr+size-1); 1727 } 1728 } 1729 1730 /* Calculate the offset and return */ 1731 *offset = (addr - dwa->target) + dwa->win->win_offset; 1732 return (dwa); 1733 } 1734 1735 /* 1736 * BHND_BUS_(READ|WRITE_* implementations 1737 */ 1738 1739 /* bhndb_bus_(read|write) common implementation */ 1740 #define BHNDB_IO_COMMON_SETUP(_io_size) \ 1741 struct bhndb_softc *sc; \ 1742 struct bhndb_dw_alloc *dwa; \ 1743 struct resource *io_res; \ 1744 bus_size_t io_offset; \ 1745 \ 1746 sc = device_get_softc(dev); \ 1747 \ 1748 BHNDB_LOCK(sc); \ 1749 dwa = bhndb_io_resource(sc, rman_get_start(r->res) + \ 1750 offset, _io_size, &io_offset); \ 1751 io_res = dwa->parent_res; \ 1752 \ 1753 KASSERT(!r->direct, \ 1754 ("bhnd_bus slow path used for direct resource")); \ 1755 \ 1756 KASSERT(rman_get_flags(io_res) & RF_ACTIVE, \ 1757 ("i/o resource is not active")); 1758 1759 #define BHNDB_IO_COMMON_TEARDOWN() \ 1760 BHNDB_UNLOCK(sc); 1761 1762 /* Defines a bhndb_bus_read_* method implementation */ 1763 #define BHNDB_IO_READ(_type, _name) \ 1764 static _type \ 1765 bhndb_bus_read_ ## _name (device_t dev, device_t child, \ 1766 struct bhnd_resource *r, bus_size_t offset) \ 1767 { \ 1768 _type v; \ 1769 BHNDB_IO_COMMON_SETUP(sizeof(_type)); \ 1770 v = bus_read_ ## _name (io_res, io_offset); \ 1771 BHNDB_IO_COMMON_TEARDOWN(); \ 1772 \ 1773 return (v); \ 1774 } 1775 1776 /* Defines a bhndb_bus_write_* method implementation */ 1777 #define BHNDB_IO_WRITE(_type, _name) \ 1778 static void \ 1779 bhndb_bus_write_ ## _name (device_t dev, device_t child, \ 1780 struct bhnd_resource *r, bus_size_t offset, _type value) \ 1781 { \ 1782 BHNDB_IO_COMMON_SETUP(sizeof(_type)); \ 1783 bus_write_ ## _name (io_res, io_offset, value); \ 1784 BHNDB_IO_COMMON_TEARDOWN(); \ 1785 } 1786 1787 /* Defines a bhndb_bus_(read|write|set)_(multi|region)_* method */ 1788 #define BHNDB_IO_MISC(_type, _ptr, _op, _size) \ 1789 static void \ 1790 bhndb_bus_ ## _op ## _ ## _size (device_t dev, \ 1791 device_t child, struct bhnd_resource *r, bus_size_t offset, \ 1792 _type _ptr datap, bus_size_t count) \ 1793 { \ 1794 BHNDB_IO_COMMON_SETUP(sizeof(_type) * count); \ 1795 bus_ ## _op ## _ ## _size (io_res, io_offset, \ 1796 datap, count); \ 1797 BHNDB_IO_COMMON_TEARDOWN(); \ 1798 } 1799 1800 /* Defines a complete set of read/write methods */ 1801 #define BHNDB_IO_METHODS(_type, _size) \ 1802 BHNDB_IO_READ(_type, _size) \ 1803 BHNDB_IO_WRITE(_type, _size) \ 1804 \ 1805 BHNDB_IO_READ(_type, stream_ ## _size) \ 1806 BHNDB_IO_WRITE(_type, stream_ ## _size) \ 1807 \ 1808 BHNDB_IO_MISC(_type, *, read_multi, _size) \ 1809 BHNDB_IO_MISC(_type, *, write_multi, _size) \ 1810 \ 1811 BHNDB_IO_MISC(_type, *, read_multi_stream, _size) \ 1812 BHNDB_IO_MISC(_type, *, write_multi_stream, _size) \ 1813 \ 1814 BHNDB_IO_MISC(_type, , set_multi, _size) \ 1815 BHNDB_IO_MISC(_type, , set_region, _size) \ 1816 BHNDB_IO_MISC(_type, *, read_region, _size) \ 1817 BHNDB_IO_MISC(_type, *, write_region, _size) \ 1818 \ 1819 BHNDB_IO_MISC(_type, *, read_region_stream, _size) \ 1820 BHNDB_IO_MISC(_type, *, write_region_stream, _size) 1821 1822 BHNDB_IO_METHODS(uint8_t, 1); 1823 BHNDB_IO_METHODS(uint16_t, 2); 1824 BHNDB_IO_METHODS(uint32_t, 4); 1825 1826 /** 1827 * Default bhndb(4) implementation of BHND_BUS_BARRIER(). 1828 */ 1829 static void 1830 bhndb_bus_barrier(device_t dev, device_t child, struct bhnd_resource *r, 1831 bus_size_t offset, bus_size_t length, int flags) 1832 { 1833 BHNDB_IO_COMMON_SETUP(length); 1834 1835 bus_barrier(io_res, io_offset + offset, length, flags); 1836 1837 BHNDB_IO_COMMON_TEARDOWN(); 1838 } 1839 1840 /** 1841 * Default bhndb(4) implementation of BUS_SETUP_INTR(). 1842 */ 1843 static int 1844 bhndb_setup_intr(device_t dev, device_t child, struct resource *r, 1845 int flags, driver_filter_t filter, driver_intr_t handler, void *arg, 1846 void **cookiep) 1847 { 1848 // TODO 1849 return (EOPNOTSUPP); 1850 } 1851 1852 /** 1853 * Default bhndb(4) implementation of BUS_TEARDOWN_INTR(). 1854 */ 1855 static int 1856 bhndb_teardown_intr(device_t dev, device_t child, struct resource *r, 1857 void *cookie) 1858 { 1859 // TODO 1860 return (EOPNOTSUPP); 1861 } 1862 1863 /** 1864 * Default bhndb(4) implementation of BUS_CONFIG_INTR(). 1865 */ 1866 static int 1867 bhndb_config_intr(device_t dev, int irq, enum intr_trigger trig, 1868 enum intr_polarity pol) 1869 { 1870 // TODO 1871 return (EOPNOTSUPP); 1872 } 1873 1874 /** 1875 * Default bhndb(4) implementation of BUS_BIND_INTR(). 1876 */ 1877 static int 1878 bhndb_bind_intr(device_t dev, device_t child, struct resource *r, int cpu) 1879 { 1880 // TODO 1881 return (EOPNOTSUPP); 1882 } 1883 1884 /** 1885 * Default bhndb(4) implementation of BUS_DESCRIBE_INTR(). 1886 */ 1887 static int 1888 bhndb_describe_intr(device_t dev, device_t child, struct resource *irq, void *cookie, 1889 const char *descr) 1890 { 1891 // TODO 1892 return (EOPNOTSUPP); 1893 } 1894 1895 /** 1896 * Default bhndb(4) implementation of BUS_GET_DMA_TAG(). 1897 */ 1898 static bus_dma_tag_t 1899 bhndb_get_dma_tag(device_t dev, device_t child) 1900 { 1901 // TODO 1902 return (NULL); 1903 } 1904 1905 static device_method_t bhndb_methods[] = { 1906 /* Device interface */ \ 1907 DEVMETHOD(device_probe, bhndb_generic_probe), 1908 DEVMETHOD(device_detach, bhndb_generic_detach), 1909 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1910 DEVMETHOD(device_suspend, bhndb_generic_suspend), 1911 DEVMETHOD(device_resume, bhndb_generic_resume), 1912 1913 /* Bus interface */ 1914 DEVMETHOD(bus_probe_nomatch, bhndb_probe_nomatch), 1915 DEVMETHOD(bus_print_child, bhndb_print_child), 1916 DEVMETHOD(bus_child_pnpinfo_str, bhndb_child_pnpinfo_str), 1917 DEVMETHOD(bus_child_location_str, bhndb_child_location_str), 1918 DEVMETHOD(bus_add_child, bhndb_add_child), 1919 DEVMETHOD(bus_child_deleted, bhndb_child_deleted), 1920 1921 DEVMETHOD(bus_alloc_resource, bhndb_alloc_resource), 1922 DEVMETHOD(bus_release_resource, bhndb_release_resource), 1923 DEVMETHOD(bus_activate_resource, bhndb_activate_resource), 1924 DEVMETHOD(bus_deactivate_resource, bhndb_deactivate_resource), 1925 1926 DEVMETHOD(bus_setup_intr, bhndb_setup_intr), 1927 DEVMETHOD(bus_teardown_intr, bhndb_teardown_intr), 1928 DEVMETHOD(bus_config_intr, bhndb_config_intr), 1929 DEVMETHOD(bus_bind_intr, bhndb_bind_intr), 1930 DEVMETHOD(bus_describe_intr, bhndb_describe_intr), 1931 1932 DEVMETHOD(bus_get_dma_tag, bhndb_get_dma_tag), 1933 1934 DEVMETHOD(bus_adjust_resource, bhndb_adjust_resource), 1935 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 1936 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 1937 DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 1938 DEVMETHOD(bus_get_resource_list, bhndb_get_resource_list), 1939 1940 DEVMETHOD(bus_read_ivar, bhndb_read_ivar), 1941 DEVMETHOD(bus_write_ivar, bhndb_write_ivar), 1942 1943 /* BHNDB interface */ 1944 DEVMETHOD(bhndb_get_chipid, bhndb_get_chipid), 1945 DEVMETHOD(bhndb_init_full_config, bhndb_generic_init_full_config), 1946 DEVMETHOD(bhndb_find_hostb_device, bhndb_find_hostb_device), 1947 DEVMETHOD(bhndb_suspend_resource, bhndb_suspend_resource), 1948 DEVMETHOD(bhndb_resume_resource, bhndb_resume_resource), 1949 1950 /* BHND interface */ 1951 DEVMETHOD(bhnd_bus_is_hw_disabled, bhndb_is_hw_disabled), 1952 DEVMETHOD(bhnd_bus_get_chipid, bhndb_get_chipid), 1953 DEVMETHOD(bhnd_bus_activate_resource, bhndb_activate_bhnd_resource), 1954 DEVMETHOD(bhnd_bus_deactivate_resource, bhndb_deactivate_bhnd_resource), 1955 DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_bus_generic_get_nvram_var), 1956 DEVMETHOD(bhnd_bus_read_1, bhndb_bus_read_1), 1957 DEVMETHOD(bhnd_bus_read_2, bhndb_bus_read_2), 1958 DEVMETHOD(bhnd_bus_read_4, bhndb_bus_read_4), 1959 DEVMETHOD(bhnd_bus_write_1, bhndb_bus_write_1), 1960 DEVMETHOD(bhnd_bus_write_2, bhndb_bus_write_2), 1961 DEVMETHOD(bhnd_bus_write_4, bhndb_bus_write_4), 1962 1963 DEVMETHOD(bhnd_bus_read_stream_1, bhndb_bus_read_stream_1), 1964 DEVMETHOD(bhnd_bus_read_stream_2, bhndb_bus_read_stream_2), 1965 DEVMETHOD(bhnd_bus_read_stream_4, bhndb_bus_read_stream_4), 1966 DEVMETHOD(bhnd_bus_write_stream_1, bhndb_bus_write_stream_1), 1967 DEVMETHOD(bhnd_bus_write_stream_2, bhndb_bus_write_stream_2), 1968 DEVMETHOD(bhnd_bus_write_stream_4, bhndb_bus_write_stream_4), 1969 1970 DEVMETHOD(bhnd_bus_read_multi_1, bhndb_bus_read_multi_1), 1971 DEVMETHOD(bhnd_bus_read_multi_2, bhndb_bus_read_multi_2), 1972 DEVMETHOD(bhnd_bus_read_multi_4, bhndb_bus_read_multi_4), 1973 DEVMETHOD(bhnd_bus_write_multi_1, bhndb_bus_write_multi_1), 1974 DEVMETHOD(bhnd_bus_write_multi_2, bhndb_bus_write_multi_2), 1975 DEVMETHOD(bhnd_bus_write_multi_4, bhndb_bus_write_multi_4), 1976 1977 DEVMETHOD(bhnd_bus_read_multi_stream_1, bhndb_bus_read_multi_stream_1), 1978 DEVMETHOD(bhnd_bus_read_multi_stream_2, bhndb_bus_read_multi_stream_2), 1979 DEVMETHOD(bhnd_bus_read_multi_stream_4, bhndb_bus_read_multi_stream_4), 1980 DEVMETHOD(bhnd_bus_write_multi_stream_1,bhndb_bus_write_multi_stream_1), 1981 DEVMETHOD(bhnd_bus_write_multi_stream_2,bhndb_bus_write_multi_stream_2), 1982 DEVMETHOD(bhnd_bus_write_multi_stream_4,bhndb_bus_write_multi_stream_4), 1983 1984 DEVMETHOD(bhnd_bus_set_multi_1, bhndb_bus_set_multi_1), 1985 DEVMETHOD(bhnd_bus_set_multi_2, bhndb_bus_set_multi_2), 1986 DEVMETHOD(bhnd_bus_set_multi_4, bhndb_bus_set_multi_4), 1987 DEVMETHOD(bhnd_bus_set_region_1, bhndb_bus_set_region_1), 1988 DEVMETHOD(bhnd_bus_set_region_2, bhndb_bus_set_region_2), 1989 DEVMETHOD(bhnd_bus_set_region_4, bhndb_bus_set_region_4), 1990 1991 DEVMETHOD(bhnd_bus_read_region_1, bhndb_bus_read_region_1), 1992 DEVMETHOD(bhnd_bus_read_region_2, bhndb_bus_read_region_2), 1993 DEVMETHOD(bhnd_bus_read_region_4, bhndb_bus_read_region_4), 1994 DEVMETHOD(bhnd_bus_write_region_1, bhndb_bus_write_region_1), 1995 DEVMETHOD(bhnd_bus_write_region_2, bhndb_bus_write_region_2), 1996 DEVMETHOD(bhnd_bus_write_region_4, bhndb_bus_write_region_4), 1997 1998 DEVMETHOD(bhnd_bus_read_region_stream_1,bhndb_bus_read_region_stream_1), 1999 DEVMETHOD(bhnd_bus_read_region_stream_2,bhndb_bus_read_region_stream_2), 2000 DEVMETHOD(bhnd_bus_read_region_stream_4,bhndb_bus_read_region_stream_4), 2001 DEVMETHOD(bhnd_bus_write_region_stream_1,bhndb_bus_write_region_stream_1), 2002 DEVMETHOD(bhnd_bus_write_region_stream_2,bhndb_bus_write_region_stream_2), 2003 DEVMETHOD(bhnd_bus_write_region_stream_4,bhndb_bus_write_region_stream_4), 2004 2005 DEVMETHOD(bhnd_bus_barrier, bhndb_bus_barrier), 2006 2007 DEVMETHOD_END 2008 }; 2009 2010 devclass_t bhndb_devclass; 2011 2012 DEFINE_CLASS_0(bhndb, bhndb_driver, bhndb_methods, sizeof(struct bhndb_softc)); 2013 2014 MODULE_VERSION(bhndb, 1); 2015 MODULE_DEPEND(bhndb, bhnd, 1, 1, 1); 2016 MODULE_DEPEND(bhndb, bhnd_chipc, 1, 1, 1); 2017