示例#1
0
文件: isa.c 项目: AhmadTux/freebsd
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)
{
	struct isa_device* idev = DEVTOISA(child);
	struct resource_list *rl = &idev->id_resources;
	int isdefault, passthrough, rids;

	isdefault = (start == 0UL && end == ~0UL) ? 1 : 0;
	passthrough = (device_get_parent(child) != bus) ? 1 : 0;

	if (!passthrough && !isdefault &&
	    resource_list_find(rl, type, *rid) == NULL) {
		switch (type) {
		case SYS_RES_IOPORT:	rids = ISA_PNP_NPORT; break;
		case SYS_RES_IRQ:	rids = ISA_PNP_NIRQ; break;
		case SYS_RES_MEMORY:	rids = ISA_PNP_NMEM; break;
		default:		rids = 0; break;
		}
		if (*rid < 0 || *rid >= rids)
			return (NULL);

		resource_list_add(rl, type, *rid, start, end, count);
	}

	return (resource_list_alloc(rl, bus, child, type, rid, start, end,
	    count, flags));
}
示例#2
0
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);
}
示例#3
0
文件: wii_bus.c 项目: coyizumi/cs111
static struct resource *
wiibus_alloc_resource(device_t bus, device_t child, int type,
    int *rid, unsigned long start, unsigned long end,
    unsigned long count, unsigned int flags)
{
	struct wiibus_softc *sc;
	struct wiibus_devinfo *dinfo;
	struct resource_list_entry *rle;
	struct resource *rv;
	int needactivate;

	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->di_resources, SYS_RES_MEMORY,
		    *rid);
		if (rle == NULL) {
			device_printf(bus, "no res entry for %s memory 0x%x\n",
			    device_get_nameunit(child), *rid);
			return (NULL);
		}
		rv = rman_reserve_resource(&sc->sc_rman, rle->start, rle->end,
		    rle->count, flags, child);
		if (rv == NULL) {
			device_printf(bus,
			    "failed to reserve resource for %s\n",
			    device_get_nameunit(child));
			return (NULL);
		}
		rman_set_rid(rv, *rid);
		break;
	case SYS_RES_IRQ:
		return (resource_list_alloc(&dinfo->di_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);
	}

	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));
			return (NULL);
		}
	}
	
	return (rv);
}
示例#4
0
static struct resource *
macgpio_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 macgpio_devinfo *dinfo;

	dinfo = device_get_ivars(child);

	if (type != SYS_RES_IRQ)
		return (NULL);

	return (resource_list_alloc(&dinfo->mdi_resources, bus, child, type, 
	    rid, start, end, count, flags));
}
示例#5
0
/*
 * This implementation simply passes the request up to the parent
 * bus, which in our case is the special i386 nexus, substituting any
 * configured values if the caller defaulted.  We can get away with
 * this because there is no special mapping for ISA resources on an Intel
 * platform.  When porting this code to another architecture, it may be
 * necessary to interpose a mapping layer here.
 */
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, int cpuid)
{
	/*
	 * Consider adding a resource definition. We allow rid 0-1 for
	 * irq and drq, 0-3 for memory and 0-7 for ports which is
	 * sufficient for isapnp.
	 */
	int passthrough = (device_get_parent(child) != bus);
	int isdefault = (start == 0UL && end == ~0UL);
	struct isa_device* idev = DEVTOISA(child);
	struct resource_list *rl = &idev->id_resources;
	struct resource_list_entry *rle;
	
	if (!passthrough && !isdefault) {
		rle = resource_list_find(rl, type, *rid);
		if (!rle) {
			if (*rid < 0)
				return 0;
			switch (type) {
			case SYS_RES_IRQ:
				if (*rid >= ISA_NIRQ)
					return 0;
				cpuid = machintr_legacy_intr_cpuid(start);
				break;
			case SYS_RES_DRQ:
				if (*rid >= ISA_NDRQ)
					return 0;
				break;
			case SYS_RES_MEMORY:
				if (*rid >= ISA_NMEM)
					return 0;
				break;
			case SYS_RES_IOPORT:
				if (*rid >= ISA_NPORT)
					return 0;
				break;
			default:
				return 0;
			}
			resource_list_add(rl, type, *rid, start, end,
			    count, cpuid);
		}
	}

	return resource_list_alloc(rl, bus, child, type, rid,
				   start, end, count, flags, cpuid);
}
示例#6
0
static struct resource *
pccard_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. We allow rid 0 for
	 * irq, 0-3 for memory and 0-1 for ports
	 */
	int passthrough = (device_get_parent(child) != bus);
	int isdefault = (start == 0UL && end == ~0UL);
	struct pccard_devinfo *devi = device_get_ivars(child);
	struct resource_list *rl = &devi->resources;
	struct resource_list_entry *rle;
	struct resource *res;

	if (!passthrough && !isdefault) {
		rle = resource_list_find(rl, type, *rid);
		if (!rle) {
			if (*rid < 0)
				return 0;
			switch (type) {
			case SYS_RES_IRQ:
				if (*rid >= PCCARD_NIRQ)
					return 0;
				break;
			case SYS_RES_DRQ:
				if (*rid >= PCCARD_NDRQ)
					return 0;
				break;
			case SYS_RES_MEMORY:
				if (*rid >= PCCARD_NMEM)
					return 0;
				break;
			case SYS_RES_IOPORT:
				if (*rid >= PCCARD_NPORT)
					return 0;
				break;
			default:
				return 0;
			}
			resource_list_add(rl, type, *rid, start, end, count);
		}
	}

	res = resource_list_alloc(rl, bus, child, type, rid, start, end, 
	    count, flags);
	return res;
}
示例#7
0
文件: isa.c 项目: ele7enxxh/dtrace-pf
/*
 * This implementation simply passes the request up to the parent
 * bus, which in our case is the special i386 nexus, substituting any
 * configured values if the caller defaulted.  We can get away with
 * this because there is no special mapping for ISA resources on an Intel
 * platform.  When porting this code to another architecture, it may be
 * necessary to interpose a mapping layer here.
 */
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 isa_device* idev = DEVTOISA(child);
	struct resource_list *rl = &idev->id_resources;
	struct resource_list_entry *rle;
	
	if (!passthrough && !isdefault) {
		rle = resource_list_find(rl, type, *rid);
		if (!rle) {
			if (*rid < 0)
				return 0;
			switch (type) {
			case SYS_RES_IRQ:
				if (*rid >= ISA_NIRQ)
					return 0;
				break;
			case SYS_RES_DRQ:
				if (*rid >= ISA_NDRQ)
					return 0;
				break;
			case SYS_RES_MEMORY:
				if (*rid >= ISA_NMEM)
					return 0;
				break;
			case SYS_RES_IOPORT:
				if (*rid >= ISA_NPORT)
					return 0;
				break;
			default:
				return 0;
			}
			resource_list_add(rl, type, *rid, start, end, count);
		}
	}

	return resource_list_alloc(rl, bus, child, type, rid,
				   start, end, count, flags);
}
示例#8
0
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));
}
示例#9
0
文件: uninorth.c 项目: coyizumi/cs111
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);
}
示例#10
0
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);
}
示例#11
0
文件: ebus.c 项目: AhmadTux/freebsd
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);
}
示例#12
0
/*
 * This implementation simply passes the request up to the parent
 * bus, which in our case is the pci chipset device, substituting any
 * configured values if the caller defaulted.  We can get away with
 * this because there is no special mapping for ISA resources on this
 * platform.  When porting this code to another architecture, it may be
 * necessary to interpose a mapping layer here.
 *
 * We manage our own interrupt resources since ISA interrupts go through
 * the ISA PIC, not the PCI interrupt controller.
 */
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. We allow rid 0-1 for
	 * irq and drq, 0-3 for memory and 0-7 for ports which is
	 * sufficient for isapnp.
	 */
	int passthrough = (device_get_parent(child) != bus);
	int isdefault = (start == 0UL && end == ~0UL);
	struct isa_device* idev = DEVTOISA(child);
	struct resource_list *rl = &idev->id_resources;
	struct resource_list_entry *rle;
	struct resource *res;
	
	if (!passthrough && !isdefault) {
		rle = resource_list_find(rl, type, *rid);
		if (!rle) {
			if (*rid < 0)
				return 0;
			switch (type) {
			case SYS_RES_IRQ:
				if (*rid >= ISA_NIRQ)
					return 0;
				break;
			case SYS_RES_DRQ:
				if (*rid >= ISA_NDRQ)
					return 0;
				break;
			case SYS_RES_MEMORY:
				if (*rid >= ISA_NMEM)
					return 0;
				break;
			case SYS_RES_IOPORT:
				if (*rid >= ISA_NPORT)
					return 0;
				break;
			default:
				return 0;
			}
			resource_list_add(rl, type, *rid, start, end, count);
		}
	}

	if (type != SYS_RES_IRQ && type != SYS_RES_DRQ)
		return resource_list_alloc(rl, bus, child, type, rid,
					   start, end, count, flags);

	if (!passthrough) {
		rl = device_get_ivars(child);
		rle = resource_list_find(rl, type, *rid);
		if (!rle)
			return 0;
		if (rle->res)
			panic("isa_alloc_resource: resource entry is busy");
		if (isdefault) {
			start = end = rle->start;
			count = 1;
		}
	}

	if (type == SYS_RES_IRQ)
	    res = rman_reserve_resource(&isa_irq_rman, start, start, 1,
					0, child);
	else
	    res = rman_reserve_resource(&isa_drq_rman, start, start, 1,
					0, child);
	    
	if (res && !passthrough) {
		rle = resource_list_find(rl, type, *rid);
		rle->start = rman_get_start(res);
		rle->end = rman_get_end(res);
		rle->count = 1;
		rle->res = res;
	}

	return res;
}
示例#13
0
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);
    }
}