source: rtems/cpukit/libblock/src/media.c @ d8ec270b

5
Last change on this file since d8ec270b was d8ec270b, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/16 at 08:29:09

libblock: Drop superfluous <stdlib.h> include

Drop superfluous <stdlib.h> include from <rtems/diskdevs.h> since this
leads to conflicts with the latest Newlib in case this header file is
used in the FreeBSD kernel space, e.g. for USB mass storage support.

  • Property mode set to 100644
File size: 20.1 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSMedia
5 *
6 * @brief Media implementation.
7 */
8
9/*
10 * Copyright (c) 2009-2013 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#include <stdlib.h>
24#include <string.h>
25#include <assert.h>
26#include <unistd.h>
27
28#include <rtems.h>
29#include <rtems/bdbuf.h>
30#include <rtems/blkdev.h>
31#include <rtems/bdpart.h>
32#include <rtems/libio.h>
33#include <rtems/dosfs.h>
34
35#include <rtems/media.h>
36
37typedef struct {
38  rtems_bdpart_partition *partitions;
39  size_t *count;
40} partition_table;
41
42typedef struct {
43  size_t index;
44  rtems_blkdev_bnum begin;
45  rtems_blkdev_bnum count;
46} partition;
47
48typedef struct media_item {
49  rtems_chain_node node;
50  struct media_item *parent;
51  char *disk_path;
52  char *mount_path;
53} media_item;
54
55typedef struct listener_item {
56  rtems_chain_node node;
57  rtems_media_listener listener;
58  void *listener_arg;
59} listener_item;
60
61static RTEMS_CHAIN_DEFINE_EMPTY(listener_item_chain);
62
63static RTEMS_CHAIN_DEFINE_EMPTY(media_item_chain);
64
65static rtems_id media_mutex = RTEMS_ID_NONE;
66
67static rtems_status_code lock(void)
68{
69  rtems_status_code sc = RTEMS_SUCCESSFUL;
70
71  sc = rtems_semaphore_obtain(media_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
72  if (sc != RTEMS_SUCCESSFUL) {
73    sc = RTEMS_NOT_CONFIGURED;
74  }
75
76  return sc;
77}
78
79static void unlock(void)
80{
81  rtems_status_code sc = RTEMS_SUCCESSFUL;
82
83  sc = rtems_semaphore_release(media_mutex);
84  assert(sc == RTEMS_SUCCESSFUL);
85}
86
87static listener_item *find_listener(
88  rtems_media_listener listener,
89  void *listener_arg
90)
91{
92  rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
93
94  while (!rtems_chain_is_tail(&listener_item_chain, node)) {
95    listener_item *item = (listener_item *) node;
96
97    if (item->listener == listener && item->listener_arg == listener_arg) {
98      return item;
99    }
100
101    node = rtems_chain_next(node);
102  }
103
104  return NULL;
105}
106
107rtems_status_code rtems_media_listener_add(
108  rtems_media_listener listener,
109  void *listener_arg
110)
111{
112  rtems_status_code sc = RTEMS_SUCCESSFUL;
113
114  sc = lock();
115  if (sc == RTEMS_SUCCESSFUL) {
116    listener_item *item = find_listener(listener, listener_arg);
117
118    if (item == NULL) {
119      item = malloc(sizeof(*item));
120      if (item != NULL) {
121        item->listener = listener;
122        item->listener_arg = listener_arg;
123        rtems_chain_append_unprotected(&listener_item_chain, &item->node);
124      } else {
125        sc = RTEMS_NO_MEMORY;
126      }
127    } else {
128      sc = RTEMS_TOO_MANY;
129    }
130
131    unlock();
132  }
133
134  return sc;
135}
136
137rtems_status_code rtems_media_listener_remove(
138  rtems_media_listener listener,
139  void *listener_arg
140)
141{
142  rtems_status_code sc = RTEMS_SUCCESSFUL;
143
144  sc = lock();
145  if (sc == RTEMS_SUCCESSFUL) {
146    listener_item *item = find_listener(listener, listener_arg);
147
148    if (item != NULL) {
149      rtems_chain_extract_unprotected(&item->node);
150      free(item);
151    } else {
152      sc = RTEMS_INVALID_ID;
153    }
154
155    unlock();
156  }
157
158  return sc;
159}
160
161static rtems_status_code notify(
162  rtems_media_event event,
163  rtems_media_state state,
164  const char *src,
165  const char *dest
166)
167{
168  rtems_status_code sc = RTEMS_SUCCESSFUL;
169  rtems_status_code rsc = RTEMS_SUCCESSFUL;
170  rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
171
172  while (!rtems_chain_is_tail(&listener_item_chain, node)) {
173    listener_item *item = (listener_item *) node;
174
175    sc = (*item->listener)(event, state, src, dest, item->listener_arg);
176    if (sc != RTEMS_SUCCESSFUL) {
177      rsc = sc;
178    }
179
180    node = rtems_chain_next(node);
181  }
182
183  return rsc;
184}
185
186static void error(
187  rtems_media_state state,
188  const char *src,
189  const char *dest
190)
191{
192  notify(RTEMS_MEDIA_EVENT_ERROR, state, src, dest);
193}
194
195static media_item *get_media_item(
196  const char *disk_path,
197  const char *mount_path
198)
199{
200  rtems_chain_node *node = rtems_chain_first(&media_item_chain);
201
202  while (!rtems_chain_is_tail(&media_item_chain, node)) {
203    media_item *item = (media_item *) node;
204
205    if (
206      (disk_path == NULL || strcmp(disk_path, item->disk_path) == 0)
207        && (mount_path == NULL
208          || (item->mount_path != NULL
209            && strcmp(mount_path, item->mount_path) == 0))
210    ) {
211      return item;
212    }
213
214    node = rtems_chain_next(node);
215  }
216
217  return NULL;
218}
219
220static void free_item(media_item *item)
221{
222  rtems_chain_extract_unprotected(&item->node);
223  free(item->mount_path);
224  free(item);
225}
226
227static void create_item(
228  media_item *parent,
229  const char *disk_path,
230  const char *mount_path
231)
232{
233  size_t disk_path_size = strlen(disk_path) + 1;
234  media_item *item = malloc(sizeof(*item) + disk_path_size);
235
236  if (item != NULL) {
237    if (mount_path != NULL) {
238      item->mount_path = strdup(mount_path);
239
240      if (item->mount_path == NULL) {
241        free(item);
242
243        return;
244      }
245    } else {
246      item->mount_path = NULL;
247    }
248
249    item->parent = parent;
250    item->disk_path = (char *) item + sizeof(*item);
251    memcpy(item->disk_path, disk_path, disk_path_size);
252    rtems_chain_append(&media_item_chain, &item->node);
253  }
254}
255
256static void remove_mount_point(const char *mount_path)
257{
258  media_item *item = get_media_item(NULL, mount_path);
259
260  if (item != NULL) {
261    free(item->mount_path);
262    item->mount_path = NULL;
263  } else {
264    error(RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN, mount_path, NULL);
265  }
266}
267
268static void remove_partition(const char *partition_path)
269{
270  media_item *item = get_media_item(partition_path, NULL);
271
272  if (item != NULL) {
273    if (item->mount_path != NULL) {
274      error(
275        RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT,
276        partition_path,
277        item->mount_path
278      );
279    }
280    free_item(item);
281  } else {
282    error(RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN, partition_path, NULL);
283  }
284}
285
286static void remove_disk(const char *disk_path)
287{
288  media_item *item = get_media_item(disk_path, NULL);
289
290  if (item != NULL) {
291    rtems_chain_node *node = rtems_chain_first(&media_item_chain);
292
293    while (!rtems_chain_is_tail(&media_item_chain, node)) {
294      media_item *child = (media_item *) node;
295
296      node = rtems_chain_next(node);
297
298      if (child->parent == item) {
299        if (child->mount_path != NULL) {
300          error(
301            RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN,
302            child->mount_path,
303            disk_path
304          );
305        }
306        error(RTEMS_MEDIA_ERROR_PARTITION_ORPHAN, child->disk_path, disk_path);
307        free_item(child);
308      }
309    }
310
311    free_item(item);
312  } else {
313    error(RTEMS_MEDIA_ERROR_DISK_UNKNOWN, disk_path, NULL);
314  }
315}
316
317static void add_disk(const char *disk_path)
318{
319  media_item *item = get_media_item(disk_path, NULL);
320
321  if (item != NULL) {
322    error(RTEMS_MEDIA_ERROR_DISK_EXISTS, disk_path, NULL);
323    remove_disk(disk_path);
324  }
325
326  create_item(NULL, disk_path, NULL);
327}
328
329static void add_partition(const char *disk_path, const char *partition_path)
330{
331  media_item *item = get_media_item(partition_path, NULL);
332  media_item *parent = get_media_item(disk_path, NULL);
333
334  if (item != NULL) {
335    error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS, partition_path, NULL);
336    remove_disk(partition_path);
337  }
338
339  if (parent != NULL) {
340    create_item(parent, partition_path, NULL);
341  } else {
342    error(
343      RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK,
344      partition_path,
345      disk_path
346    );
347  }
348}
349
350static void add_mount_point(const char *disk_path, const char *mount_path)
351{
352  media_item *item = get_media_item(disk_path, NULL);
353
354  if (item != NULL) {
355    if (item->mount_path != NULL) {
356      error(RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS, item->mount_path, NULL);
357      free(item->mount_path);
358    }
359    item->mount_path = strdup(mount_path);
360  } else {
361    error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN, disk_path, NULL);
362  }
363}
364
365static bool is_add_state(rtems_media_state state)
366{
367  return state == RTEMS_MEDIA_STATE_SUCCESS;
368}
369
370static bool is_remove_state(rtems_media_state state)
371{
372  return state == RTEMS_MEDIA_STATE_SUCCESS
373    || state == RTEMS_MEDIA_STATE_FAILED;
374}
375
376static rtems_status_code remember_event(
377  rtems_media_event event,
378  rtems_media_state state,
379  const char *src,
380  const char *dest
381)
382{
383  switch (event) {
384    case RTEMS_MEDIA_EVENT_DISK_ATTACH:
385      if (is_add_state(state)) {
386        add_disk(dest);
387      }
388      break;
389    case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
390      if (is_add_state(state)) {
391        add_partition(src, dest);
392      }
393      break;
394    case RTEMS_MEDIA_EVENT_MOUNT:
395      if (is_add_state(state)) {
396        add_mount_point(src, dest);
397      }
398      break;
399    case RTEMS_MEDIA_EVENT_UNMOUNT:
400      if (is_remove_state(state)) {
401        remove_mount_point(src);
402      }
403      break;
404    case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
405      if (is_remove_state(state)) {
406        remove_partition(src);
407      }
408      break;
409    case RTEMS_MEDIA_EVENT_DISK_DETACH:
410      if (is_remove_state(state)) {
411        remove_disk(src);
412      }
413      break;
414    default:
415      break;
416  }
417
418  return RTEMS_SUCCESSFUL;
419}
420
421static rtems_status_code process_event(
422  rtems_media_event event,
423  const char *src,
424  char **dest_ptr,
425  rtems_media_worker worker,
426  void *worker_arg
427)
428{
429  rtems_status_code sc = RTEMS_SUCCESSFUL;
430  rtems_media_state state = RTEMS_MEDIA_STATE_FAILED;
431  char *dest = NULL;
432
433  sc = notify(event, RTEMS_MEDIA_STATE_INQUIRY, src, NULL);
434  if (sc == RTEMS_SUCCESSFUL) {
435    state = RTEMS_MEDIA_STATE_READY;
436  } else {
437    state = RTEMS_MEDIA_STATE_ABORTED;
438  }
439
440  sc = (*worker)(state, src, &dest, worker_arg);
441  if (state == RTEMS_MEDIA_STATE_READY) {
442    if (sc == RTEMS_SUCCESSFUL) {
443      state = RTEMS_MEDIA_STATE_SUCCESS;
444    } else {
445      state = RTEMS_MEDIA_STATE_FAILED;
446    }
447  }
448
449  notify(event, state, src, dest);
450  remember_event(event, state, src, dest);
451
452  if (state == RTEMS_MEDIA_STATE_SUCCESS) {
453    sc = RTEMS_SUCCESSFUL;
454  } else if (state == RTEMS_MEDIA_STATE_ABORTED) {
455    sc = RTEMS_UNSATISFIED;
456  } else {
457    sc = RTEMS_IO_ERROR;
458  }
459
460  if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
461    *dest_ptr = dest;
462  } else {
463    free(dest);
464  }
465
466  return sc;
467}
468
469static rtems_status_code mount_worker(
470  rtems_media_state state,
471  const char *src,
472  char **dest,
473  void *worker_arg
474)
475{
476  int rv = 0;
477
478  if (state == RTEMS_MEDIA_STATE_READY) {
479    rtems_dosfs_mount_options mount_options;
480    char *mount_path = NULL;
481
482    if (worker_arg == NULL) {
483      mount_path = rtems_media_replace_prefix(RTEMS_MEDIA_MOUNT_BASE, src);
484    } else {
485      mount_path = strdup(worker_arg);
486    }
487
488    if (mount_path == NULL) {
489      return RTEMS_IO_ERROR;
490    }
491
492    rv = rtems_mkdir(mount_path, S_IRWXU | S_IRWXG | S_IRWXO);
493    if (rv != 0) {
494      free(mount_path);
495
496      return RTEMS_IO_ERROR;
497    }
498
499    memset(&mount_options, 0, sizeof(mount_options));
500
501    /* In case this fails, we fall back to use the default converter */
502    mount_options.converter = rtems_dosfs_create_utf8_converter("CP850");
503
504    rv = mount(
505      src,
506      mount_path,
507      RTEMS_FILESYSTEM_TYPE_DOSFS,
508      RTEMS_FILESYSTEM_READ_WRITE,
509      &mount_options
510    );
511    if (rv != 0) {
512      rmdir(mount_path);
513      free(mount_path);
514
515      return RTEMS_IO_ERROR;
516    }
517
518    *dest = mount_path;
519  }
520
521  return RTEMS_SUCCESSFUL;
522}
523
524static rtems_status_code do_mount(
525  const char *src,
526  char **dest_ptr,
527  rtems_media_worker worker,
528  void *worker_arg
529)
530{
531  if (worker == NULL) {
532    worker = mount_worker;
533  }
534
535  return process_event(
536    RTEMS_MEDIA_EVENT_MOUNT,
537    src,
538    dest_ptr,
539    worker,
540    worker_arg
541  );
542}
543
544static rtems_status_code do_partition_attach(
545  const char *src,
546  char **dest_ptr,
547  rtems_media_worker worker,
548  void *worker_arg
549)
550{
551  rtems_status_code sc = RTEMS_SUCCESSFUL;
552  char *part_path = NULL;
553
554  if (worker != NULL) {
555    sc = process_event(
556      RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
557      src,
558      &part_path,
559      worker,
560      worker_arg
561    );
562
563    if (sc == RTEMS_SUCCESSFUL) {
564      sc = do_mount(part_path, NULL, NULL, NULL);
565    }
566  } else {
567    sc = RTEMS_INVALID_ADDRESS;
568  }
569
570  if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
571    *dest_ptr = part_path;
572  } else {
573    free(part_path);
574  }
575
576  return sc;
577}
578
579static rtems_status_code partition_attach_worker(
580  rtems_media_state state,
581  const char *src,
582  char **dest,
583  void *worker_arg
584)
585{
586  rtems_status_code sc = RTEMS_SUCCESSFUL;
587
588  if (state == RTEMS_MEDIA_STATE_READY) {
589    partition *part = worker_arg;
590    char *part_path = rtems_media_append_minor(src, part->index);
591
592    if (part_path == NULL) {
593      return RTEMS_IO_ERROR;
594    }
595
596    sc = rtems_blkdev_create_partition(
597      part_path,
598      src,
599      part->begin,
600      part->count
601    );
602    if (sc != RTEMS_SUCCESSFUL) {
603      free(part_path);
604
605      return RTEMS_IO_ERROR;
606    }
607
608    *dest = part_path;
609  }
610
611  return RTEMS_SUCCESSFUL;
612}
613
614static rtems_status_code attach_and_mount_partitions(
615  const char *disk_path,
616  const rtems_bdpart_partition *partitions,
617  size_t count
618)
619{
620  rtems_status_code sc = RTEMS_SUCCESSFUL;
621  size_t i = 0;
622
623  for (i = 0; i < count; ++i) {
624    partition part_desc = {
625      .index = i,
626      .begin = partitions [i].begin,
627      .count = partitions [i].end - partitions [i].begin
628    };
629    char *part_path = NULL;
630
631    sc = process_event(
632      RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
633      disk_path,
634      &part_path,
635      partition_attach_worker,
636      &part_desc
637    );
638
639    if (sc == RTEMS_SUCCESSFUL) {
640      sc = do_mount(part_path, NULL, NULL, NULL);
641    }
642
643    free(part_path);
644  }
645
646  return sc;
647}
648
649static rtems_status_code partition_inquiry_worker(
650  rtems_media_state state,
651  const char *src,
652  char **dest RTEMS_UNUSED,
653  void *worker_arg
654)
655{
656  rtems_status_code sc = RTEMS_SUCCESSFUL;
657
658  if (state == RTEMS_MEDIA_STATE_READY) {
659    partition_table *pt = worker_arg;
660    rtems_bdpart_format format;
661
662    sc = rtems_bdpart_read(src, &format, pt->partitions, pt->count);
663    if (sc != RTEMS_SUCCESSFUL || *pt->count == 0) {
664      return RTEMS_IO_ERROR;
665    }
666  }
667
668  return RTEMS_SUCCESSFUL;
669}
670
671static rtems_status_code do_partition_inquiry(
672  const char *src,
673  char **dest_ptr,
674  rtems_media_worker worker,
675  void *worker_arg
676)
677{
678  rtems_status_code sc = RTEMS_SUCCESSFUL;
679
680  if (worker == NULL) {
681    rtems_bdpart_partition partitions [RTEMS_BDPART_PARTITION_NUMBER_HINT];
682    size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
683    partition_table pt = {
684     .partitions = partitions,
685     .count = &count
686    };
687
688    sc = process_event(
689      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
690      src,
691      dest_ptr,
692      partition_inquiry_worker,
693      &pt
694    );
695
696    if (sc == RTEMS_SUCCESSFUL) {
697      sc = attach_and_mount_partitions(src, partitions, count);
698    }
699  } else {
700    sc = process_event(
701      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
702      src,
703      dest_ptr,
704      worker,
705      worker_arg
706    );
707  }
708
709  return sc;
710}
711
712static rtems_status_code do_disk_attach(
713  const char *src,
714  char **dest_ptr,
715  rtems_media_worker worker,
716  void *worker_arg
717)
718{
719  rtems_status_code sc = RTEMS_SUCCESSFUL;
720  rtems_status_code rsc = RTEMS_SUCCESSFUL;
721  char *disk_path = NULL;
722
723  if (worker != NULL) {
724    rsc = process_event(
725      RTEMS_MEDIA_EVENT_DISK_ATTACH,
726      src,
727      &disk_path,
728      worker,
729      worker_arg
730    );
731   
732    if (rsc == RTEMS_SUCCESSFUL) {
733      sc = do_mount(disk_path, NULL, NULL, NULL);
734
735      if (sc != RTEMS_SUCCESSFUL) {
736        do_partition_inquiry(disk_path, NULL, NULL, NULL);
737      }
738    }
739  } else {
740    rsc = RTEMS_INVALID_ADDRESS;
741  }
742
743  if (dest_ptr != NULL && rsc == RTEMS_SUCCESSFUL) {
744    *dest_ptr = disk_path;
745  } else {
746    free(disk_path);
747  }
748
749  return rsc;
750}
751
752static rtems_status_code unmount_worker(
753  rtems_media_state state,
754  const char *src,
755  char **dest RTEMS_UNUSED,
756  void *worker_arg RTEMS_UNUSED
757)
758{
759  rtems_status_code sc = RTEMS_SUCCESSFUL;
760
761  if (state == RTEMS_MEDIA_STATE_READY) {
762    int rv = unmount(src);
763
764    if (rv == 0) {
765      rv = rmdir(src);
766      if (rv != 0) {
767        sc = RTEMS_IO_ERROR;
768      }
769    } else {
770      sc = RTEMS_IO_ERROR;
771    }
772  }
773
774  return sc;
775}
776
777static rtems_status_code do_unmount(
778  const char *src,
779  char **dest_ptr,
780  rtems_media_worker worker,
781  void *worker_arg
782)
783{
784  if (worker == NULL) {
785    worker = unmount_worker;
786    worker_arg = NULL;
787  }
788
789  return process_event(
790    RTEMS_MEDIA_EVENT_UNMOUNT,
791    src,
792    dest_ptr,
793    worker,
794    worker_arg
795  );
796}
797
798static rtems_status_code disk_detach_worker(
799  rtems_media_state state,
800  const char *src,
801  char **dest RTEMS_UNUSED,
802  void *worker_arg RTEMS_UNUSED
803)
804{
805  rtems_status_code rsc = RTEMS_SUCCESSFUL;
806
807  if (state == RTEMS_MEDIA_STATE_READY) {
808    int rv = unlink(src);
809
810    if (rv != 0) {
811      rsc = RTEMS_IO_ERROR;
812    }
813  }
814
815  return rsc;
816}
817
818static rtems_status_code detach_item(rtems_media_event event, media_item *item)
819{
820  rtems_status_code sc = RTEMS_SUCCESSFUL;
821  rtems_status_code rsc = RTEMS_SUCCESSFUL;
822
823  if (item->mount_path != NULL) {
824    sc = do_unmount(item->mount_path, NULL, NULL, NULL);
825    if (sc != RTEMS_SUCCESSFUL) {
826      rsc = RTEMS_IO_ERROR;
827    }
828  }
829
830  sc = process_event(event, item->disk_path, NULL, disk_detach_worker, NULL);
831  if (sc != RTEMS_SUCCESSFUL) {
832    rsc = RTEMS_IO_ERROR;
833  }
834
835  return rsc;
836}
837
838static rtems_status_code detach_parent_item(media_item *parent)
839{
840  rtems_status_code sc = RTEMS_SUCCESSFUL;
841  rtems_status_code rsc = RTEMS_SUCCESSFUL;
842
843  rtems_chain_node *node = rtems_chain_first(&media_item_chain);
844
845  while (!rtems_chain_is_tail(&media_item_chain, node)) {
846    media_item *child = (media_item *) node;
847
848    node = rtems_chain_next(node);
849
850    if (child->parent == parent) {
851      sc = detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, child);
852      if (sc != RTEMS_SUCCESSFUL) {
853        rsc = RTEMS_IO_ERROR;
854      }
855    }
856  }
857
858  sc = detach_item(RTEMS_MEDIA_EVENT_DISK_DETACH, parent);
859  if (sc != RTEMS_SUCCESSFUL) {
860    rsc = RTEMS_IO_ERROR;
861  }
862
863  return rsc;
864}
865
866static rtems_status_code do_disk_detach(
867  const char *src,
868  char **dest_ptr,
869  rtems_media_worker worker,
870  void *worker_arg
871)
872{
873  if (worker == NULL) {
874    media_item *parent = get_media_item(src, NULL);
875
876    if (parent != NULL) {
877      return detach_parent_item(parent);
878    }
879
880    worker = disk_detach_worker;
881    worker_arg = NULL;
882  }
883
884  return process_event(
885    RTEMS_MEDIA_EVENT_DISK_DETACH,
886    src,
887    dest_ptr,
888    worker,
889    worker_arg
890  );
891}
892
893static rtems_status_code do_partition_detach(
894  const char *src,
895  char **dest_ptr,
896  rtems_media_worker worker,
897  void *worker_arg
898)
899{
900  if (worker == NULL) {
901    media_item *item = get_media_item(src, NULL);
902
903    if (item != NULL) {
904      return detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, item);
905    }
906
907    worker = disk_detach_worker;
908    worker_arg = NULL;
909  }
910
911  return process_event(
912    RTEMS_MEDIA_EVENT_PARTITION_DETACH,
913    src,
914    dest_ptr,
915    worker,
916    worker_arg
917  );
918}
919
920rtems_status_code rtems_media_post_event(
921  rtems_media_event event,
922  const char *src,
923  char **dest_ptr,
924  rtems_media_worker worker,
925  void *worker_arg
926)
927{
928  rtems_status_code sc = RTEMS_SUCCESSFUL;
929
930  sc = lock();
931  if (sc != RTEMS_SUCCESSFUL) {
932    return sc;
933  }
934
935  switch (event) {
936    case RTEMS_MEDIA_EVENT_DISK_ATTACH:
937      sc = do_disk_attach(src, dest_ptr, worker, worker_arg);
938      break;
939    case RTEMS_MEDIA_EVENT_DISK_DETACH:
940      sc = do_disk_detach(src, dest_ptr, worker, worker_arg);
941      break;
942    case RTEMS_MEDIA_EVENT_MOUNT:
943      sc = do_mount(src, dest_ptr, worker, worker_arg);
944      break;
945    case RTEMS_MEDIA_EVENT_UNMOUNT:
946      sc = do_unmount(src, dest_ptr, worker, worker_arg);
947      break;
948    case RTEMS_MEDIA_EVENT_PARTITION_INQUIRY:
949      sc = do_partition_inquiry(src, dest_ptr, worker, worker_arg);
950      break;
951    case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
952      sc = do_partition_attach(src, dest_ptr, worker, worker_arg);
953      break;
954    case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
955      sc = do_partition_detach(src, dest_ptr, worker, worker_arg);
956      break;
957    default:
958      sc = RTEMS_INVALID_ID;
959      break;
960  }
961
962  unlock();
963
964  return sc;
965}
966
967rtems_status_code rtems_media_initialize(void)
968{
969  rtems_status_code sc = RTEMS_SUCCESSFUL;
970
971  if (media_mutex == RTEMS_ID_NONE) {
972    sc = rtems_semaphore_create(
973      rtems_build_name('M', 'D', 'I', 'A'),
974      1,
975      RTEMS_LOCAL | RTEMS_PRIORITY
976        | RTEMS_INHERIT_PRIORITY | RTEMS_BINARY_SEMAPHORE,
977      0,
978      &media_mutex
979    );
980    if (sc != RTEMS_SUCCESSFUL) {
981      sc = RTEMS_NO_MEMORY;
982    }
983  }
984
985  return sc;
986}
Note: See TracBrowser for help on using the repository browser.