source: rtems/cpukit/libblock/src/media.c @ 3d60c1b

4.115
Last change on this file since 3d60c1b was 3ab9c76d, checked in by Sebastian Huber <sebastian.huber@…>, on 03/05/12 at 15:22:33

libblock: Use new API for disk media

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