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

4.115
Last change on this file since d91e3a7 was d91e3a7, checked in by Sebastian Huber <sebastian.huber@…>, on 08/13/10 at 12:40:16

2010-08-13 Sebastian Huber <sebastian.huber@…>

  • libblock/include/rtems/media.h, libblock/src/media-desc.c, libblock/src/media-dev-ident.c, libblock/src/media-path.c, libblock/src/media-server.c, libblock/src/media.c: New files.
  • Makefile.am, preinstall.am, libblock/Makefile.am: Reflect changes above.
  • Property mode set to 100644
File size: 20.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSMedia
5 *
6 * @brief Media implementation.
7 */
8
9/*
10 * Copyright (c) 2009, 2010 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
26#include <rtems.h>
27#include <rtems/bdbuf.h>
28#include <rtems/diskdevs.h>
29#include <rtems/bdpart.h>
30#include <rtems/libio.h>
31
32#include <rtems/media.h>
33
34typedef struct {
35  rtems_bdpart_partition *partitions;
36  size_t *count;
37} partition_table;
38
39typedef struct {
40  dev_t physical_disk;
41  dev_t logical_disk;
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(&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    strcpy(item->disk_path, disk_path);
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    rtems_device_minor_number minor =
581      rtems_filesystem_dev_minor_t(part->logical_disk);
582    char *part_path = rtems_media_append_minor(src, minor);
583
584    if (part_path == NULL) {
585      return RTEMS_IO_ERROR;
586    }
587
588    sc = rtems_disk_create_log(
589      part->logical_disk,
590      part->physical_disk,
591      part->begin,
592      part->count,
593      part_path
594    );
595    if (sc != RTEMS_SUCCESSFUL) {
596      free(part_path);
597
598      return RTEMS_IO_ERROR;
599    }
600
601    *dest = part_path;
602  }
603
604  return RTEMS_SUCCESSFUL;
605}
606
607static rtems_status_code attach_and_mount_partitions(
608  const char *disk_path,
609  rtems_bdpart_partition *partitions,
610  size_t count
611)
612{
613  rtems_status_code sc = RTEMS_SUCCESSFUL;
614  rtems_device_major_number major = 0;
615  rtems_device_minor_number minor = 0;
616  dev_t dev = 0;
617  size_t i = 0;
618
619  sc = rtems_media_get_device_identifier(disk_path, &dev);
620  if (sc != RTEMS_SUCCESSFUL) {
621    return RTEMS_INVALID_ID;
622  }
623
624  major = rtems_filesystem_dev_major_t(dev);
625  minor = rtems_filesystem_dev_minor_t(dev) + 1;
626
627  for (i = 0; i < count; ++i, ++minor) {
628    partition part_desc = {
629      .physical_disk = dev,
630      .logical_disk = rtems_filesystem_make_dev_t(major, minor),
631      .begin = partitions [i].begin,
632      .count = partitions [i].end - partitions [i].begin
633    };
634    char *part_path = NULL;
635
636    sc = process_event(
637      RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
638      disk_path,
639      &part_path,
640      partition_attach_worker,
641      &part_desc
642    );
643
644    if (sc == RTEMS_SUCCESSFUL) {
645      sc = do_mount(part_path, NULL, NULL, NULL);
646    }
647
648    free(part_path);
649  }
650
651  return sc;
652}
653
654static rtems_status_code partition_inquiry_worker(
655  rtems_media_state state,
656  const char *src,
657  char **dest __attribute__((unused)),
658  void *worker_arg
659)
660{
661  rtems_status_code sc = RTEMS_SUCCESSFUL;
662
663  if (state == RTEMS_MEDIA_STATE_READY) {
664    partition_table *pt = worker_arg;
665    rtems_bdpart_format format;
666
667    sc = rtems_bdpart_read(src, &format, pt->partitions, pt->count);
668    if (sc != RTEMS_SUCCESSFUL || *pt->count == 0) {
669      return RTEMS_IO_ERROR;
670    }
671  }
672
673  return RTEMS_SUCCESSFUL;
674}
675
676static rtems_status_code do_partition_inquiry(
677  const char *src,
678  char **dest_ptr,
679  rtems_media_worker worker,
680  void *worker_arg
681)
682{
683  rtems_status_code sc = RTEMS_SUCCESSFUL;
684
685  if (worker == NULL) {
686    rtems_bdpart_partition partitions [RTEMS_BDPART_PARTITION_NUMBER_HINT];
687    size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
688    partition_table pt = {
689     .partitions = partitions,
690     .count = &count
691    };
692
693    sc = process_event(
694      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
695      src,
696      dest_ptr,
697      partition_inquiry_worker,
698      &pt
699    );
700
701    if (sc == RTEMS_SUCCESSFUL) {
702      sc = attach_and_mount_partitions(src, partitions, count);
703    }
704  } else {
705    sc = process_event(
706      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
707      src,
708      dest_ptr,
709      worker,
710      worker_arg
711    );
712  }
713
714  return sc;
715}
716
717static rtems_status_code do_disk_attach(
718  const char *src,
719  char **dest_ptr,
720  rtems_media_worker worker,
721  void *worker_arg
722)
723{
724  rtems_status_code sc = RTEMS_SUCCESSFUL;
725  rtems_status_code rsc = RTEMS_SUCCESSFUL;
726  char *disk_path = NULL;
727
728  if (worker != NULL) {
729    rsc = process_event(
730      RTEMS_MEDIA_EVENT_DISK_ATTACH,
731      src,
732      &disk_path,
733      worker,
734      worker_arg
735    );
736   
737    if (rsc == RTEMS_SUCCESSFUL) {
738      sc = do_mount(disk_path, NULL, NULL, NULL);
739
740      if (sc != RTEMS_SUCCESSFUL) {
741        do_partition_inquiry(disk_path, NULL, NULL, NULL);
742      }
743    }
744  } else {
745    rsc = RTEMS_INVALID_ADDRESS;
746  }
747
748  if (dest_ptr != NULL && rsc == RTEMS_SUCCESSFUL) {
749    *dest_ptr = disk_path;
750  } else {
751    free(disk_path);
752  }
753
754  return rsc;
755}
756
757static rtems_status_code unmount_worker(
758  rtems_media_state state,
759  const char *src,
760  char **dest __attribute__((unused)),
761  void *worker_arg __attribute__((unused))
762)
763{
764  rtems_status_code sc = RTEMS_SUCCESSFUL;
765
766  if (state == RTEMS_MEDIA_STATE_READY) {
767    int rv = unmount(src);
768
769    if (rv == 0) {
770      rv = rmdir(src);
771      if (rv != 0) {
772        sc = RTEMS_IO_ERROR;
773      }
774    } else {
775      sc = RTEMS_IO_ERROR;
776    }
777  }
778
779  return sc;
780}
781
782static rtems_status_code do_unmount(
783  const char *src,
784  char **dest_ptr,
785  rtems_media_worker worker,
786  void *worker_arg
787)
788{
789  if (worker == NULL) {
790    worker = unmount_worker;
791    worker_arg = NULL;
792  }
793
794  return process_event(
795    RTEMS_MEDIA_EVENT_UNMOUNT,
796    src,
797    dest_ptr,
798    worker,
799    worker_arg
800  );
801}
802
803static rtems_status_code disk_detach_worker(
804  rtems_media_state state,
805  const char *src,
806  char **dest __attribute__((unused)),
807  void *worker_arg __attribute__((unused))
808)
809{
810  rtems_status_code sc = RTEMS_SUCCESSFUL;
811  rtems_status_code rsc = RTEMS_SUCCESSFUL;
812
813  if (state == RTEMS_MEDIA_STATE_READY) {
814    dev_t dev = 0;
815
816    sc = rtems_media_get_device_identifier(src, &dev);
817    if (sc != RTEMS_SUCCESSFUL) {
818      return RTEMS_IO_ERROR;
819    }
820
821    sc = rtems_bdbuf_syncdev(dev);
822    if (sc != RTEMS_SUCCESSFUL) {
823      rsc = RTEMS_IO_ERROR;
824    }
825
826    sc = rtems_disk_delete(dev);
827    if (sc != RTEMS_SUCCESSFUL) {
828      rsc = RTEMS_IO_ERROR;
829    }
830
831    rtems_bdbuf_purge_dev(dev);
832
833    if (rtems_filesystem_dev_minor_t(dev) == 0) {
834      sc = rtems_io_unregister_driver(rtems_filesystem_dev_major_t(dev));
835      if (sc != RTEMS_SUCCESSFUL) {
836        rsc = RTEMS_IO_ERROR;
837      }
838    }
839  }
840
841  return rsc;
842}
843
844static rtems_status_code detach_item(rtems_media_event event, media_item *item)
845{
846  rtems_status_code sc = RTEMS_SUCCESSFUL;
847  rtems_status_code rsc = RTEMS_SUCCESSFUL;
848
849  if (item->mount_path != NULL) {
850    sc = do_unmount(item->mount_path, NULL, NULL, NULL);
851    if (sc != RTEMS_SUCCESSFUL) {
852      rsc = RTEMS_IO_ERROR;
853    }
854  }
855
856  sc = process_event(event, item->disk_path, NULL, disk_detach_worker, NULL);
857  if (sc != RTEMS_SUCCESSFUL) {
858    rsc = RTEMS_IO_ERROR;
859  }
860
861  return rsc;
862}
863
864static rtems_status_code detach_parent_item(media_item *parent)
865{
866  rtems_status_code sc = RTEMS_SUCCESSFUL;
867  rtems_status_code rsc = RTEMS_SUCCESSFUL;
868
869  rtems_chain_node *node = rtems_chain_first(&media_item_chain);
870
871  while (!rtems_chain_is_tail(&media_item_chain, node)) {
872    media_item *child = (media_item *) node;
873
874    node = rtems_chain_next(node);
875
876    if (child->parent == parent) {
877      sc = detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, child);
878      if (sc != RTEMS_SUCCESSFUL) {
879        rsc = RTEMS_IO_ERROR;
880      }
881    }
882  }
883
884  sc = detach_item(RTEMS_MEDIA_EVENT_DISK_DETACH, parent);
885  if (sc != RTEMS_SUCCESSFUL) {
886    rsc = RTEMS_IO_ERROR;
887  }
888
889  return rsc;
890}
891
892static rtems_status_code do_disk_detach(
893  const char *src,
894  char **dest_ptr,
895  rtems_media_worker worker,
896  void *worker_arg
897)
898{
899  if (worker == NULL) {
900    media_item *parent = get_media_item(src, NULL);
901
902    if (parent != NULL) {
903      return detach_parent_item(parent);
904    }
905
906    worker = disk_detach_worker;
907    worker_arg = NULL;
908  }
909
910  return process_event(
911    RTEMS_MEDIA_EVENT_DISK_DETACH,
912    src,
913    dest_ptr,
914    worker,
915    worker_arg
916  );
917}
918
919static rtems_status_code do_partition_detach(
920  const char *src,
921  char **dest_ptr,
922  rtems_media_worker worker,
923  void *worker_arg
924)
925{
926  if (worker == NULL) {
927    media_item *item = get_media_item(src, NULL);
928
929    if (item != NULL) {
930      return detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, item);
931    }
932
933    worker = disk_detach_worker;
934    worker_arg = NULL;
935  }
936
937  return process_event(
938    RTEMS_MEDIA_EVENT_PARTITION_DETACH,
939    src,
940    dest_ptr,
941    worker,
942    worker_arg
943  );
944}
945
946rtems_status_code rtems_media_post_event(
947  rtems_media_event event,
948  const char *src,
949  char **dest_ptr,
950  rtems_media_worker worker,
951  void *worker_arg
952)
953{
954  rtems_status_code sc = RTEMS_SUCCESSFUL;
955
956  sc = lock();
957  if (sc != RTEMS_SUCCESSFUL) {
958    return sc;
959  }
960
961  switch (event) {
962    case RTEMS_MEDIA_EVENT_DISK_ATTACH:
963      sc = do_disk_attach(src, dest_ptr, worker, worker_arg);
964      break;
965    case RTEMS_MEDIA_EVENT_DISK_DETACH:
966      sc = do_disk_detach(src, dest_ptr, worker, worker_arg);
967      break;
968    case RTEMS_MEDIA_EVENT_MOUNT:
969      sc = do_mount(src, dest_ptr, worker, worker_arg);
970      break;
971    case RTEMS_MEDIA_EVENT_UNMOUNT:
972      sc = do_unmount(src, dest_ptr, worker, worker_arg);
973      break;
974    case RTEMS_MEDIA_EVENT_PARTITION_INQUIRY:
975      sc = do_partition_inquiry(src, dest_ptr, worker, worker_arg);
976      break;
977    case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
978      sc = do_partition_attach(src, dest_ptr, worker, worker_arg);
979      break;
980    case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
981      sc = do_partition_detach(src, dest_ptr, worker, worker_arg);
982      break;
983    default:
984      sc = RTEMS_INVALID_ID;
985      break;
986  }
987
988  unlock();
989
990  return sc;
991}
992
993rtems_status_code rtems_media_initialize(void)
994{
995  rtems_status_code sc = RTEMS_SUCCESSFUL;
996
997  if (media_mutex == RTEMS_ID_NONE) {
998    sc = rtems_semaphore_create(
999      rtems_build_name('M', 'D', 'I', 'A'),
1000      1,
1001      RTEMS_LOCAL | RTEMS_PRIORITY
1002        | RTEMS_INHERIT_PRIORITY | RTEMS_BINARY_SEMAPHORE,
1003      0,
1004      &media_mutex
1005    );
1006    if (sc != RTEMS_SUCCESSFUL) {
1007      sc = RTEMS_NO_MEMORY;
1008    }
1009  }
1010
1011  return sc;
1012}
Note: See TracBrowser for help on using the repository browser.