<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>change log for rtems (2010-08-13)</title>
</head>
<body text='#000000' bgcolor='#ffffff'>
<a name='cs1'></a>
<table border='0' cellspacing='0' cellpadding='5' width='100%' bgcolor='#eeeeee'>
<tr><td colspan='3' bgcolor='#dddddd'>
 <font color='#bb2222'><strong>sh</strong></font>
</td></tr>
<tr><td colspan='3' bgcolor='#dddddd'><pre>2010-08-13 Sebastian Huber <sebastian.huber@embedded-brains.de>

        * 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.
</pre></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/ChangeLog.diff?r1=text&tr1=1.2563&r2=text&tr2=1.2564&diff_format=h">M</a></td><td width='1%'>1.2564</td><td width='100%'>cpukit/ChangeLog</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/Makefile.am.diff?r1=text&tr1=1.100&r2=text&tr2=1.101&diff_format=h">M</a></td><td width='1%'>1.101</td><td width='100%'>cpukit/Makefile.am</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libblock/Makefile.am.diff?r1=text&tr1=1.38&r2=text&tr2=1.39&diff_format=h">M</a></td><td width='1%'>1.39</td><td width='100%'>cpukit/libblock/Makefile.am</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libblock/include/rtems/media.h?rev=1.1&content-type=text/vnd.viewcvs-markup">A</a></td><td width='1%'><font color="#000088">1.1</font></td><td width='100%'><font color="#000088">cpukit/libblock/include/rtems/media.h</font></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libblock/src/media-desc.c?rev=1.1&content-type=text/vnd.viewcvs-markup">A</a></td><td width='1%'><font color="#000088">1.1</font></td><td width='100%'><font color="#000088">cpukit/libblock/src/media-desc.c</font></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libblock/src/media-dev-ident.c?rev=1.1&content-type=text/vnd.viewcvs-markup">A</a></td><td width='1%'><font color="#000088">1.1</font></td><td width='100%'><font color="#000088">cpukit/libblock/src/media-dev-ident.c</font></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libblock/src/media-path.c?rev=1.1&content-type=text/vnd.viewcvs-markup">A</a></td><td width='1%'><font color="#000088">1.1</font></td><td width='100%'><font color="#000088">cpukit/libblock/src/media-path.c</font></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libblock/src/media-server.c?rev=1.1&content-type=text/vnd.viewcvs-markup">A</a></td><td width='1%'><font color="#000088">1.1</font></td><td width='100%'><font color="#000088">cpukit/libblock/src/media-server.c</font></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libblock/src/media.c?rev=1.1&content-type=text/vnd.viewcvs-markup">A</a></td><td width='1%'><font color="#000088">1.1</font></td><td width='100%'><font color="#000088">cpukit/libblock/src/media.c</font></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/preinstall.am.diff?r1=text&tr1=1.46&r2=text&tr2=1.47&diff_format=h">M</a></td><td width='1%'>1.47</td><td width='100%'>cpukit/preinstall.am</td></tr>
</table>
<pre>
<font color='#006600'>diff -u rtems/cpukit/ChangeLog:1.2563 rtems/cpukit/ChangeLog:1.2564
--- rtems/cpukit/ChangeLog:1.2563       Thu Aug 12 23:49:30 2010
+++ rtems/cpukit/ChangeLog      Fri Aug 13 07:40:15 2010
</font><font color='#997700'>@@ -1,3 +1,11 @@
</font><font color='#000088'>+2010-08-13    Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+       * 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.
+
</font> 2010-08-13        Chris Johns <chrisj@rtems.org>
 
        * libfs/src/imfs/imfs_eval.c: Add the missing ';' for the debug

<font color='#006600'>diff -u rtems/cpukit/Makefile.am:1.100 rtems/cpukit/Makefile.am:1.101
--- rtems/cpukit/Makefile.am:1.100      Thu Jun 17 10:29:22 2010
+++ rtems/cpukit/Makefile.am    Fri Aug 13 07:40:16 2010
</font><font color='#997700'>@@ -124,7 +124,8 @@
</font>     libblock/include/rtems/flashdisk.h libblock/include/rtems/ramdisk.h \
     libblock/include/rtems/nvdisk.h libblock/include/rtems/nvdisk-sram.h \
     libblock/include/rtems/ide_part_table.h \
<font color='#880000'>-    libblock/include/rtems/bdpart.h
</font><font color='#000088'>+    libblock/include/rtems/bdpart.h \
+    libblock/include/rtems/media.h
</font> 
 ## ftpd
 if LIBNETWORKING

<font color='#006600'>diff -u rtems/cpukit/libblock/Makefile.am:1.38 rtems/cpukit/libblock/Makefile.am:1.39
--- rtems/cpukit/libblock/Makefile.am:1.38      Fri Apr 30 03:42:12 2010
+++ rtems/cpukit/libblock/Makefile.am   Fri Aug 13 07:40:16 2010
</font><font color='#997700'>@@ -20,6 +20,11 @@
</font>     src/bdpart-register.c \
     src/bdpart-sort.c \
     src/bdpart-write.c \
<font color='#000088'>+    src/media-path.c \
+    src/media.c \
+    src/media-server.c \
+    src/media-desc.c \
+    src/media-dev-ident.c \
</font>     include/rtems/bdbuf.h include/rtems/blkdev.h \
     include/rtems/diskdevs.h include/rtems/flashdisk.h \
     include/rtems/ramdisk.h include/rtems/nvdisk.h include/rtems/nvdisk-sram.h \

