Lines Matching +full:dma +full:- +full:window
1 /*-
2 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
39 * a BHND-compatible bus (e.g. bcma or siba).
172 (unsigned long long) sc->chipid.enum_addr);
188 for (u_int i = 0; i < hw->num_hw_reqs; i++) {
192 match = &hw->hw_reqs[i];
198 if (BHNDB_IS_CORE_DISABLED(sc->dev, sc->bus_dev, core))
225 * priorities of per-core port resources.
255 for (regw = br->cfg->register_windows;
256 regw->win_type != BHNDB_REGWIN_T_INVALID; regw++)
262 if (regw->win_type != BHNDB_REGWIN_T_CORE)
265 /* Skip non-matching cores. */
271 regw->d.core.port_type,
272 regw->d.core.port,
273 regw->d.core.region,
278 /* Skip non-applicable register windows */
286 * Apply the register window's region offset, if any.
288 if (regw->d.core.offset > size) {
289 device_printf(sc->dev, "invalid register "
290 "window offset %#jx for region %#jx+%#jx\n",
291 regw->d.core.offset, addr, size);
295 addr += regw->d.core.offset;
298 * Always defer to the register window's size.
300 * If the port size is smaller than the window size,
304 * If the port size is larger than the window size, this
306 * within the region to a too-small window.
308 size = regw->win_size;
313 regw->d.core.port_type, regw->d.core.port,
314 regw->d.core.region);
316 alloc_flags = pp->alloc_flags;
324 * The window priority for a statically mapped region is
350 if (BHNDB_IS_CORE_DISABLED(sc->dev, sc->bus_dev, core))
359 if (hp->priority == BHNDB_PRIORITY_NONE)
364 for (u_int i = 0; i < hp->num_ports; i++) {
367 pp = &hp->ports[i];
371 pp->type, pp->port, pp->region,
387 pp->priority, pp->alloc_flags, NULL);
392 switch (pp->priority) {
411 if (prio_total <= br->dwa_count) {
413 br->min_prio = BHNDB_PRIORITY_LOW;
415 } else if (prio_default + prio_high <= br->dwa_count) {
417 br->min_prio = BHNDB_PRIORITY_DEFAULT;
421 br->min_prio = BHNDB_PRIORITY_HIGH;
430 prio_min = br->min_prio;
431 device_printf(sc->dev, "min_prio: %d\n", prio_min);
433 STAILQ_FOREACH(region, &br->bus_regions, link) {
434 prio = region->priority;
435 flags = region->alloc_flags;
438 type_msg = region->static_regwin ? "static" : "dynamic";
440 device_printf(sc->dev, "region 0x%llx+0x%llx priority "
442 (unsigned long long) region->addr,
443 (unsigned long long) region->size,
444 region->priority,
467 * @retval non-zero if an error occurs fetching device info for comparison.
476 hw_table = BHNDB_BUS_GET_HARDWARE_TABLE(sc->parent_dev, sc->dev);
477 for (next = hw_table; next->hw_reqs != NULL; next++) {
523 sc->dev = dev;
524 sc->parent_dev = device_get_parent(dev);
525 sc->bridge_core = *bridge_core;
526 sc->chipid = *cid;
528 if ((error = bhnd_service_registry_init(&sc->services)))
537 device_printf(sc->dev, "unable to identify device, "
540 hwcfg = BHNDB_BUS_GET_GENERIC_HWCFG(sc->parent_dev, dev);
543 hwcfg = hw->cfg;
547 device_printf(sc->dev, "%s resource configuration\n", hw->name);
552 sc->bus_res = bhndb_alloc_resources(sc->dev, sc->parent_dev, hwcfg);
553 if (sc->bus_res == NULL) {
554 device_printf(sc->dev, "failed to allocate bridge resource "
561 sc->bus_dev = BUS_ADD_CHILD(dev, BHND_PROBE_BUS, "bhnd", DEVICE_UNIT_ANY);
562 if (sc->bus_dev == NULL) {
567 dinfo = device_get_ivars(sc->bus_dev);
568 dinfo->addrspace = BHNDB_ADDRSPACE_BRIDGED;
572 eio = bhnd_erom_iores_new(sc->bus_dev, 0);
580 hwprio = BHNDB_BUS_GET_HARDWARE_PRIO(sc->parent_dev, sc->dev);
581 error = bhndb_init_region_cfg(sc, erom, sc->bus_res, cores, ncores,
584 device_printf(sc->dev, "failed to initialize resource "
598 if (sc->bus_res != NULL)
599 bhndb_free_resources(sc->bus_res);
604 bhnd_service_registry_fini(&sc->services);
632 if ((error = bhnd_service_registry_fini(&sc->services)))
636 bhndb_free_resources(sc->bus_res);
670 bus_res = sc->bus_res;
672 /* Guarantee that all in-use dynamic register windows are mapped to
676 for (size_t i = 0; i < bus_res->dwa_count; i++) {
677 dwa = &bus_res->dw_alloc[i];
680 if (bhndb_dw_is_free(bus_res, dwa) && dwa->target == 0x0)
683 /* Otherwise, ensure the register window is correct before
685 error = BHNDB_SET_WINDOW_ADDR(dev, dwa->win, dwa->target);
713 /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */
718 dwa = bhndb_dw_find_resource(sc->bus_res, r);
728 /* Release the resource's window reference */
729 bhndb_dw_release(sc->bus_res, dwa, r);
744 /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */
790 while (imd_dev != NULL && device_get_parent(imd_dev) != sc->dev)
794 panic("bhndb address space request for non-child device %s\n",
798 return (dinfo->addrspace);
815 return (&sc->bus_res->ht_mem_rman);
825 return (&sc->bus_res->br_mem_rman);
827 return (&sc->bus_res->br_irq_rman);
856 dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE;
857 resource_list_init(&dinfo->resources);
872 resource_list_free(&dinfo->resources);
886 return (&sc->chipid);
901 if (BHNDB_BUS_IS_CORE_DISABLED(sc->parent_dev, dev, core))
904 /* Otherwise, we treat bridge-capable cores as unpopulated if they're
907 return (!bhnd_cores_equal(core, &sc->bridge_core));
916 * This function uses a heuristic valid on all known PCI/PCIe/PCMCIA-bridged
924 *core = sc->bridge_core;
936 return (&sc->services);
963 return (BUS_ALLOC_RESOURCE(device_get_parent(sc->parent_dev),
981 if (rle->res != NULL) {
989 start = rle->start;
990 end = rle->end;
991 count = ulmax(count, rle->count);
995 if (start > end || count > ((end - start) + 1))
1024 rle->res = rv;
1025 rle->start = rman_get_start(rv);
1026 rle->end = rman_get_end(rv);
1027 rle->count = rman_get_size(rv);
1050 return (BUS_RELEASE_RESOURCE(device_get_parent(sc->parent_dev),
1069 rle->res = NULL;
1094 return (BUS_ADJUST_RESOURCE(device_get_parent(sc->parent_dev),
1112 error = bhndb_find_resource_limits(sc->bus_res, r, &mstart,
1156 /* Configure child resource with window-adjusted real bus values */
1170 * Attempt activation of a fixed register window mapping for @p child.
1180 * @retval ENOENT if no fixed register window was found.
1181 * @retval non-zero if @p r could not be activated.
1193 win = region->static_regwin;
1195 KASSERT(win != NULL && BHNDB_REGWIN_T_IS_STATIC(win->win_type),
1196 ("can't activate non-static region"));
1202 bridge_res = bhndb_host_resource_for_regwin(sc->bus_res->res, win);
1207 parent_offset = r_start - region->addr;
1208 parent_offset += win->win_offset;
1223 * Attempt to allocate/retain a dynamic register window for @p r, returning
1224 * the retained window.
1227 * @param r The resource for which a window will be retained.
1241 /* Look for an existing dynamic window we can reference */
1242 dwa = bhndb_dw_find_mapping(sc->bus_res, r_start, r_size);
1244 if (bhndb_dw_retain(sc->bus_res, dwa, r) == 0)
1250 /* Otherwise, try to reserve a free window */
1251 dwa = bhndb_dw_next_free(sc->bus_res);
1257 /* Window must be large enough to map the entire resource */
1258 if (dwa->win->win_size < rman_get_size(r))
1261 /* Set the window target */
1262 error = bhndb_dw_set_addr(sc->dev, sc->bus_res, dwa, rman_get_start(r),
1265 device_printf(sc->dev, "dynamic window initialization "
1266 "for 0x%llx-0x%llx failed: %d\n",
1268 (unsigned long long) r_start + r_size - 1,
1274 if (bhndb_dw_retain(sc->bus_res, dwa, r))
1281 * Activate a resource using any viable static or dynamic register window.
1290 * @retval non-zero activation failed.
1319 device_printf(sc->dev, "unsupported resource type %d\n", type);
1334 parent = bhndb_host_resource_for_range(sc->bus_res->res,
1337 device_printf(sc->dev, "host resource not found "
1338 "for 0x%llx-0x%llx\n",
1340 (unsigned long long) r_start + r_size - 1);
1346 r_start - rman_get_start(parent), r_size);
1358 region = bhndb_find_resource_region(sc->bus_res, r_start, r_size);
1360 dw_priority = region->priority;
1363 if (region && region->static_regwin) {
1366 device_printf(sc->dev, "static window allocation "
1367 "for 0x%llx-0x%llx failed\n",
1369 (unsigned long long) r_start + r_size - 1);
1373 /* A dynamic window will be required; is this resource high enough
1374 * priority to be reserved a dynamic window? */
1375 if (dw_priority < sc->bus_res->min_prio) {
1382 /* Find and retain a usable window */
1394 parent_offset = dwa->win->win_offset;
1395 parent_offset += r_start - dwa->target;
1397 error = bhndb_init_child_resource(r, dwa->parent_res, parent_offset,
1398 dwa->win->win_size);
1411 bhndb_dw_release(sc->bus_res, dwa, r);
1428 return (BUS_ACTIVATE_RESOURCE(device_get_parent(sc->parent_dev),
1454 device_get_parent(sc->parent_dev), child, r));
1463 /* No bridge-level state to be freed */
1467 /* Free any dynamic window allocation. */
1470 dwa = bhndb_dw_find_resource(sc->bus_res, r);
1472 bhndb_dw_release(sc->bus_res, dwa, r);
1491 return (&dinfo->resources);
1504 * static register window, a dynamic register window, or it will configure @p r
1505 * as an indirect resource -- in that order.
1518 KASSERT(!r->direct,
1521 KASSERT(!(rman_get_flags(r->res) & RF_ACTIVE),
1529 error = BUS_ACTIVATE_RESOURCE(dev, child, r->res);
1531 r->direct = true;
1535 r_start = rman_get_start(r->res);
1536 r_size = rman_get_size(r->res);
1547 region = bhndb_find_resource_region(sc->bus_res,
1550 r_prio = region->priority;
1554 /* If less than the minimum dynamic window priority,
1556 if (r_prio < sc->bus_res->min_prio)
1569 error = bhndb_try_activate_resource(sc, child, r->res, &indirect);
1571 r->direct = true;
1573 /* The request was valid, but no viable register window is
1576 r->direct = false;
1582 device_printf(child, "activated 0x%llx-0x%llx as %s "
1585 (unsigned long long) r_start + r_size - 1,
1586 r->direct ? "direct" : "indirect");
1602 if (!r->direct)
1605 KASSERT(rman_get_flags(r->res) & RF_ACTIVE,
1609 error = BUS_DEACTIVATE_RESOURCE(dev, child, r->res);
1611 r->direct = false;
1622 * - Configure and return a free allocation record
1623 * - Return an existing allocation record mapping the requested space, or
1624 * - Steal, configure, and return an in-use allocation record.
1651 br = sc->bus_res;
1655 /* Try to fetch a free window */
1662 for (size_t i = 0; i < br->dwa_count; i++) {
1665 dwa = &br->dw_alloc[i];
1666 win = dwa->win;
1668 KASSERT(win->win_type == BHNDB_REGWIN_T_DYN,
1669 ("invalid register window type"));
1672 if (addr < dwa->target)
1675 if (addr + size > dwa->target + win->win_size)
1683 /* Try to steal a window; this should only be required on very early
1684 * PCI_V0 (BCM4318, etc) Wi-Fi chipsets */
1689 if ((region->alloc_flags & BHNDB_ALLOC_FULFILL_ON_OVERCOMMIT) == 0)
1692 /* Steal a window. This acquires our backing spinlock, disabling
1700 panic("register windows exhausted attempting to map 0x%llx-0x%llx\n",
1701 (unsigned long long) addr, (unsigned long long) addr+size-1);
1738 /* Adjust the window if the I/O request won't fit in the current
1740 if (addr < dwa->target ||
1741 addr > dwa->target + dwa->win->win_size ||
1742 (dwa->target + dwa->win->win_size) - addr < size)
1746 panic("borrowed register window does not map expected "
1747 "range 0x%llx-0x%llx\n",
1749 (unsigned long long) addr+size-1);
1752 error = bhndb_dw_set_addr(sc->dev, sc->bus_res, dwa, addr,
1755 panic("failed to set register window target mapping "
1756 "0x%llx-0x%llx\n",
1758 (unsigned long long) addr+size-1);
1763 *offset = (addr - dwa->target) + dwa->win->win_offset;
1783 dwa = bhndb_io_resource(sc, rman_get_start(r->res) + \
1785 io_res = dwa->parent_res; \
1787 KASSERT(!r->direct, \
1795 bhndb_dw_return_stolen(sc->dev, sc->bus_res, \
1937 error = bus_setup_intr(isrc->is_owner, isrc->is_res, flags, filter,
1938 handler, arg, &ih->ih_cookiep);
1946 bhndb_register_intr_handler(sc->bus_res, ih);
1971 ih = bhndb_find_intr_handler(sc->bus_res, cookiep);
1977 bhndb_deregister_intr_handler(sc->bus_res, ih);
1982 isrc = ih->ih_isrc;
1983 error = bus_teardown_intr(isrc->is_owner, isrc->is_res, ih->ih_cookiep);
1988 bhndb_register_intr_handler(sc->bus_res, ih);
2014 STAILQ_FOREACH(ih, &sc->bus_res->bus_intrs, ih_link) {
2015 if (ih->ih_res == irq) {
2016 isrc = ih->ih_isrc;
2023 panic("%s requested bind of invalid irq %#jx-%#jx",
2029 return (bus_bind_intr(isrc->is_owner, isrc->is_res, cpu));
2050 ih = bhndb_find_intr_handler(sc->bus_res, cookie);
2056 isrc = ih->ih_isrc;
2061 return (BUS_DESCRIBE_INTR(device_get_parent(isrc->is_owner),
2062 isrc->is_owner, isrc->is_res, ih->ih_cookiep, descr));
2101 hwcfg = sc->bus_res->cfg;
2103 /* Is DMA supported? */
2104 if (sc->bus_res->res->dma_tags == NULL)
2109 /* Backplane must support 64-bit addressing */
2110 if (!(sc->chipid.chip_caps & BHND_CAP_BP64))
2121 for (size_t i = 0; i < sc->bus_res->res->num_dma_tags; i++) {
2125 dwin = &hwcfg->dma_translations[i];
2128 if ((dwin->base_addr & addr_mask) != dwin->base_addr)
2132 if ((dwin->flags & flags) != flags)
2135 /* The window must cover at least part of our addressable
2137 masked = (dwin->addr_mask | dwin->addrext_mask) & addr_mask;
2145 match_dmat = sc->bus_res->res->dma_tags[i];
2170 * A bridge may have multiple DMA translation descriptors, each with
2172 * BHND_BUS_GET_DMA_TRANSLATION() to fetch both the best available DMA
2173 * translation, and its corresponding DMA tag.
2176 * responsible for creating their own restricted DMA tag; since we
2178 * bridge parent's DMA tag directly;
2180 return (bus_get_dma_tag(sc->parent_dev));