示例#1
0
struct resource *
quicc_bus_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 quicc_device *qd;
	struct resource_list_entry *rle;

	if (device_get_parent(child) != dev)
		return (NULL);

	/* We only support default allocations. */
	if (!RMAN_IS_DEFAULT_RANGE(start, end))
		return (NULL);

	qd = device_get_ivars(child);
	rle = resource_list_find(&qd->qd_rlist, type, *rid);
	if (rle == NULL)
		return (NULL);

	if (rle->res == NULL) {
		rle->res = rman_reserve_resource(qd->qd_rman, rle->start,
		    rle->start + rle->count - 1, rle->count, flags, child);
		if (rle->res != NULL) {
			rman_set_bustag(rle->res, &bs_be_tag);
			rman_set_bushandle(rle->res, rle->start);
		}
	}
	return (rle->res);
}
示例#2
0
static struct resource *
localbus_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 localbus_devinfo *di;
	struct resource_list_entry *rle;

	/*
	 * Request for the default allocation with a given rid: use resource
	 * list stored in the local device info.
	 */
	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
		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;
		end = rle->end;
		count = rle->count;
	}

	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
示例#3
0
static struct resource *
gic_v3_acpi_bus_alloc_res(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 gic_v3_acpi_devinfo *di;
	struct resource_list_entry *rle;

	/* We only allocate memory */
	if (type != SYS_RES_MEMORY)
		return (NULL);

	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);

		/* Find defaults for this rid */
		rle = resource_list_find(&di->di_rl, type, *rid);
		if (rle == NULL)
			return (NULL);

		start = rle->start;
		end = rle->end;
		count = rle->count;
	}

	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
示例#4
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);
}
示例#5
0
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;

	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);
}
示例#6
0
static struct resource *
simplebus_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 simplebus_softc *sc;
	struct simplebus_devinfo *di;
	struct resource_list_entry *rle;
	int j;

	sc = device_get_softc(bus);

	/*
	 * Request for the default allocation with a given rid: use resource
	 * list stored in the local device info.
	 */
	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);

		if (type == SYS_RES_IOPORT)
			type = SYS_RES_MEMORY;

		rle = resource_list_find(&di->rl, 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;
		end = rle->end;
		count = rle->count;
        }

	if (type == SYS_RES_MEMORY) {
		/* Remap through ranges property */
		for (j = 0; j < sc->nranges; j++) {
			if (start >= sc->ranges[j].bus && end <
			    sc->ranges[j].bus + sc->ranges[j].size) {
				start -= sc->ranges[j].bus;
				start += sc->ranges[j].host;
				end -= sc->ranges[j].bus;
				end += sc->ranges[j].host;
				break;
			}
		}
		if (j == sc->nranges && sc->nranges != 0) {
			if (bootverbose)
				device_printf(bus, "Could not map resource "
				    "%#jx-%#jx\n", start, end);

			return (NULL);
		}
	}

	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
示例#7
0
/*
 * 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,
    rman_res_t start, rman_res_t end, rman_res_t 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 (RMAN_IS_DEFAULT_RANGE(start, end) && (count == 1)) {
		if (device_get_parent(child) != bus || 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;
	}

	switch (type) {
	case SYS_RES_IRQ:
		rm = &irq_rman;
		break;

	case SYS_RES_MEMORY:
	case SYS_RES_IOPORT:
		rm = &mem_rman;
		break;

	default:
		return (NULL);
	}

	rv = rman_reserve_resource(rm, start, end, count, flags, child);
	if (rv == NULL)
		return (NULL);

	rman_set_rid(rv, *rid);
	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);
}
示例#8
0
static struct resource *
mv_pcib_ctrl_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 mv_pcib_ctrl_devinfo *di;
	struct resource_list_entry *rle;
	struct mv_pcib_ctrl_softc *sc;
	int i;

	if (RMAN_IS_DEFAULT_RANGE(start, end)) {

		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);
		if (type != SYS_RES_MEMORY)
			return (NULL);

		/* Find defaults for this rid */
		rle = resource_list_find(&di->di_rl, type, *rid);

		if (rle == NULL)
			return (NULL);

		start = rle->start;
		end = rle->end;
		count = rle->count;
	}

	sc = device_get_softc(bus);
	if (type == SYS_RES_MEMORY) {
		/* Remap through ranges property */
		for (i = 0; i < sc->nranges; i++) {
			if (start >= sc->ranges[i].bus && end <
			    sc->ranges[i].bus + sc->ranges[i].size) {
				start -= sc->ranges[i].bus;
				start += sc->ranges[i].host;
				end -= sc->ranges[i].bus;
				end += sc->ranges[i].host;
				break;
			}
		}

		if (i == sc->nranges && sc->nranges != 0) {
			device_printf(bus, "Could not map resource "
			    "%#llx-%#llx\n", start, end);
			return (NULL);
		}
	}

	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