<font color='#006600'>diff -u /dev/null rtems/cpukit/libblock/include/rtems/media.h:1.1
--- /dev/null   Fri Aug 13 08:11:41 2010
+++ rtems/cpukit/libblock/include/rtems/media.h Fri Aug 13 07:40:16 2010
</font><font color='#997700'>@@ -0,0 +1,525 @@
</font><font color='#000088'>+/**
+ * @file
+ *
+ * @ingroup RTEMSMedia
+ *
+ * @brief Media API.
+ */
+
+/*
+ * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef RTEMS_MEDIA_H
+#define RTEMS_MEDIA_H
+
+#include <rtems.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup RTEMSMedia Media Manager
+ *
+ * @brief Removable media support.
+ *
+ * The media manager may be used to maintain the life cycle of a removable
+ * media.  Currently only disk devices are supported.  The initiator posts an
+ * event to the media manager and it will respond with appropriate default
+ * actions.  For example a disk attach will lead to inspection of the partition
+ * table and mounted file systems.  Clients can register listeners to react to
+ * events.
+ * @{
+ */
+
+#define RTEMS_MEDIA_MOUNT_BASE "/media"
+
+#define RTEMS_MEDIA_DELIMITER '-'
+
+/**
+ * Disk life cycle events:
+ * @dot
+ *   digraph disk_events {
+ *     "DISK ATTACH" -> "PARTITION INQUIRY";
+ *     "DISK ATTACH" -> "MOUNT";
+ *     "PARTITION INQUIRY" -> "PARTITION ATTACH";
+ *     "PARTITION INQUIRY" -> "DISK DETACH";
+ *     "PARTITION ATTACH" -> "MOUNT";
+ *     "MOUNT" -> "UNMOUNT";
+ *     "UNMOUNT" -> "PARTITION DETACH";
+ *     "UNMOUNT" -> "DISK DETACH";
+ *     "PARTITION DETACH" -> "DISK DETACH";
+ *   }
+ * @enddot
+ */
+typedef enum {
+  RTEMS_MEDIA_EVENT_DISK_ATTACH,
+  RTEMS_MEDIA_EVENT_DISK_DETACH,
+  RTEMS_MEDIA_EVENT_MOUNT,
+  RTEMS_MEDIA_EVENT_UNMOUNT,
+  RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
+  RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
+  RTEMS_MEDIA_EVENT_PARTITION_DETACH,
+  RTEMS_MEDIA_EVENT_ERROR
+} rtems_media_event;
+
+/**
+ * Normal state transition:
+ * @dot
+ *   digraph state {
+ *     INQUIRY -> READY [label="all listeners\nreturned successful"];
+ *     INQUIRY -> ABORTED [label="otherwise"];
+ *     READY -> SUCCESS [label="the worker\nreturned successful"];
+ *     READY -> FAILED [label="otherwise"];
+ *   }
+ * @enddot
+ */
+typedef enum {
+  RTEMS_MEDIA_STATE_INQUIRY,
+  RTEMS_MEDIA_STATE_READY,
+  RTEMS_MEDIA_STATE_ABORTED,
+  RTEMS_MEDIA_STATE_SUCCESS,
+  RTEMS_MEDIA_STATE_FAILED,
+  RTEMS_MEDIA_ERROR_DISK_UNKNOWN,
+  RTEMS_MEDIA_ERROR_DISK_EXISTS,
+  RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN,
+  RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS,
+  RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN,
+  RTEMS_MEDIA_ERROR_PARTITION_ORPHAN,
+  RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT,
+  RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK,
+  RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN,
+  RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS,
+  RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN
+} rtems_media_state;
+
+/**
+ * @brief Event listener.
+ *
+ * The listener will be called with the @a listener_arg passed to
+ * rtems_media_listener_add().
+ *
+ * Source and destination values for each event and state:
+ * <table>
+ *   <tr><th>Event</th><th>State</th><th>Source</th><th>Destination</th></tr>
+ *   <tr>
+ *     <td rowspan="5">RTEMS_MEDIA_EVENT_DISK_ATTACH</td>
+ *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>driver name</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_READY</td><td>driver name</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>driver name</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>driver name</td><td>disk path</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>driver name</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="5">RTEMS_MEDIA_EVENT_DISK_DETACH</td>
+ *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_READY</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="5">RTEMS_MEDIA_EVENT_PARTITION_INQUIRY</td>
+ *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_READY</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="5">RTEMS_MEDIA_EVENT_PARTITION_ATTACH</td>
+ *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_READY</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_SUCCESS</td>
+ *     <td>disk path</td><td>partition path</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="5">RTEMS_MEDIA_EVENT_PARTITION_DETACH</td>
+ *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_READY</td><td>partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="5">RTEMS_MEDIA_EVENT_MOUNT</td>
+ *     <td>RTEMS_MEDIA_STATE_INQUIRY</td>
+ *     <td>disk or partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_READY</td>
+ *     <td>disk or partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_ABORTED</td>
+ *     <td>disk or partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_SUCCESS</td>
+ *     <td>disk or partition path</td><td>mount path</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_FAILED</td>
+ *     <td>disk or partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="5">RTEMS_MEDIA_EVENT_UNMOUNT</td>
+ *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>mount path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_READY</td><td>mount path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>mount path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>mount path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>mount path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="11">RTEMS_MEDIA_EVENT_ERROR</td>
+ *     <td>RTEMS_MEDIA_ERROR_DISK_UNKNOWN</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_DISK_EXISTS</td><td>disk path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN</td>
+ *     <td>disk or partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS</td>
+ *     <td>disk or partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN</td>
+ *     <td>partition path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_PARTITION_ORPHAN</td>
+ *     <td>partition path</td><td>disk path</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT</td>
+ *     <td>partition path</td><td>mount path</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK</td>
+ *     <td>partition path</td><td>disk path</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN</td>
+ *     <td>mount path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS</td>
+ *     <td>mount path</td><td>NULL</td>
+ *   </tr>
+ *   <tr>
+ *     <td>RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN</td>
+ *     <td>mount path</td><td>disk path</td>
+ *   </tr>
+ * </table>
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR In the inquiry state this will abort the action.
+ */
+typedef rtems_status_code (*rtems_media_listener)(
+  rtems_media_event event,
+  rtems_media_state state,
+  const char *src,
+  const char *dest,
+  void *listener_arg
+);
+
+/**
+ * @brief Do the work corresponding to an event.
+ *
+ * The @a state will be
+ * - RTEMS_MEDIA_STATE_READY, or
+ * - RTEMS_MEDIA_STATE_ABORTED.
+ *
+ * It will be called with the @a src and @a worker_arg arguments passed to
+ * rtems_media_post_event().
+ *
+ * The destination shall be returned in @a dest in case of success.  It shall
+ * be allocated with malloc().
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Failure.
+ */
+typedef rtems_status_code (*rtems_media_worker)(
+  rtems_media_state state,
+  const char *src,
+  char **dest,
+  void *worker_arg
+);
+
+/**
+ * @name Base
+ *
+ * @{
+ */
+
+/**
+ * @brief Initializes the media manager.
+ *
+ * Calling this function more than once will have no effects.  There is no
+ * protection against concurrent access.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NO_MEMORY Not enough resources.
+ */
+rtems_status_code rtems_media_initialize(void);
+
+/**
+ * @brief Adds the @a listener with argument @a listener_arg.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NO_MEMORY Not enough memory.
+ * @retval RTEMS_TOO_MANY Such a listener is already present.
+ */
+rtems_status_code rtems_media_listener_add(
+  rtems_media_listener listener,
+  void *listener_arg
+);
+
+/**
+ * @brief Removes the @a listener with argument @a listener_arg.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID No such listener is present.
+ */
+rtems_status_code rtems_media_listener_remove(
+  rtems_media_listener listener,
+  void *listener_arg
+);
+
+/**
+ * @brief Posts the @a event with source @a src.
+ *
+ * The @a worker will be called with the @a worker_arg argument.
+ *
+ * The destination will be returned in @a dest in case of success.  It will be
+ * allocated with malloc() and should be freed if not needed anymore.
+ *
+ * The work will be done by the calling thread.  You can avoid this if you use
+ * the media server via rtems_media_server_post_event().
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_UNSATISFIED One or more listeners aborted the action.
+ * @retval RTEMS_IO_ERROR The worker returned with an error status.
+ */
+rtems_status_code rtems_media_post_event(
+  rtems_media_event event,
+  const char *src,
+  char **dest,
+  rtems_media_worker worker,
+  void *worker_arg
+);
+
+/** @} */
+
+/**
+ * @name Server
+ *
+ * @{
+ */
+
+/**
+ * @brief Initializes the media manager and media server.
+ *
+ * It creates a server task with the @a priority, @a stack_size, @a modes, and
+ * @a attributes parameters.
+ *
+ * A message queue will be used for communication with the server task which
+ * may buffer up to @a message_count messages.
+ *
+ * Calling this function more than once will have no effects.  There is no
+ * protection against concurrent access.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NO_MEMORY Not enough resources.
+ */
+rtems_status_code rtems_media_server_initialize(
+  rtems_task_priority priority,
+  size_t stack_size,
+  rtems_mode modes,
+  rtems_attribute attributes,
+  uint32_t message_count
+);
+
+/**
+ * @brief Sends an event message to the media server.
+ *
+ * @see See rtems_media_post_event().
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_UNSATISFIED Message queue is full.
+ * @retval RTEMS_NO_MEMORY Not enough memory for the message.
+ */
+rtems_status_code rtems_media_server_post_event(
+  rtems_media_event event,
+  const char *src,
+  rtems_media_worker worker,
+  void *worker_arg
+);
+
+/**
+ * @brief See rtems_media_server_post_event().
+ */
+static inline rtems_status_code rtems_media_server_disk_attach(
+  const char *driver_name,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  return rtems_media_server_post_event(
+    RTEMS_MEDIA_EVENT_DISK_ATTACH,
+    driver_name,
+    worker,
+    worker_arg
+  );
+}
+
+/**
+ * @brief See rtems_media_server_post_event().
+ */
+static inline rtems_status_code rtems_media_server_disk_detach(
+  const char *disk_path
+)
+{
+  return rtems_media_server_post_event(
+    RTEMS_MEDIA_EVENT_DISK_DETACH,
+    disk_path,
+    NULL,
+    NULL
+  );
+}
+
+/** @} */
+
+/**
+ * @name Path Construction
+ *
+ * @{
+ */
+
+/**
+ * @brief Creates a new path as "prefix/name-major".
+ *
+ * @return New string, or @c NULL if no memory is available.
+ */
+char *rtems_media_create_path(
+  const char *prefix,
+  const char *name,
+  rtems_device_major_number major
+);
+
+/**
+ * @brief Replaces the prefix of the @a path with @a new_prefix.
+ *
+ * The prefix is everything up to the last '/'.
+ *
+ * @return New string, or @c NULL if no memory is available.
+ */
+char *rtems_media_replace_prefix(const char *new_prefix, const char *path);
+
+/**
+ * @brief Appends the @a minor number to the @a path resulting in "path-minor".
+ *
+ * @return New string, or @c NULL if no memory is available.
+ */
+char *rtems_media_append_minor(
+  const char *path,
+  rtems_device_minor_number minor
+);
+
+/** @} */
+
+/**
+ * @name Support
+ *
+ * @{
+ */
+
+/**
+ * @brief Returns the device identifier for the device located at
+ * @a device_path in @a device_identifier.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID No device at this path.
+ */
+rtems_status_code rtems_media_get_device_identifier(
+  const char *device_path,
+  dev_t *device_identifier
+);
+
+const char *rtems_media_event_description(rtems_media_event event);
+
+const char *rtems_media_state_description(rtems_media_state state);
+
+/** @} */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* RTEMS_MEDIA_H */
</font>
<font color='#006600'>diff -u /dev/null rtems/cpukit/libblock/src/media-desc.c:1.1
--- /dev/null   Fri Aug 13 08:11:41 2010
+++ rtems/cpukit/libblock/src/media-desc.c      Fri Aug 13 07:40:16 2010
</font><font color='#997700'>@@ -0,0 +1,72 @@
</font><font color='#000088'>+/**
+ * @file
+ *
+ * @ingroup RTEMSMedia
+ *
+ * @brief Media implementation.
+ */
+
+/*
+ * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems/media.h>
+
+static const char *const rtems_media_event_desc_table [] = {
+  [RTEMS_MEDIA_EVENT_DISK_ATTACH] = "DISK ATTACH",
+  [RTEMS_MEDIA_EVENT_DISK_DETACH] = "DISK DETACH",
+  [RTEMS_MEDIA_EVENT_MOUNT] = "MOUNT",
+  [RTEMS_MEDIA_EVENT_UNMOUNT] = "UNMOUNT",
+  [RTEMS_MEDIA_EVENT_PARTITION_INQUIRY] = "PARTITION INQUIRY",
+  [RTEMS_MEDIA_EVENT_PARTITION_ATTACH] = "PARTITION ATTACH",
+  [RTEMS_MEDIA_EVENT_PARTITION_DETACH] = "PARTITION DETACH"
+};
+
+static const char *const rtems_media_state_desc_table [] = {
+  [RTEMS_MEDIA_STATE_INQUIRY] = "INQUIRY",
+  [RTEMS_MEDIA_STATE_ABORTED] = "ABORTED",
+  [RTEMS_MEDIA_STATE_READY] = "SUCCESS",
+  [RTEMS_MEDIA_STATE_FAILED] = "FAILED",
+  [RTEMS_MEDIA_STATE_SUCCESS] = "SUCCESS",
+  [RTEMS_MEDIA_ERROR_DISK_UNKNOWN] = "ERROR DISK UNKNOWN",
+  [RTEMS_MEDIA_ERROR_DISK_EXISTS] = "ERROR DISK EXISTS",
+  [RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN] = "ERROR DISK OR PARTITION UNKNOWN",
+  [RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS] = "ERROR DISK OR PARTITION EXISTS",
+  [RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN] = "ERROR PARTITION UNKNOWN",
+  [RTEMS_MEDIA_ERROR_PARTITION_ORPHAN] = "ERROR PARTITION ORPHAN",
+  [RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT] = "ERROR PARTITION DETACH WITH MOUNT",
+  [RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK] = "ERROR PARTITION WITH UNKNOWN DISK",
+  [RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN] = "ERROR MOUNT POINT UNKNOWN",
+  [RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS] = "ERROR MOUNT POINT EXISTS",
+  [RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN] = "ERROR MOUNT POINT ORPHAN"
+};
+
+#define TC(table) (sizeof(table) / sizeof(table [0]))
+
+const char *rtems_media_event_description(rtems_media_event event)
+{
+  if ((size_t) event < TC(rtems_media_event_desc_table)) {
+    return rtems_media_event_desc_table [event];
+  } else {
+    return "INVALID";
+  }<span style="background-color: #FF0000"> </span>
+}
+
+const char *rtems_media_state_description(rtems_media_state state)
+{
+  if ((size_t) state < TC(rtems_media_state_desc_table)) {
+    return rtems_media_state_desc_table [state];
+  } else {
+    return "INVALID";
+  }
+}
</font>
<font color='#006600'>diff -u /dev/null rtems/cpukit/libblock/src/media-dev-ident.c:1.1
--- /dev/null   Fri Aug 13 08:11:41 2010
+++ rtems/cpukit/libblock/src/media-dev-ident.c Fri Aug 13 07:40:16 2010
</font><font color='#997700'>@@ -0,0 +1,47 @@
</font><font color='#000088'>+/**
+ * @file
+ *
+ * @ingroup RTEMSMedia
+ *
+ * @brief Media implementation.
+ */
+
+/*
+ * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <rtems.h>
+
+#include <rtems/media.h>
+
+rtems_status_code rtems_media_get_device_identifier(
+  const char *device_path,
+  dev_t *device_identifier
+)
+{
+  int rv = 0;
+  struct stat st;
+
+  rv = stat(device_path, &st);
+  if (rv != 0) {
+    return RTEMS_INVALID_ID;
+  }
+
+  *device_identifier = st.st_rdev;
+
+  return RTEMS_SUCCESSFUL;
+}
</font>
<font color='#006600'>diff -u /dev/null rtems/cpukit/libblock/src/media-path.c:1.1
--- /dev/null   Fri Aug 13 08:11:41 2010
+++ rtems/cpukit/libblock/src/media-path.c      Fri Aug 13 07:40:16 2010
</font><font color='#997700'>@@ -0,0 +1,82 @@
</font><font color='#000088'>+/**
+ * @file
+ *
+ * @ingroup RTEMSMedia
+ *
+ * @brief Media implementation.
+ */
+
+/*
+ * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <rtems/media.h>
+
+char *rtems_media_create_path(const char *prefix, const char *name, rtems_device_major_number major)
+{
+  size_t const len = strlen(prefix) + 1 + strlen(name) + 1 + 10 + 1;
+  char *const s = malloc(len);
+
+  if (s != NULL) {
+    int rv = snprintf(s, len, "%s/%s-%" PRIu32, prefix, name, major);
+
+    if (rv >= (int) len) {
+      free(s);
+
+      return NULL;
+    }
+  }
+
+  return s;
+}
+
+char *rtems_media_replace_prefix(const char *new_prefix, const char *path)
+{
+  const char *const name_try = strrchr(path, '/');
+  const char *const name = (name_try == NULL) ? path : name_try + 1;
+  size_t const new_prefix_len = strlen(new_prefix);
+  size_t const name_len = strlen(name);
+  size_t const len = new_prefix_len + 1 + name_len + 1;
+  char *const s =  malloc(len);
+
+  if (s != NULL) {
+    strcpy(s, new_prefix);
+    strcpy(s + new_prefix_len, "/");
+    strcpy(s + new_prefix_len + 1, name);
+  }
+
+  return s;
+}
+
+char *rtems_media_append_minor(const char *path, rtems_device_minor_number minor)
+{
+  size_t const len = strlen(path) + 1 + 10 + 1;
+  char *const s = malloc(len);
+
+  if (s != NULL) {
+    int rv = snprintf(s, len, "%s-%" PRIu32, path, minor);
+
+    if (rv >= (int) len) {
+      free(s);
+
+      return NULL;
+    }
+  }
+
+  return s;
+}
</font>
<font color='#006600'>diff -u /dev/null rtems/cpukit/libblock/src/media-server.c:1.1
--- /dev/null   Fri Aug 13 08:11:42 2010
+++ rtems/cpukit/libblock/src/media-server.c    Fri Aug 13 07:40:16 2010
</font><font color='#997700'>@@ -0,0 +1,158 @@
</font><font color='#000088'>+/**
+ * @file
+ *
+ * @ingroup RTEMSMedia
+ *
+ * @brief Media implementation.
+ */
+
+/*
+ * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems.h>
+#include <rtems/chain.h>
+
+#include <rtems/media.h>
+
+typedef struct {
+  rtems_media_event event;
+  char *src;
+  rtems_media_worker worker;
+  void *arg;
+} media_server_event;
+
+static rtems_id message_queue_id = RTEMS_ID_NONE;
+
+static void rtems_media_server(rtems_task_argument arg __attribute__((unused)))
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  while (true) {
+    media_server_event msg;
+    size_t msg_size = sizeof(msg);
+
+    sc = rtems_message_queue_receive(
+      message_queue_id,
+      &msg,
+      &msg_size,
+      RTEMS_WAIT,
+      RTEMS_NO_TIMEOUT
+    );
+    if (sc != RTEMS_SUCCESSFUL) {
+      break;
+    }
+
+    rtems_media_post_event(msg.event, msg.src, NULL, msg.worker, msg.arg);
+
+    free(msg.src);
+  }
+
+  rtems_task_delete(RTEMS_SELF);
+}
+
+rtems_status_code rtems_media_server_initialize(
+  rtems_task_priority priority,
+  size_t stack_size,
+  rtems_mode modes,
+  rtems_attribute attributes,
+  uint32_t message_count
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_id task_id = RTEMS_ID_NONE;
+
+  if (message_queue_id == RTEMS_ID_NONE) {
+    sc = rtems_media_initialize();
+    if (sc != RTEMS_SUCCESSFUL) {
+      goto error;
+    }
+
+    sc = rtems_message_queue_create(
+      rtems_build_name('M', 'D', 'I', 'A'),
+      message_count,
+      sizeof(media_server_event),
+      RTEMS_DEFAULT_ATTRIBUTES,
+      &message_queue_id
+    );
+    if (sc != RTEMS_SUCCESSFUL) {
+      goto error;
+    }
+
+    sc = rtems_task_create(
+      rtems_build_name('M', 'D', 'I', 'A'),
+      priority,
+      stack_size,
+      modes,
+      attributes,
+      &task_id
+    );
+    if (sc != RTEMS_SUCCESSFUL) {
+      goto error;
+    }
+
+    sc = rtems_task_start(task_id, rtems_media_server, 0);
+    if (sc != RTEMS_SUCCESSFUL) {
+      goto error;
+    }
+  }
+<span style="background-color: #FF0000">  </span>
+  return RTEMS_SUCCESSFUL;
+
+error:
+
+  if (task_id != RTEMS_ID_NONE) {
+    rtems_task_delete(task_id);
+  }
+
+  rtems_message_queue_delete(message_queue_id);
+
+  return RTEMS_NO_MEMORY;
+}
+
+rtems_status_code rtems_media_server_post_event(
+  rtems_media_event event,
+  const char *src,
+  rtems_media_worker worker,
+  void *arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  media_server_event msg = {
+    .event = event,
+    .src = strdup(src),
+    .worker = worker,
+    .arg = arg
+  };
+
+  if (msg.src == NULL) {
+    return RTEMS_NO_MEMORY;
+  }
+
+  sc = rtems_message_queue_send(
+    message_queue_id,
+    &msg,
+    sizeof(msg)
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    free(msg.src);
+
+    return RTEMS_UNSATISFIED;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
</font>
<font color='#006600'>diff -u /dev/null rtems/cpukit/libblock/src/media.c:1.1
--- /dev/null   Fri Aug 13 08:11:42 2010
+++ rtems/cpukit/libblock/src/media.c   Fri Aug 13 07:40:16 2010
</font><font color='#997700'>@@ -0,0 +1,1012 @@
</font><font color='#000088'>+/**
+ * @file
+ *
+ * @ingroup RTEMSMedia
+ *
+ * @brief Media implementation.
+ */
+
+/*
+ * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <string.h>
+#include <assert.h>
+
+#include <rtems.h>
+#include <rtems/bdbuf.h>
+#include <rtems/diskdevs.h>
+#include <rtems/bdpart.h>
+#include <rtems/libio.h>
+
+#include <rtems/media.h>
+
+typedef struct {
+  rtems_bdpart_partition *partitions;
+  size_t *count;
+} partition_table;
+
+typedef struct {
+  dev_t physical_disk;
+  dev_t logical_disk;
+  rtems_blkdev_bnum begin;
+  rtems_blkdev_bnum count;
+} partition;
+
+typedef struct media_item {
+  rtems_chain_node node;
+  struct media_item *parent;
+  char *disk_path;
+  char *mount_path;
+} media_item;
+
+typedef struct listener_item {
+  rtems_chain_node node;
+  rtems_media_listener listener;
+  void *listener_arg;
+} listener_item;
+
+static RTEMS_CHAIN_DEFINE_EMPTY(listener_item_chain);
+
+static RTEMS_CHAIN_DEFINE_EMPTY(media_item_chain);
+
+static rtems_id media_mutex = RTEMS_ID_NONE;
+
+static rtems_status_code lock(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  sc = rtems_semaphore_obtain(media_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  if (sc != RTEMS_SUCCESSFUL) {
+    sc = RTEMS_NOT_CONFIGURED;
+  }
+
+  return sc;
+}
+
+static void unlock(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  sc = rtems_semaphore_release(media_mutex);
+  assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static listener_item *find_listener(
+  rtems_media_listener listener,
+  void *listener_arg
+)
+{
+  rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
+
+  while (!rtems_chain_is_tail(&listener_item_chain, node)) {
+    listener_item *item = (listener_item *) node;
+
+    if (item->listener == listener && item->listener_arg == listener_arg) {
+      return item;
+    }
+
+    node = rtems_chain_next(node);
+  }
+
+  return NULL;
+}
+
+rtems_status_code rtems_media_listener_add(
+  rtems_media_listener listener,
+  void *listener_arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  sc = lock();
+  if (sc == RTEMS_SUCCESSFUL) {
+    listener_item *item = find_listener(listener, listener_arg);
+
+    if (item == NULL) {
+      item = malloc(sizeof(*item));
+      if (item != NULL) {
+        item->listener = listener;
+        item->listener_arg = listener_arg;
+        rtems_chain_append_unprotected(&listener_item_chain, &item->node);
+      } else {
+        sc = RTEMS_NO_MEMORY;
+      }
+    } else {
+      sc = RTEMS_TOO_MANY;
+    }
+
+    unlock();
+  }
+
+  return sc;
+}
+
+rtems_status_code rtems_media_listener_remove(
+  rtems_media_listener listener,
+  void *listener_arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  sc = lock();
+  if (sc == RTEMS_SUCCESSFUL) {
+    listener_item *item = find_listener(listener, listener_arg);
+
+    if (item != NULL) {
+      rtems_chain_extract(&item->node);
+      free(item);
+    } else {
+      sc = RTEMS_INVALID_ID;
+    }
+
+    unlock();
+  }
+
+  return sc;
+}
+
+static rtems_status_code notify(
+  rtems_media_event event,
+  rtems_media_state state,
+  const char *src,
+  const char *dest
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_status_code rsc = RTEMS_SUCCESSFUL;
+  rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
+
+  while (!rtems_chain_is_tail(&listener_item_chain, node)) {
+    listener_item *item = (listener_item *) node;
+
+    sc = (*item->listener)(event, state, src, dest, item->listener_arg);
+    if (sc != RTEMS_SUCCESSFUL) {
+      rsc = sc;
+    }
+
+    node = rtems_chain_next(node);
+  }
+
+  return rsc;
+}
+
+static void error(
+  rtems_media_state state,
+  const char *src,
+  const char *dest
+)
+{
+  notify(RTEMS_MEDIA_EVENT_ERROR, state, src, dest);
+}
+
+static media_item *get_media_item(
+  const char *disk_path,
+  const char *mount_path
+)
+{
+  rtems_chain_node *node = rtems_chain_first(&media_item_chain);
+
+  while (!rtems_chain_is_tail(&media_item_chain, node)) {
+    media_item *item = (media_item *) node;
+
+    if (
+      (disk_path == NULL || strcmp(disk_path, item->disk_path) == 0)
+        && (mount_path == NULL || strcmp(mount_path, item->mount_path) == 0)
+    ) {
+      return item;
+    }
+
+    node = rtems_chain_next(node);
+  }
+
+  return NULL;
+}
+
+static void free_item(media_item *item)
+{
+  rtems_chain_extract(&item->node);
+  free(item->mount_path);
+  free(item);
+}
+
+static void create_item(
+  media_item *parent,
+  const char *disk_path,
+  const char *mount_path
+)
+{
+  size_t disk_path_size = strlen(disk_path) + 1;
+  media_item *item = malloc(sizeof(*item) + disk_path_size);
+
+  if (item != NULL) {
+    if (mount_path != NULL) {
+      item->mount_path = strdup(mount_path);
+
+      if (item->mount_path == NULL) {
+        free(item);
+
+        return;
+      }
+    } else {
+      item->mount_path = NULL;
+    }
+
+    item->parent = parent;
+    item->disk_path = (char *) item + sizeof(*item);
+    strcpy(item->disk_path, disk_path);
+    rtems_chain_append(&media_item_chain, &item->node);
+  }
+}
+
+static void remove_mount_point(const char *mount_path)
+{
+  media_item *item = get_media_item(NULL, mount_path);
+
+  if (item != NULL) {
+    free(item->mount_path);
+    item->mount_path = NULL;
+  } else {
+    error(RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN, mount_path, NULL);
+  }
+}
+
+static void remove_partition(const char *partition_path)
+{
+  media_item *item = get_media_item(partition_path, NULL);
+
+  if (item != NULL) {
+    if (item->mount_path != NULL) {
+      error(
+        RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT,
+        partition_path,
+        item->mount_path
+      );
+    }
+    free_item(item);
+  } else {
+    error(RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN, partition_path, NULL);
+  }
+}
+
+static void remove_disk(const char *disk_path)
+{
+  media_item *item = get_media_item(disk_path, NULL);
+
+  if (item != NULL) {
+    rtems_chain_node *node = rtems_chain_first(&media_item_chain);
+
+    while (!rtems_chain_is_tail(&media_item_chain, node)) {
+      media_item *child = (media_item *) node;
+
+      node = rtems_chain_next(node);
+
+      if (child->parent == item) {
+        if (child->mount_path != NULL) {
+          error(
+            RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN,
+            child->mount_path,
+            disk_path
+          );
+        }
+        error(RTEMS_MEDIA_ERROR_PARTITION_ORPHAN, child->disk_path, disk_path);
+        free_item(child);
+      }
+    }
+
+    free_item(item);
+  } else {
+    error(RTEMS_MEDIA_ERROR_DISK_UNKNOWN, disk_path, NULL);
+  }
+}
+
+static void add_disk(const char *disk_path)
+{
+  media_item *item = get_media_item(disk_path, NULL);
+
+  if (item != NULL) {
+    error(RTEMS_MEDIA_ERROR_DISK_EXISTS, disk_path, NULL);
+    remove_disk(disk_path);
+  }
+
+  create_item(NULL, disk_path, NULL);
+}
+
+static void add_partition(const char *disk_path, const char *partition_path)
+{
+  media_item *item = get_media_item(partition_path, NULL);
+  media_item *parent = get_media_item(disk_path, NULL);
+
+  if (item != NULL) {
+    error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS, partition_path, NULL);
+    remove_disk(partition_path);
+  }
+
+  if (parent != NULL) {
+    create_item(parent, partition_path, NULL);
+  } else {
+    error(
+      RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK,
+      partition_path,
+      disk_path
+    );
+  }
+}
+
+static void add_mount_point(const char *disk_path, const char *mount_path)
+{
+  media_item *item = get_media_item(disk_path, NULL);
+
+  if (item != NULL) {
+    if (item->mount_path != NULL) {
+      error(RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS, item->mount_path, NULL);
+      free(item->mount_path);
+    }
+    item->mount_path = strdup(mount_path);
+  } else {
+    error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN, disk_path, NULL);
+  }
+}
+
+static bool is_add_state(rtems_media_state state)
+{
+  return state == RTEMS_MEDIA_STATE_SUCCESS;
+}
+
+static bool is_remove_state(rtems_media_state state)
+{
+  return state == RTEMS_MEDIA_STATE_SUCCESS
+    || state == RTEMS_MEDIA_STATE_FAILED;
+}
+
+static rtems_status_code remember_event(
+  rtems_media_event event,
+  rtems_media_state state,
+  const char *src,
+  const char *dest
+)
+{
+  switch (event) {
+    case RTEMS_MEDIA_EVENT_DISK_ATTACH:
+      if (is_add_state(state)) {
+        add_disk(dest);
+      }
+      break;
+    case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
+      if (is_add_state(state)) {
+        add_partition(src, dest);
+      }
+      break;
+    case RTEMS_MEDIA_EVENT_MOUNT:
+      if (is_add_state(state)) {
+        add_mount_point(src, dest);
+      }
+      break;
+    case RTEMS_MEDIA_EVENT_UNMOUNT:
+      if (is_remove_state(state)) {
+        remove_mount_point(src);
+      }
+      break;
+    case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
+      if (is_remove_state(state)) {
+        remove_partition(src);
+      }
+      break;
+    case RTEMS_MEDIA_EVENT_DISK_DETACH:
+      if (is_remove_state(state)) {
+        remove_disk(src);
+      }
+      break;
+    default:
+      break;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code process_event(
+  rtems_media_event event,
+  const char *src,
+  char **dest_ptr,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_media_state state = RTEMS_MEDIA_STATE_FAILED;
+  char *dest = NULL;
+
+  sc = notify(event, RTEMS_MEDIA_STATE_INQUIRY, src, NULL);
+  if (sc == RTEMS_SUCCESSFUL) {
+    state = RTEMS_MEDIA_STATE_READY;
+  } else {
+    state = RTEMS_MEDIA_STATE_ABORTED;
+  }
+
+  sc = (*worker)(state, src, &dest, worker_arg);
+  if (state == RTEMS_MEDIA_STATE_READY) {
+    if (sc == RTEMS_SUCCESSFUL) {
+      state = RTEMS_MEDIA_STATE_SUCCESS;
+    } else {
+      state = RTEMS_MEDIA_STATE_FAILED;
+    }
+  }
+
+  notify(event, state, src, dest);
+  remember_event(event, state, src, dest);
+
+  if (state == RTEMS_MEDIA_STATE_SUCCESS) {
+    sc = RTEMS_SUCCESSFUL;
+  } else if (state == RTEMS_MEDIA_STATE_ABORTED) {
+    sc = RTEMS_UNSATISFIED;
+  } else {
+    sc = RTEMS_IO_ERROR;
+  }
+
+  if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
+    *dest_ptr = dest;
+  } else {
+    free(dest);
+  }
+
+  return sc;
+}
+
+static rtems_status_code mount_worker(
+  rtems_media_state state,
+  const char *src,
+  char **dest,
+  void *worker_arg
+)
+{
+  int rv = 0;
+
+  if (state == RTEMS_MEDIA_STATE_READY) {
+    char *mount_path = NULL;
+
+    if (worker_arg == NULL) {
+      mount_path = rtems_media_replace_prefix(RTEMS_MEDIA_MOUNT_BASE, src);
+    } else {
+      mount_path = strdup(worker_arg);
+    }
+
+    if (mount_path == NULL) {
+      return RTEMS_IO_ERROR;
+    }
+
+    rv = rtems_mkdir(mount_path, S_IRWXU | S_IRWXG | S_IRWXO);
+    if (rv != 0) {
+      free(mount_path);
+
+      return RTEMS_IO_ERROR;
+    }
+
+    rv = mount(
+      src,
+      mount_path,
+      RTEMS_FILESYSTEM_TYPE_DOSFS,
+      RTEMS_FILESYSTEM_READ_WRITE,
+      NULL
+    );
+    if (rv != 0) {
+      rmdir(mount_path);
+      free(mount_path);
+
+      return RTEMS_IO_ERROR;
+    }
+
+    *dest = mount_path;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code do_mount(
+  const char *src,
+  char **dest_ptr,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  if (worker == NULL) {
+    worker = mount_worker;
+  }
+
+  return process_event(
+    RTEMS_MEDIA_EVENT_MOUNT,
+    src,
+    dest_ptr,
+    worker,
+    worker_arg
+  );
+}
+
+static rtems_status_code do_partition_attach(
+  const char *src,
+  char **dest_ptr,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  char *part_path = NULL;
+
+  if (worker != NULL) {
+    sc = process_event(
+      RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
+      src,
+      &part_path,
+      worker,
+      worker_arg
+    );
+
+    if (sc == RTEMS_SUCCESSFUL) {
+      sc = do_mount(part_path, NULL, NULL, NULL);
+    }
+  } else {
+    sc = RTEMS_INVALID_ADDRESS;
+  }
+
+  if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
+    *dest_ptr = part_path;
+  } else {
+    free(part_path);
+  }
+
+  return sc;
+}
+
+static rtems_status_code partition_attach_worker(
+  rtems_media_state state,
+  const char *src,
+  char **dest,
+  void *worker_arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  if (state == RTEMS_MEDIA_STATE_READY) {
+    partition *part = worker_arg;
+    rtems_device_minor_number minor =
+      rtems_filesystem_dev_minor_t(part->logical_disk);
+    char *part_path = rtems_media_append_minor(src, minor);
+
+    if (part_path == NULL) {
+      return RTEMS_IO_ERROR;
+    }
+
+    sc = rtems_disk_create_log(
+      part->logical_disk,
+      part->physical_disk,
+      part->begin,
+      part->count,
+      part_path
+    );
+    if (sc != RTEMS_SUCCESSFUL) {
+      free(part_path);
+
+      return RTEMS_IO_ERROR;
+    }
+
+    *dest = part_path;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code attach_and_mount_partitions(
+  const char *disk_path,
+  rtems_bdpart_partition *partitions,
+  size_t count
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_device_major_number major = 0;
+  rtems_device_minor_number minor = 0;
+  dev_t dev = 0;
+  size_t i = 0;
+
+  sc = rtems_media_get_device_identifier(disk_path, &dev);
+  if (sc != RTEMS_SUCCESSFUL) {
+    return RTEMS_INVALID_ID;
+  }
+
+  major = rtems_filesystem_dev_major_t(dev);
+  minor = rtems_filesystem_dev_minor_t(dev) + 1;
+
+  for (i = 0; i < count; ++i, ++minor) {
+    partition part_desc = {
+      .physical_disk = dev,
+      .logical_disk = rtems_filesystem_make_dev_t(major, minor),
+      .begin = partitions [i].begin,
+      .count = partitions [i].end - partitions [i].begin
+    };
+    char *part_path = NULL;
+
+    sc = process_event(
+      RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
+      disk_path,
+      &part_path,
+      partition_attach_worker,
+      &part_desc
+    );
+
+    if (sc == RTEMS_SUCCESSFUL) {
+      sc = do_mount(part_path, NULL, NULL, NULL);
+    }
+
+    free(part_path);
+  }
+
+  return sc;
+}
+
+static rtems_status_code partition_inquiry_worker(
+  rtems_media_state state,
+  const char *src,
+  char **dest __attribute__((unused)),
+  void *worker_arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  if (state == RTEMS_MEDIA_STATE_READY) {
+    partition_table *pt = worker_arg;
+    rtems_bdpart_format format;
+
+    sc = rtems_bdpart_read(src, &format, pt->partitions, pt->count);
+    if (sc != RTEMS_SUCCESSFUL || *pt->count == 0) {
+      return RTEMS_IO_ERROR;
+    }
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code do_partition_inquiry(
+  const char *src,
+  char **dest_ptr,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  if (worker == NULL) {
+    rtems_bdpart_partition partitions [RTEMS_BDPART_PARTITION_NUMBER_HINT];
+    size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
+    partition_table pt = {
+     .partitions = partitions,
+     .count = &count
+    };
+
+    sc = process_event(
+      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
+      src,
+      dest_ptr,
+      partition_inquiry_worker,
+      &pt
+    );
+
+    if (sc == RTEMS_SUCCESSFUL) {
+      sc = attach_and_mount_partitions(src, partitions, count);
+    }
+  } else {
+    sc = process_event(
+      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
+      src,
+      dest_ptr,
+      worker,
+      worker_arg
+    );
+  }
+
+  return sc;
+}
+
+static rtems_status_code do_disk_attach(
+  const char *src,
+  char **dest_ptr,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_status_code rsc = RTEMS_SUCCESSFUL;
+  char *disk_path = NULL;
+
+  if (worker != NULL) {
+    rsc = process_event(
+      RTEMS_MEDIA_EVENT_DISK_ATTACH,
+      src,
+      &disk_path,
+      worker,
+      worker_arg
+    );
+<span style="background-color: #FF0000">    </span>
+    if (rsc == RTEMS_SUCCESSFUL) {
+      sc = do_mount(disk_path, NULL, NULL, NULL);
+
+      if (sc != RTEMS_SUCCESSFUL) {
+        do_partition_inquiry(disk_path, NULL, NULL, NULL);
+      }
+    }
+  } else {
+    rsc = RTEMS_INVALID_ADDRESS;
+  }
+
+  if (dest_ptr != NULL && rsc == RTEMS_SUCCESSFUL) {
+    *dest_ptr = disk_path;
+  } else {
+    free(disk_path);
+  }
+
+  return rsc;
+}
+
+static rtems_status_code unmount_worker(
+  rtems_media_state state,
+  const char *src,
+  char **dest __attribute__((unused)),
+  void *worker_arg __attribute__((unused))
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  if (state == RTEMS_MEDIA_STATE_READY) {
+    int rv = unmount(src);
+
+    if (rv == 0) {
+      rv = rmdir(src);
+      if (rv != 0) {
+        sc = RTEMS_IO_ERROR;
+      }
+    } else {
+      sc = RTEMS_IO_ERROR;
+    }
+  }
+
+  return sc;
+}
+
+static rtems_status_code do_unmount(
+  const char *src,
+  char **dest_ptr,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  if (worker == NULL) {
+    worker = unmount_worker;
+    worker_arg = NULL;
+  }
+
+  return process_event(
+    RTEMS_MEDIA_EVENT_UNMOUNT,
+    src,
+    dest_ptr,
+    worker,
+    worker_arg
+  );
+}
+
+static rtems_status_code disk_detach_worker(
+  rtems_media_state state,
+  const char *src,
+  char **dest __attribute__((unused)),
+  void *worker_arg __attribute__((unused))
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_status_code rsc = RTEMS_SUCCESSFUL;
+
+  if (state == RTEMS_MEDIA_STATE_READY) {
+    dev_t dev = 0;
+
+    sc = rtems_media_get_device_identifier(src, &dev);
+    if (sc != RTEMS_SUCCESSFUL) {
+      return RTEMS_IO_ERROR;
+    }
+
+    sc = rtems_bdbuf_syncdev(dev);
+    if (sc != RTEMS_SUCCESSFUL) {
+      rsc = RTEMS_IO_ERROR;
+    }
+
+    sc = rtems_disk_delete(dev);
+    if (sc != RTEMS_SUCCESSFUL) {
+      rsc = RTEMS_IO_ERROR;
+    }
+
+    rtems_bdbuf_purge_dev(dev);
+
+    if (rtems_filesystem_dev_minor_t(dev) == 0) {
+      sc = rtems_io_unregister_driver(rtems_filesystem_dev_major_t(dev));
+      if (sc != RTEMS_SUCCESSFUL) {
+        rsc = RTEMS_IO_ERROR;
+      }
+    }
+  }
+
+  return rsc;
+}
+
+static rtems_status_code detach_item(rtems_media_event event, media_item *item)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_status_code rsc = RTEMS_SUCCESSFUL;
+
+  if (item->mount_path != NULL) {
+    sc = do_unmount(item->mount_path, NULL, NULL, NULL);
+    if (sc != RTEMS_SUCCESSFUL) {
+      rsc = RTEMS_IO_ERROR;
+    }
+  }
+
+  sc = process_event(event, item->disk_path, NULL, disk_detach_worker, NULL);
+  if (sc != RTEMS_SUCCESSFUL) {
+    rsc = RTEMS_IO_ERROR;
+  }
+
+  return rsc;
+}
+
+static rtems_status_code detach_parent_item(media_item *parent)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_status_code rsc = RTEMS_SUCCESSFUL;
+
+  rtems_chain_node *node = rtems_chain_first(&media_item_chain);
+
+  while (!rtems_chain_is_tail(&media_item_chain, node)) {
+    media_item *child = (media_item *) node;
+
+    node = rtems_chain_next(node);
+
+    if (child->parent == parent) {
+      sc = detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, child);
+      if (sc != RTEMS_SUCCESSFUL) {
+        rsc = RTEMS_IO_ERROR;
+      }
+    }
+  }
+
+  sc = detach_item(RTEMS_MEDIA_EVENT_DISK_DETACH, parent);
+  if (sc != RTEMS_SUCCESSFUL) {
+    rsc = RTEMS_IO_ERROR;
+  }
+
+  return rsc;
+}
+
+static rtems_status_code do_disk_detach(
+  const char *src,
+  char **dest_ptr,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  if (worker == NULL) {
+    media_item *parent = get_media_item(src, NULL);
+
+    if (parent != NULL) {
+      return detach_parent_item(parent);
+    }
+
+    worker = disk_detach_worker;
+    worker_arg = NULL;
+  }
+
+  return process_event(
+    RTEMS_MEDIA_EVENT_DISK_DETACH,
+    src,
+    dest_ptr,
+    worker,
+    worker_arg
+  );
+}
+
+static rtems_status_code do_partition_detach(
+  const char *src,
+  char **dest_ptr,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  if (worker == NULL) {
+    media_item *item = get_media_item(src, NULL);
+
+    if (item != NULL) {
+      return detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, item);
+    }
+
+    worker = disk_detach_worker;
+    worker_arg = NULL;
+  }
+
+  return process_event(
+    RTEMS_MEDIA_EVENT_PARTITION_DETACH,
+    src,
+    dest_ptr,
+    worker,
+    worker_arg
+  );
+}
+
+rtems_status_code rtems_media_post_event(
+  rtems_media_event event,
+  const char *src,
+  char **dest_ptr,
+  rtems_media_worker worker,
+  void *worker_arg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  sc = lock();
+  if (sc != RTEMS_SUCCESSFUL) {
+    return sc;
+  }
+
+  switch (event) {
+    case RTEMS_MEDIA_EVENT_DISK_ATTACH:
+      sc = do_disk_attach(src, dest_ptr, worker, worker_arg);
+      break;
+    case RTEMS_MEDIA_EVENT_DISK_DETACH:
+      sc = do_disk_detach(src, dest_ptr, worker, worker_arg);
+      break;
+    case RTEMS_MEDIA_EVENT_MOUNT:
+      sc = do_mount(src, dest_ptr, worker, worker_arg);
+      break;
+    case RTEMS_MEDIA_EVENT_UNMOUNT:
+      sc = do_unmount(src, dest_ptr, worker, worker_arg);
+      break;
+    case RTEMS_MEDIA_EVENT_PARTITION_INQUIRY:
+      sc = do_partition_inquiry(src, dest_ptr, worker, worker_arg);
+      break;
+    case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
+      sc = do_partition_attach(src, dest_ptr, worker, worker_arg);
+      break;
+    case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
+      sc = do_partition_detach(src, dest_ptr, worker, worker_arg);
+      break;
+    default:
+      sc = RTEMS_INVALID_ID;
+      break;
+  }
+
+  unlock();
+
+  return sc;
+}
+
+rtems_status_code rtems_media_initialize(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  if (media_mutex == RTEMS_ID_NONE) {
+    sc = rtems_semaphore_create(
+      rtems_build_name('M', 'D', 'I', 'A'),
+      1,
+      RTEMS_LOCAL | RTEMS_PRIORITY
+        | RTEMS_INHERIT_PRIORITY | RTEMS_BINARY_SEMAPHORE,
+      0,
+      &media_mutex
+    );
+    if (sc != RTEMS_SUCCESSFUL) {
+      sc = RTEMS_NO_MEMORY;
+    }
+  }
+
+  return sc;
+}
</font>
<font color='#006600'>diff -u rtems/cpukit/preinstall.am:1.46 rtems/cpukit/preinstall.am:1.47
--- rtems/cpukit/preinstall.am:1.46     Mon Jun 14 06:57:06 2010
+++ rtems/cpukit/preinstall.am  Fri Aug 13 07:40:16 2010
</font><font color='#997700'>@@ -289,6 +289,10 @@
</font>   $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bdpart.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/bdpart.h
 
<font color='#000088'>+$(PROJECT_INCLUDE)/rtems/media.h: libblock/include/rtems/media.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/media.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/media.h
+
</font> if LIBNETWORKING
 $(PROJECT_INCLUDE)/rtems/ftpd.h: ftpd/ftpd.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/ftpd.h
</pre>
<p> </p>
<a name='cs2'></a>
<table border='0' cellspacing='0' cellpadding='5' width='100%' bgcolor='#eeeeee'>
<tr><td colspan='3' bgcolor='#dddddd'>
 <font color='#bb2222'><strong>sh</strong></font>
</td></tr>
<tr><td colspan='3' bgcolor='#dddddd'><pre>2010-08-13 Sebastian Huber <sebastian.huber@embedded-brains.de>

        * libblock/src/media.c: Use unprotected chain extract.
</pre></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/ChangeLog.diff?r1=text&tr1=1.2564&r2=text&tr2=1.2565&diff_format=h">M</a></td><td width='1%'>1.2565</td><td width='100%'>cpukit/ChangeLog</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libblock/src/media.c.diff?r1=text&tr1=1.1&r2=text&tr2=1.2&diff_format=h">M</a></td><td width='1%'>1.2</td><td width='100%'>cpukit/libblock/src/media.c</td></tr>
</table>
<pre>
<font color='#006600'>diff -u rtems/cpukit/ChangeLog:1.2564 rtems/cpukit/ChangeLog:1.2565
--- rtems/cpukit/ChangeLog:1.2564       Fri Aug 13 07:40:15 2010
+++ rtems/cpukit/ChangeLog      Fri Aug 13 07:50:55 2010
</font><font color='#997700'>@@ -1,5 +1,9 @@
</font> 2010-08-13        Sebastian Huber <sebastian.huber@embedded-brains.de>
 
<font color='#000088'>+   * libblock/src/media.c: Use unprotected chain extract.
+
+2010-08-13     Sebastian Huber <sebastian.huber@embedded-brains.de>
+
</font>   * 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.

<font color='#006600'>diff -u rtems/cpukit/libblock/src/media.c:1.1 rtems/cpukit/libblock/src/media.c:1.2
--- rtems/cpukit/libblock/src/media.c:1.1       Fri Aug 13 07:40:16 2010
+++ rtems/cpukit/libblock/src/media.c   Fri Aug 13 07:50:56 2010
</font><font color='#997700'>@@ -144,7 +144,7 @@
</font>     listener_item *item = find_listener(listener, listener_arg);
 
     if (item != NULL) {
<font color='#880000'>-      rtems_chain_extract(&item->node);
</font><font color='#000088'>+      rtems_chain_extract_unprotected(&item->node);
</font>       free(item);
     } else {
       sc = RTEMS_INVALID_ID;
</pre>
<p> </p>

<p>--<br />
<small>Generated by <a href="http://www.codewiz.org/projects/index.html#loginfo">Deluxe Loginfo</a> 2.122 by Bernardo Innocenti <bernie@develer.com></small></p>
</body>
</html>