static int ebus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { struct resource_list *rl; struct resource_list_entry *rle; int passthrough = (device_get_parent(child) != bus); int rv; rl = BUS_GET_RESOURCE_LIST(bus, child); switch (type) { case SYS_RES_MEMORY: if ((rv = rman_release_resource(res)) != 0) return (rv); if (!passthrough) { rle = resource_list_find(rl, type, rid); KASSERT(rle != NULL, ("ebus_release_resource: " "resource entry not found!")); KASSERT(rle->res != NULL, ("ebus_alloc_resource: " "resource entry is not busy")); rle->res = NULL; } break; case SYS_RES_IRQ: return (resource_list_release(rl, bus, child, type, rid, res)); default: panic("ebus_release_resource: unsupported resource type %d", type); } return (0); }
static struct resource * ofwbus_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct ofwbus_softc *sc; struct rman *rm; struct resource *rv; struct resource_list_entry *rle; int isdefault, passthrough; isdefault = RMAN_IS_DEFAULT_RANGE(start, end); passthrough = (device_get_parent(child) != bus); sc = device_get_softc(bus); rle = NULL; if (!passthrough && isdefault) { rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), type, *rid); if (rle == NULL) { if (bootverbose) device_printf(bus, "no default resources for " "rid = %d, type = %d\n", *rid, type); return (NULL); } start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } switch (type) { case SYS_RES_IRQ: rm = &sc->sc_intr_rman; break; case SYS_RES_MEMORY: rm = &sc->sc_mem_rman; break; default: return (NULL); } rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, *rid, rv) != 0) { rman_release_resource(rv); return (NULL); } if (!passthrough && rle != NULL) { rle->res = rv; rle->start = rman_get_start(rv); rle->end = rman_get_end(rv); rle->count = rle->end - rle->start + 1; } return (rv); }
static int sbus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { struct resource_list *rl; struct resource_list_entry *rle; int error, passthrough; passthrough = (device_get_parent(child) != bus); rl = BUS_GET_RESOURCE_LIST(bus, child); if (type == SYS_RES_MEMORY) { if ((rman_get_flags(r) & RF_ACTIVE) != 0) { error = bus_deactivate_resource(child, type, rid, r); if (error) return (error); } error = rman_release_resource(r); if (error != 0) return (error); if (!passthrough) { rle = resource_list_find(rl, type, rid); KASSERT(rle != NULL, ("%s: resource entry not found!", __func__)); KASSERT(rle->res != NULL, ("%s: resource entry is not busy", __func__)); rle->res = NULL; } return (0); } return (resource_list_release(rl, bus, child, type, rid, r)); }
static int sbus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { struct resource_list *rl; struct resource_list_entry *rle; int error, passthrough; passthrough = (device_get_parent(child) != bus); rl = BUS_GET_RESOURCE_LIST(bus, child); if (type == SYS_RES_IRQ) return (resource_list_release(rl, bus, child, type, rid, r)); if ((rman_get_flags(r) & RF_ACTIVE) != 0) { error = bus_deactivate_resource(child, type, rid, r); if (error != 0) return (error); } error = rman_release_resource(r); if (error != 0 || passthrough) return (error); rle = resource_list_find(rl, type, rid); if (rle == NULL) panic("%s: cannot find resource", __func__); if (rle->res == NULL) panic("%s: resource entry is not busy", __func__); rle->res = NULL; return (0); }
static struct resource * ofwbus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct ofwbus_softc *sc; struct rman *rm; struct resource *rv; struct resource_list_entry *rle; int isdefault, passthrough; isdefault = (start == 0UL && end == ~0UL); passthrough = (device_get_parent(child) != bus); sc = device_get_softc(bus); rle = NULL; if (!passthrough && isdefault) { rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("%s: resource entry is busy", __func__); start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } switch (type) { case SYS_RES_IRQ: rm = &sc->sc_intr_rman; break; case SYS_RES_MEMORY: rm = &sc->sc_mem_rman; break; default: return (NULL); } rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, *rid, rv) != 0) { rman_release_resource(rv); return (NULL); } if (!passthrough && rle != NULL) { rle->res = rv; rle->start = rman_get_start(rv); rle->end = rman_get_end(rv); rle->count = rle->end - rle->start + 1; } return (rv); }
static struct resource_list * ndis_get_resource_list(device_t dev, device_t child) { struct ndis_softc *sc; sc = device_get_softc(dev); return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); }
static struct resource * central_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct resource_list *rl; struct resource_list_entry *rle; struct central_softc *sc; struct resource *res; bus_addr_t coffset; bus_addr_t cend; bus_addr_t phys; int isdefault; int passthrough; int i; isdefault = (start == 0UL && end == ~0UL); passthrough = (device_get_parent(child) != bus); res = NULL; rle = NULL; rl = BUS_GET_RESOURCE_LIST(bus, child); sc = device_get_softc(bus); switch (type) { case SYS_RES_IRQ: return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); case SYS_RES_MEMORY: if (!passthrough) { rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("%s: resource entry is busy", __func__); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } for (i = 0; i < sc->sc_nrange; i++) { coffset = sc->sc_ranges[i].coffset; cend = coffset + sc->sc_ranges[i].size - 1; if (start >= coffset && end <= cend) { start -= coffset; end -= coffset; phys = sc->sc_ranges[i].poffset | ((bus_addr_t)sc->sc_ranges[i].pspace << 32); res = bus_generic_alloc_resource(bus, child, type, rid, phys + start, phys + end, count, flags); if (!passthrough) rle->res = res; break; } } break; } return (res); }
static int jz4780_pinctrl_attach(device_t dev) { struct jz4780_pinctrl_softc *sc; struct resource_list *rs; struct resource_list_entry *re; phandle_t dt_parent, dt_child; int i, ret; sc = device_get_softc(dev); sc->dev = dev; /* * Fetch our own resource list to dole memory between children */ rs = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); if (rs == NULL) return (ENXIO); re = resource_list_find(rs, SYS_RES_MEMORY, 0); if (re == NULL) return (ENXIO); simplebus_init(dev, 0); /* Iterate over this node children, looking for pin controllers */ dt_parent = ofw_bus_get_node(dev); i = 0; for (dt_child = OF_child(dt_parent); dt_child != 0; dt_child = OF_peer(dt_child)) { struct simplebus_devinfo *ndi; device_t child; bus_addr_t phys; bus_size_t size; /* Add gpio controller child */ if (!OF_hasprop(dt_child, "gpio-controller")) continue; child = simplebus_add_device(dev, dt_child, 0, NULL, -1, NULL); if (child == NULL) break; /* Setup child resources */ phys = CHIP_REG_OFFSET(re->start, i); size = CHIP_REG_STRIDE; if (phys + size - 1 <= re->end) { ndi = device_get_ivars(child); resource_list_add(&ndi->rl, SYS_RES_MEMORY, 0, phys, phys + size - 1, size); } i++; } ret = bus_generic_attach(dev); if (ret == 0) { fdt_pinctrl_register(dev, "ingenic,pins"); fdt_pinctrl_configure_tree(dev); } return (ret); }
static int chipc_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { struct chipc_softc *sc; struct chipc_region *cr; struct rman *rm; struct resource_list_entry *rle; int error; sc = device_get_softc(dev); /* Handled by parent bus? */ rm = chipc_get_rman(sc, type); if (rm == NULL || !rman_is_region_manager(r, rm)) { return (bus_generic_rl_release_resource(dev, child, type, rid, r)); } /* Locate the mapping region */ cr = chipc_find_region(sc, rman_get_start(r), rman_get_end(r)); if (cr == NULL) return (EINVAL); /* Deactivate resources */ if (rman_get_flags(r) & RF_ACTIVE) { error = BUS_DEACTIVATE_RESOURCE(dev, child, type, rid, r); if (error) return (error); } if ((error = rman_release_resource(r))) return (error); /* Drop allocation reference */ chipc_release_region(sc, cr, RF_ALLOCATED); /* Clear reference from the resource list entry if exists */ rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child), type, rid); if (rle != NULL) rle->res = NULL; return (0); }
static int ofwbus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { struct resource_list_entry *rle; int error; /* Clean resource list entry */ rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), type, rid); if (rle != NULL) rle->res = NULL; if ((rman_get_flags(r) & RF_ACTIVE) != 0) { error = bus_deactivate_resource(child, type, rid, r); if (error) return (error); } return (rman_release_resource(r)); }
static void chipc_probe_nomatch(device_t dev, device_t child) { struct resource_list *rl; const char *name; name = device_get_name(child); if (name == NULL) name = "unknown device"; device_printf(dev, "<%s> at", name); rl = BUS_GET_RESOURCE_LIST(dev, child); if (rl != NULL) { resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); } printf(" (no driver attached)\n"); }
static struct resource * gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct gpiobus_softc *sc; struct resource *rv; struct resource_list *rl; struct resource_list_entry *rle; int isdefault; if (type != SYS_RES_IRQ) return (NULL); isdefault = (start == 0UL && end == ~0UL && count == 1); rle = NULL; if (isdefault) { rl = BUS_GET_RESOURCE_LIST(bus, child); if (rl == NULL) return (NULL); rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("%s: resource entry is busy", __func__); start = rle->start; count = rle->count; end = rle->end; } sc = device_get_softc(bus); rv = rman_reserve_resource(&sc->sc_intr_rman, start, end, count, flags, child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, *rid, rv) != 0) { rman_release_resource(rv); return (NULL); } return (rv); }
static int chipc_print_child(device_t dev, device_t child) { struct resource_list *rl; int retval = 0; retval += bus_print_child_header(dev, child); rl = BUS_GET_RESOURCE_LIST(dev, child); if (rl != NULL) { retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); } retval += bus_print_child_domain(dev, child); retval += bus_print_child_footer(dev, child); return (retval); }
/** * Helper function for implementing BUS_PRINT_CHILD(). * * This implementation requests the device's struct resource_list via * BUS_GET_RESOURCE_LIST. */ int bhnd_generic_print_child(device_t dev, device_t child) { struct resource_list *rl; int retval = 0; retval += bus_print_child_header(dev, child); rl = BUS_GET_RESOURCE_LIST(dev, child); if (rl != NULL) { retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); } retval += printf(" at core %u", bhnd_get_core_index(child)); retval += bus_print_child_domain(dev, child); retval += bus_print_child_footer(dev, child); return (retval); }
/** * Helper function for implementing BUS_PRINT_CHILD(). * * This implementation requests the device's struct resource_list via * BUS_GET_RESOURCE_LIST. */ void bhnd_generic_probe_nomatch(device_t dev, device_t child) { struct resource_list *rl; const struct bhnd_nomatch *nm; bool report; /* Fetch reporting configuration for this device */ report = true; for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) { if (nm->vendor != bhnd_get_vendor(child)) continue; if (nm->device != bhnd_get_device(child)) continue; report = false; if (bootverbose && nm->if_verbose) report = true; break; } if (!report) return; /* Print the non-matched device info */ device_printf(dev, "<%s %s>", bhnd_get_vendor_name(child), bhnd_get_device_name(child)); rl = BUS_GET_RESOURCE_LIST(dev, child); if (rl != NULL) resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); printf(" at core %u (no driver attached)\n", bhnd_get_core_index(child)); }
static struct resource * chipc_alloc_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct chipc_softc *sc; struct chipc_region *cr; struct resource_list_entry *rle; struct resource *rv; struct rman *rm; int error; bool passthrough, isdefault; sc = device_get_softc(dev); passthrough = (device_get_parent(child) != dev); isdefault = RMAN_IS_DEFAULT_RANGE(start, end); rle = NULL; /* Fetch the resource manager, delegate request if necessary */ rm = chipc_get_rman(sc, type); if (rm == NULL) { /* Requested resource type is delegated to our parent */ rv = bus_generic_rl_alloc_resource(dev, child, type, rid, start, end, count, flags); return (rv); } /* Populate defaults */ if (!passthrough && isdefault) { /* Fetch the resource list entry. */ rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child), type, *rid); if (rle == NULL) { device_printf(dev, "default resource %#x type %d for child %s " "not found\n", *rid, type, device_get_nameunit(child)); return (NULL); } if (rle->res != NULL) { device_printf(dev, "resource entry %#x type %d for child %s is busy " "[%d]\n", *rid, type, device_get_nameunit(child), rman_get_flags(rle->res)); return (NULL); } start = rle->start; end = rle->end; count = ulmax(count, rle->count); } /* Locate a mapping region */ if ((cr = chipc_find_region(sc, start, end)) == NULL) { /* Resource requests outside our shared port regions can be * delegated to our parent. */ rv = bus_generic_rl_alloc_resource(dev, child, type, rid, start, end, count, flags); return (rv); } /* Try to retain a region reference */ if ((error = chipc_retain_region(sc, cr, RF_ALLOCATED))) return (NULL); /* Make our rman reservation */ rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, child); if (rv == NULL) { chipc_release_region(sc, cr, RF_ALLOCATED); return (NULL); } rman_set_rid(rv, *rid); /* Activate */ if (flags & RF_ACTIVE) { error = bus_activate_resource(child, type, *rid, rv); if (error) { device_printf(dev, "failed to activate entry %#x type %d for " "child %s: %d\n", *rid, type, device_get_nameunit(child), error); chipc_release_region(sc, cr, RF_ALLOCATED); rman_release_resource(rv); return (NULL); } } /* Update child's resource list entry */ if (rle != NULL) { rle->res = rv; rle->start = rman_get_start(rv); rle->end = rman_get_end(rv); rle->count = rman_get_size(rv); } return (rv); }
static struct resource * ebus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct ebus_softc *sc; struct resource_list *rl; struct resource_list_entry *rle = NULL; struct resource *res; struct ebus_rinfo *ri; bus_space_tag_t bt; bus_space_handle_t bh; int passthrough = (device_get_parent(child) != bus); int isdefault = (start == 0UL && end == ~0UL); int ridx, rv; sc = (struct ebus_softc *)device_get_softc(bus); rl = BUS_GET_RESOURCE_LIST(bus, child); /* * Map EBus ranges to PCI ranges. This may include changing the * allocation type. */ switch (type) { case SYS_RES_MEMORY: KASSERT(!(isdefault && passthrough), ("ebus_alloc_resource: passthrough of default alloc")); if (!passthrough) { rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); KASSERT(rle->res == NULL, ("ebus_alloc_resource: resource entry is busy")); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } (void)ofw_isa_range_map(sc->sc_range, sc->sc_nrange, &start, &end, &ridx); ri = &sc->sc_rinfo[ridx]; res = rman_reserve_resource(&ri->eri_rman, start, end, count, flags, child); if (res == NULL) return (NULL); rman_set_rid(res, *rid); bt = rman_get_bustag(ri->eri_res); rman_set_bustag(res, bt); rv = bus_space_subregion(bt, rman_get_bushandle(ri->eri_res), rman_get_start(res) - rman_get_start(ri->eri_res), count, &bh); if (rv != 0) { rman_release_resource(res); return (NULL); } rman_set_bushandle(res, bh); if (!passthrough) rle->res = res; return (res); case SYS_RES_IRQ: return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); } return (NULL); }
static struct resource * ebus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct ebus_softc *sc; struct resource_list *rl; struct resource_list_entry *rle = NULL; struct resource *res; struct ebus_rinfo *eri; struct ebus_nexus_ranges *enr; uint64_t cend, cstart, offset; int i, isdefault, passthrough, ridx; isdefault = (start == 0UL && end == ~0UL); passthrough = (device_get_parent(child) != bus); sc = device_get_softc(bus); rl = BUS_GET_RESOURCE_LIST(bus, child); switch (type) { case SYS_RES_MEMORY: KASSERT(!(isdefault && passthrough), ("%s: passthrough of default allocation", __func__)); if (!passthrough) { rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); KASSERT(rle->res == NULL, ("%s: resource entry is busy", __func__)); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } res = NULL; if ((sc->sc_flags & EBUS_PCI) != 0) { /* * Map EBus ranges to PCI ranges. This may include * changing the allocation type. */ (void)ofw_isa_range_map(sc->sc_range, sc->sc_nrange, &start, &end, &ridx); eri = &sc->sc_rinfo[ridx]; res = rman_reserve_resource(&eri->eri_rman, start, end, count, flags & ~RF_ACTIVE, child); if (res == NULL) return (NULL); rman_set_rid(res, *rid); if ((flags & RF_ACTIVE) != 0 && bus_activate_resource( child, type, *rid, res) != 0) { rman_release_resource(res); return (NULL); } } else { /* Map EBus ranges to nexus ranges. */ for (i = 0; i < sc->sc_nrange; i++) { enr = &((struct ebus_nexus_ranges *) sc->sc_range)[i]; cstart = (((uint64_t)enr->child_hi) << 32) | enr->child_lo; cend = cstart + enr->size - 1; if (start >= cstart && end <= cend) { offset = (((uint64_t)enr->phys_hi) << 32) | enr->phys_lo; start += offset - cstart; end += offset - cstart; res = bus_generic_alloc_resource(bus, child, type, rid, start, end, count, flags); break; } } } if (!passthrough) rle->res = res; return (res); case SYS_RES_IRQ: return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); } return (NULL); }
int openpic_attach(device_t dev) { struct openpic_softc *sc; u_int cpu, ipi, irq; u_int32_t x; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_rid = 0; sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, RF_ACTIVE); if (sc->sc_memr == NULL) { device_printf(dev, "Could not alloc mem resource!\n"); return (ENXIO); } sc->sc_bt = rman_get_bustag(sc->sc_memr); sc->sc_bh = rman_get_bushandle(sc->sc_memr); /* Reset the PIC */ x = openpic_read(sc, OPENPIC_CONFIG); x |= OPENPIC_CONFIG_RESET; openpic_write(sc, OPENPIC_CONFIG, x); while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) { powerpc_sync(); DELAY(100); } /* Check if this is a cascaded PIC */ sc->sc_irq = 0; sc->sc_intr = NULL; do { struct resource_list *rl; rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); if (rl == NULL) break; if (resource_list_find(rl, SYS_RES_IRQ, 0) == NULL) break; sc->sc_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irq, RF_ACTIVE); /* XXX Cascaded PICs pass NULL trapframes! */ bus_setup_intr(dev, sc->sc_intr, INTR_TYPE_MISC | INTR_MPSAFE, openpic_intr, NULL, dev, &sc->sc_icookie); } while (0); /* Reset the PIC */ x = openpic_read(sc, OPENPIC_CONFIG); x |= OPENPIC_CONFIG_RESET; openpic_write(sc, OPENPIC_CONFIG, x); while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) { powerpc_sync(); DELAY(100); } x = openpic_read(sc, OPENPIC_FEATURE); switch (x & OPENPIC_FEATURE_VERSION_MASK) { case 1: sc->sc_version = "1.0"; break; case 2: sc->sc_version = "1.2"; break; case 3: sc->sc_version = "1.3"; break; default: sc->sc_version = "unknown"; break; } sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >> OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1; sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >> OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1; /* * PSIM seems to report 1 too many IRQs and CPUs */ if (sc->sc_psim) { sc->sc_nirq--; sc->sc_ncpu--; } if (bootverbose) device_printf(dev, "Version %s, supports %d CPUs and %d irqs\n", sc->sc_version, sc->sc_ncpu, sc->sc_nirq); for (cpu = 0; cpu < sc->sc_ncpu; cpu++) openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 15); /* Reset and disable all interrupts. */ for (irq = 0; irq < sc->sc_nirq; irq++) { x = irq; /* irq == vector. */ x |= OPENPIC_IMASK; x |= OPENPIC_POLARITY_NEGATIVE; x |= OPENPIC_SENSE_LEVEL; x |= 8 << OPENPIC_PRIORITY_SHIFT; openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); } /* Reset and disable all IPIs. */ for (ipi = 0; ipi < 4; ipi++) { x = sc->sc_nirq + ipi; x |= OPENPIC_IMASK; x |= 15 << OPENPIC_PRIORITY_SHIFT; openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x); } /* we don't need 8259 passthrough mode */ x = openpic_read(sc, OPENPIC_CONFIG); x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE; openpic_write(sc, OPENPIC_CONFIG, x); /* send all interrupts to cpu 0 */ for (irq = 0; irq < sc->sc_nirq; irq++) openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0); /* clear all pending interrupts from cpu 0 */ for (irq = 0; irq < sc->sc_nirq; irq++) { (void)openpic_read(sc, OPENPIC_PCPU_IACK(0)); openpic_write(sc, OPENPIC_PCPU_EOI(0), 0); } for (cpu = 0; cpu < sc->sc_ncpu; cpu++) openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0); powerpc_register_pic(dev, sc->sc_nirq); /* If this is not a cascaded PIC, it must be the root PIC */ if (sc->sc_intr == NULL) root_pic = dev; return (0); }
static void isa_setup_children(device_t dev, phandle_t parent) { struct isa_regs *regs; struct resource_list *rl; device_t cdev; u_int64_t end, start; ofw_isa_intr_t *intrs, rintr; phandle_t node; uint32_t *drqs, *regidx; int i, ndrq, nintr, nreg, nregidx, rid, rtype; char *name; /* * Loop through children and fake up PnP devices for them. * Their resources are added as fully mapped and specified because * adjusting the resources and the resource list entries respectively * in isa_alloc_resource() causes trouble with drivers which use * rman_get_start(), pass-through or allocate and release resources * multiple times, etc. Adjusting the resources might be better off * in a bus_activate_resource method but the common ISA code doesn't * allow for an isa_activate_resource(). */ for (node = OF_child(parent); node != 0; node = OF_peer(node)) { if ((OF_getprop_alloc(node, "name", 1, (void **)&name)) == -1) continue; /* * Keyboard and mouse controllers hang off of the `8042' * node but we have no real use for the `8042' itself. */ if (strcmp(name, "8042") == 0) { isa_setup_children(dev, node); free(name, M_OFWPROP); continue; } for (i = 0; ofw_isa_pnp_map[i].name != NULL; i++) if (strcmp(ofw_isa_pnp_map[i].name, name) == 0) break; if (ofw_isa_pnp_map[i].name == NULL) { device_printf(dev, "no PnP map entry for node " "0x%lx: %s\n", (unsigned long)node, name); free(name, M_OFWPROP); continue; } if ((cdev = BUS_ADD_CHILD(dev, ISA_ORDER_PNPBIOS, NULL, -1)) == NULL) panic("isa_setup_children: BUS_ADD_CHILD failed"); isa_set_logicalid(cdev, ofw_isa_pnp_map[i].id); isa_set_vendorid(cdev, ofw_isa_pnp_map[i].id); rl = BUS_GET_RESOURCE_LIST(dev, cdev); nreg = OF_getprop_alloc(node, "reg", sizeof(*regs), (void **)®s); for (i = 0; i < nreg; i++) { start = ISA_REG_PHYS(®s[i]); end = start + regs[i].size - 1; rtype = ofw_isa_range_map(isab_ranges, isab_nrange, &start, &end, NULL); rid = 0; while (resource_list_find(rl, rtype, rid) != NULL) rid++; bus_set_resource(cdev, rtype, rid, start, end - start + 1); } if (nreg == -1 && parent != isab_node) { /* * The "reg" property still might be an index into * the set of registers of the parent device like * with the nodes hanging off of the `8042' node. */ nregidx = OF_getprop_alloc(node, "reg", sizeof(*regidx), (void **)®idx); if (nregidx > 2) panic("isa_setup_children: impossible number " "of register indices"); if (nregidx != -1 && (nreg = OF_getprop_alloc(parent, "reg", sizeof(*regs), (void **)®s)) >= nregidx) { for (i = 0; i < nregidx; i++) { start = ISA_REG_PHYS(®s[regidx[i]]); end = start + regs[regidx[i]].size - 1; rtype = ofw_isa_range_map(isab_ranges, isab_nrange, &start, &end, NULL); rid = 0; while (resource_list_find(rl, rtype, rid) != NULL) rid++; bus_set_resource(cdev, rtype, rid, start, end - start + 1); } } if (regidx != NULL) free(regidx, M_OFWPROP); } if (regs != NULL) free(regs, M_OFWPROP); nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs), (void **)&intrs); for (i = 0; i < nintr; i++) { if (intrs[i] > 7) panic("isa_setup_children: intr too large"); rintr = ofw_isa_route_intr(device_get_parent(dev), node, &isa_iinfo, intrs[i]); if (rintr == PCI_INVALID_IRQ) { device_printf(dev, "could not map ISA " "interrupt %d for node 0x%lx: %s\n", intrs[i], (unsigned long)node, name); continue; } bus_set_resource(cdev, SYS_RES_IRQ, i, rintr, 1); } if (intrs != NULL) free(intrs, M_OFWPROP); ndrq = OF_getprop_alloc(node, "dma-channel", sizeof(*drqs), (void **)&drqs); for (i = 0; i < ndrq; i++) bus_set_resource(cdev, SYS_RES_DRQ, i, drqs[i], 1); if (drqs != NULL) free(drqs, M_OFWPROP); /* * Devices using DMA hang off of the `dma' node instead of * directly from the ISA bridge node. */ if (strcmp(name, "dma") == 0) isa_setup_children(dev, node); free(name, M_OFWPROP); } }
/** * Helper function for implementing BHND_BUS_ALLOC_RESOURCE(). * * This simple implementation of BHND_BUS_ALLOC_RESOURCE() determines * any default values via BUS_GET_RESOURCE_LIST(), and calls * BHND_BUS_ALLOC_RESOURCE() method of the parent of @p dev. * * If no parent device is available, the request is instead delegated to * BUS_ALLOC_RESOURCE(). */ struct bhnd_resource * bhnd_generic_alloc_bhnd_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct bhnd_resource *r; struct resource_list *rl; struct resource_list_entry *rle; bool isdefault; bool passthrough; passthrough = (device_get_parent(child) != dev); isdefault = RMAN_IS_DEFAULT_RANGE(start, end); /* the default RID must always be the first device port/region. */ if (!passthrough && *rid == 0) { int rid0 = bhnd_get_port_rid(child, BHND_PORT_DEVICE, 0, 0); KASSERT(*rid == rid0, ("rid 0 does not map to the first device port (%d)", rid0)); } /* Determine locally-known defaults before delegating the request. */ if (!passthrough && isdefault) { /* fetch resource list from child's bus */ rl = BUS_GET_RESOURCE_LIST(dev, child); if (rl == NULL) return (NULL); /* no resource list */ /* look for matching type/rid pair */ rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child), type, *rid); if (rle == NULL) return (NULL); /* set default values */ start = rle->start; end = rle->end; count = ulmax(count, rle->count); } /* Try to delegate to our parent. */ if (device_get_parent(dev) != NULL) { return (BHND_BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid, start, end, count, flags)); } /* If this is the bus root, use a real bus-allocated resource */ r = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT); if (r == NULL) return NULL; /* Allocate the bus resource, marking it as 'direct' (not requiring * any bus window remapping to perform I/O) */ r->direct = true; r->res = BUS_ALLOC_RESOURCE(dev, child, type, rid, start, end, count, flags); if (r->res == NULL) { free(r, M_BHND); return NULL; } return (r); }
static int acpi_sysres_attach(device_t dev) { device_t bus; struct resource_list_entry *bus_rle, *dev_rle; struct resource_list *bus_rl, *dev_rl; int done, type; u_long start, end, count; /* * Loop through all current resources to see if the new one overlaps * any existing ones. If so, grow the old one up and/or down * accordingly. Discard any that are wholly contained in the old. If * the resource is unique, add it to the parent. It will later go into * the rman pool. */ bus = device_get_parent(dev); dev_rl = BUS_GET_RESOURCE_LIST(bus, dev); bus_rl = BUS_GET_RESOURCE_LIST(device_get_parent(bus), bus); STAILQ_FOREACH(dev_rle, dev_rl, link) { if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY) continue; start = dev_rle->start; end = dev_rle->end; count = dev_rle->count; type = dev_rle->type; done = FALSE; STAILQ_FOREACH(bus_rle, bus_rl, link) { if (bus_rle->type != type) continue; /* New resource wholly contained in old, discard. */ if (start >= bus_rle->start && end <= bus_rle->end) break; /* New tail overlaps old head, grow existing resource downward. */ if (start < bus_rle->start && end >= bus_rle->start) { bus_rle->count += bus_rle->start - start; bus_rle->start = start; done = TRUE; } /* New head overlaps old tail, grow existing resource upward. */ if (start <= bus_rle->end && end > bus_rle->end) { bus_rle->count += end - bus_rle->end; bus_rle->end = end; done = TRUE; } /* If we adjusted the old resource, we're finished. */ if (done) break; } /* If we didn't merge with anything, add this resource. */ if (bus_rle == NULL) bus_set_resource(bus, type, acpi_sysres_rid++, start, count); } /* After merging/moving resources to the parent, free the list. */ resource_list_free(dev_rl); return (0); }
static int sbus_attach(device_t dev) { struct sbus_softc *sc; struct sbus_devinfo *sdi; struct sbus_icarg *sica; struct sbus_ranges *range; struct resource *res; struct resource_list *rl; device_t cdev; bus_addr_t intrclr, intrmap, phys; bus_size_t size; u_long vec; phandle_t child, node; uint32_t prop; int i, j; sc = device_get_softc(dev); sc->sc_dev = dev; node = ofw_bus_get_node(dev); i = 0; sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, RF_ACTIVE); if (sc->sc_sysio_res == NULL) panic("%s: cannot allocate device memory", __func__); if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1) panic("%s: cannot get IGN", __func__); sc->sc_ign = INTIGN(prop); /* * Record clock frequency for synchronous SCSI. * IS THIS THE CORRECT DEFAULT?? */ if (OF_getprop(node, "clock-frequency", &prop, sizeof(prop)) == -1) prop = 25000000; sc->sc_clockfreq = prop; prop /= 1000; device_printf(dev, "clock %d.%03d MHz\n", prop / 1000, prop % 1000); /* * Collect address translations from the OBP. */ if ((sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range)) == -1) { panic("%s: error getting ranges property", __func__); } sc->sc_rd = malloc(sizeof(*sc->sc_rd) * sc->sc_nrange, M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_rd == NULL) panic("%s: cannot allocate rmans", __func__); /* * Preallocate all space that the SBus bridge decodes, so that nothing * else gets in the way; set up rmans etc. */ rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); for (i = 0; i < sc->sc_nrange; i++) { phys = range[i].poffset | ((bus_addr_t)range[i].pspace << 32); size = range[i].size; sc->sc_rd[i].rd_slot = range[i].cspace; sc->sc_rd[i].rd_coffset = range[i].coffset; sc->sc_rd[i].rd_cend = sc->sc_rd[i].rd_coffset + size; j = resource_list_add_next(rl, SYS_RES_MEMORY, phys, phys + size - 1, size); if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &j, RF_ACTIVE)) == NULL) panic("%s: cannot allocate decoded range", __func__); sc->sc_rd[i].rd_bushandle = rman_get_bushandle(res); sc->sc_rd[i].rd_rman.rm_type = RMAN_ARRAY; sc->sc_rd[i].rd_rman.rm_descr = "SBus Device Memory"; if (rman_init(&sc->sc_rd[i].rd_rman) != 0 || rman_manage_region(&sc->sc_rd[i].rd_rman, 0, size) != 0) panic("%s: failed to set up memory rman", __func__); sc->sc_rd[i].rd_poffset = phys; sc->sc_rd[i].rd_pend = phys + size; sc->sc_rd[i].rd_res = res; } free(range, M_OFWPROP); /* * Get the SBus burst transfer size if burst transfers are supported. */ if (OF_getprop(node, "up-burst-sizes", &sc->sc_burst, sizeof(sc->sc_burst)) == -1 || sc->sc_burst == 0) sc->sc_burst = (SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF; /* initalise the IOMMU */ /* punch in our copies */ sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(SBUS_IOMMU_BITS); sc->sc_is.is_bustag = rman_get_bustag(sc->sc_sysio_res); sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_sysio_res); sc->sc_is.is_iommu = SBR_IOMMU; sc->sc_is.is_dtag = SBR_IOMMU_TLB_TAG_DIAG; sc->sc_is.is_ddram = SBR_IOMMU_TLB_DATA_DIAG; sc->sc_is.is_dqueue = SBR_IOMMU_QUEUE_DIAG; sc->sc_is.is_dva = SBR_IOMMU_SVADIAG; sc->sc_is.is_dtcmp = 0; sc->sc_is.is_sb[0] = SBR_STRBUF; sc->sc_is.is_sb[1] = 0; /* * Note: the SBus IOMMU ignores the high bits of an address, so a NULL * DMA pointer will be translated by the first page of the IOTSB. * To detect bugs we'll allocate and ignore the first entry. */ iommu_init(device_get_nameunit(dev), &sc->sc_is, 3, -1, 1); /* Create the DMA tag. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_cdmatag) != 0) panic("%s: bus_dma_tag_create failed", __func__); /* Customize the tag. */ sc->sc_cdmatag->dt_cookie = &sc->sc_is; sc->sc_cdmatag->dt_mt = &iommu_dma_methods; /* * Hunt through all the interrupt mapping regs and register our * interrupt controller for the corresponding interrupt vectors. * We do this early in order to be able to catch stray interrupts. */ for (i = 0; i <= SBUS_MAX_INO; i++) { if (sbus_find_intrmap(sc, i, &intrmap, &intrclr) == 0) continue; sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT); if (sica == NULL) panic("%s: could not allocate interrupt controller " "argument", __func__); sica->sica_sc = sc; sica->sica_map = intrmap; sica->sica_clr = intrclr; #ifdef SBUS_DEBUG device_printf(dev, "intr map (INO %d, %s) %#lx: %#lx, clr: %#lx\n", i, (i & INTMAP_OBIO_MASK) == 0 ? "SBus slot" : "OBIO", (u_long)intrmap, (u_long)SYSIO_READ8(sc, intrmap), (u_long)intrclr); #endif j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i), &sbus_ic, sica); if (j != 0) device_printf(dev, "could not register interrupt " "controller for INO %d (%d)\n", i, j); } /* Enable the over-temperature and power-fail interrupts. */ i = 4; sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE); if (sc->sc_ot_ires == NULL || INTIGN(vec = rman_get_start(sc->sc_ot_ires)) != sc->sc_ign || INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec || intr_vectors[vec].iv_ic != &sbus_ic || bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC | INTR_BRIDGE, NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0) panic("%s: failed to set up temperature interrupt", __func__); i = 3; sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE); if (sc->sc_pf_ires == NULL || INTIGN(vec = rman_get_start(sc->sc_pf_ires)) != sc->sc_ign || INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec || intr_vectors[vec].iv_ic != &sbus_ic || bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC | INTR_BRIDGE, NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0) panic("%s: failed to set up power fail interrupt", __func__); /* Initialize the counter-timer. */ sparc64_counter_init(device_get_nameunit(dev), rman_get_bustag(sc->sc_sysio_res), rman_get_bushandle(sc->sc_sysio_res), SBR_TC0); /* * Loop through ROM children, fixing any relative addresses * and then configuring each device. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { if ((sdi = sbus_setup_dinfo(dev, sc, child)) == NULL) continue; /* * For devices where there are variants that are actually * split into two SBus devices (as opposed to the first * half of the device being a SBus device and the second * half hanging off of the first one) like 'auxio' and * 'SUNW,fdtwo' or 'dma' and 'esp' probe the SBus device * which is a prerequisite to the driver attaching to the * second one with a lower order. Saves us from dealing * with different probe orders in the respective device * drivers which generally is more hackish. */ cdev = device_add_child_ordered(dev, (OF_child(child) == 0 && sbus_inlist(sdi->sdi_obdinfo.obd_name, sbus_order_first)) ? SBUS_ORDER_FIRST : SBUS_ORDER_NORMAL, NULL, -1); if (cdev == NULL) { device_printf(dev, "<%s>: device_add_child_ordered failed\n", sdi->sdi_obdinfo.obd_name); sbus_destroy_dinfo(sdi); continue; } device_set_ivars(cdev, sdi); } return (bus_generic_attach(dev)); }
/* * All resources are assigned directly to us by acpi, * so 'child' is bypassed here. */ static struct resource_list * acpi_cpu_get_rlist(device_t dev, device_t child __unused) { return BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); }
static struct resource * sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct sbus_softc *sc; struct rman *rm; struct resource *rv; struct resource_list *rl; struct resource_list_entry *rle; device_t schild; bus_addr_t toffs; bus_size_t tend; int i, slot; int isdefault, passthrough; isdefault = RMAN_IS_DEFAULT_RANGE(start, end); passthrough = (device_get_parent(child) != bus); rle = NULL; sc = device_get_softc(bus); rl = BUS_GET_RESOURCE_LIST(bus, child); switch (type) { case SYS_RES_IRQ: return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); case SYS_RES_MEMORY: if (!passthrough) { rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("%s: resource entry is busy", __func__); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } rm = NULL; schild = child; while (device_get_parent(schild) != bus) schild = device_get_parent(schild); slot = sbus_get_slot(schild); for (i = 0; i < sc->sc_nrange; i++) { if (sc->sc_rd[i].rd_slot != slot || start < sc->sc_rd[i].rd_coffset || start > sc->sc_rd[i].rd_cend) continue; /* Disallow cross-range allocations. */ if (end > sc->sc_rd[i].rd_cend) return (NULL); /* We've found the connection to the parent bus */ toffs = start - sc->sc_rd[i].rd_coffset; tend = end - sc->sc_rd[i].rd_coffset; rm = &sc->sc_rd[i].rd_rman; break; } if (rm == NULL) return (NULL); rv = rman_reserve_resource(rm, toffs, tend, count, flags & ~RF_ACTIVE, child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, *rid, rv)) { rman_release_resource(rv); return (NULL); } if (!passthrough) rle->res = rv; return (rv); default: return (NULL); } }
struct resource * isa_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { /* * Consider adding a resource definition. */ int passthrough = (device_get_parent(child) != bus); int isdefault = (start == 0UL && end == ~0UL); struct resource_list *rl; struct resource_list_entry *rle; u_long base, limit; rl = BUS_GET_RESOURCE_LIST(bus, child); if (!passthrough && !isdefault) { rle = resource_list_find(rl, type, *rid); if (!rle) { if (*rid < 0) return (NULL); switch (type) { case SYS_RES_IRQ: if (*rid >= ISA_NIRQ) return (NULL); break; case SYS_RES_DRQ: if (*rid >= ISA_NDRQ) return (NULL); break; case SYS_RES_MEMORY: if (*rid >= ISA_NMEM) return (NULL); break; case SYS_RES_IOPORT: if (*rid >= ISA_NPORT) return (NULL); break; default: return (NULL); } resource_list_add(rl, type, *rid, start, end, count); } } /* * Sanity check if the resource in the respective entry is fully * mapped and specified and its type allocable. A driver could * have added an out of range resource on its own. */ if (!passthrough) { if ((rle = resource_list_find(rl, type, *rid)) == NULL) return (NULL); base = limit = 0; switch (type) { case SYS_RES_MEMORY: base = isa_mem_base; limit = base + isa_mem_limit; break; case SYS_RES_IOPORT: base = isa_io_base; limit = base + isa_io_limit; break; case SYS_RES_IRQ: if (rle->start != rle->end || rle->start <= 7) return (NULL); break; case SYS_RES_DRQ: break; default: return (NULL); } if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { if (!INRANGE(rle->start, base, limit) || !INRANGE(rle->end, base, limit)) return (NULL); } } return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); }
static struct resource * nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct nexus_softc *sc; struct rman *rm; struct resource *rv; struct resource_list_entry *rle; device_t nexus; int isdefault, needactivate, passthrough; isdefault = (start == 0UL && end == ~0UL); needactivate = flags & RF_ACTIVE; passthrough = (device_get_parent(child) != bus); nexus = bus; while (strcmp(device_get_name(device_get_parent(nexus)), "root") != 0) nexus = device_get_parent(nexus); sc = device_get_softc(nexus); rle = NULL; if (!passthrough) { rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("%s: resource entry is busy", __func__); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } switch (type) { case SYS_RES_IRQ: rm = &sc->sc_intr_rman; break; case SYS_RES_MEMORY: rm = &sc->sc_mem_rman; break; default: return (NULL); } flags &= ~RF_ACTIVE; rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); if (type == SYS_RES_MEMORY) { rman_set_bustag(rv, &nexus_bustag); rman_set_bushandle(rv, rman_get_start(rv)); } if (needactivate) { if (bus_activate_resource(child, type, *rid, rv) != 0) { rman_release_resource(rv); return (NULL); } } if (!passthrough) { rle->res = rv; rle->start = rman_get_start(rv); rle->end = rman_get_end(rv); rle->count = rle->end - rle->start + 1; } return (rv); }