diff options
Diffstat (limited to 'cpukit/libblock/src/media.c')
-rw-r--r-- | cpukit/libblock/src/media.c | 1012 |
1 files changed, 1012 insertions, 0 deletions
diff --git a/cpukit/libblock/src/media.c b/cpukit/libblock/src/media.c new file mode 100644 index 0000000000..b4ddd6ad7c --- /dev/null +++ b/cpukit/libblock/src/media.c @@ -0,0 +1,1012 @@ +/** + * @file + * + * @ingroup RTEMSMedia + * + * @brief Media implementation. + */ + +/* + * Copyright (c) 2009, 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include <string.h> +#include <assert.h> + +#include <rtems.h> +#include <rtems/bdbuf.h> +#include <rtems/diskdevs.h> +#include <rtems/bdpart.h> +#include <rtems/libio.h> + +#include <rtems/media.h> + +typedef struct { + rtems_bdpart_partition *partitions; + size_t *count; +} partition_table; + +typedef struct { + dev_t physical_disk; + dev_t logical_disk; + rtems_blkdev_bnum begin; + rtems_blkdev_bnum count; +} partition; + +typedef struct media_item { + rtems_chain_node node; + struct media_item *parent; + char *disk_path; + char *mount_path; +} media_item; + +typedef struct listener_item { + rtems_chain_node node; + rtems_media_listener listener; + void *listener_arg; +} listener_item; + +static RTEMS_CHAIN_DEFINE_EMPTY(listener_item_chain); + +static RTEMS_CHAIN_DEFINE_EMPTY(media_item_chain); + +static rtems_id media_mutex = RTEMS_ID_NONE; + +static rtems_status_code lock(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = rtems_semaphore_obtain(media_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) { + sc = RTEMS_NOT_CONFIGURED; + } + + return sc; +} + +static void unlock(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = rtems_semaphore_release(media_mutex); + assert(sc == RTEMS_SUCCESSFUL); +} + +static listener_item *find_listener( + rtems_media_listener listener, + void *listener_arg +) +{ + rtems_chain_node *node = rtems_chain_first(&listener_item_chain); + + while (!rtems_chain_is_tail(&listener_item_chain, node)) { + listener_item *item = (listener_item *) node; + + if (item->listener == listener && item->listener_arg == listener_arg) { + return item; + } + + node = rtems_chain_next(node); + } + + return NULL; +} + +rtems_status_code rtems_media_listener_add( + rtems_media_listener listener, + void *listener_arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = lock(); + if (sc == RTEMS_SUCCESSFUL) { + listener_item *item = find_listener(listener, listener_arg); + + if (item == NULL) { + item = malloc(sizeof(*item)); + if (item != NULL) { + item->listener = listener; + item->listener_arg = listener_arg; + rtems_chain_append_unprotected(&listener_item_chain, &item->node); + } else { + sc = RTEMS_NO_MEMORY; + } + } else { + sc = RTEMS_TOO_MANY; + } + + unlock(); + } + + return sc; +} + +rtems_status_code rtems_media_listener_remove( + rtems_media_listener listener, + void *listener_arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = lock(); + if (sc == RTEMS_SUCCESSFUL) { + listener_item *item = find_listener(listener, listener_arg); + + if (item != NULL) { + rtems_chain_extract_unprotected(&item->node); + free(item); + } else { + sc = RTEMS_INVALID_ID; + } + + unlock(); + } + + return sc; +} + +static rtems_status_code notify( + rtems_media_event event, + rtems_media_state state, + const char *src, + const char *dest +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_status_code rsc = RTEMS_SUCCESSFUL; + rtems_chain_node *node = rtems_chain_first(&listener_item_chain); + + while (!rtems_chain_is_tail(&listener_item_chain, node)) { + listener_item *item = (listener_item *) node; + + sc = (*item->listener)(event, state, src, dest, item->listener_arg); + if (sc != RTEMS_SUCCESSFUL) { + rsc = sc; + } + + node = rtems_chain_next(node); + } + + return rsc; +} + +static void error( + rtems_media_state state, + const char *src, + const char *dest +) +{ + notify(RTEMS_MEDIA_EVENT_ERROR, state, src, dest); +} + +static media_item *get_media_item( + const char *disk_path, + const char *mount_path +) +{ + rtems_chain_node *node = rtems_chain_first(&media_item_chain); + + while (!rtems_chain_is_tail(&media_item_chain, node)) { + media_item *item = (media_item *) node; + + if ( + (disk_path == NULL || strcmp(disk_path, item->disk_path) == 0) + && (mount_path == NULL || strcmp(mount_path, item->mount_path) == 0) + ) { + return item; + } + + node = rtems_chain_next(node); + } + + return NULL; +} + +static void free_item(media_item *item) +{ + rtems_chain_extract(&item->node); + free(item->mount_path); + free(item); +} + +static void create_item( + media_item *parent, + const char *disk_path, + const char *mount_path +) +{ + size_t disk_path_size = strlen(disk_path) + 1; + media_item *item = malloc(sizeof(*item) + disk_path_size); + + if (item != NULL) { + if (mount_path != NULL) { + item->mount_path = strdup(mount_path); + + if (item->mount_path == NULL) { + free(item); + + return; + } + } else { + item->mount_path = NULL; + } + + item->parent = parent; + item->disk_path = (char *) item + sizeof(*item); + memcpy(item->disk_path, disk_path, disk_path_size); + rtems_chain_append(&media_item_chain, &item->node); + } +} + +static void remove_mount_point(const char *mount_path) +{ + media_item *item = get_media_item(NULL, mount_path); + + if (item != NULL) { + free(item->mount_path); + item->mount_path = NULL; + } else { + error(RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN, mount_path, NULL); + } +} + +static void remove_partition(const char *partition_path) +{ + media_item *item = get_media_item(partition_path, NULL); + + if (item != NULL) { + if (item->mount_path != NULL) { + error( + RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT, + partition_path, + item->mount_path + ); + } + free_item(item); + } else { + error(RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN, partition_path, NULL); + } +} + +static void remove_disk(const char *disk_path) +{ + media_item *item = get_media_item(disk_path, NULL); + + if (item != NULL) { + rtems_chain_node *node = rtems_chain_first(&media_item_chain); + + while (!rtems_chain_is_tail(&media_item_chain, node)) { + media_item *child = (media_item *) node; + + node = rtems_chain_next(node); + + if (child->parent == item) { + if (child->mount_path != NULL) { + error( + RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN, + child->mount_path, + disk_path + ); + } + error(RTEMS_MEDIA_ERROR_PARTITION_ORPHAN, child->disk_path, disk_path); + free_item(child); + } + } + + free_item(item); + } else { + error(RTEMS_MEDIA_ERROR_DISK_UNKNOWN, disk_path, NULL); + } +} + +static void add_disk(const char *disk_path) +{ + media_item *item = get_media_item(disk_path, NULL); + + if (item != NULL) { + error(RTEMS_MEDIA_ERROR_DISK_EXISTS, disk_path, NULL); + remove_disk(disk_path); + } + + create_item(NULL, disk_path, NULL); +} + +static void add_partition(const char *disk_path, const char *partition_path) +{ + media_item *item = get_media_item(partition_path, NULL); + media_item *parent = get_media_item(disk_path, NULL); + + if (item != NULL) { + error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS, partition_path, NULL); + remove_disk(partition_path); + } + + if (parent != NULL) { + create_item(parent, partition_path, NULL); + } else { + error( + RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK, + partition_path, + disk_path + ); + } +} + +static void add_mount_point(const char *disk_path, const char *mount_path) +{ + media_item *item = get_media_item(disk_path, NULL); + + if (item != NULL) { + if (item->mount_path != NULL) { + error(RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS, item->mount_path, NULL); + free(item->mount_path); + } + item->mount_path = strdup(mount_path); + } else { + error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN, disk_path, NULL); + } +} + +static bool is_add_state(rtems_media_state state) +{ + return state == RTEMS_MEDIA_STATE_SUCCESS; +} + +static bool is_remove_state(rtems_media_state state) +{ + return state == RTEMS_MEDIA_STATE_SUCCESS + || state == RTEMS_MEDIA_STATE_FAILED; +} + +static rtems_status_code remember_event( + rtems_media_event event, + rtems_media_state state, + const char *src, + const char *dest +) +{ + switch (event) { + case RTEMS_MEDIA_EVENT_DISK_ATTACH: + if (is_add_state(state)) { + add_disk(dest); + } + break; + case RTEMS_MEDIA_EVENT_PARTITION_ATTACH: + if (is_add_state(state)) { + add_partition(src, dest); + } + break; + case RTEMS_MEDIA_EVENT_MOUNT: + if (is_add_state(state)) { + add_mount_point(src, dest); + } + break; + case RTEMS_MEDIA_EVENT_UNMOUNT: + if (is_remove_state(state)) { + remove_mount_point(src); + } + break; + case RTEMS_MEDIA_EVENT_PARTITION_DETACH: + if (is_remove_state(state)) { + remove_partition(src); + } + break; + case RTEMS_MEDIA_EVENT_DISK_DETACH: + if (is_remove_state(state)) { + remove_disk(src); + } + break; + default: + break; + } + + return RTEMS_SUCCESSFUL; +} + +static rtems_status_code process_event( + rtems_media_event event, + const char *src, + char **dest_ptr, + rtems_media_worker worker, + void *worker_arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_media_state state = RTEMS_MEDIA_STATE_FAILED; + char *dest = NULL; + + sc = notify(event, RTEMS_MEDIA_STATE_INQUIRY, src, NULL); + if (sc == RTEMS_SUCCESSFUL) { + state = RTEMS_MEDIA_STATE_READY; + } else { + state = RTEMS_MEDIA_STATE_ABORTED; + } + + sc = (*worker)(state, src, &dest, worker_arg); + if (state == RTEMS_MEDIA_STATE_READY) { + if (sc == RTEMS_SUCCESSFUL) { + state = RTEMS_MEDIA_STATE_SUCCESS; + } else { + state = RTEMS_MEDIA_STATE_FAILED; + } + } + + notify(event, state, src, dest); + remember_event(event, state, src, dest); + + if (state == RTEMS_MEDIA_STATE_SUCCESS) { + sc = RTEMS_SUCCESSFUL; + } else if (state == RTEMS_MEDIA_STATE_ABORTED) { + sc = RTEMS_UNSATISFIED; + } else { + sc = RTEMS_IO_ERROR; + } + + if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) { + *dest_ptr = dest; + } else { + free(dest); + } + + return sc; +} + +static rtems_status_code mount_worker( + rtems_media_state state, + const char *src, + char **dest, + void *worker_arg +) +{ + int rv = 0; + + if (state == RTEMS_MEDIA_STATE_READY) { + char *mount_path = NULL; + + if (worker_arg == NULL) { + mount_path = rtems_media_replace_prefix(RTEMS_MEDIA_MOUNT_BASE, src); + } else { + mount_path = strdup(worker_arg); + } + + if (mount_path == NULL) { + return RTEMS_IO_ERROR; + } + + rv = rtems_mkdir(mount_path, S_IRWXU | S_IRWXG | S_IRWXO); + if (rv != 0) { + free(mount_path); + + return RTEMS_IO_ERROR; + } + + rv = mount( + src, + mount_path, + RTEMS_FILESYSTEM_TYPE_DOSFS, + RTEMS_FILESYSTEM_READ_WRITE, + NULL + ); + if (rv != 0) { + rmdir(mount_path); + free(mount_path); + + return RTEMS_IO_ERROR; + } + + *dest = mount_path; + } + + return RTEMS_SUCCESSFUL; +} + +static rtems_status_code do_mount( + const char *src, + char **dest_ptr, + rtems_media_worker worker, + void *worker_arg +) +{ + if (worker == NULL) { + worker = mount_worker; + } + + return process_event( + RTEMS_MEDIA_EVENT_MOUNT, + src, + dest_ptr, + worker, + worker_arg + ); +} + +static rtems_status_code do_partition_attach( + const char *src, + char **dest_ptr, + rtems_media_worker worker, + void *worker_arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + char *part_path = NULL; + + if (worker != NULL) { + sc = process_event( + RTEMS_MEDIA_EVENT_PARTITION_ATTACH, + src, + &part_path, + worker, + worker_arg + ); + + if (sc == RTEMS_SUCCESSFUL) { + sc = do_mount(part_path, NULL, NULL, NULL); + } + } else { + sc = RTEMS_INVALID_ADDRESS; + } + + if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) { + *dest_ptr = part_path; + } else { + free(part_path); + } + + return sc; +} + +static rtems_status_code partition_attach_worker( + rtems_media_state state, + const char *src, + char **dest, + void *worker_arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (state == RTEMS_MEDIA_STATE_READY) { + partition *part = worker_arg; + rtems_device_minor_number minor = + rtems_filesystem_dev_minor_t(part->logical_disk); + char *part_path = rtems_media_append_minor(src, minor); + + if (part_path == NULL) { + return RTEMS_IO_ERROR; + } + + sc = rtems_disk_create_log( + part->logical_disk, + part->physical_disk, + part->begin, + part->count, + part_path + ); + if (sc != RTEMS_SUCCESSFUL) { + free(part_path); + + return RTEMS_IO_ERROR; + } + + *dest = part_path; + } + + return RTEMS_SUCCESSFUL; +} + +static rtems_status_code attach_and_mount_partitions( + const char *disk_path, + rtems_bdpart_partition *partitions, + size_t count +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_device_major_number major = 0; + rtems_device_minor_number minor = 0; + dev_t dev = 0; + size_t i = 0; + + sc = rtems_media_get_device_identifier(disk_path, &dev); + if (sc != RTEMS_SUCCESSFUL) { + return RTEMS_INVALID_ID; + } + + major = rtems_filesystem_dev_major_t(dev); + minor = rtems_filesystem_dev_minor_t(dev) + 1; + + for (i = 0; i < count; ++i, ++minor) { + partition part_desc = { + .physical_disk = dev, + .logical_disk = rtems_filesystem_make_dev_t(major, minor), + .begin = partitions [i].begin, + .count = partitions [i].end - partitions [i].begin + }; + char *part_path = NULL; + + sc = process_event( + RTEMS_MEDIA_EVENT_PARTITION_ATTACH, + disk_path, + &part_path, + partition_attach_worker, + &part_desc + ); + + if (sc == RTEMS_SUCCESSFUL) { + sc = do_mount(part_path, NULL, NULL, NULL); + } + + free(part_path); + } + + return sc; +} + +static rtems_status_code partition_inquiry_worker( + rtems_media_state state, + const char *src, + char **dest __attribute__((unused)), + void *worker_arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (state == RTEMS_MEDIA_STATE_READY) { + partition_table *pt = worker_arg; + rtems_bdpart_format format; + + sc = rtems_bdpart_read(src, &format, pt->partitions, pt->count); + if (sc != RTEMS_SUCCESSFUL || *pt->count == 0) { + return RTEMS_IO_ERROR; + } + } + + return RTEMS_SUCCESSFUL; +} + +static rtems_status_code do_partition_inquiry( + const char *src, + char **dest_ptr, + rtems_media_worker worker, + void *worker_arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (worker == NULL) { + rtems_bdpart_partition partitions [RTEMS_BDPART_PARTITION_NUMBER_HINT]; + size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT; + partition_table pt = { + .partitions = partitions, + .count = &count + }; + + sc = process_event( + RTEMS_MEDIA_EVENT_PARTITION_INQUIRY, + src, + dest_ptr, + partition_inquiry_worker, + &pt + ); + + if (sc == RTEMS_SUCCESSFUL) { + sc = attach_and_mount_partitions(src, partitions, count); + } + } else { + sc = process_event( + RTEMS_MEDIA_EVENT_PARTITION_INQUIRY, + src, + dest_ptr, + worker, + worker_arg + ); + } + + return sc; +} + +static rtems_status_code do_disk_attach( + const char *src, + char **dest_ptr, + rtems_media_worker worker, + void *worker_arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_status_code rsc = RTEMS_SUCCESSFUL; + char *disk_path = NULL; + + if (worker != NULL) { + rsc = process_event( + RTEMS_MEDIA_EVENT_DISK_ATTACH, + src, + &disk_path, + worker, + worker_arg + ); + + if (rsc == RTEMS_SUCCESSFUL) { + sc = do_mount(disk_path, NULL, NULL, NULL); + + if (sc != RTEMS_SUCCESSFUL) { + do_partition_inquiry(disk_path, NULL, NULL, NULL); + } + } + } else { + rsc = RTEMS_INVALID_ADDRESS; + } + + if (dest_ptr != NULL && rsc == RTEMS_SUCCESSFUL) { + *dest_ptr = disk_path; + } else { + free(disk_path); + } + + return rsc; +} + +static rtems_status_code unmount_worker( + rtems_media_state state, + const char *src, + char **dest __attribute__((unused)), + void *worker_arg __attribute__((unused)) +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (state == RTEMS_MEDIA_STATE_READY) { + int rv = unmount(src); + + if (rv == 0) { + rv = rmdir(src); + if (rv != 0) { + sc = RTEMS_IO_ERROR; + } + } else { + sc = RTEMS_IO_ERROR; + } + } + + return sc; +} + +static rtems_status_code do_unmount( + const char *src, + char **dest_ptr, + rtems_media_worker worker, + void *worker_arg +) +{ + if (worker == NULL) { + worker = unmount_worker; + worker_arg = NULL; + } + + return process_event( + RTEMS_MEDIA_EVENT_UNMOUNT, + src, + dest_ptr, + worker, + worker_arg + ); +} + +static rtems_status_code disk_detach_worker( + rtems_media_state state, + const char *src, + char **dest __attribute__((unused)), + void *worker_arg __attribute__((unused)) +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_status_code rsc = RTEMS_SUCCESSFUL; + + if (state == RTEMS_MEDIA_STATE_READY) { + dev_t dev = 0; + + sc = rtems_media_get_device_identifier(src, &dev); + if (sc != RTEMS_SUCCESSFUL) { + return RTEMS_IO_ERROR; + } + + sc = rtems_bdbuf_syncdev(dev); + if (sc != RTEMS_SUCCESSFUL) { + rsc = RTEMS_IO_ERROR; + } + + sc = rtems_disk_delete(dev); + if (sc != RTEMS_SUCCESSFUL) { + rsc = RTEMS_IO_ERROR; + } + + rtems_bdbuf_purge_dev(dev); + + if (rtems_filesystem_dev_minor_t(dev) == 0) { + sc = rtems_io_unregister_driver(rtems_filesystem_dev_major_t(dev)); + if (sc != RTEMS_SUCCESSFUL) { + rsc = RTEMS_IO_ERROR; + } + } + } + + return rsc; +} + +static rtems_status_code detach_item(rtems_media_event event, media_item *item) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_status_code rsc = RTEMS_SUCCESSFUL; + + if (item->mount_path != NULL) { + sc = do_unmount(item->mount_path, NULL, NULL, NULL); + if (sc != RTEMS_SUCCESSFUL) { + rsc = RTEMS_IO_ERROR; + } + } + + sc = process_event(event, item->disk_path, NULL, disk_detach_worker, NULL); + if (sc != RTEMS_SUCCESSFUL) { + rsc = RTEMS_IO_ERROR; + } + + return rsc; +} + +static rtems_status_code detach_parent_item(media_item *parent) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_status_code rsc = RTEMS_SUCCESSFUL; + + rtems_chain_node *node = rtems_chain_first(&media_item_chain); + + while (!rtems_chain_is_tail(&media_item_chain, node)) { + media_item *child = (media_item *) node; + + node = rtems_chain_next(node); + + if (child->parent == parent) { + sc = detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, child); + if (sc != RTEMS_SUCCESSFUL) { + rsc = RTEMS_IO_ERROR; + } + } + } + + sc = detach_item(RTEMS_MEDIA_EVENT_DISK_DETACH, parent); + if (sc != RTEMS_SUCCESSFUL) { + rsc = RTEMS_IO_ERROR; + } + + return rsc; +} + +static rtems_status_code do_disk_detach( + const char *src, + char **dest_ptr, + rtems_media_worker worker, + void *worker_arg +) +{ + if (worker == NULL) { + media_item *parent = get_media_item(src, NULL); + + if (parent != NULL) { + return detach_parent_item(parent); + } + + worker = disk_detach_worker; + worker_arg = NULL; + } + + return process_event( + RTEMS_MEDIA_EVENT_DISK_DETACH, + src, + dest_ptr, + worker, + worker_arg + ); +} + +static rtems_status_code do_partition_detach( + const char *src, + char **dest_ptr, + rtems_media_worker worker, + void *worker_arg +) +{ + if (worker == NULL) { + media_item *item = get_media_item(src, NULL); + + if (item != NULL) { + return detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, item); + } + + worker = disk_detach_worker; + worker_arg = NULL; + } + + return process_event( + RTEMS_MEDIA_EVENT_PARTITION_DETACH, + src, + dest_ptr, + worker, + worker_arg + ); +} + +rtems_status_code rtems_media_post_event( + rtems_media_event event, + const char *src, + char **dest_ptr, + rtems_media_worker worker, + void *worker_arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = lock(); + if (sc != RTEMS_SUCCESSFUL) { + return sc; + } + + switch (event) { + case RTEMS_MEDIA_EVENT_DISK_ATTACH: + sc = do_disk_attach(src, dest_ptr, worker, worker_arg); + break; + case RTEMS_MEDIA_EVENT_DISK_DETACH: + sc = do_disk_detach(src, dest_ptr, worker, worker_arg); + break; + case RTEMS_MEDIA_EVENT_MOUNT: + sc = do_mount(src, dest_ptr, worker, worker_arg); + break; + case RTEMS_MEDIA_EVENT_UNMOUNT: + sc = do_unmount(src, dest_ptr, worker, worker_arg); + break; + case RTEMS_MEDIA_EVENT_PARTITION_INQUIRY: + sc = do_partition_inquiry(src, dest_ptr, worker, worker_arg); + break; + case RTEMS_MEDIA_EVENT_PARTITION_ATTACH: + sc = do_partition_attach(src, dest_ptr, worker, worker_arg); + break; + case RTEMS_MEDIA_EVENT_PARTITION_DETACH: + sc = do_partition_detach(src, dest_ptr, worker, worker_arg); + break; + default: + sc = RTEMS_INVALID_ID; + break; + } + + unlock(); + + return sc; +} + +rtems_status_code rtems_media_initialize(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (media_mutex == RTEMS_ID_NONE) { + sc = rtems_semaphore_create( + rtems_build_name('M', 'D', 'I', 'A'), + 1, + RTEMS_LOCAL | RTEMS_PRIORITY + | RTEMS_INHERIT_PRIORITY | RTEMS_BINARY_SEMAPHORE, + 0, + &media_mutex + ); + if (sc != RTEMS_SUCCESSFUL) { + sc = RTEMS_NO_MEMORY; + } + } + + return sc; +} |