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);
628 if ((error = bhnd_service_registry_fini(&sc->services)))
632 bhndb_free_resources(sc->bus_res);
666 bus_res = sc->bus_res;
668 /* Guarantee that all in-use dynamic register windows are mapped to
672 for (size_t i = 0; i < bus_res->dwa_count; i++) {
673 dwa = &bus_res->dw_alloc[i];
676 if (bhndb_dw_is_free(bus_res, dwa) && dwa->target == 0x0)
679 /* Otherwise, ensure the register window is correct before
681 error = BHNDB_SET_WINDOW_ADDR(dev, dwa->win, dwa->target);
709 /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */
714 dwa = bhndb_dw_find_resource(sc->bus_res, r);
724 /* Release the resource's window reference */
725 bhndb_dw_release(sc->bus_res, dwa, r);
740 /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */
786 while (imd_dev != NULL && device_get_parent(imd_dev) != sc->dev)
790 panic("bhndb address space request for non-child device %s\n",
794 return (dinfo->addrspace);
811 return (&sc->bus_res->ht_mem_rman);
821 return (&sc->bus_res->br_mem_rman);
823 return (&sc->bus_res->br_irq_rman);
852 dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE;
853 resource_list_init(&dinfo->resources);
868 resource_list_free(&dinfo->resources);
882 return (&sc->chipid);
897 if (BHNDB_BUS_IS_CORE_DISABLED(sc->parent_dev, dev, core))
900 /* Otherwise, we treat bridge-capable cores as unpopulated if they're
903 return (!bhnd_cores_equal(core, &sc->bridge_core));
912 * This function uses a heuristic valid on all known PCI/PCIe/PCMCIA-bridged
920 *core = sc->bridge_core;
932 return (&sc->services);
959 return (BUS_ALLOC_RESOURCE(device_get_parent(sc->parent_dev),
977 if (rle->res != NULL) {
985 start = rle->start;
986 end = rle->end;
987 count = ulmax(count, rle->count);
991 if (start > end || count > ((end - start) + 1))
1020 rle->res = rv;
1021 rle->start = rman_get_start(rv);
1022 rle->end = rman_get_end(rv);
1023 rle->count = rman_get_size(rv);
1046 return (BUS_RELEASE_RESOURCE(device_get_parent(sc->parent_dev),
1067 rle->res = NULL;
1091 return (BUS_ADJUST_RESOURCE(device_get_parent(sc->parent_dev),
1109 error = bhndb_find_resource_limits(sc->bus_res, r, &mstart,
1153 /* Configure child resource with window-adjusted real bus values */
1167 * Attempt activation of a fixed register window mapping for @p child.
1177 * @retval ENOENT if no fixed register window was found.
1178 * @retval non-zero if @p r could not be activated.
1190 win = region->static_regwin;
1192 KASSERT(win != NULL && BHNDB_REGWIN_T_IS_STATIC(win->win_type),
1193 ("can't activate non-static region"));
1199 bridge_res = bhndb_host_resource_for_regwin(sc->bus_res->res, win);
1204 parent_offset = r_start - region->addr;
1205 parent_offset += win->win_offset;
1220 * Attempt to allocate/retain a dynamic register window for @p r, returning
1221 * the retained window.
1224 * @param r The resource for which a window will be retained.
1238 /* Look for an existing dynamic window we can reference */
1239 dwa = bhndb_dw_find_mapping(sc->bus_res, r_start, r_size);
1241 if (bhndb_dw_retain(sc->bus_res, dwa, r) == 0)
1247 /* Otherwise, try to reserve a free window */
1248 dwa = bhndb_dw_next_free(sc->bus_res);
1254 /* Window must be large enough to map the entire resource */
1255 if (dwa->win->win_size < rman_get_size(r))
1258 /* Set the window target */
1259 error = bhndb_dw_set_addr(sc->dev, sc->bus_res, dwa, rman_get_start(r),
1262 device_printf(sc->dev, "dynamic window initialization "
1263 "for 0x%llx-0x%llx failed: %d\n",
1265 (unsigned long long) r_start + r_size - 1,
1271 if (bhndb_dw_retain(sc->bus_res, dwa, r))
1278 * Activate a resource using any viable static or dynamic register window.
1287 * @retval non-zero activation failed.
1316 device_printf(sc->dev, "unsupported resource type %d\n", type);
1331 parent = bhndb_host_resource_for_range(sc->bus_res->res,
1334 device_printf(sc->dev, "host resource not found "
1335 "for 0x%llx-0x%llx\n",
1337 (unsigned long long) r_start + r_size - 1);
1343 r_start - rman_get_start(parent), r_size);
1355 region = bhndb_find_resource_region(sc->bus_res, r_start, r_size);
1357 dw_priority = region->priority;
1360 if (region && region->static_regwin) {
1363 device_printf(sc->dev, "static window allocation "
1364 "for 0x%llx-0x%llx failed\n",
1366 (unsigned long long) r_start + r_size - 1);
1370 /* A dynamic window will be required; is this resource high enough
1371 * priority to be reserved a dynamic window? */
1372 if (dw_priority < sc->bus_res->min_prio) {
1379 /* Find and retain a usable window */
1391 parent_offset = dwa->win->win_offset;
1392 parent_offset += r_start - dwa->target;
1394 error = bhndb_init_child_resource(r, dwa->parent_res, parent_offset,
1395 dwa->win->win_size);
1408 bhndb_dw_release(sc->bus_res, dwa, r);
1425 return (BUS_ACTIVATE_RESOURCE(device_get_parent(sc->parent_dev),
1451 device_get_parent(sc->parent_dev), child, r));
1460 /* No bridge-level state to be freed */
1464 /* Free any dynamic window allocation. */
1467 dwa = bhndb_dw_find_resource(sc->bus_res, r);
1469 bhndb_dw_release(sc->bus_res, dwa, r);
1488 return (&dinfo->resources);
1501 * static register window, a dynamic register window, or it will configure @p r
1502 * as an indirect resource -- in that order.
1515 KASSERT(!r->direct,
1518 KASSERT(!(rman_get_flags(r->res) & RF_ACTIVE),
1526 error = BUS_ACTIVATE_RESOURCE(dev, child, r->res);
1528 r->direct = true;
1532 r_start = rman_get_start(r->res);
1533 r_size = rman_get_size(r->res);
1544 region = bhndb_find_resource_region(sc->bus_res,
1547 r_prio = region->priority;
1551 /* If less than the minimum dynamic window priority,
1553 if (r_prio < sc->bus_res->min_prio)
1566 error = bhndb_try_activate_resource(sc, child, r->res, &indirect);
1568 r->direct = true;
1570 /* The request was valid, but no viable register window is
1573 r->direct = false;
1579 device_printf(child, "activated 0x%llx-0x%llx as %s "
1582 (unsigned long long) r_start + r_size - 1,
1583 r->direct ? "direct" : "indirect");
1599 if (!r->direct)
1602 KASSERT(rman_get_flags(r->res) & RF_ACTIVE,
1606 error = BUS_DEACTIVATE_RESOURCE(dev, child, r->res);
1608 r->direct = false;
1619 * - Configure and return a free allocation record
1620 * - Return an existing allocation record mapping the requested space, or
1621 * - Steal, configure, and return an in-use allocation record.
1648 br = sc->bus_res;
1652 /* Try to fetch a free window */
1659 for (size_t i = 0; i < br->dwa_count; i++) {
1662 dwa = &br->dw_alloc[i];
1663 win = dwa->win;
1665 KASSERT(win->win_type == BHNDB_REGWIN_T_DYN,
1666 ("invalid register window type"));
1669 if (addr < dwa->target)
1672 if (addr + size > dwa->target + win->win_size)
1680 /* Try to steal a window; this should only be required on very early
1681 * PCI_V0 (BCM4318, etc) Wi-Fi chipsets */
1686 if ((region->alloc_flags & BHNDB_ALLOC_FULFILL_ON_OVERCOMMIT) == 0)
1689 /* Steal a window. This acquires our backing spinlock, disabling
1697 panic("register windows exhausted attempting to map 0x%llx-0x%llx\n",
1698 (unsigned long long) addr, (unsigned long long) addr+size-1);
1735 /* Adjust the window if the I/O request won't fit in the current
1737 if (addr < dwa->target ||
1738 addr > dwa->target + dwa->win->win_size ||
1739 (dwa->target + dwa->win->win_size) - addr < size)
1743 panic("borrowed register window does not map expected "
1744 "range 0x%llx-0x%llx\n",
1746 (unsigned long long) addr+size-1);
1749 error = bhndb_dw_set_addr(sc->dev, sc->bus_res, dwa, addr,
1752 panic("failed to set register window target mapping "
1753 "0x%llx-0x%llx\n",
1755 (unsigned long long) addr+size-1);
1760 *offset = (addr - dwa->target) + dwa->win->win_offset;
1780 dwa = bhndb_io_resource(sc, rman_get_start(r->res) + \
1782 io_res = dwa->parent_res; \
1784 KASSERT(!r->direct, \
1792 bhndb_dw_return_stolen(sc->dev, sc->bus_res, \
1934 error = bus_setup_intr(isrc->is_owner, isrc->is_res, flags, filter,
1935 handler, arg, &ih->ih_cookiep);
1943 bhndb_register_intr_handler(sc->bus_res, ih);
1968 ih = bhndb_find_intr_handler(sc->bus_res, cookiep);
1974 bhndb_deregister_intr_handler(sc->bus_res, ih);
1979 isrc = ih->ih_isrc;
1980 error = bus_teardown_intr(isrc->is_owner, isrc->is_res, ih->ih_cookiep);
1985 bhndb_register_intr_handler(sc->bus_res, ih);
2011 STAILQ_FOREACH(ih, &sc->bus_res->bus_intrs, ih_link) {
2012 if (ih->ih_res == irq) {
2013 isrc = ih->ih_isrc;
2020 panic("%s requested bind of invalid irq %#jx-%#jx",
2026 return (bus_bind_intr(isrc->is_owner, isrc->is_res, cpu));
2047 ih = bhndb_find_intr_handler(sc->bus_res, cookie);
2053 isrc = ih->ih_isrc;
2058 return (BUS_DESCRIBE_INTR(device_get_parent(isrc->is_owner),
2059 isrc->is_owner, isrc->is_res, ih->ih_cookiep, descr));
2098 hwcfg = sc->bus_res->cfg;
2100 /* Is DMA supported? */
2101 if (sc->bus_res->res->dma_tags == NULL)
2106 /* Backplane must support 64-bit addressing */
2107 if (!(sc->chipid.chip_caps & BHND_CAP_BP64))
2118 for (size_t i = 0; i < sc->bus_res->res->num_dma_tags; i++) {
2122 dwin = &hwcfg->dma_translations[i];
2125 if ((dwin->base_addr & addr_mask) != dwin->base_addr)
2129 if ((dwin->flags & flags) != flags)
2132 /* The window must cover at least part of our addressable
2134 masked = (dwin->addr_mask | dwin->addrext_mask) & addr_mask;
2142 match_dmat = sc->bus_res->res->dma_tags[i];
2167 * A bridge may have multiple DMA translation descriptors, each with
2169 * BHND_BUS_GET_DMA_TRANSLATION() to fetch both the best available DMA
2170 * translation, and its corresponding DMA tag.
2173 * responsible for creating their own restricted DMA tag; since we
2175 * bridge parent's DMA tag directly;
2177 return (bus_get_dma_tag(sc->parent_dev));