File indexing completed on 2025-05-11 08:24:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <stdlib.h>
0037 #include <string.h>
0038 #include <assert.h>
0039 #include <unistd.h>
0040
0041 #include <rtems/media.h>
0042
0043 #include <rtems.h>
0044 #include <rtems/bdbuf.h>
0045 #include <rtems/blkdev.h>
0046 #include <rtems/bdpart.h>
0047 #include <rtems/libio.h>
0048 #include <rtems/dosfs.h>
0049 #include <rtems/thread.h>
0050
0051 typedef struct {
0052 rtems_bdpart_partition *partitions;
0053 size_t *count;
0054 } partition_table;
0055
0056 typedef struct {
0057 size_t index;
0058 rtems_blkdev_bnum begin;
0059 rtems_blkdev_bnum count;
0060 } partition;
0061
0062 typedef struct media_item {
0063 rtems_chain_node node;
0064 struct media_item *parent;
0065 char *disk_path;
0066 char *mount_path;
0067 } media_item;
0068
0069 typedef struct listener_item {
0070 rtems_chain_node node;
0071 rtems_media_listener listener;
0072 void *listener_arg;
0073 } listener_item;
0074
0075 static RTEMS_CHAIN_DEFINE_EMPTY(listener_item_chain);
0076
0077 static RTEMS_CHAIN_DEFINE_EMPTY(media_item_chain);
0078
0079 static rtems_mutex media_mutex = RTEMS_MUTEX_INITIALIZER("Media");
0080
0081 static void lock(void)
0082 {
0083 rtems_mutex_lock(&media_mutex);
0084 }
0085
0086 static void unlock(void)
0087 {
0088 rtems_mutex_unlock(&media_mutex);
0089 }
0090
0091 static listener_item *find_listener(
0092 rtems_media_listener listener,
0093 void *listener_arg
0094 )
0095 {
0096 rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
0097
0098 while (!rtems_chain_is_tail(&listener_item_chain, node)) {
0099 listener_item *item = (listener_item *) node;
0100
0101 if (item->listener == listener && item->listener_arg == listener_arg) {
0102 return item;
0103 }
0104
0105 node = rtems_chain_next(node);
0106 }
0107
0108 return NULL;
0109 }
0110
0111 rtems_status_code rtems_media_listener_add(
0112 rtems_media_listener listener,
0113 void *listener_arg
0114 )
0115 {
0116 rtems_status_code sc = RTEMS_SUCCESSFUL;
0117 listener_item *item;
0118
0119 lock();
0120
0121 item = find_listener(listener, listener_arg);
0122
0123 if (item == NULL) {
0124 item = malloc(sizeof(*item));
0125 if (item != NULL) {
0126 item->listener = listener;
0127 item->listener_arg = listener_arg;
0128 rtems_chain_initialize_node(&item->node);
0129 rtems_chain_append_unprotected(&listener_item_chain, &item->node);
0130 } else {
0131 sc = RTEMS_NO_MEMORY;
0132 }
0133 } else {
0134 sc = RTEMS_TOO_MANY;
0135 }
0136
0137 unlock();
0138
0139 return sc;
0140 }
0141
0142 rtems_status_code rtems_media_listener_remove(
0143 rtems_media_listener listener,
0144 void *listener_arg
0145 )
0146 {
0147 rtems_status_code sc = RTEMS_SUCCESSFUL;
0148 listener_item *item;
0149
0150 lock();
0151
0152 item = find_listener(listener, listener_arg);
0153
0154 if (item != NULL) {
0155 rtems_chain_extract_unprotected(&item->node);
0156 free(item);
0157 } else {
0158 sc = RTEMS_INVALID_ID;
0159 }
0160
0161 unlock();
0162
0163 return sc;
0164 }
0165
0166 static rtems_status_code notify(
0167 rtems_media_event event,
0168 rtems_media_state state,
0169 const char *src,
0170 const char *dest
0171 )
0172 {
0173 rtems_status_code sc = RTEMS_SUCCESSFUL;
0174 rtems_status_code rsc = RTEMS_SUCCESSFUL;
0175 rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
0176
0177 while (!rtems_chain_is_tail(&listener_item_chain, node)) {
0178 listener_item *item = (listener_item *) node;
0179
0180 sc = (*item->listener)(event, state, src, dest, item->listener_arg);
0181 if (sc != RTEMS_SUCCESSFUL) {
0182 rsc = sc;
0183 }
0184
0185 node = rtems_chain_next(node);
0186 }
0187
0188 return rsc;
0189 }
0190
0191 static void error(
0192 rtems_media_state state,
0193 const char *src,
0194 const char *dest
0195 )
0196 {
0197 (void) notify(RTEMS_MEDIA_EVENT_ERROR, state, src, dest);
0198 }
0199
0200 static media_item *get_media_item(
0201 const char *disk_path,
0202 const char *mount_path
0203 )
0204 {
0205 rtems_chain_node *node = rtems_chain_first(&media_item_chain);
0206
0207 while (!rtems_chain_is_tail(&media_item_chain, node)) {
0208 media_item *item = (media_item *) node;
0209
0210 if (
0211 (disk_path == NULL || strcmp(disk_path, item->disk_path) == 0)
0212 && (mount_path == NULL
0213 || (item->mount_path != NULL
0214 && strcmp(mount_path, item->mount_path) == 0))
0215 ) {
0216 return item;
0217 }
0218
0219 node = rtems_chain_next(node);
0220 }
0221
0222 return NULL;
0223 }
0224
0225 static void free_item(media_item *item)
0226 {
0227 rtems_chain_extract_unprotected(&item->node);
0228 free(item->mount_path);
0229 free(item);
0230 }
0231
0232 static void create_item(
0233 media_item *parent,
0234 const char *disk_path,
0235 const char *mount_path
0236 )
0237 {
0238 size_t disk_path_size = strlen(disk_path) + 1;
0239 media_item *item = malloc(sizeof(*item) + disk_path_size);
0240
0241 if (item != NULL) {
0242 if (mount_path != NULL) {
0243 item->mount_path = strdup(mount_path);
0244
0245 if (item->mount_path == NULL) {
0246 free(item);
0247
0248 return;
0249 }
0250 } else {
0251 item->mount_path = NULL;
0252 }
0253
0254 item->parent = parent;
0255 item->disk_path = (char *) item + sizeof(*item);
0256 memcpy(item->disk_path, disk_path, disk_path_size);
0257 rtems_chain_initialize_node(&item->node);
0258 rtems_chain_append(&media_item_chain, &item->node);
0259 }
0260 }
0261
0262 static void remove_mount_point(const char *mount_path)
0263 {
0264 media_item *item = get_media_item(NULL, mount_path);
0265
0266 if (item != NULL) {
0267 free(item->mount_path);
0268 item->mount_path = NULL;
0269 } else {
0270 error(RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN, mount_path, NULL);
0271 }
0272 }
0273
0274 static void remove_partition(const char *partition_path)
0275 {
0276 media_item *item = get_media_item(partition_path, NULL);
0277
0278 if (item != NULL) {
0279 if (item->mount_path != NULL) {
0280 error(
0281 RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT,
0282 partition_path,
0283 item->mount_path
0284 );
0285 }
0286 free_item(item);
0287 } else {
0288 error(RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN, partition_path, NULL);
0289 }
0290 }
0291
0292 static void remove_disk(const char *disk_path)
0293 {
0294 media_item *item = get_media_item(disk_path, NULL);
0295
0296 if (item != NULL) {
0297 rtems_chain_node *node = rtems_chain_first(&media_item_chain);
0298
0299 while (!rtems_chain_is_tail(&media_item_chain, node)) {
0300 media_item *child = (media_item *) node;
0301
0302 node = rtems_chain_next(node);
0303
0304 if (child->parent == item) {
0305 if (child->mount_path != NULL) {
0306 error(
0307 RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN,
0308 child->mount_path,
0309 disk_path
0310 );
0311 }
0312 error(RTEMS_MEDIA_ERROR_PARTITION_ORPHAN, child->disk_path, disk_path);
0313 free_item(child);
0314 }
0315 }
0316
0317 free_item(item);
0318 } else {
0319 error(RTEMS_MEDIA_ERROR_DISK_UNKNOWN, disk_path, NULL);
0320 }
0321 }
0322
0323 static void add_disk(const char *disk_path)
0324 {
0325 media_item *item = get_media_item(disk_path, NULL);
0326
0327 if (item != NULL) {
0328 error(RTEMS_MEDIA_ERROR_DISK_EXISTS, disk_path, NULL);
0329 remove_disk(disk_path);
0330 }
0331
0332 create_item(NULL, disk_path, NULL);
0333 }
0334
0335 static void add_partition(const char *disk_path, const char *partition_path)
0336 {
0337 media_item *item = get_media_item(partition_path, NULL);
0338 media_item *parent = get_media_item(disk_path, NULL);
0339
0340 if (item != NULL) {
0341 error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS, partition_path, NULL);
0342 remove_disk(partition_path);
0343 }
0344
0345 if (parent != NULL) {
0346 create_item(parent, partition_path, NULL);
0347 } else {
0348 error(
0349 RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK,
0350 partition_path,
0351 disk_path
0352 );
0353 }
0354 }
0355
0356 static void add_mount_point(const char *disk_path, const char *mount_path)
0357 {
0358 media_item *item = get_media_item(disk_path, NULL);
0359
0360 if (item != NULL) {
0361 if (item->mount_path != NULL) {
0362 error(RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS, item->mount_path, NULL);
0363 free(item->mount_path);
0364 }
0365 item->mount_path = strdup(mount_path);
0366 } else {
0367 error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN, disk_path, NULL);
0368 }
0369 }
0370
0371 static bool is_add_state(rtems_media_state state)
0372 {
0373 return state == RTEMS_MEDIA_STATE_SUCCESS;
0374 }
0375
0376 static bool is_remove_state(rtems_media_state state)
0377 {
0378 return state == RTEMS_MEDIA_STATE_SUCCESS
0379 || state == RTEMS_MEDIA_STATE_FAILED;
0380 }
0381
0382 static rtems_status_code remember_event(
0383 rtems_media_event event,
0384 rtems_media_state state,
0385 const char *src,
0386 const char *dest
0387 )
0388 {
0389 switch (event) {
0390 case RTEMS_MEDIA_EVENT_DISK_ATTACH:
0391 if (is_add_state(state)) {
0392 add_disk(dest);
0393 }
0394 break;
0395 case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
0396 if (is_add_state(state)) {
0397 add_partition(src, dest);
0398 }
0399 break;
0400 case RTEMS_MEDIA_EVENT_MOUNT:
0401 if (is_add_state(state)) {
0402 add_mount_point(src, dest);
0403 }
0404 break;
0405 case RTEMS_MEDIA_EVENT_UNMOUNT:
0406 if (is_remove_state(state)) {
0407 remove_mount_point(src);
0408 }
0409 break;
0410 case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
0411 if (is_remove_state(state)) {
0412 remove_partition(src);
0413 }
0414 break;
0415 case RTEMS_MEDIA_EVENT_DISK_DETACH:
0416 if (is_remove_state(state)) {
0417 remove_disk(src);
0418 }
0419 break;
0420 default:
0421 break;
0422 }
0423
0424 return RTEMS_SUCCESSFUL;
0425 }
0426
0427 static rtems_status_code process_event(
0428 rtems_media_event event,
0429 const char *src,
0430 char **dest_ptr,
0431 rtems_media_worker worker,
0432 void *worker_arg
0433 )
0434 {
0435 rtems_status_code sc = RTEMS_SUCCESSFUL;
0436 rtems_status_code sc_retry = RTEMS_SUCCESSFUL;
0437 rtems_media_state state;
0438 char *dest = NULL;
0439
0440 do {
0441 sc = notify(event, RTEMS_MEDIA_STATE_INQUIRY, src, NULL);
0442 if (sc == RTEMS_SUCCESSFUL) {
0443 state = RTEMS_MEDIA_STATE_READY;
0444 } else {
0445 state = RTEMS_MEDIA_STATE_ABORTED;
0446 }
0447
0448 sc = (*worker)(state, src, &dest, worker_arg);
0449 if (state == RTEMS_MEDIA_STATE_READY) {
0450 if (sc == RTEMS_SUCCESSFUL) {
0451 state = RTEMS_MEDIA_STATE_SUCCESS;
0452 } else {
0453 state = RTEMS_MEDIA_STATE_FAILED;
0454 }
0455 }
0456
0457 sc_retry = notify(event, state, src, dest);
0458 } while (state == RTEMS_MEDIA_STATE_FAILED
0459 && sc_retry == RTEMS_INCORRECT_STATE);
0460 remember_event(event, state, src, dest);
0461
0462 if (state == RTEMS_MEDIA_STATE_SUCCESS) {
0463 sc = RTEMS_SUCCESSFUL;
0464 } else if (state == RTEMS_MEDIA_STATE_ABORTED) {
0465 sc = RTEMS_UNSATISFIED;
0466 } else {
0467 sc = RTEMS_IO_ERROR;
0468 }
0469
0470 if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
0471 *dest_ptr = dest;
0472 } else {
0473 free(dest);
0474 }
0475
0476 return sc;
0477 }
0478
0479 static rtems_status_code mount_worker(
0480 rtems_media_state state,
0481 const char *src,
0482 char **dest,
0483 void *worker_arg
0484 )
0485 {
0486 int rv = 0;
0487
0488 if (state == RTEMS_MEDIA_STATE_READY) {
0489 rtems_dosfs_mount_options mount_options;
0490 char *mount_path = NULL;
0491
0492 if (worker_arg == NULL) {
0493 mount_path = rtems_media_replace_prefix(RTEMS_MEDIA_MOUNT_BASE, src);
0494 } else {
0495 mount_path = strdup(worker_arg);
0496 }
0497
0498 if (mount_path == NULL) {
0499 return RTEMS_IO_ERROR;
0500 }
0501
0502 rv = rtems_mkdir(mount_path, S_IRWXU | S_IRWXG | S_IRWXO);
0503 if (rv != 0) {
0504 free(mount_path);
0505
0506 return RTEMS_IO_ERROR;
0507 }
0508
0509 memset(&mount_options, 0, sizeof(mount_options));
0510
0511
0512 mount_options.converter = rtems_dosfs_create_utf8_converter("CP850");
0513
0514 rv = mount(
0515 src,
0516 mount_path,
0517 RTEMS_FILESYSTEM_TYPE_DOSFS,
0518 RTEMS_FILESYSTEM_READ_WRITE,
0519 &mount_options
0520 );
0521 if (rv != 0) {
0522 (void) rmdir(mount_path);
0523 free(mount_path);
0524 (*mount_options.converter->handler->destroy)(mount_options.converter);
0525
0526 return RTEMS_IO_ERROR;
0527 }
0528
0529 *dest = mount_path;
0530 }
0531
0532 return RTEMS_SUCCESSFUL;
0533 }
0534
0535 static rtems_status_code do_mount(
0536 const char *src,
0537 char **dest_ptr,
0538 rtems_media_worker worker,
0539 void *worker_arg
0540 )
0541 {
0542 if (worker == NULL) {
0543 worker = mount_worker;
0544 }
0545
0546 return process_event(
0547 RTEMS_MEDIA_EVENT_MOUNT,
0548 src,
0549 dest_ptr,
0550 worker,
0551 worker_arg
0552 );
0553 }
0554
0555 static rtems_status_code do_partition_attach(
0556 const char *src,
0557 char **dest_ptr,
0558 rtems_media_worker worker,
0559 void *worker_arg
0560 )
0561 {
0562 rtems_status_code sc = RTEMS_SUCCESSFUL;
0563 char *part_path = NULL;
0564
0565 if (worker != NULL) {
0566 sc = process_event(
0567 RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
0568 src,
0569 &part_path,
0570 worker,
0571 worker_arg
0572 );
0573
0574 if (sc == RTEMS_SUCCESSFUL) {
0575 sc = do_mount(part_path, NULL, NULL, NULL);
0576 }
0577 } else {
0578 sc = RTEMS_INVALID_ADDRESS;
0579 }
0580
0581 if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
0582 *dest_ptr = part_path;
0583 } else {
0584 free(part_path);
0585 }
0586
0587 return sc;
0588 }
0589
0590 static rtems_status_code partition_attach_worker(
0591 rtems_media_state state,
0592 const char *src,
0593 char **dest,
0594 void *worker_arg
0595 )
0596 {
0597 rtems_status_code sc = RTEMS_SUCCESSFUL;
0598
0599 if (state == RTEMS_MEDIA_STATE_READY) {
0600 partition *part = worker_arg;
0601 char *part_path = rtems_media_append_minor(src, part->index);
0602
0603 if (part_path == NULL) {
0604 return RTEMS_IO_ERROR;
0605 }
0606
0607 sc = rtems_blkdev_create_partition(
0608 part_path,
0609 src,
0610 part->begin,
0611 part->count
0612 );
0613 if (sc != RTEMS_SUCCESSFUL) {
0614 free(part_path);
0615
0616 return RTEMS_IO_ERROR;
0617 }
0618
0619 *dest = part_path;
0620 }
0621
0622 return RTEMS_SUCCESSFUL;
0623 }
0624
0625 static rtems_status_code attach_and_mount_partitions(
0626 const char *disk_path,
0627 const rtems_bdpart_partition *partitions,
0628 size_t count
0629 )
0630 {
0631 rtems_status_code sc = RTEMS_SUCCESSFUL;
0632 size_t i = 0;
0633
0634 for (i = 0; i < count; ++i) {
0635 partition part_desc = {
0636 .index = i,
0637 .begin = partitions [i].begin,
0638 .count = partitions [i].end - partitions [i].begin
0639 };
0640 char *part_path = NULL;
0641
0642 sc = process_event(
0643 RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
0644 disk_path,
0645 &part_path,
0646 partition_attach_worker,
0647 &part_desc
0648 );
0649
0650 if (sc == RTEMS_SUCCESSFUL) {
0651 sc = do_mount(part_path, NULL, NULL, NULL);
0652 }
0653
0654 free(part_path);
0655 }
0656
0657 return sc;
0658 }
0659
0660 static rtems_status_code partition_inquiry_worker(
0661 rtems_media_state state,
0662 const char *src,
0663 char **dest RTEMS_UNUSED,
0664 void *worker_arg
0665 )
0666 {
0667 rtems_status_code sc = RTEMS_SUCCESSFUL;
0668
0669 if (state == RTEMS_MEDIA_STATE_READY) {
0670 partition_table *pt = worker_arg;
0671 rtems_bdpart_format format;
0672
0673 sc = rtems_bdpart_read(src, &format, pt->partitions, pt->count);
0674 if (sc != RTEMS_SUCCESSFUL || *pt->count == 0) {
0675 return RTEMS_IO_ERROR;
0676 }
0677 }
0678
0679 return RTEMS_SUCCESSFUL;
0680 }
0681
0682 static rtems_status_code do_partition_inquiry(
0683 const char *src,
0684 char **dest_ptr,
0685 rtems_media_worker worker,
0686 void *worker_arg
0687 )
0688 {
0689 rtems_status_code sc = RTEMS_SUCCESSFUL;
0690
0691 if (worker == NULL) {
0692 rtems_bdpart_partition partitions [RTEMS_BDPART_PARTITION_NUMBER_HINT];
0693 size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
0694 partition_table pt = {
0695 .partitions = partitions,
0696 .count = &count
0697 };
0698
0699 sc = process_event(
0700 RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
0701 src,
0702 dest_ptr,
0703 partition_inquiry_worker,
0704 &pt
0705 );
0706
0707 if (sc == RTEMS_SUCCESSFUL) {
0708 sc = attach_and_mount_partitions(src, partitions, count);
0709 }
0710 } else {
0711 sc = process_event(
0712 RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
0713 src,
0714 dest_ptr,
0715 worker,
0716 worker_arg
0717 );
0718 }
0719
0720 return sc;
0721 }
0722
0723 static rtems_status_code do_disk_attach(
0724 const char *src,
0725 char **dest_ptr,
0726 rtems_media_worker worker,
0727 void *worker_arg
0728 )
0729 {
0730 rtems_status_code sc = RTEMS_SUCCESSFUL;
0731 rtems_status_code rsc = RTEMS_SUCCESSFUL;
0732 char *disk_path = NULL;
0733
0734 if (worker != NULL) {
0735 rsc = process_event(
0736 RTEMS_MEDIA_EVENT_DISK_ATTACH,
0737 src,
0738 &disk_path,
0739 worker,
0740 worker_arg
0741 );
0742
0743 if (rsc == RTEMS_SUCCESSFUL) {
0744 sc = do_mount(disk_path, NULL, NULL, NULL);
0745
0746 if (sc != RTEMS_SUCCESSFUL) {
0747 do_partition_inquiry(disk_path, NULL, NULL, NULL);
0748 }
0749 }
0750 } else {
0751 rsc = RTEMS_INVALID_ADDRESS;
0752 }
0753
0754 if (dest_ptr != NULL && rsc == RTEMS_SUCCESSFUL) {
0755 *dest_ptr = disk_path;
0756 } else {
0757 free(disk_path);
0758 }
0759
0760 return rsc;
0761 }
0762
0763 static rtems_status_code unmount_worker(
0764 rtems_media_state state,
0765 const char *src,
0766 char **dest RTEMS_UNUSED,
0767 void *worker_arg RTEMS_UNUSED
0768 )
0769 {
0770 rtems_status_code sc = RTEMS_SUCCESSFUL;
0771
0772 if (state == RTEMS_MEDIA_STATE_READY) {
0773 int rv = unmount(src);
0774
0775 if (rv == 0) {
0776 rv = rmdir(src);
0777 if (rv != 0) {
0778 sc = RTEMS_IO_ERROR;
0779 }
0780 } else {
0781 sc = RTEMS_IO_ERROR;
0782 }
0783 }
0784
0785 return sc;
0786 }
0787
0788 static rtems_status_code do_unmount(
0789 const char *src,
0790 char **dest_ptr,
0791 rtems_media_worker worker,
0792 void *worker_arg
0793 )
0794 {
0795 if (worker == NULL) {
0796 worker = unmount_worker;
0797 worker_arg = NULL;
0798 }
0799
0800 return process_event(
0801 RTEMS_MEDIA_EVENT_UNMOUNT,
0802 src,
0803 dest_ptr,
0804 worker,
0805 worker_arg
0806 );
0807 }
0808
0809 static rtems_status_code disk_detach_worker(
0810 rtems_media_state state,
0811 const char *src,
0812 char **dest RTEMS_UNUSED,
0813 void *worker_arg RTEMS_UNUSED
0814 )
0815 {
0816 rtems_status_code rsc = RTEMS_SUCCESSFUL;
0817
0818 if (state == RTEMS_MEDIA_STATE_READY) {
0819 int rv = unlink(src);
0820
0821 if (rv != 0) {
0822 rsc = RTEMS_IO_ERROR;
0823 }
0824 }
0825
0826 return rsc;
0827 }
0828
0829 static rtems_status_code detach_item(rtems_media_event event, media_item *item)
0830 {
0831 rtems_status_code sc = RTEMS_SUCCESSFUL;
0832 rtems_status_code rsc = RTEMS_SUCCESSFUL;
0833
0834 if (item->mount_path != NULL) {
0835 sc = do_unmount(item->mount_path, NULL, NULL, NULL);
0836 if (sc != RTEMS_SUCCESSFUL) {
0837 rsc = RTEMS_IO_ERROR;
0838 }
0839 }
0840
0841 sc = process_event(event, item->disk_path, NULL, disk_detach_worker, NULL);
0842 if (sc != RTEMS_SUCCESSFUL) {
0843 rsc = RTEMS_IO_ERROR;
0844 }
0845
0846 return rsc;
0847 }
0848
0849 static rtems_status_code detach_parent_item(media_item *parent)
0850 {
0851 rtems_status_code sc = RTEMS_SUCCESSFUL;
0852 rtems_status_code rsc = RTEMS_SUCCESSFUL;
0853
0854 rtems_chain_node *node = rtems_chain_first(&media_item_chain);
0855
0856 while (!rtems_chain_is_tail(&media_item_chain, node)) {
0857 media_item *child = (media_item *) node;
0858
0859 node = rtems_chain_next(node);
0860
0861 if (child->parent == parent) {
0862 sc = detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, child);
0863 if (sc != RTEMS_SUCCESSFUL) {
0864 rsc = RTEMS_IO_ERROR;
0865 }
0866 }
0867 }
0868
0869 sc = detach_item(RTEMS_MEDIA_EVENT_DISK_DETACH, parent);
0870 if (sc != RTEMS_SUCCESSFUL) {
0871 rsc = RTEMS_IO_ERROR;
0872 }
0873
0874 return rsc;
0875 }
0876
0877 static rtems_status_code do_disk_detach(
0878 const char *src,
0879 char **dest_ptr,
0880 rtems_media_worker worker,
0881 void *worker_arg
0882 )
0883 {
0884 if (worker == NULL) {
0885 media_item *parent = get_media_item(src, NULL);
0886
0887 if (parent != NULL) {
0888 return detach_parent_item(parent);
0889 }
0890
0891 worker = disk_detach_worker;
0892 worker_arg = NULL;
0893 }
0894
0895 return process_event(
0896 RTEMS_MEDIA_EVENT_DISK_DETACH,
0897 src,
0898 dest_ptr,
0899 worker,
0900 worker_arg
0901 );
0902 }
0903
0904 static rtems_status_code do_partition_detach(
0905 const char *src,
0906 char **dest_ptr,
0907 rtems_media_worker worker,
0908 void *worker_arg
0909 )
0910 {
0911 if (worker == NULL) {
0912 media_item *item = get_media_item(src, NULL);
0913
0914 if (item != NULL) {
0915 return detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, item);
0916 }
0917
0918 worker = disk_detach_worker;
0919 worker_arg = NULL;
0920 }
0921
0922 return process_event(
0923 RTEMS_MEDIA_EVENT_PARTITION_DETACH,
0924 src,
0925 dest_ptr,
0926 worker,
0927 worker_arg
0928 );
0929 }
0930
0931 rtems_status_code rtems_media_post_event(
0932 rtems_media_event event,
0933 const char *src,
0934 char **dest_ptr,
0935 rtems_media_worker worker,
0936 void *worker_arg
0937 )
0938 {
0939 rtems_status_code sc = RTEMS_SUCCESSFUL;
0940
0941 lock();
0942
0943 switch (event) {
0944 case RTEMS_MEDIA_EVENT_DISK_ATTACH:
0945 sc = do_disk_attach(src, dest_ptr, worker, worker_arg);
0946 break;
0947 case RTEMS_MEDIA_EVENT_DISK_DETACH:
0948 sc = do_disk_detach(src, dest_ptr, worker, worker_arg);
0949 break;
0950 case RTEMS_MEDIA_EVENT_MOUNT:
0951 sc = do_mount(src, dest_ptr, worker, worker_arg);
0952 break;
0953 case RTEMS_MEDIA_EVENT_UNMOUNT:
0954 sc = do_unmount(src, dest_ptr, worker, worker_arg);
0955 break;
0956 case RTEMS_MEDIA_EVENT_PARTITION_INQUIRY:
0957 sc = do_partition_inquiry(src, dest_ptr, worker, worker_arg);
0958 break;
0959 case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
0960 sc = do_partition_attach(src, dest_ptr, worker, worker_arg);
0961 break;
0962 case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
0963 sc = do_partition_detach(src, dest_ptr, worker, worker_arg);
0964 break;
0965 default:
0966 sc = RTEMS_INVALID_ID;
0967 break;
0968 }
0969
0970 unlock();
0971
0972 return sc;
0973 }