* @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
| 3406 | * resource could be allocated |
| 3407 | */ |
| 3408 | struct resource * |
| 3409 | resource_list_alloc(struct resource_list *rl, device_t bus, device_t child, |
| 3410 | int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) |
| 3411 | { |
| 3412 | struct resource_list_entry *rle = NULL; |
| 3413 | int passthrough = (device_get_parent(child) != bus); |
| 3414 | int isdefault = RMAN_IS_DEFAULT_RANGE(start, end); |
| 3415 | |
| 3416 | if (passthrough) { |
| 3417 | return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, |
| 3418 | type, rid, start, end, count, flags)); |
| 3419 | } |
| 3420 | |
| 3421 | rle = resource_list_find(rl, type, *rid); |
| 3422 | |
| 3423 | if (!rle) |
| 3424 | return (NULL); /* no resource of that type/rid */ |
| 3425 | |
| 3426 | if (rle->res) { |
| 3427 | if (rle->flags & RLE_RESERVED) { |
| 3428 | if (rle->flags & RLE_ALLOCATED) |
| 3429 | return (NULL); |
| 3430 | if ((flags & RF_ACTIVE) && |
| 3431 | bus_activate_resource(child, type, *rid, |
| 3432 | rle->res) != 0) |
| 3433 | return (NULL); |
| 3434 | rle->flags |= RLE_ALLOCATED; |
| 3435 | return (rle->res); |
| 3436 | } |
| 3437 | device_printf(bus, |
| 3438 | "resource entry %#x type %d for child %s is busy\n", *rid, |
| 3439 | type, device_get_nameunit(child)); |
| 3440 | return (NULL); |
| 3441 | } |
| 3442 | |
| 3443 | if (isdefault) { |
| 3444 | start = rle->start; |
| 3445 | count = ulmax(count, rle->count); |
| 3446 | end = ulmax(rle->end, start + count - 1); |
| 3447 | } |
| 3448 | |
| 3449 | rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, |
| 3450 | type, rid, start, end, count, flags); |
| 3451 | |
| 3452 | /* |
| 3453 | * Record the new range. |
| 3454 | */ |
| 3455 | if (rle->res) { |
| 3456 | rle->start = rman_get_start(rle->res); |
| 3457 | rle->end = rman_get_end(rle->res); |
| 3458 | rle->count = count; |
| 3459 | } |
| 3460 | |
| 3461 | return (rle->res); |
| 3462 | } |
| 3463 | |
| 3464 | /** |
| 3465 | * @brief Helper function for implementing BUS_RELEASE_RESOURCE() |
no test coverage detected