示例#9
0
文件: at91.c 项目: 2asoft/freebsd
static struct resource *
at91_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 at91_softc *sc = device_get_softc(dev);
	struct resource_list_entry *rle;
	struct at91_ivar *ivar = device_get_ivars(child);
	struct resource_list *rl = &ivar->resources;
	bus_space_handle_t bsh;

	if (device_get_parent(child) != dev)
		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
		    type, rid, start, end, count, flags));
	
	rle = resource_list_find(rl, type, *rid);
	if (rle == NULL)
		return (NULL);
	if (rle->res)
		panic("Resource rid %d type %d already in use", *rid, type);
	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
		start = rle->start;
		count = ulmax(count, rle->count);
		end = ulmax(rle->end, start + count - 1);
	}
	switch (type)
	{
	case SYS_RES_IRQ:
		rle->res = rman_reserve_resource(&sc->sc_irq_rman,
		    start, end, count, flags, child);
		break;
	case SYS_RES_MEMORY:
		rle->res = rman_reserve_resource(&sc->sc_mem_rman,
		    start, end, count, flags, child);
		if (rle->res != NULL) {
			bus_space_map(arm_base_bs_tag, start,
			    rman_get_size(rle->res), 0, &bsh);
			rman_set_bustag(rle->res, arm_base_bs_tag);
			rman_set_bushandle(rle->res, bsh);
		}
		break;
	}
	if (rle->res) {
		rle->start = rman_get_start(rle->res);
		rle->end = rman_get_end(rle->res);
		rle->count = count;
		rman_set_rid(rle->res, *rid);
	}
	return (rle->res);
}
示例#10
0
static struct resource *
gpiobus_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 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 = (RMAN_IS_DEFAULT_RANGE(start, end) && 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);
}
示例#11
0
static struct resource *
gic_v3_ofw_bus_alloc_res(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 gic_v3_ofw_devinfo *di;
	struct resource_list_entry *rle;
	int ranges_len;

	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);
		if (type != SYS_RES_MEMORY)
			return (NULL);

		/* Find defaults for this rid */
		rle = resource_list_find(&di->di_rl, type, *rid);
		if (rle == NULL)
			return (NULL);

		start = rle->start;
		end = rle->end;
		count = rle->count;
	}
	/*
	 * XXX: No ranges remap!
	 *	Absolute address is expected.
	 */
	if (ofw_bus_has_prop(bus, "ranges")) {
		ranges_len = OF_getproplen(ofw_bus_get_node(bus), "ranges");
		if (ranges_len != 0) {
			if (bootverbose) {
				device_printf(child,
				    "Ranges remap not supported\n");
			}
			return (NULL);
		}
	}
	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
示例#12
0
/**
 * 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);
}
示例#13
0
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);
}
示例#14
0
文件: chipc.c 项目: wulf7/freebsd
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);
}
示例#15
0
static struct resource *
lbc_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 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 (!RMAN_IS_DEFAULT_RANGE(start, end))
		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 %#jx - %#jx "
		    "(%#jx)\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);
}
示例#16
0
static struct resource *
ebus_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 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 = RMAN_IS_DEFAULT_RANGE(start, end);
	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.
			 */
			type = 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);
}
示例#17
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);
    }
}
示例#18
0
/*
 * 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,
	rman_res_t start, rman_res_t end, rman_res_t 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, %jd, %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 = (RMAN_IS_DEFAULT_RANGE(start, end) && 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 == NULL) {
		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);
}