FreeBSD/sys/kern/subr_bus.c
/**
 * @brief Helper function for implementing BUS_ALLOC_RESOURCE()
 *
 * Implement BUS_ALLOC_RESOURCE() by looking up a resource from the list
 * and passing the allocation up to the parent of @p bus. This assumes
 * that the first entry of @c device_get_ivars(child) is a struct
 * resource_list. This also handles 'passthrough' allocations where a
 * child is a remote descendant of bus by passing the allocation up to
 * the parent of bus.
 *
 * Typically, a bus driver would store a list of child resources
 * somewhere in the child device's ivars (see device_get_ivars()) and
 * its implementation of BUS_ALLOC_RESOURCE() would find that list and
 * then call resource_list_alloc() to perform the allocation.
 *
 * @param rl		the resource list to allocate from
 * @param bus		the parent device of @p child
 * @param child		the device which is requesting an allocation
 * @param type		the type of resource to allocate
 * @param rid		a pointer to the resource identifier
 * @param start		hint at the start of the resource range - pass
 *			@c 0 for any start address
 * @param end		hint at the end of the resource range - pass
 *			@c ~0 for any end address
 * @param count		hint at the size of range required - pass @c 1
 *			for any size
 * @param flags		any extra flags to control the resource
 *			allocation - see @c RF_XXX flags in
 *			<sys/rman.h> for details
 *
 * @returns		the resource which was allocated or @c NULL if no
 *			resource could be allocated
 */
@brief Helper function for implementing BUS_ALLOC_RESOURCE()
Implement BUS_ALLOC_RESOURCE() by looking up a resource from the list
and passing the allocation up to the parent of @p bus. This assumes
that the first entry of @c device_get_ivars(child) is a struct
resource_list. This also handles 'passthrough' allocations where a
child is a remote descendant of bus by passing the allocation up to
the parent of bus.

Typically, a bus driver would store a list of child resources
somewhere in the child device's ivars ) and
its implementation of BUS_ALLOC_RESOURCE() would find that list and
then call resource_list_alloc() to perform the allocation.



@returns             the resource which was allocated or @c NULL if no
resource could be allocated
@brief Helper function for implementing BUS_ALLOC_RESOURCE () Implement BUS_ALLOC_RESOURCE () by looking up a resource from the list and passing the allocation up to the parent of @p bus . This assumes that the first entry of @c device_get_ivars ( child ) is a struct resource_list . This also handles ' passthrough ' allocations where a child is a remote descendant of bus by passing the allocation up to the parent of bus . Typically a bus driver would store a list of child resources somewhere in the child device ' s ivars ) and its implementation of BUS_ALLOC_RESOURCE () would find that list and then call resource_list_alloc () to perform the allocation . @returns the resource which was allocated or @c NULL if no resource could be allocated
struct resource *
resource_list_alloc(struct resource_list *rl, 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 resource_list_entry *rle = NULL;
	int passthrough = (device_get_parent(child) != bus);
	int isdefault = RMAN_IS_DEFAULT_RANGE(start, end);
	if (passthrough) {
		return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
		    type, rid, start, end, count, flags));
	}
	rle = resource_list_find(rl, type, *rid);
	if (!rle)
		return (NULL);		
	if (rle->res) {
		if (rle->flags & RLE_RESERVED) {
			if (rle->flags & RLE_ALLOCATED)
				return (NULL);
			if ((flags & RF_ACTIVE) &&
			    bus_activate_resource(child, type, *rid,
			    rle->res) != 0)
				return (NULL);
			rle->flags |= RLE_ALLOCATED;
			return (rle->res);
		}
		device_printf(bus,
		    "resource entry %#x type %d for child %s is busy\n", *rid,
		    type, device_get_nameunit(child));
		return (NULL);
	}
	if (isdefault) {
		start = rle->start;
		count = ulmax(count, rle->count);
		end = ulmax(rle->end, start + count - 1);
	}
	rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
	    type, rid, start, end, count, flags);
	if (rle->res) {
		rle->start = rman_get_start(rle->res);
		rle->end = rman_get_end(rle->res);
		rle->count = count;
	}
	return (rle->res);
}
struct resource * resource_list_alloc ( struct resource_list * rl , 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 resource_list_entry * rle = NULL ; int passthrough = ( device_get_parent ( child ) != bus ) ; int isdefault = RMAN_IS_DEFAULT_RANGE ( start , end ) ; if ( passthrough ) { return ( BUS_ALLOC_RESOURCE ( device_get_parent ( bus ) , child , type , rid , start , end , count , flags ) ) ; } rle = resource_list_find ( rl , type , * rid ) ; if ( ! rle ) return ( NULL ) ; if ( rle -> res ) { if ( rle -> flags & RLE_RESERVED ) { if ( rle -> flags & RLE_ALLOCATED ) return ( NULL ) ; if ( ( flags & RF_ACTIVE ) && bus_activate_resource ( child , type , * rid , rle -> res ) != 0 ) return ( NULL ) ; rle -> flags |= RLE_ALLOCATED ; return ( rle -> res ) ; } device_printf ( bus , " \n " , * rid , type , device_get_nameunit ( child ) ) ; return ( NULL ) ; } if ( isdefault ) { start = rle -> start ; count = ulmax ( count , rle -> count ) ; end = ulmax ( rle -> end , start + count - 1 ) ; } rle -> res = BUS_ALLOC_RESOURCE ( device_get_parent ( bus ) , child , type , rid , start , end , count , flags ) ; if ( rle -> res ) { rle -> start = rman_get_start ( rle -> res ) ; rle -> end = rman_get_end ( rle -> res ) ; rle -> count = count ; } return ( rle -> res ) ; }
@brief Helper function for implementing BUS_ALLOC_RESOURCE()
 Implement BUS_ALLOC_RESOURCE() by looking up a resource from the list
 and passing the allocation up to the parent of @p bus.
@brief Helper function for implementing BUS_ALLOC_RESOURCE () Implement BUS_ALLOC_RESOURCE () by looking up a resource from the list and passing the allocation up to the parent of @p bus .
/* no resource of that type/rid */ /*
	 * Record the new range.
	 */