static int obio_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { struct resource_list *rl; struct resource_list_entry *rle; rl = obio_get_resource_list(dev, child); if (rl == NULL) return (EINVAL); rle = resource_list_find(rl, type, rid); if (rle == NULL) return (EINVAL); rman_release_resource(r); rle->res = NULL; return (0); }
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 struct resource * obio_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 *rv; struct rman *rm; bus_space_handle_t bh = 0; struct obio_softc *sc = device_get_softc(bus); switch (type) { case SYS_RES_IRQ: rm = &sc->oba_irq_rman; break; case SYS_RES_MEMORY: return (NULL); case SYS_RES_IOPORT: rm = &sc->oba_rman; bh = sc->oba_addr; start = bh; break; default: return (NULL); } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == NULL) return (NULL); if (type == SYS_RES_IRQ) return (rv); rman_set_rid(rv, *rid); rman_set_bustag(rv, mips_bus_space_generic); rman_set_bushandle(rv, bh); if (0) { if (bus_activate_resource(child, type, *rid, rv)) { rman_release_resource(rv); return (NULL); } } return (rv); }
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 int cbb_pci_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { struct cbb_softc *sc; int error; sc = device_get_softc(bus); if (type == PCI_RES_BUS) { if (!rman_is_region_manager(r, &sc->bus.rman)) return (EINVAL); if (rman_get_flags(r) & RF_ACTIVE) { error = bus_deactivate_resource(child, type, rid, r); if (error) return (error); } return (rman_release_resource(r)); } return (cbb_release_resource(bus, child, type, rid, r)); }
static int thunder_pem_release_resource(device_t dev, device_t child, int type, int rid, struct resource *res) { device_t parent_dev; #if defined(NEW_PCIB) && defined(PCI_RES_BUS) struct thunder_pem_softc *sc = device_get_softc(dev); if (type == PCI_RES_BUS) return (pci_domain_release_bus(sc->id, child, rid, res)); #endif /* Find parent device. On ThunderX we know an exact path. */ parent_dev = device_get_parent(device_get_parent(dev)); if ((type != SYS_RES_MEMORY) && (type != SYS_RES_IOPORT)) return (BUS_RELEASE_RESOURCE(parent_dev, child, type, rid, res)); return (rman_release_resource(res)); }
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); }
/* * Allocate resources at the behalf of a child. This only handles interrupts, * since i/o resources are usually set up by the firmware, and thus need not * be handled here. */ 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 = device_get_softc(bus); struct resource *rv; struct rman *rm; int needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; 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, child); if (rv == NULL) return (NULL); 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)) { rman_release_resource(rv); return (NULL); } } return (rv); }
int pci_host_generic_core_release_resource(device_t dev, device_t child, int type, int rid, struct resource *res) { struct generic_pcie_core_softc *sc; struct rman *rm; sc = device_get_softc(dev); #if defined(NEW_PCIB) && defined(PCI_RES_BUS) if (type == PCI_RES_BUS) { return (pci_domain_release_bus(sc->ecam, child, rid, res)); } #endif rm = generic_pcie_rman(sc, type); if (rm != NULL) { KASSERT(rman_is_region_manager(res, rm), ("rman mismatch")); rman_release_resource(res); } return (bus_generic_release_resource(dev, child, type, rid, res)); }
static struct resource * apb_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 apb_softc *sc = device_get_softc(bus); struct apb_ivar *ivar = device_get_ivars(child); struct resource *rv; struct resource_list_entry *rle; struct rman *rm; int isdefault, needactivate, passthrough; isdefault = (RMAN_IS_DEFAULT_RANGE(start, end)); needactivate = flags & RF_ACTIVE; /* * Pass memory requests to nexus device */ passthrough = (device_get_parent(child) != bus); rle = NULL; dprintf("%s: entry (%p, %p, %d, %d, %p, %p, %jd, %d)\n", __func__, bus, child, type, *rid, (void *)(intptr_t)start, (void *)(intptr_t)end, count, flags); if (passthrough) return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid, start, end, count, flags)); /* * If this is an allocation of the "default" range for a given RID, * and we know what the resources for this device are (ie. they aren't * maintained by a child bus), then work out the start/end values. */ if (isdefault) { rle = resource_list_find(&ivar->resources, type, *rid); if (rle == NULL) { return (NULL); } if (rle->res != NULL) { panic("%s: resource entry is busy", __func__); } start = rle->start; end = rle->end; count = rle->count; dprintf("%s: default resource (%p, %p, %ld)\n", __func__, (void *)(intptr_t)start, (void *)(intptr_t)end, count); } switch (type) { case SYS_RES_IRQ: rm = &sc->apb_irq_rman; break; case SYS_RES_MEMORY: rm = &sc->apb_mem_rman; break; default: printf("%s: unknown resource type %d\n", __func__, type); return (0); } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == 0) { printf("%s: could not reserve resource\n", __func__); return (0); } rman_set_rid(rv, *rid); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { printf("%s: could not activate resource\n", __func__); rman_release_resource(rv); return (0); } } return (rv); }
static struct resource * thunder_pem_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 thunder_pem_softc *sc = device_get_softc(dev); struct rman *rm = NULL; struct resource *res; device_t parent_dev; #if defined(NEW_PCIB) && defined(PCI_RES_BUS) if (type == PCI_RES_BUS) return (pci_domain_alloc_bus(sc->id, child, rid, start, end, count, flags)); #endif rm = thunder_pem_rman(sc, type); if (rm == NULL) { /* Find parent device. On ThunderX we know an exact path. */ parent_dev = device_get_parent(device_get_parent(dev)); return (BUS_ALLOC_RESOURCE(parent_dev, dev, type, rid, start, end, count, flags)); } if (!RMAN_IS_DEFAULT_RANGE(start, end)) { /* * We might get PHYS addresses here inherited from EFI. * Convert to PCI if necessary. */ if (range_addr_is_phys(sc->ranges, start, count)) { start = range_addr_phys_to_pci(sc->ranges, start); end = start + count - 1; } } if (bootverbose) { device_printf(dev, "thunder_pem_alloc_resource: start=%#lx, end=%#lx, count=%#lx\n", start, end, count); } res = rman_reserve_resource(rm, start, end, count, flags, child); if (res == NULL) goto fail; rman_set_rid(res, *rid); if (flags & RF_ACTIVE) if (bus_activate_resource(child, type, *rid, res)) { rman_release_resource(res); goto fail; } return (res); fail: if (bootverbose) { device_printf(dev, "%s FAIL: type=%d, rid=%d, " "start=%016lx, end=%016lx, count=%016lx, flags=%x\n", __func__, type, *rid, start, end, count, flags); } return (NULL); }
static struct resource * fdtbus_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 fdtbus_softc *sc; struct resource *res; struct rman *rm; struct fdtbus_devinfo *di; struct resource_list_entry *rle; int needactivate; /* * Request for the default allocation with a given rid: use resource * list stored in the local device info. */ if ((start == 0UL) && (end == ~0UL)) { if ((di = device_get_ivars(child)) == NULL) return (NULL); if (type == SYS_RES_IOPORT) type = SYS_RES_MEMORY; rle = resource_list_find(&di->di_res, type, *rid); if (rle == NULL) { device_printf(bus, "no default resources for " "rid = %d, type = %d\n", *rid, type); return (NULL); } start = rle->start; end = rle->end; count = rle->count; } sc = device_get_softc(bus); needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; switch (type) { case SYS_RES_IRQ: rm = &sc->sc_irq; break; case SYS_RES_IOPORT: case SYS_RES_MEMORY: rm = &sc->sc_mem; break; default: return (NULL); } res = rman_reserve_resource(rm, start, end, count, flags, child); if (res == NULL) { device_printf(bus, "failed to reserve resource %#lx - %#lx " "(%#lx)\n", start, end, count); return (NULL); } rman_set_rid(res, *rid); if (type == SYS_RES_IOPORT || type == SYS_RES_MEMORY) { /* XXX endianess should be set based on SOC node */ rman_set_bustag(res, fdtbus_bs_tag); rman_set_bushandle(res, rman_get_start(res)); } if (needactivate) if (bus_activate_resource(child, type, *rid, res)) { device_printf(child, "resource activation failed\n"); rman_release_resource(res); return (NULL); } return (res); }
int pci_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { return (rman_release_resource(r)); }
static struct resource * obio_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 obio_softc *sc = device_get_softc(bus); struct obio_ivar *ivar = device_get_ivars(child); struct resource *rv; struct resource_list_entry *rle; struct rman *rm; int isdefault, needactivate, passthrough; isdefault = (start == 0UL && end == ~0UL); needactivate = flags & RF_ACTIVE; passthrough = (device_get_parent(child) != bus); rle = NULL; if (passthrough) return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid, start, end, count, flags)); /* * If this is an allocation of the "default" range for a given RID, * and we know what the resources for this device are (ie. they aren't * maintained by a child bus), then work out the start/end values. */ if (isdefault) { rle = resource_list_find(&ivar->resources, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) { panic("%s: resource entry is busy", __func__); } start = rle->start; end = rle->end; count = rle->count; } switch (type) { case SYS_RES_IRQ: rm = &sc->oba_irq_rman; break; case SYS_RES_MEMORY: rm = &sc->oba_mem_rman; break; default: printf("%s: unknown resource type %d\n", __func__, type); return (0); } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == 0) { printf("%s: could not reserve resource\n", __func__); return (0); } rman_set_rid(rv, *rid); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { printf("%s: could not activate resource\n", __func__); rman_release_resource(rv); return (0); } } return (rv); }
static struct resource * unin_chip_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 unin_chip_softc *sc; int needactivate; struct resource *rv; struct rman *rm; u_long adjstart, adjend, adjcount; struct unin_chip_devinfo *dinfo; struct resource_list_entry *rle; sc = device_get_softc(bus); dinfo = device_get_ivars(child); needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; switch (type) { case SYS_RES_MEMORY: case SYS_RES_IOPORT: rle = resource_list_find(&dinfo->udi_resources, SYS_RES_MEMORY, *rid); if (rle == NULL) { device_printf(bus, "no rle for %s memory %d\n", device_get_nameunit(child), *rid); return (NULL); } rle->end = rle->end - 1; /* Hack? */ if (start < rle->start) adjstart = rle->start; else if (start > rle->end) adjstart = rle->end; else adjstart = start; if (end < rle->start) adjend = rle->start; else if (end > rle->end) adjend = rle->end; else adjend = end; adjcount = adjend - adjstart; rm = &sc->sc_mem_rman; break; case SYS_RES_IRQ: /* Check for passthrough from subattachments. */ if (device_get_parent(child) != bus) return BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid, start, end, count, flags); rle = resource_list_find(&dinfo->udi_resources, SYS_RES_IRQ, *rid); if (rle == NULL) { if (dinfo->udi_ninterrupts >= 6) { device_printf(bus, "%s has more than 6 interrupts\n", device_get_nameunit(child)); return (NULL); } resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ, dinfo->udi_ninterrupts, start, start, 1); dinfo->udi_interrupts[dinfo->udi_ninterrupts] = start; dinfo->udi_ninterrupts++; } return (resource_list_alloc(&dinfo->udi_resources, bus, child, type, rid, start, end, count, flags)); default: device_printf(bus, "unknown resource request from %s\n", device_get_nameunit(child)); return (NULL); } rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags, child); if (rv == NULL) { device_printf(bus, "failed to reserve resource %#lx - %#lx (%#lx)" " for %s\n", adjstart, adjend, adjcount, device_get_nameunit(child)); return (NULL); } rman_set_rid(rv, *rid); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv) != 0) { device_printf(bus, "failed to activate resource for %s\n", device_get_nameunit(child)); rman_release_resource(rv); return (NULL); } } return (rv); }
/* * Free a region allocated using sgmap_alloc_region(). */ void sgmap_free_region(struct sgmap *sgmap, void *mh) { struct resource *res = mh; rman_release_resource(res); }
static struct resource * pxa_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct obio_softc *sc; struct obio_device *od; struct resource *rv; struct resource_list *rl; struct resource_list_entry *rle; struct rman *rm; int needactivate; sc = (struct obio_softc *)device_get_softc(dev); od = (struct obio_device *)device_get_ivars(child); rl = &od->od_resources; rle = resource_list_find(rl, type, *rid); if (rle == NULL) { /* We can allocate GPIO-based IRQs lazily. */ if (type == SYS_RES_IRQ) return (pxa_alloc_gpio_irq(dev, child, type, rid, start, end, count, flags)); return (NULL); } if (rle->res != NULL) panic("pxa_alloc_resource: resource is busy"); switch (type) { case SYS_RES_IRQ: rm = &sc->obio_irq; break; case SYS_RES_MEMORY: rm = &sc->obio_mem; break; default: return (NULL); } needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; rv = rman_reserve_resource(rm, rle->start, rle->end, rle->count, flags, child); if (rv == NULL) return (NULL); rle->res = rv; rman_set_rid(rv, *rid); if (type == SYS_RES_MEMORY) { rman_set_bustag(rv, sc->obio_bst); rman_set_bushandle(rv, rle->start); } if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { rman_release_resource(rv); return (NULL); } } return (rv); }
static struct resource * ps3bus_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 ps3bus_devinfo *dinfo; struct ps3bus_softc *sc; int needactivate; struct resource *rv; struct rman *rm; rman_res_t adjstart, adjend, adjcount; struct resource_list_entry *rle; sc = device_get_softc(bus); dinfo = device_get_ivars(child); needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; switch (type) { case SYS_RES_MEMORY: rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, *rid); if (rle == NULL) { device_printf(bus, "no rle for %s memory %d\n", device_get_nameunit(child), *rid); return (NULL); } if (start < rle->start) adjstart = rle->start; else if (start > rle->end) adjstart = rle->end; else adjstart = start; if (end < rle->start) adjend = rle->start; else if (end > rle->end) adjend = rle->end; else adjend = end; adjcount = adjend - adjstart; rm = &sc->sc_mem_rman; break; case SYS_RES_IRQ: rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, *rid); rm = &sc->sc_intr_rman; adjstart = rle->start; adjcount = ulmax(count, rle->count); adjend = ulmax(rle->end, rle->start + adjcount - 1); break; default: device_printf(bus, "unknown resource request from %s\n", device_get_nameunit(child)); return (NULL); } rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags, child); if (rv == NULL) { device_printf(bus, "failed to reserve resource %#lx - %#lx (%#lx)" " for %s\n", adjstart, adjend, adjcount, device_get_nameunit(child)); return (NULL); } rman_set_rid(rv, *rid); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv) != 0) { device_printf(bus, "failed to activate resource for %s\n", device_get_nameunit(child)); rman_release_resource(rv); return (NULL); } } return (rv); }
/* * Allocate a resource on behalf of child. NB: child is usually going to be a * child of one of our descendants, not a direct child of nexus0. * (Exceptions include npx.) */ 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_device *ndev = DEVTONX(child); struct resource *rv; struct resource_list_entry *rle; struct rman *rm; int needactivate = flags & RF_ACTIVE; /* * If this is an allocation of the "default" range for a given RID, and * we know what the resources for this device are (ie. they aren't maintained * by a child bus), then work out the start/end values. */ if ((start == 0UL) && (end == ~0UL) && (count == 1)) { if (ndev == NULL) return(NULL); rle = resource_list_find(&ndev->nx_resources, type, *rid); if (rle == NULL) return(NULL); start = rle->start; end = rle->end; count = rle->count; } flags &= ~RF_ACTIVE; switch (type) { case SYS_RES_IRQ: rm = &irq_rman; break; case SYS_RES_DRQ: rm = &drq_rman; break; case SYS_RES_IOPORT: rm = &port_rman; break; case SYS_RES_MEMORY: rm = &mem_rman; break; default: return 0; } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == 0) return 0; if (type == SYS_RES_MEMORY) { rman_set_bustag(rv, I386_BUS_SPACE_MEM); } else if (type == SYS_RES_IOPORT) { rman_set_bustag(rv, I386_BUS_SPACE_IO); #ifndef PC98 rman_set_bushandle(rv, rv->r_start); #endif } #ifdef PC98 if ((type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) && i386_bus_space_handle_alloc(rv->r_bustag, rv->r_start, count, &rv->r_bushandle) != 0) { rman_release_resource(rv); return 0; } #endif if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { #ifdef PC98 if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { i386_bus_space_handle_free(rv->r_bustag, rv->r_bushandle, rv->r_bushandle->bsh_sz); } #endif rman_release_resource(rv); return 0; } } return rv; }
static struct resource * pxa_smi_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct pxa_smi_softc *sc; struct smi_ivars *smid; struct resource *rv; struct resource_list *rl; struct resource_list_entry *rle; int needactivate; sc = (struct pxa_smi_softc *)device_get_softc(dev); smid = (struct smi_ivars *)device_get_ivars(child); rl = &smid->smid_resources; if (type == SYS_RES_IOPORT) type = SYS_RES_MEMORY; rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("pxa_smi_alloc_resource: resource is busy"); needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; switch (type) { case SYS_RES_MEMORY: rv = rman_reserve_resource(&sc->ps_mem, rle->start, rle->end, rle->count, flags, child); if (rv == NULL) return (NULL); rle->res = rv; rman_set_rid(rv, *rid); rman_set_bustag(rv, sc->ps_bst); rman_set_bushandle(rv, rle->start); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv) != 0) { rman_release_resource(rv); return (NULL); } } break; case SYS_RES_IRQ: rv = bus_alloc_resource(dev, type, rid, rle->start, rle->end, rle->count, flags); if (rv == NULL) return (NULL); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv) != 0) { bus_release_resource(dev, type, *rid, rv); return (NULL); } } break; default: return (NULL); } 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 *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); }
struct resource * pci_vf_alloc_mem_resource(device_t dev, device_t child, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct pci_devinfo *dinfo; struct pcicfg_iov *iov; struct pci_map *map; struct resource *res; struct resource_list_entry *rle; rman_res_t bar_start, bar_end; pci_addr_t bar_length; int error; dinfo = device_get_ivars(child); iov = dinfo->cfg.iov; map = pci_find_bar(child, *rid); if (map == NULL) return (NULL); bar_length = 1 << map->pm_size; bar_start = map->pm_value; bar_end = bar_start + bar_length - 1; /* Make sure that the resource fits the constraints. */ if (bar_start >= end || bar_end <= bar_start || count != 1) return (NULL); /* Clamp the resource to the constraints if necessary. */ if (bar_start < start) bar_start = start; if (bar_end > end) bar_end = end; bar_length = bar_end - bar_start + 1; res = rman_reserve_resource(&iov->rman, bar_start, bar_end, bar_length, flags, child); if (res == NULL) return (NULL); rle = resource_list_add(&dinfo->resources, SYS_RES_MEMORY, *rid, bar_start, bar_end, 1); if (rle == NULL) { rman_release_resource(res); return (NULL); } rman_set_rid(res, *rid); if (flags & RF_ACTIVE) { error = bus_activate_resource(child, SYS_RES_MEMORY, *rid, res); if (error != 0) { resource_list_delete(&dinfo->resources, SYS_RES_MEMORY, *rid); rman_release_resource(res); return (NULL); } } rle->res = res; return (res); }
static int nexus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { return (rman_release_resource(res)); }
/* * Allocate a resource on behalf of child. NB: child is usually going to be a * child of one of our descendants, not a direct child of nexus0. * (Exceptions include npx.) */ 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, int cpuid) { struct nexus_device *ndev = DEVTONX(child); struct resource *rv; struct resource_list_entry *rle; struct rman *rm; int needactivate = flags & RF_ACTIVE; /* * If this is an allocation of the "default" range for a given RID, and * we know what the resources for this device are (ie. they aren't maintained * by a child bus), then work out the start/end values. */ if ((start == 0UL) && (end == ~0UL) && (count == 1)) { if (ndev == NULL) return(NULL); rle = resource_list_find(&ndev->nx_resources, type, *rid); if (rle == NULL) return(NULL); start = rle->start; end = rle->end; count = rle->count; cpuid = rle->cpuid; } flags &= ~RF_ACTIVE; switch (type) { case SYS_RES_IRQ: KASSERT(cpuid >= 0 && cpuid < ncpus, ("nexus invalid cpuid %d:\n", cpuid)); rm = &irq_rman[cpuid]; break; case SYS_RES_DRQ: rm = &drq_rman; break; case SYS_RES_IOPORT: rm = &port_rman; break; case SYS_RES_MEMORY: rm = &mem_rman; break; default: return 0; } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == 0) return 0; rman_set_rid(rv, *rid); if (type == SYS_RES_MEMORY) { rman_set_bustag(rv, I386_BUS_SPACE_MEM); } else if (type == SYS_RES_IOPORT) { rman_set_bustag(rv, I386_BUS_SPACE_IO); rman_set_bushandle(rv, rv->r_start); } if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { rman_release_resource(rv); return 0; } } return rv; }
struct resource * thunder_pcie_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 thunder_pcie_softc *sc = device_get_softc(dev); struct rman *rm = NULL; struct resource *res; pci_addr_t map, testval; switch (type) { case SYS_RES_IOPORT: goto fail; break; case SYS_RES_MEMORY: rm = &sc->mem_rman; break; default: return (bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); }; if ((start == 0UL) && (end == ~0UL)) { /* Read BAR manually to get resource address and size */ pci_read_bar(child, *rid, &map, &testval, NULL); /* Mask the information bits */ if (PCI_BAR_MEM(map)) map &= PCIM_BAR_MEM_BASE; else map &= PCIM_BAR_IO_BASE; if (PCI_BAR_MEM(testval)) testval &= PCIM_BAR_MEM_BASE; else testval &= PCIM_BAR_IO_BASE; start = map; count = (~testval) + 1; /* * Internal ThunderX devices supports up to 3 64-bit BARs. * If we're allocating anything above, that means upper layer * wants us to allocate VF-BAR. In that case reserve bigger * slice to make a room for other VFs adjacent to this one. */ if (*rid > PCIR_BAR(5)) count = count * thunder_pcie_max_vfs; end = start + count - 1; } /* Convert input BUS address to required PHYS */ if (range_addr_is_pci(sc->ranges, start, count) == 0) goto fail; start = range_addr_pci_to_phys(sc->ranges, start); end = start + count - 1; if (bootverbose) { device_printf(dev, "rman_reserve_resource: start=%#lx, end=%#lx, count=%#lx\n", start, end, count); } res = rman_reserve_resource(rm, start, end, count, flags, child); if (res == NULL) goto fail; rman_set_rid(res, *rid); if ((flags & RF_ACTIVE) != 0) if (bus_activate_resource(child, type, *rid, res)) { rman_release_resource(res); goto fail; } return (res); fail: if (bootverbose) { device_printf(dev, "%s FAIL: type=%d, rid=%d, " "start=%016lx, end=%016lx, count=%016lx, flags=%x\n", __func__, type, *rid, start, end, count, flags); } return (NULL); }
static struct resource * sbus_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 sbus_softc *sc; struct sbus_devinfo *sdi; struct rman *rm; struct resource *rv; struct resource_list *rl; struct resource_list_entry *rle; bus_space_handle_t bh; bus_addr_t toffs; bus_size_t tend; int i; int isdefault = (start == 0UL && end == ~0UL); int needactivate = flags & RF_ACTIVE; sc = (struct sbus_softc *)device_get_softc(bus); sdi = device_get_ivars(child); rl = &sdi->sdi_rl; rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("sbus_alloc_resource: resource entry is busy"); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } switch (type) { case SYS_RES_IRQ: rv = bus_alloc_resource(bus, type, rid, start, end, count, flags); if (rv == NULL) return (NULL); break; case SYS_RES_MEMORY: rm = NULL; bh = toffs = tend = 0; for (i = 0; i < sc->sc_nrange; i++) { if (sc->sc_rd[i].rd_slot != sdi->sdi_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; bh = sc->sc_rd[i].rd_bushandle; } if (toffs == NULL) return (NULL); flags &= ~RF_ACTIVE; rv = rman_reserve_resource(rm, toffs, tend, count, flags, child); if (rv == NULL) return (NULL); rman_set_bustag(rv, sc->sc_cbustag); rman_set_bushandle(rv, bh + rman_get_start(rv)); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { rman_release_resource(rv); return (NULL); } } break; default: return (NULL); } rle->res = rv; return (rv); }
static struct resource * lbc_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 lbc_softc *sc; struct lbc_devinfo *di; struct resource_list_entry *rle; struct resource *res; struct rman *rm; int needactivate; /* We only support default allocations. */ if (start != 0ul || end != ~0ul) return (NULL); sc = device_get_softc(bus); if (type == SYS_RES_IRQ) return (bus_alloc_resource(bus, type, rid, start, end, count, flags)); /* * Request for the default allocation with a given rid: use resource * list stored in the local device info. */ if ((di = device_get_ivars(child)) == NULL) return (NULL); if (type == SYS_RES_IOPORT) type = SYS_RES_MEMORY; rid = &di->di_bank; rle = resource_list_find(&di->di_res, type, *rid); if (rle == NULL) { device_printf(bus, "no default resources for " "rid = %d, type = %d\n", *rid, type); return (NULL); } start = rle->start; count = rle->count; end = start + count - 1; sc = device_get_softc(bus); needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; rm = &sc->sc_rman; res = rman_reserve_resource(rm, start, end, count, flags, child); if (res == NULL) { device_printf(bus, "failed to reserve resource %#lx - %#lx " "(%#lx)\n", start, end, count); return (NULL); } rman_set_rid(res, *rid); rman_set_bustag(res, &bs_be_tag); rman_set_bushandle(res, rman_get_start(res)); if (needactivate) if (bus_activate_resource(child, type, *rid, res)) { device_printf(child, "resource activation failed\n"); rman_release_resource(res); return (NULL); } return (res); }
/* * Allocate a resource on behalf of child. NB: child is usually going to be a * child of one of our descendants, not a direct child of nexus0. * (Exceptions include footbridge.) */ 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_device *ndev = DEVTONX(child); struct resource *rv; struct resource_list_entry *rle; struct rman *rm; int isdefault, needactivate, passthrough; dprintf("%s: entry (%p, %p, %d, %p, %p, %p, %ld, %d)\n", __func__, bus, child, type, rid, (void *)(intptr_t)start, (void *)(intptr_t)end, count, flags); dprintf("%s: requested rid is %d\n", __func__, *rid); isdefault = (start == 0UL && end == ~0UL && count == 1); needactivate = flags & RF_ACTIVE; passthrough = (device_get_parent(child) != bus); rle = NULL; /* * If this is an allocation of the "default" range for a given RID, * and we know what the resources for this device are (ie. they aren't * maintained by a child bus), then work out the start/end values. */ if (isdefault) { rle = resource_list_find(&ndev->nx_resources, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) { panic("%s: resource entry is busy", __func__); } start = rle->start; end = rle->end; count = rle->count; } switch (type) { case SYS_RES_IRQ: rm = &irq_rman; break; case SYS_RES_MEMORY: rm = &mem_rman; break; default: printf("%s: unknown resource type %d\n", __func__, type); return (0); } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == 0) { printf("%s: could not reserve resource for %s\n", __func__, device_get_nameunit(child)); return (0); } rman_set_rid(rv, *rid); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { printf("%s: could not activate resource\n", __func__); rman_release_resource(rv); return (0); } } return (rv); }
int puc_bfe_attach(device_t dev) { char buffer[64]; struct puc_bar *bar; struct puc_port *port; struct puc_softc *sc; struct rman *rm; intptr_t res; bus_addr_t ofs, start; bus_size_t size; bus_space_handle_t bsh; bus_space_tag_t bst; int error, idx; sc = device_get_softc(dev); for (idx = 0; idx < PUC_PCI_BARS; idx++) sc->sc_bar[idx].b_rid = -1; do { sc->sc_ioport.rm_type = RMAN_ARRAY; error = rman_init(&sc->sc_ioport); if (!error) { sc->sc_iomem.rm_type = RMAN_ARRAY; error = rman_init(&sc->sc_iomem); if (!error) { sc->sc_irq.rm_type = RMAN_ARRAY; error = rman_init(&sc->sc_irq); if (!error) break; rman_fini(&sc->sc_iomem); } rman_fini(&sc->sc_ioport); } return (error); } while (0); snprintf(buffer, sizeof(buffer), "%s I/O port mapping", device_get_nameunit(dev)); sc->sc_ioport.rm_descr = strdup(buffer, M_PUC); snprintf(buffer, sizeof(buffer), "%s I/O memory mapping", device_get_nameunit(dev)); sc->sc_iomem.rm_descr = strdup(buffer, M_PUC); snprintf(buffer, sizeof(buffer), "%s port numbers", device_get_nameunit(dev)); sc->sc_irq.rm_descr = strdup(buffer, M_PUC); error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); KASSERT(error == 0, ("%s %d", __func__, __LINE__)); sc->sc_nports = (int)res; sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port), M_PUC, M_WAITOK|M_ZERO); error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports); if (error) goto fail; error = puc_config(sc, PUC_CFG_SETUP, 0, &res); if (error) goto fail; for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; port->p_nr = idx + 1; error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res); if (error) goto fail; port->p_type = res; error = puc_config(sc, PUC_CFG_GET_RID, idx, &res); if (error) goto fail; bar = puc_get_bar(sc, res); if (bar == NULL) { error = ENXIO; goto fail; } port->p_bar = bar; start = rman_get_start(bar->b_res); error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res); if (error) goto fail; ofs = res; error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res); if (error) goto fail; size = res; rm = (bar->b_type == SYS_RES_IOPORT) ? &sc->sc_ioport: &sc->sc_iomem; port->p_rres = rman_reserve_resource(rm, start + ofs, start + ofs + size - 1, size, 0, NULL); if (port->p_rres != NULL) { bsh = rman_get_bushandle(bar->b_res); bst = rman_get_bustag(bar->b_res); bus_space_subregion(bst, bsh, ofs, size, &bsh); rman_set_bushandle(port->p_rres, bsh); rman_set_bustag(port->p_rres, bst); } port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr, port->p_nr, 1, 0, NULL); if (port->p_ires == NULL) { error = ENXIO; goto fail; } error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res); if (error) goto fail; port->p_rclk = res; port->p_dev = device_add_child(dev, NULL, -1); if (port->p_dev != NULL) device_set_ivars(port->p_dev, (void *)port); } error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res); if (error) goto fail; sc->sc_ilr = res; if (bootverbose && sc->sc_ilr != 0) device_printf(dev, "using interrupt latch register\n"); sc->sc_irid = 0; sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE|RF_SHAREABLE); if (sc->sc_ires != NULL) { error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie); if (error) error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE, NULL, (driver_intr_t *)puc_intr, sc, &sc->sc_icookie); else sc->sc_fastintr = 1; if (error) { device_printf(dev, "could not activate interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); sc->sc_ires = NULL; } } if (sc->sc_ires == NULL) { /* XXX no interrupt resource. Force polled mode. */ sc->sc_polled = 1; } /* Probe and attach our children. */ for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; if (port->p_dev == NULL) continue; error = device_probe_and_attach(port->p_dev); if (error) { device_delete_child(dev, port->p_dev); port->p_dev = NULL; } } /* * If there are no serdev devices, then our interrupt handler * will do nothing. Tear it down. */ if (sc->sc_serdevs == 0UL) bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); return (0); fail: for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; if (port->p_dev != NULL) device_delete_child(dev, port->p_dev); if (port->p_rres != NULL) rman_release_resource(port->p_rres); if (port->p_ires != NULL) rman_release_resource(port->p_ires); } for (idx = 0; idx < PUC_PCI_BARS; idx++) { bar = &sc->sc_bar[idx]; if (bar->b_res != NULL) bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid, bar->b_res); } rman_fini(&sc->sc_irq); free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); rman_fini(&sc->sc_iomem); free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); rman_fini(&sc->sc_ioport); free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); free(sc->sc_port, M_PUC); return (error); }
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); }