summaryrefslogtreecommitdiffstats
path: root/cpukit/libblock/include
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libblock/include')
-rw-r--r--cpukit/libblock/include/rtems/bdbuf.h594
-rw-r--r--cpukit/libblock/include/rtems/bdpart.h409
-rw-r--r--cpukit/libblock/include/rtems/blkdev.h276
-rw-r--r--cpukit/libblock/include/rtems/diskdevs.h341
-rw-r--r--cpukit/libblock/include/rtems/flashdisk.h366
-rw-r--r--cpukit/libblock/include/rtems/ide_part_table.h217
-rw-r--r--cpukit/libblock/include/rtems/media.h521
-rw-r--r--cpukit/libblock/include/rtems/nvdisk-sram.h25
-rw-r--r--cpukit/libblock/include/rtems/nvdisk.h209
-rw-r--r--cpukit/libblock/include/rtems/ramdisk.h243
10 files changed, 3201 insertions, 0 deletions
diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h
new file mode 100644
index 0000000000..66a9bbf59b
--- /dev/null
+++ b/cpukit/libblock/include/rtems/bdbuf.h
@@ -0,0 +1,594 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_bdbuf
+ *
+ * Block device buffer management.
+ */
+
+/*
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * Copyright (C) 2008,2009 Chris Johns <chrisj@rtems.org>
+ * Rewritten to remove score mutex access. Fixes many performance
+ * issues.
+ * Change to support demand driven variable buffer sizes.
+ *
+ * Copyright (c) 2009 embedded brains GmbH.
+ *
+ * @(#) bdbuf.h,v 1.9 2005/02/02 00:06:18 joel Exp
+ */
+
+#ifndef _RTEMS_BDBUF_H
+#define _RTEMS_BDBUF_H
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/chain.h>
+
+#include <rtems/blkdev.h>
+#include <rtems/diskdevs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup rtems_libblock Block Device Library
+ *
+ * Block device modules.
+ */
+
+/**
+ * @defgroup rtems_bdbuf Block Device Buffer Management
+ *
+ * @ingroup rtems_libblock
+ *
+ * The Block Device Buffer Management implements a cache between the disk
+ * devices and file systems. The code provides read ahead and write queuing to
+ * the drivers and fast cache look-up using an AVL tree.
+ *
+ * The block size used by a file system can be set at runtime and must be a
+ * multiple of the disk device block size. The disk device's physical block
+ * size is called the media block size. The file system can set the block size
+ * it uses to a larger multiple of the media block size. The driver must be
+ * able to handle buffers sizes larger than one media block.
+ *
+ * The user configures the amount of memory to be used as buffers in the cache,
+ * and the minimum and maximum buffer size. The cache will allocate additional
+ * memory for the buffer descriptors and groups. There are enough buffer
+ * descriptors allocated so all the buffer memory can be used as minimum sized
+ * buffers.
+ *
+ * The cache is a single pool of buffers. The buffer memory is divided into
+ * groups where the size of buffer memory allocated to a group is the maximum
+ * buffer size. A group's memory can be divided down into small buffer sizes
+ * that are a multiple of 2 of the minimum buffer size. A group is the minimum
+ * allocation unit for buffers of a specific size. If a buffer of maximum size
+ * is request the group will have a single buffer. If a buffer of minimum size
+ * is requested the group is divided into minimum sized buffers and the
+ * remaining buffers are held ready for use. A group keeps track of which
+ * buffers are with a file system or driver and groups who have buffer in use
+ * cannot be realloced. Groups with no buffers in use can be taken and
+ * realloced to a new size. This is how buffers of different sizes move around
+ * the cache.
+
+ * The buffers are held in various lists in the cache. All buffers follow this
+ * state machine:
+ *
+ * @dot
+ * digraph state {
+ * size="16,8";
+ * f [label="FREE",style="filled",fillcolor="aquamarine"];
+ * e [label="EMPTY",style="filled",fillcolor="seagreen"];
+ * c [label="CACHED",style="filled",fillcolor="chartreuse"];
+ * ac [label="ACCESS CACHED",style="filled",fillcolor="royalblue"];
+ * am [label="ACCESS MODIFIED",style="filled",fillcolor="royalblue"];
+ * ae [label="ACCESS EMPTY",style="filled",fillcolor="royalblue"];
+ * ap [label="ACCESS PURGED",style="filled",fillcolor="royalblue"];
+ * t [label="TRANSFER",style="filled",fillcolor="red"];
+ * tp [label="TRANSFER PURGED",style="filled",fillcolor="red"];
+ * s [label="SYNC",style="filled",fillcolor="red"];
+ * m [label="MODIFIED",style="filled",fillcolor="gold"];
+ * i [label="INITIAL"];
+ *
+ * legend_transfer [label="Transfer Wake-Up",fontcolor="red",shape="none"];
+ * legend_access [label="Access Wake-Up",fontcolor="royalblue",shape="none"];
+ *
+ * i -> f [label="Init"];
+ * f -> e [label="Buffer Recycle"];
+ * e -> ae [label="Get"];
+ * e -> t [label="Read"];
+ * e -> f [label="Nobody Waits"];
+ * c -> ac [label="Get\nRead"];
+ * c -> e [label="Buffer Recycle\nPurge"];
+ * c -> f [label="Reallocate\nBlock Size Changed"];
+ * t -> c [label="Transfer Done",color="red",fontcolor="red"];
+ * t -> e [label="Transfer Error",color="red",fontcolor="red"];
+ * t -> tp [label="Purge"];
+ * tp -> e [label="Transfer Done\nTransfer Error",color="red",fontcolor="red"];
+ * m -> t [label="Swapout"];
+ * m -> s [label="Block Size Changed"];
+ * m -> am [label="Get\nRead"];
+ * m -> e [label="Purge"];
+ * ac -> m [label="Release Modified",color="royalblue",fontcolor="royalblue"];
+ * ac -> s [label="Sync",color="royalblue",fontcolor="royalblue"];
+ * ac -> c [label="Release",color="royalblue",fontcolor="royalblue"];
+ * ac -> ap [label="Purge"];
+ * am -> m [label="Release\nRelease Modified",color="royalblue",fontcolor="royalblue"];
+ * am -> s [label="Sync",color="royalblue",fontcolor="royalblue"];
+ * am -> ap [label="Purge"];
+ * ae -> m [label="Release Modified",color="royalblue",fontcolor="royalblue"];
+ * ae -> s [label="Sync",color="royalblue",fontcolor="royalblue"];
+ * ae -> e [label="Release",color="royalblue",fontcolor="royalblue"];
+ * ae -> ap [label="Purge"];
+ * ap -> e [label="Release\nRelease Modified\nSync",color="royalblue",fontcolor="royalblue"];
+ * s -> t [label="Swapout"];
+ * s -> e [label="Purge",color="red",fontcolor="red"];
+ * }
+ * @enddot
+ *
+ * Empty or cached buffers are added to the LRU list and removed from this
+ * queue when a caller requests a buffer. This is referred to as getting a
+ * buffer in the code and the event get in the state diagram. The buffer is
+ * assigned to a block and inserted to the AVL based on the block/device key.
+ * If the block is to be read by the user and not in the cache it is transfered
+ * from the disk into memory. If no buffers are on the LRU list the modified
+ * list is checked. If buffers are on the modified the swap out task will be
+ * woken. The request blocks until a buffer is available for recycle.
+ *
+ * A block being accessed is given to the file system layer and not accessible
+ * to another requester until released back to the cache. The same goes to a
+ * buffer in the transfer state. The transfer state means being read or
+ * written. If the file system has modifed the block and releases it as
+ * modified it placed on the cache's modified list and a hold timer
+ * initialised. The buffer is held for the hold time before being written to
+ * disk. Buffers are held for a configurable period of time on the modified
+ * list as a write sets the state to transfer and this locks the buffer out
+ * from the file system until the write completes. Buffers are often accessed
+ * and modified in a series of small updates so if sent to the disk when
+ * released as modified the user would have to block waiting until it had been
+ * written. This would be a performance problem.
+ *
+ * The code performs multiple block reads and writes. Multiple block reads or
+ * read ahead increases performance with hardware that supports it. It also
+ * helps with a large cache as the disk head movement is reduced. It however
+ * is a speculative operation so excessive use can remove valuable and needed
+ * blocks from the cache.
+ *
+ * The cache has the following lists of buffers:
+ * - LRU: Accessed or transfered buffers released in least recently used
+ * order. Empty buffers will be placed to the front.
+ * - Modified: Buffers waiting to be written to disk.
+ * - Sync: Buffers to be synchronized with the disk.
+ *
+ * A cache look-up will be performed to find a suitable buffer. A suitable
+ * buffer is one that matches the same allocation size as the device the buffer
+ * is for. The a buffer's group has no buffers in use with the file system or
+ * driver the group is reallocated. This means the buffers in the group are
+ * invalidated, resized and placed on the LRU queue. There is a performance
+ * issue with this design. The reallocation of a group may forced recently
+ * accessed buffers out of the cache when they should not. The design should be
+ * change to have groups on a LRU list if they have no buffers in use.
+ *
+ * @{
+ */
+
+/**
+ * @brief State of a buffer of the cache.
+ *
+ * The state has several implications. Depending on the state a buffer can be
+ * in the AVL tree, in a list, in use by an entity and a group user or not.
+ *
+ * <table>
+ * <tr>
+ * <th>State</th><th>Valid Data</th><th>AVL Tree</th>
+ * <th>LRU List</th><th>Modified List</th><th>Synchronization List</th>
+ * <th>Group User</th><th>External User</th>
+ * </tr>
+ * <tr>
+ * <td>FREE</td><td></td><td></td>
+ * <td>X</td><td></td><td></td><td></td><td></td>
+ * </tr>
+ * <tr>
+ * <td>EMPTY</td><td></td><td>X</td>
+ * <td></td><td></td><td></td><td></td><td></td>
+ * </tr>
+ * <tr>
+ * <td>CACHED</td><td>X</td><td>X</td>
+ * <td>X</td><td></td><td></td><td></td><td></td>
+ * </tr>
+ * <tr>
+ * <td>ACCESS CACHED</td><td>X</td><td>X</td>
+ * <td></td><td></td><td></td><td>X</td><td>X</td>
+ * </tr>
+ * <tr>
+ * <td>ACCESS MODIFIED</td><td>X</td><td>X</td>
+ * <td></td><td></td><td></td><td>X</td><td>X</td>
+ * </tr>
+ * <tr>
+ * <td>ACCESS EMPTY</td><td></td><td>X</td>
+ * <td></td><td></td><td></td><td>X</td><td>X</td>
+ * </tr>
+ * <tr>
+ * <td>ACCESS PURGED</td><td></td><td>X</td>
+ * <td></td><td></td><td></td><td>X</td><td>X</td>
+ * </tr>
+ * <tr>
+ * <td>MODIFIED</td><td>X</td><td>X</td>
+ * <td></td><td>X</td><td></td><td>X</td><td></td>
+ * </tr>
+ * <tr>
+ * <td>SYNC</td><td>X</td><td>X</td>
+ * <td></td><td></td><td>X</td><td>X</td><td></td>
+ * </tr>
+ * <tr>
+ * <td>TRANSFER</td><td>X</td><td>X</td>
+ * <td></td><td></td><td></td><td>X</td><td>X</td>
+ * </tr>
+ * <tr>
+ * <td>TRANSFER PURGED</td><td></td><td>X</td>
+ * <td></td><td></td><td></td><td>X</td><td>X</td>
+ * </tr>
+ * </table>
+ */
+typedef enum
+{
+ /**
+ * @brief Free.
+ */
+ RTEMS_BDBUF_STATE_FREE = 0,
+
+ /**
+ * @brief Empty.
+ */
+ RTEMS_BDBUF_STATE_EMPTY,
+
+ /**
+ * @brief Cached.
+ */
+ RTEMS_BDBUF_STATE_CACHED,
+
+ /**
+ * @brief Accessed by upper layer with cached data.
+ */
+ RTEMS_BDBUF_STATE_ACCESS_CACHED,
+
+ /**
+ * @brief Accessed by upper layer with modified data.
+ */
+ RTEMS_BDBUF_STATE_ACCESS_MODIFIED,
+
+ /**
+ * @brief Accessed by upper layer with invalid data.
+ */
+ RTEMS_BDBUF_STATE_ACCESS_EMPTY,
+
+ /**
+ * @brief Accessed by upper layer with purged data.
+ */
+ RTEMS_BDBUF_STATE_ACCESS_PURGED,
+
+ /**
+ * @brief Modified by upper layer.
+ */
+ RTEMS_BDBUF_STATE_MODIFIED,
+
+ /**
+ * @brief Scheduled for synchronization.
+ */
+ RTEMS_BDBUF_STATE_SYNC,
+
+ /**
+ * @brief In transfer by block device driver.
+ */
+ RTEMS_BDBUF_STATE_TRANSFER,
+
+ /**
+ * @brief In transfer by block device driver and purged.
+ */
+ RTEMS_BDBUF_STATE_TRANSFER_PURGED
+} rtems_bdbuf_buf_state;
+
+/**
+ * Forward reference to the block.
+ */
+struct rtems_bdbuf_group;
+typedef struct rtems_bdbuf_group rtems_bdbuf_group;
+
+/**
+ * To manage buffers we using buffer descriptors (BD). A BD holds a buffer plus
+ * a range of other information related to managing the buffer in the cache. To
+ * speed-up buffer lookup descriptors are organized in AVL-Tree. The fields
+ * 'dev' and 'block' are search keys.
+ */
+typedef struct rtems_bdbuf_buffer
+{
+ rtems_chain_node link; /**< Link the BD onto a number of lists. */
+
+ struct rtems_bdbuf_avl_node
+ {
+ struct rtems_bdbuf_buffer* left; /**< Left Child */
+ struct rtems_bdbuf_buffer* right; /**< Right Child */
+ signed char cache; /**< Cache */
+ signed char bal; /**< The balance of the sub-tree */
+ } avl;
+
+ dev_t dev; /**< device number */
+
+ rtems_blkdev_bnum block; /**< block number on the device */
+
+ unsigned char* buffer; /**< Pointer to the buffer memory area */
+
+ volatile rtems_bdbuf_buf_state state; /**< State of the buffer. */
+
+ volatile uint32_t waiters; /**< The number of threads waiting on this
+ * buffer. */
+ rtems_bdbuf_group* group; /**< Pointer to the group of BDs this BD is
+ * part of. */
+ volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer
+ * has been held in the cache modified. */
+
+ int references; /**< Allow reference counting by owner. */
+ void* user; /**< User data. */
+} rtems_bdbuf_buffer;
+
+/**
+ * A group is a continuous block of buffer descriptors. A group covers the
+ * maximum configured buffer size and is the allocation size for the buffers to
+ * a specific buffer size. If you allocate a buffer to be a specific size, all
+ * buffers in the group, if there are more than 1 will also be that size. The
+ * number of buffers in a group is a multiple of 2, ie 1, 2, 4, 8, etc.
+ */
+struct rtems_bdbuf_group
+{
+ rtems_chain_node link; /**< Link the groups on a LRU list if they
+ * have no buffers in use. */
+ size_t bds_per_group; /**< The number of BD allocated to this
+ * group. This value must be a multiple of
+ * 2. */
+ uint32_t users; /**< How many users the block has. */
+ rtems_bdbuf_buffer* bdbuf; /**< First BD this block covers. */
+};
+
+/**
+ * Buffering configuration definition. See confdefs.h for support on using this
+ * structure.
+ */
+typedef struct rtems_bdbuf_config {
+ uint32_t max_read_ahead_blocks; /**< Number of blocks to read
+ * ahead. */
+ uint32_t max_write_blocks; /**< Number of blocks to write
+ * at once. */
+ rtems_task_priority swapout_priority; /**< Priority of the swap out
+ * task. */
+ uint32_t swapout_period; /**< Period swapout checks buf
+ * timers. */
+ uint32_t swap_block_hold; /**< Period a buffer is held. */
+ size_t swapout_workers; /**< The number of worker
+ * threads for the swapout
+ * task. */
+ rtems_task_priority swapout_worker_priority; /**< Priority of the swap out
+ * task. */
+ size_t size; /**< Size of memory in the
+ * cache */
+ uint32_t buffer_min; /**< Minimum buffer size. */
+ uint32_t buffer_max; /**< Maximum buffer size
+ * supported. It is also the
+ * allocation size. */
+} rtems_bdbuf_config;
+
+/**
+ * External reference to the configuration.
+ *
+ * The configuration is provided by the application.
+ */
+extern const rtems_bdbuf_config rtems_bdbuf_configuration;
+
+/**
+ * The max_read_ahead_blocks value is altered if there are fewer buffers
+ * than this defined max. This stops thrashing in the cache.
+ */
+#define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT 0
+
+/**
+ * Default maximum number of blocks to write at once.
+ */
+#define RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT 16
+
+/**
+ * Default swap-out task priority.
+ */
+#define RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT 15
+
+/**
+ * Default swap-out task swap period in milli seconds.
+ */
+#define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250
+
+/**
+ * Default swap-out task block hold time in milli seconds.
+ */
+#define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT 1000
+
+/**
+ * Default swap-out worker tasks. Currently disabled.
+ */
+#define RTEMS_BDBUF_SWAPOUT_WORKER_TASKS_DEFAULT 0
+
+/**
+ * Default swap-out worker task priority. The same as the swapout task.
+ */
+#define RTEMS_BDBUF_SWAPOUT_WORKER_TASK_PRIORITY_DEFAULT \
+ RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT
+
+/**
+ * Default size of memory allocated to the cache.
+ */
+#define RTEMS_BDBUF_CACHE_MEMORY_SIZE_DEFAULT (64 * 512)
+
+/**
+ * Default minimum size of buffers.
+ */
+#define RTEMS_BDBUF_BUFFER_MIN_SIZE_DEFAULT (512)
+
+/**
+ * Default maximum size of buffers.
+ */
+#define RTEMS_BDBUF_BUFFER_MAX_SIZE_DEFAULT (4096)
+
+/**
+ * Prepare buffering layer to work - initialize buffer descritors and (if it is
+ * neccessary) buffers. After initialization all blocks is placed into the
+ * ready state.
+ *
+ * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
+ * successfully or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_init (void);
+
+/**
+ * Get block buffer for data to be written into. The buffers is set to the
+ * access or modifed access state. If the buffer is in the cache and modified
+ * the state is access modified else the state is access. This buffer contents
+ * are not initialised if the buffer is not already in the cache. If the block
+ * is already resident in memory it is returned how-ever if not in memory the
+ * buffer is not read from disk. This call is used when writing the whole block
+ * on a disk rather than just changing a part of it. If there is no buffers
+ * available this call will block. A buffer obtained with this call will not be
+ * involved in a transfer request and will not be returned to another user
+ * until released. If the buffer is already with a user when this call is made
+ * the call is blocked until the buffer is returned. The highest priority
+ * waiter will obtain the buffer first.
+ *
+ * The block number is the linear block number. This is relative to the start
+ * of the partition on the media.
+ *
+ * @param device Device number (constructed of major and minor device number)
+ * @param block Linear media block number
+ * @param bd Reference to the buffer descriptor pointer.
+ *
+ * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
+ * successfully or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_get (dev_t device, rtems_blkdev_bnum block, rtems_bdbuf_buffer** bd);
+
+/**
+ * Get the block buffer and if not already in the cache read from the disk. If
+ * specified block already cached return. The buffer is set to the access or
+ * modifed access state. If the buffer is in the cache and modified the state
+ * is access modified else the state is access. If block is already being read
+ * from disk for being written to disk this call blocks. If the buffer is
+ * waiting to be written it is removed from modified queue and returned to the
+ * user. If the buffer is not in the cache a new buffer is obtained and the
+ * data read from disk. The call may block until these operations complete. A
+ * buffer obtained with this call will not be involved in a transfer request
+ * and will not be returned to another user until released. If the buffer is
+ * already with a user when this call is made the call is blocked until the
+ * buffer is returned. The highest priority waiter will obtain the buffer
+ * first.
+ *
+ * @param device Device number (constructed of major and minor device number)
+ * @param block Linear media block number
+ * @param bd Reference to the buffer descriptor pointer.
+ *
+ * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
+ * successfully or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_read (dev_t device, rtems_blkdev_bnum block, rtems_bdbuf_buffer** bd);
+
+/**
+ * Release the buffer obtained by a read call back to the cache. If the buffer
+ * was obtained by a get call and was not already in the cache the release
+ * modified call should be used. A buffer released with this call obtained by a
+ * get call may not be in sync with the contents on disk. If the buffer was in
+ * the cache and modified before this call it will be returned to the modified
+ * queue. The buffers is returned to the end of the LRU list.
+ *
+ * @param bd Reference to the buffer descriptor.
+ *
+ * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
+ * successfully or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_release (rtems_bdbuf_buffer* bd);
+
+/**
+ * Release the buffer allocated with a get or read call placing it on the
+ * modidied list. If the buffer was not released modified before the hold
+ * timer is set to the configuration value. If the buffer had been released
+ * modified before but not written to disk the hold timer is not updated. The
+ * buffer will be written to disk when the hold timer has expired, there are
+ * not more buffers available in the cache and a get or read buffer needs one
+ * or a sync call has been made. If the buffer is obtained with a get or read
+ * before the hold timer has expired the buffer will be returned to the user.
+ *
+ * @param bd Reference to the buffer descriptor.
+ *
+ * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
+ * successfully or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd);
+
+/**
+ * Release the buffer as modified and wait until it has been synchronized with
+ * the disk by writing it. This buffer will be the first to be transfer to disk
+ * and other buffers may also be written if the maximum number of blocks in a
+ * requests allows it.
+ *
+ * @note This code does not lock the sync mutex and stop additions to the
+ * modified queue.
+
+ * @param bd Reference to the buffer descriptor.
+ *
+ * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
+ * successfully or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_sync (rtems_bdbuf_buffer* bd);
+
+/**
+ * Synchronize all modified buffers for this device with the disk and wait
+ * until the transfers have completed. The sync mutex for the cache is locked
+ * stopping the addition of any further modifed buffers. It is only the
+ * currently modified buffers that are written.
+ *
+ * @note Nesting calls to sync multiple devices will be handled sequentially. A
+ * nested call will be blocked until the first sync request has complete.
+ *
+ * @param dev Block device number
+ *
+ * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
+ * successfully or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_syncdev (dev_t dev);
+
+/**
+ * @brief Purges all buffers that matches the device identifier @a dev.
+ *
+ * This may result in loss of data.
+ */
+void
+rtems_bdbuf_purge_dev (dev_t dev);
+
+/**
+ * @brief Purges all buffers that matches the device major number @a major.
+ *
+ * This may result in loss of data.
+ */
+void
+rtems_bdbuf_purge_major (rtems_device_major_number major);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libblock/include/rtems/bdpart.h b/cpukit/libblock/include/rtems/bdpart.h
new file mode 100644
index 0000000000..907866eb43
--- /dev/null
+++ b/cpukit/libblock/include/rtems/bdpart.h
@@ -0,0 +1,409 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_bdpart
+ *
+ * Block device partition management.
+ */
+
+/*
+ * Copyright (c) 2009, 2010
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-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_BDPART_H
+#define RTEMS_BDPART_H
+
+#include <uuid/uuid.h>
+
+#include <rtems.h>
+#include <rtems/blkdev.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup rtems_bdpart Block Device Partition Management
+ *
+ * @ingroup rtems_libblock
+ *
+ * This module provides functions to manage partitions of a disk device.
+ *
+ * A @ref rtems_disk "disk" is a set of blocks which are identified by a
+ * consecutive set of non-negative integers starting at zero. There are also
+ * logical disks which contain a subset of consecutive disk blocks. The
+ * logical disks are used to represent the partitions of a disk. The disk
+ * devices are accessed via the @ref rtems_disk "block device buffer module".
+ *
+ * The partition format on the physical disk will be converted to an internal
+ * representation. It is possible to convert the internal representation into
+ * a specific output format and write it to the physical disk. One of the
+ * constrains for the internal representation was to support the GPT format
+ * easily.
+ *
+ * Currently two physical partition formats are supported. These are the MBR
+ * and the GPT format. Please note that the GPT support is not implemented.
+ * With MBR format we mean the partition format of the wide spread IBM
+ * PC-compatible systems. The GPT format is defined in the Extensible Firmware
+ * Interface (EFI).
+ *
+ * The most common task will be to read the partition information of a disk and
+ * register logical disks for each partition. This can be done with the
+ * rtems_bdpart_register_from_disk() function. Afterwards you can
+ * @ref rtems_fsmount "mount" the file systems within the partitions.
+ *
+ * You can read the partition information from a disk with rtems_bdpart_read()
+ * and write it to the disk with rtems_bdpart_write().
+ *
+ * To create a partition table from scratch for a disk use
+ * rtems_bdpart_create().
+ *
+ * You can access some disk functions with the shell command @c fdisk.
+ *
+ * References used to create this module:
+ * - <a href="http://en.wikipedia.org/wiki/UUID">Universally Unique Identifier</a>
+ * - <a href="http://en.wikipedia.org/wiki/Globally_Unique_Identifier">Globally Unique Identifier</a>
+ * - <a href="http://en.wikipedia.org/wiki/Disk_partitioning">Disk Paritioning</a>
+ * - <a href="http://en.wikipedia.org/wiki/GUID_Partition_Table">GUID Partition Table</a>
+ * - <a href="http://en.wikipedia.org/wiki/Master_boot_record">Master Boot Record</a>
+ * - <a href="http://en.wikipedia.org/wiki/Extended_boot_record">Extended Boot Record</a>
+ * - <a href="http://en.wikipedia.org/wiki/Cylinder-head-sector">Cylinder Head Sector</a>
+ * - <a href="http://www.win.tue.nl/~aeb/partitions/partition_types-1.html">Partition Types</a>
+ *
+ * @{
+ */
+
+/**
+ * @name MBR Partition Types and Flags
+ *
+ * @{
+ */
+
+#define RTEMS_BDPART_MBR_EMPTY 0x0U
+
+#define RTEMS_BDPART_MBR_FAT_12 0x1U
+
+#define RTEMS_BDPART_MBR_FAT_16 0x4U
+
+#define RTEMS_BDPART_MBR_FAT_16_LBA 0xeU
+
+#define RTEMS_BDPART_MBR_FAT_32 0xbU
+
+#define RTEMS_BDPART_MBR_FAT_32_LBA 0xcU
+
+#define RTEMS_BDPART_MBR_EXTENDED 0x5U
+
+#define RTEMS_BDPART_MBR_DATA 0xdaU
+
+#define RTEMS_BDPART_MBR_GPT 0xeeU
+
+#define RTEMS_BDPART_MBR_FLAG_ACTIVE 0x80U
+
+/** @} */
+
+/**
+ * Recommended maximum partition table size.
+ */
+#define RTEMS_BDPART_PARTITION_NUMBER_HINT 16
+
+/**
+ * Partition description.
+ */
+typedef struct rtems_bdpart_partition {
+ /**
+ * Block index for partition begin.
+ */
+ rtems_blkdev_bnum begin;
+
+ /**
+ * Block index for partition end (this block is not a part of the partition).
+ */
+ rtems_blkdev_bnum end;
+
+ /**
+ * Partition type.
+ */
+ uuid_t type;
+
+ /**
+ * Partition ID.
+ */
+ uuid_t id;
+
+ /**
+ * Partition flags.
+ */
+ uint64_t flags;
+} rtems_bdpart_partition;
+
+/**
+ * Disk format for the partition tables.
+ */
+typedef enum {
+ /**
+ * Type value for MBR format.
+ */
+ RTEMS_BDPART_FORMAT_MBR,
+
+ /**
+ * Type value for GPT format.
+ */
+ RTEMS_BDPART_FORMAT_GPT
+} rtems_bdpart_format_type;
+
+/**
+ * Disk format description.
+ */
+typedef union {
+ /**
+ * Format type.
+ */
+ rtems_bdpart_format_type type;
+
+ /**
+ * MBR format fields.
+ */
+ struct {
+ rtems_bdpart_format_type type;
+
+ /**
+ * Disk ID in MBR at offset 440.
+ */
+ uint32_t disk_id;
+
+ /**
+ * This option is used for partition table creation and validation checks
+ * before a write to the disk. It ensures that the first primary
+ * partition and the logical partitions start at head one and sector one
+ * under the virtual one head and 63 sectors geometry. Each begin and
+ * end of a partition will be aligned to the virtual cylinder boundary.
+ */
+ bool dos_compatibility;
+ } mbr;
+
+ /**
+ * GPT format fields.
+ */
+ struct {
+ rtems_bdpart_format_type type;
+
+ /**
+ * Disk ID in GPT header.
+ */
+ uuid_t disk_id;
+ } gpt;
+} rtems_bdpart_format;
+
+/**
+ * Reads the partition information from the physical disk device with name
+ * @a disk_name.
+ *
+ * The partition information will be stored in the partition table
+ * @a partitions with a maximum of @a count partitions. The number of actual
+ * partitions will be stored in @a count. If there are more partitions than
+ * space for storage an error status will be returned. The partition table
+ * format recognized on the disk will be stored in @a format.
+ */
+rtems_status_code rtems_bdpart_read(
+ const char *disk_name,
+ rtems_bdpart_format *format,
+ rtems_bdpart_partition *partitions,
+ size_t *count
+);
+
+/**
+ * Sorts the partition table @a partitions with @a count partitions to have
+ * ascending begin blocks
+ */
+void rtems_bdpart_sort( rtems_bdpart_partition *partitions, size_t count);
+
+/**
+ * Writes the partition table to the physical disk device with name
+ * @a disk_name.
+ *
+ * The partition table @a partitions with @a count partitions will be written
+ * to the disk. The output format for the partition table on the disk is
+ * specified by @a format. There are some consistency checks applied to the
+ * partition table. The partition table must be sorted such that the begin
+ * blocks are in ascending order. This can be done with the
+ * rtems_bdpart_sort() function. The partitions must not overlap. The
+ * partitions must have a positive size. The partitions must be within the
+ * disk. Depending on the output format there are additional constrains.
+ */
+rtems_status_code rtems_bdpart_write(
+ const char *disk_name,
+ const rtems_bdpart_format *format,
+ const rtems_bdpart_partition *partitions,
+ size_t count
+);
+
+/**
+ * Creates a partition table in @a partitions with @a count partitions for the
+ * physical disk device with name @a disk_name.
+ *
+ * The array of positive integer weights in @a distribution must have exactly
+ * @a count elements. The weights in the distribution array are summed up.
+ * Each weight is then divided by the sum to obtain the disk fraction which
+ * forms the corresponding partition. The partition boundaries are generated
+ * with respect to the output format in @a format.
+ */
+rtems_status_code rtems_bdpart_create(
+ const char *disk_name,
+ const rtems_bdpart_format *format,
+ rtems_bdpart_partition *partitions,
+ const unsigned *distribution,
+ size_t count
+);
+
+/**
+ * Registers the partitions as logical disks for the physical disk device with
+ * name @a disk_name.
+ *
+ * For each partition of the partition table @a partitions with @a count
+ * partitions a logical disk is registered. The partition number equals the
+ * partition table index plus one. The name of the logical disk device is the
+ * concatenation of the physical disk device name and the partition number.
+ */
+rtems_status_code rtems_bdpart_register(
+ const char *disk_name,
+ const rtems_bdpart_partition *partitions,
+ size_t count
+);
+
+/**
+ * Reads the partition table from the disk device with name @a disk_name and
+ * registers the partitions as logical disks.
+ *
+ * @see rtems_bdpart_register() and rtems_fsmount().
+ */
+rtems_status_code rtems_bdpart_register_from_disk( const char *disk_name);
+
+/**
+ * Deletes the logical disks associated with the partitions of the disk device
+ * with name @a disk_name.
+ *
+ * The partition table @a partitions with @a count partitions will be used to
+ * determine which disks need to be deleted. It may be obtained from
+ * rtems_bdpart_read().
+ */
+rtems_status_code rtems_bdpart_unregister(
+ const char *disk_name,
+ const rtems_bdpart_partition *partitions,
+ size_t count
+);
+
+/**
+ * Mounts all supported file systems inside the logical disks derived from the
+ * partitions of the physical disk device with name @a disk_name.
+ *
+ * For each partition in the partition table @a partitions with @a count
+ * partitions it will be checked if it contains a supported file system. In
+ * this case a mount point derived from the disk name will be created in the
+ * mount base path @a mount_base. The file system will be mounted there. The
+ * partition number equals the partition table index plus one. The mount point
+ * name for each partition will be the concatenation of the mount base path,
+ * the disk device file name and the parition number.
+ *
+ * @see rtems_bdpart_read().
+ */
+rtems_status_code rtems_bdpart_mount(
+ const char *disk_name,
+ const rtems_bdpart_partition *partitions,
+ size_t count,
+ const char *mount_base
+);
+
+/**
+ * Unmounts all file systems mounted with rtems_bdpart_mount().
+ */
+rtems_status_code rtems_bdpart_unmount(
+ const char *disk_name,
+ const rtems_bdpart_partition *partitions,
+ size_t count,
+ const char *mount_base
+);
+
+/**
+ * Prints the partition table @a partitions with @a count partitions to
+ * standard output.
+ */
+void rtems_bdpart_dump( const rtems_bdpart_partition *partitions, size_t count);
+
+/**
+ * Returns the partition type for the MBR partition type value @a mbr_type in
+ * @a type.
+ */
+void rtems_bdpart_to_partition_type( uint8_t mbr_type, uuid_t type);
+
+/**
+ * Converts the partition type in @a type to the MBR partition type.
+ *
+ * The result will be stored in @a mbr_type. Returns @c true in case of a
+ * successful convertion and otherwise @c false. Both arguments must not be
+ * @c NULL.
+ */
+bool rtems_bdpart_to_mbr_partition_type(
+ const uuid_t type,
+ uint8_t *mbr_type
+);
+
+/** @} */
+
+#define RTEMS_BDPART_MBR_CYLINDER_SIZE 63
+
+#define RTEMS_BDPART_NUMBER_SIZE 4
+
+#define RTEMS_BDPART_BLOCK_SIZE 512
+
+#define RTEMS_BDPART_MBR_TABLE_ENTRY_SIZE 16
+
+#define RTEMS_BDPART_MBR_OFFSET_TABLE_0 446
+
+#define RTEMS_BDPART_MBR_OFFSET_TABLE_1 \
+ (RTEMS_BDPART_MBR_OFFSET_TABLE_0 + RTEMS_BDPART_MBR_TABLE_ENTRY_SIZE)
+
+#define RTEMS_BDPART_MBR_OFFSET_DISK_ID 440
+
+#define RTEMS_BDPART_MBR_OFFSET_SIGNATURE_0 510
+
+#define RTEMS_BDPART_MBR_OFFSET_SIGNATURE_1 511
+
+#define RTEMS_BDPART_MBR_SIGNATURE_0 0x55U
+
+#define RTEMS_BDPART_MBR_SIGNATURE_1 0xaaU
+
+#define RTEMS_BDPART_MBR_OFFSET_BEGIN 8
+
+#define RTEMS_BDPART_MBR_OFFSET_SIZE 12
+
+#define RTEMS_BDPART_MBR_OFFSET_TYPE 4
+
+#define RTEMS_BDPART_MBR_OFFSET_FLAGS 0
+
+static inline uint8_t rtems_bdpart_mbr_partition_type(
+ const uuid_t type
+)
+{
+ return type [0];
+}
+
+rtems_status_code rtems_bdpart_get_disk_data(
+ const char *disk_name,
+ dev_t *disk,
+ rtems_blkdev_bnum *disk_end
+);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* RTEMS_BDPART_H */
diff --git a/cpukit/libblock/include/rtems/blkdev.h b/cpukit/libblock/include/rtems/blkdev.h
new file mode 100644
index 0000000000..e9fa86b248
--- /dev/null
+++ b/cpukit/libblock/include/rtems/blkdev.h
@@ -0,0 +1,276 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_blkdev
+ *
+ * Block device management.
+ */
+
+/*
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#ifndef _RTEMS_BLKDEV_H
+#define _RTEMS_BLKDEV_H
+
+#include <rtems.h>
+#include <rtems/diskdevs.h>
+#include <sys/ioctl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup rtems_blkdev Block Device Management
+ *
+ * @ingroup rtems_libblock
+ *
+ * Interface between device drivers and the
+ * @ref rtems_bdbuf "block device buffer module".
+ *
+ * The heart of the block device driver is the @ref RTEMS_BLKIO_REQUEST IO
+ * control. This call puts IO @ref rtems_blkdev_request "requests" to the block
+ * device for asynchronous processing. When a driver executes a request, it
+ * invokes the request done callback function to finish the request.
+ *
+ * @{
+ */
+
+/**
+ * Block device request type.
+ *
+ * @warning The sync request is an IO one and only used from the cache. Use the
+ * Block IO when operating at the device level. We need a sync request
+ * to avoid requests looping for ever.
+ */
+typedef enum rtems_blkdev_request_op {
+ RTEMS_BLKDEV_REQ_READ, /**< Read the requested blocks of data. */
+ RTEMS_BLKDEV_REQ_WRITE, /**< Write the requested blocks of data. */
+ RTEMS_BLKDEV_REQ_SYNC /**< Sync any data with the media. */
+} rtems_blkdev_request_op;
+
+/**
+ * @brief Block device request done callback function type.
+ *
+ * The first parameter @a arg must be the argument provided by the block device
+ * request structure @ref rtems_blkdev_request.
+ *
+ * The second parameter @a status should contain the status of the operation:
+ * - @c RTEMS_SUCCESSFUL Operation was successful.
+ * - @c RTEMS_IO_ERROR Some sort of input or output error.
+ * - @c RTEMS_UNSATISFIED Media no more present.
+ */
+typedef void (*rtems_blkdev_request_cb)(void *arg, rtems_status_code status);
+
+/**
+ * Block device scatter or gather buffer structure.
+ */
+typedef struct rtems_blkdev_sg_buffer {
+ /**
+ * Block index.
+ */
+ rtems_blkdev_bnum block;
+
+ /**
+ * Buffer length.
+ */
+ uint32_t length;
+
+ /**
+ * Buffer pointer.
+ */
+ void *buffer;
+
+ /**
+ * User pointer.
+ */
+ void *user;
+} rtems_blkdev_sg_buffer;
+
+/**
+ * The block device request structure is used to read or write a number of
+ * blocks from or to the device.
+ *
+ * TODO: The use of these req blocks is not a great design. The req is a
+ * struct with a single 'bufs' declared in the req struct and the
+ * others are added in the outer level struct. This relies on the
+ * structs joining as a single array and that assumes the compiler
+ * packs the structs. Why not just place on a list ? The BD has a
+ * node that can be used.
+ */
+typedef struct rtems_blkdev_request {
+ /**
+ * Block device operation (read or write).
+ */
+ rtems_blkdev_request_op req;
+
+ /**
+ * Request done callback function.
+ */
+ rtems_blkdev_request_cb req_done;
+
+ /**
+ * Argument to be passed to callback function.
+ */
+ void *done_arg;
+
+ /**
+ * Last IO operation completion status.
+ */
+ rtems_status_code status;
+
+ /**
+ * Number of blocks for this request.
+ */
+ uint32_t bufnum;
+
+ /**
+ * The task requesting the IO operation.
+ */
+ rtems_id io_task;
+
+ /**
+ * List of scatter or gather buffers.
+ */
+ rtems_blkdev_sg_buffer bufs[0];
+} rtems_blkdev_request;
+
+/**
+ * The start block in a request.
+ *
+ * Only valid if the driver has returned the @ref RTEMS_BLKIO_CAPABILITIES of
+ * @ref RTEMS_BLKDEV_CAP_MULTISECTOR_CONT.
+ */
+#define RTEMS_BLKDEV_START_BLOCK(req) (req->bufs[0].block)
+
+/**
+ * @name IO Control Request Codes
+ *
+ * @{
+ */
+
+#define RTEMS_BLKIO_REQUEST _IOWR('B', 1, rtems_blkdev_request)
+#define RTEMS_BLKIO_GETMEDIABLKSIZE _IOR('B', 2, uint32_t)
+#define RTEMS_BLKIO_GETBLKSIZE _IOR('B', 3, uint32_t)
+#define RTEMS_BLKIO_SETBLKSIZE _IOW('B', 4, uint32_t)
+#define RTEMS_BLKIO_GETSIZE _IOR('B', 5, rtems_blkdev_bnum)
+#define RTEMS_BLKIO_SYNCDEV _IO('B', 6)
+#define RTEMS_BLKIO_DELETED _IO('B', 7)
+#define RTEMS_BLKIO_CAPABILITIES _IO('B', 8)
+
+/** @} */
+
+/**
+ * Only consecutive multi-sector buffer requests are supported.
+ *
+ * This option means the cache will only supply multiple buffers that are
+ * inorder so the ATA multi-sector command for example can be used. This is a
+ * hack to work around the current ATA driver.
+ */
+#define RTEMS_BLKDEV_CAP_MULTISECTOR_CONT (1 << 0)
+
+/**
+ * The driver will accept a sync call. A sync call is made to a driver
+ * after a bdbuf cache sync has finished.
+ */
+#define RTEMS_BLKDEV_CAP_SYNC (1 << 1)
+
+/**
+ * The device driver interface conventions suppose that a driver may contain an
+ * initialize, open, close, read, write and IO control entry points. These
+ * primitives (except initialize) can be implemented in a generic fashion based
+ * upon the supplied block device driver IO control handler. Every block device
+ * driver should provide an initialize entry point, which registers the
+ * appropriate IO control handler.
+ */
+#define RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
+ rtems_blkdev_generic_open, \
+ rtems_blkdev_generic_close, \
+ rtems_blkdev_generic_read, \
+ rtems_blkdev_generic_write, \
+ rtems_blkdev_generic_ioctl
+
+/**
+ * Generic block device read primitive.
+ *
+ * Implemented using block device buffer management primitives.
+ */
+rtems_device_driver
+rtems_blkdev_generic_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+/**
+ * Generic block device write primitive.
+ *
+ * Implemented using block device buffer management primitives.
+ */
+rtems_device_driver
+rtems_blkdev_generic_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+/**
+ * Generic block device open primitive.
+ *
+ * Implemented using block device buffer management primitives.
+ */
+rtems_device_driver
+rtems_blkdev_generic_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+/**
+ * Generic block device close primitive.
+ *
+ * Implemented using block device buffer management primitives.
+ */
+rtems_device_driver
+rtems_blkdev_generic_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+/**
+ * Generic block device IO control primitive.
+ *
+ * Implemented using block device buffer management primitives.
+ */
+rtems_device_driver
+rtems_blkdev_generic_ioctl(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+/**
+ * Common IO control primitive.
+ *
+ * Use this in all block devices to handle the common set of ioctl requests.
+ */
+int
+rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
+
+/**
+ * @brief Generic block operations driver address table.
+ */
+extern const rtems_driver_address_table rtems_blkdev_generic_ops;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libblock/include/rtems/diskdevs.h b/cpukit/libblock/include/rtems/diskdevs.h
new file mode 100644
index 0000000000..8884999d95
--- /dev/null
+++ b/cpukit/libblock/include/rtems/diskdevs.h
@@ -0,0 +1,341 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_disk
+ *
+ * @brief Block device disk management API.
+ */
+
+/*
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#ifndef _RTEMS_DISKDEVS_H
+#define _RTEMS_DISKDEVS_H
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct rtems_disk_device rtems_disk_device;
+
+/**
+ * @defgroup rtems_disk Block Device Disk Management
+ *
+ * @ingroup rtems_libblock
+ *
+ * @brief This module provides functions to manage disk devices.
+ *
+ * A disk is a set of blocks which are identified by a consecutive set of
+ * non-negative integers starting at zero. There are also logical disks which
+ * contain a subset of consecutive disk blocks. The logical disks are used to
+ * represent the partitions of a disk. The disk devices are accessed via the
+ * @ref rtems_bdbuf "block device buffer module".
+ *
+ * @{
+ */
+
+/**
+ * @brief Block device block index type.
+ */
+typedef uint32_t rtems_blkdev_bnum;
+
+/**
+ * @brief Block device IO control handler type.
+ */
+typedef int (*rtems_block_device_ioctl)(
+ rtems_disk_device *dd,
+ uint32_t req,
+ void *argp
+);
+
+/**
+ * @brief Description of a disk device (logical and physical disks).
+ *
+ * An array of pointer tables to rtems_disk_device structures is maintained.
+ * The first table will be indexed by the major number and the second table
+ * will be indexed by the minor number. This allows quick lookup using a data
+ * structure of moderated size.
+ */
+struct rtems_disk_device {
+ /**
+ * @brief Device identifier (concatenation of major and minor number).
+ */
+ dev_t dev;
+
+ /**
+ * @brief Physical device identifier (equals the @c dev entry if it specifies a
+ * physical device).
+ */
+ rtems_disk_device *phys_dev;
+
+ /**
+ * @brief Driver capabilities.
+ */
+ uint32_t capabilities;
+
+ /**
+ * @brief Disk device name.
+ */
+ char *name;
+
+ /**
+ * @brief Usage counter.
+ *
+ * Devices cannot be deleted if they are in use.
+ */
+ unsigned uses;
+
+ /**
+ * @brief Start block number.
+ *
+ * Equals zero for physical devices. It is a block offset to the related
+ * physical device for logical device.
+ */
+ rtems_blkdev_bnum start;
+
+ /**
+ * @brief Size of the physical or logical disk in blocks.
+ */
+ rtems_blkdev_bnum size;
+
+ /**
+ * @brief Device block size in bytes.
+ *
+ * This is the minimum transfer unit. It can be any size.
+ */
+ uint32_t block_size;
+
+ /**
+ * @brief Device media block size in bytes.
+ *
+ * This is the media transfer unit the hardware defaults to.
+ */
+ uint32_t media_block_size;
+
+ /**
+ * @brief IO control handler for this disk.
+ */
+ rtems_block_device_ioctl ioctl;
+
+ /**
+ * @brief Private data for the disk driver.
+ */
+ void *driver_data;
+
+ /**
+ * @brief Indicates that this disk should be deleted as soon as the last user
+ * releases this disk.
+ */
+ bool deleted;
+};
+
+/**
+ * @name Disk Device Data
+ *
+ * @{
+ */
+
+static inline dev_t rtems_disk_get_device_identifier(
+ const rtems_disk_device *dd
+)
+{
+ return dd->dev;
+}
+
+static inline rtems_device_major_number rtems_disk_get_major_number(
+ const rtems_disk_device *dd
+)
+{
+ return rtems_filesystem_dev_major_t(dd->dev);
+}
+
+static inline rtems_device_minor_number rtems_disk_get_minor_number(
+ const rtems_disk_device *dd
+)
+{
+ return rtems_filesystem_dev_minor_t(dd->dev);
+}
+
+static inline void *rtems_disk_get_driver_data(
+ const rtems_disk_device *dd
+)
+{
+ return dd->driver_data;
+}
+
+static inline uint32_t rtems_disk_get_media_block_size(
+ const rtems_disk_device *dd
+)
+{
+ return dd->media_block_size;
+}
+
+/** @} */
+
+/**
+ * @name Disk Device Maintainance
+ *
+ * @{
+ */
+
+/**
+ * @brief Creates a physical disk with device identifier @a dev.
+ *
+ * The block size @a block_size must be positive. The disk will have
+ * @a block_count blocks. The block index starts with zero. The associated disk
+ * device driver will be invoked via the IO control handler @a handler. A
+ * device node will be registered in the file system with absolute path @a
+ * name, if @a name is not @c NULL. This function is usually invoked from a
+ * block device driver during initialization when a physical device is detected
+ * in the system. The device driver provides an IO control handler to allow
+ * block device operations.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NOT_CONFIGURED Cannot lock disk device operation mutex.
+ * @retval RTEMS_INVALID_ADDRESS IO control handler is @c NULL.
+ * @retval RTEMS_INVALID_NUMBER Block size is zero.
+ * @retval RTEMS_NO_MEMORY Not enough memory.
+ * @retval RTEMS_RESOURCE_IN_USE Disk device descriptor is already in use.
+ * @retval RTEMS_UNSATISFIED Cannot create device node.
+ */
+rtems_status_code rtems_disk_create_phys(
+ dev_t dev,
+ uint32_t block_size,
+ rtems_blkdev_bnum block_count,
+ rtems_block_device_ioctl handler,
+ void *driver_data,
+ const char *name
+);
+
+/**
+ * @brief Creates a logical disk with device identifier @a dev.
+ *
+ * A logical disk manages a subset of consecutive blocks contained in the
+ * physical disk with identifier @a phys. The start block index of the logical
+ * disk device is @a begin_block. The block count of the logcal disk will be
+ * @a block_count. The blocks must be within the range of blocks managed by
+ * the associated physical disk device. A device node will be registered in
+ * the file system with absolute path @a name, if @a name is not @c NULL. The
+ * block size and IO control handler are inherited by the physical disk.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NOT_CONFIGURED Cannot lock disk device operation mutex.
+ * @retval RTEMS_INVALID_ID Specified physical disk identifier does not
+ * correspond to a physical disk.
+ * @retval RTEMS_INVALID_NUMBER Begin block or block count are out of range.
+ * @retval RTEMS_NO_MEMORY Not enough memory.
+ * @retval RTEMS_RESOURCE_IN_USE Disk device descriptor for logical disk
+ * identifier is already in use.
+ * @retval RTEMS_UNSATISFIED Cannot create device node.
+ */
+rtems_status_code rtems_disk_create_log(
+ dev_t dev,
+ dev_t phys,
+ rtems_blkdev_bnum begin_block,
+ rtems_blkdev_bnum block_count,
+ const char *name
+);
+
+/**
+ * @brief Deletes a physical or logical disk device with identifier @a dev.
+ *
+ * Marks the disk device as deleted. When a physical disk device is deleted,
+ * all corresponding logical disk devices will marked as deleted too. Disks
+ * that are marked as deleted and have a usage counter of zero will be deleted.
+ * The corresponding device nodes will be removed from the file system. In
+ * case of a physical disk deletion the IO control handler will be invoked with
+ * a RTEMS_BLKIO_DELETED request. Disks that are still in use will be deleted
+ * upon release.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NOT_CONFIGURED Cannot lock disk device operation mutex.
+ * @retval RTEMS_INVALID_ID No disk for specified device identifier.
+ */
+rtems_status_code rtems_disk_delete(dev_t dev);
+
+/**
+ * @brief Returns the disk device descriptor for the device identifier @a dev.
+ *
+ * Increments usage counter by one. You should release the disk device
+ * descriptor with rtems_disk_release().
+ *
+ * @return Pointer to the disk device descriptor or @c NULL if no corresponding
+ * disk exists.
+ */
+rtems_disk_device *rtems_disk_obtain(dev_t dev);
+
+/**
+ * @brief Releases the disk device descriptor @a dd.
+ *
+ * Decrements usage counter by one.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ */
+rtems_status_code rtems_disk_release(rtems_disk_device *dd);
+
+/** @} */
+
+/**
+ * @name Disk Management
+ *
+ * @{
+ */
+
+/**
+ * @brief Initializes the disk device management.
+ *
+ * This functions returns successful if the disk device management is already
+ * initialized. There is no protection against concurrent access.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful initialization.
+ * @retval RTEMS_NO_MEMORY Not enough memory or no semaphore available.
+ * @retval RTEMS_UNSATISFIED Block device buffer initialization failed.
+ */
+rtems_status_code rtems_disk_io_initialize(void);
+
+/**
+ * @brief Releases all resources allocated for disk device management.
+ *
+ * There is no protection against concurrent access. If parts of the system
+ * are still in use the behaviour is undefined.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ */
+rtems_status_code rtems_disk_io_done(void);
+
+/** @} */
+
+/** @} */
+
+/**
+ * @brief Disk device iterator.
+ *
+ * Returns the next disk device descriptor with a device identifier larger than
+ * @a dev. If there is no such device, @c NULL will be returned. Use minus
+ * one to start the search.
+ *
+ * @code
+ * rtems_status_code sc = RTEMS_SUCCESSFUL;
+ * rtems_disk_device *dd = (dev_t) -1;
+ *
+ * while (sc == RTEMS_SUCCESSFUL && (dd = rtems_disk_next(dev)) != NULL) {
+ * dev = rtems_disk_get_device_identifier(dd);
+ * sc = rtems_disk_release(dd);
+ * }
+ * @endcode
+ */
+rtems_disk_device *rtems_disk_next(dev_t dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libblock/include/rtems/flashdisk.h b/cpukit/libblock/include/rtems/flashdisk.h
new file mode 100644
index 0000000000..c24b9b08be
--- /dev/null
+++ b/cpukit/libblock/include/rtems/flashdisk.h
@@ -0,0 +1,366 @@
+/*
+ * flashdisk.h -- Flash disk block device implementation
+ *
+ * Copyright (C) 2007 Chris Johns
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#if !defined (_RTEMS_FLASHDISK_H_)
+#define _RTEMS_FLASHDISK_H_
+
+#include <stdint.h>
+#include <sys/ioctl.h>
+
+#include <rtems.h>
+
+/**
+ * The base name of the flash disks.
+ */
+#define RTEMS_FLASHDISK_DEVICE_BASE_NAME "/dev/fdd"
+
+/**
+ * Flash disk specific ioctl request types. To use open the
+ * device and issue the ioctl call.
+ *
+ * @code
+ * int fd = open ("/dev/flashdisk0", O_WRONLY, 0);
+ * if (fd < 0)
+ * {
+ * printf ("driver open failed: %s\n", strerror (errno));
+ * exit (1);
+ * }
+ * if (ioctl (fd, RTEMS_FDISK_IOCTL_ERASE_DISK) < 0)
+ * {
+ * printf ("driver erase failed: %s\n", strerror (errno));
+ * exit (1);
+ * }
+ * close (fd);
+ * @endcode
+ */
+#define RTEMS_FDISK_IOCTL_ERASE_DISK _IO('B', 128)
+#define RTEMS_FDISK_IOCTL_COMPACT _IO('B', 129)
+#define RTEMS_FDISK_IOCTL_ERASE_USED _IO('B', 130)
+#define RTEMS_FDISK_IOCTL_MONITORING _IO('B', 131)
+#define RTEMS_FDISK_IOCTL_INFO_LEVEL _IO('B', 132)
+#define RTEMS_FDISK_IOCTL_PRINT_STATUS _IO('B', 133)
+
+/**
+ * Flash Disk Monitoring Data allows a user to obtain
+ * the current status of the disk.
+ */
+typedef struct rtems_fdisk_monitor_data
+{
+ uint32_t block_size;
+ uint32_t block_count;
+ uint32_t unavail_blocks;
+ uint32_t device_count;
+ uint32_t segment_count;
+ uint32_t page_count;
+ uint32_t blocks_used;
+ uint32_t segs_available;
+ uint32_t segs_used;
+ uint32_t segs_failed;
+ uint32_t seg_erases;
+ uint32_t pages_desc;
+ uint32_t pages_active;
+ uint32_t pages_used;
+ uint32_t pages_bad;
+ uint32_t info_level;
+} rtems_fdisk_monitor_data;
+
+/**
+ * Flash Segment Descriptor holds, number of continuous segments in the
+ * device of this type, the base segment number in the device, the
+ * address offset of the base segment in the device, and the size of
+ * segment.
+ *
+ * Typically this structure is part of a table of segments in the
+ * device which is referenced in the flash disk configuration table.
+ * The reference is kept in the driver and used all the time to
+ * manage the flash device, therefore it must always exist.
+ */
+typedef struct rtems_fdisk_segment_desc
+{
+ uint16_t count; /**< Number of segments of this type in a row. */
+ uint16_t segment; /**< The base segment number. */
+ uint32_t offset; /**< Address offset of base segment in device. */
+ uint32_t size; /**< Size of the segment in bytes. */
+} rtems_fdisk_segment_desc;
+
+/**
+ * Return the number of kilo-bytes.
+ */
+#define RTEMS_FDISK_KBYTES(_k) (UINT32_C(1024) * (_k))
+
+/**
+ * Forward declaration of the device descriptor.
+ */
+struct rtems_fdisk_device_desc;
+
+/**
+ * Flash Low Level driver handlers.
+
+ * Typically this structure is part of a table of handlers in the
+ * device which is referenced in the flash disk configuration table.
+ * The reference is kept in the driver and used all the time to
+ * manage the flash device, therefore it must always exist.
+ */
+typedef struct rtems_fdisk_driver_handlers
+{
+ /**
+ * Read data from the device into the buffer. Return an errno
+ * error number if the device cannot be read. A segment descriptor
+ * can describe more than one segment in a device if the device has
+ * repeating segments. The segment number is the device segment to
+ * access and the segment descriptor must reference the segment
+ * being requested. For example the segment number must resided in
+ * the range [base, base + count).
+ *
+ * @param sd The segment descriptor.
+ * @param device The device to read data from.
+ * @param segment The segment within the device to read.
+ * @param offset The offset in the segment to read.
+ * @param buffer The buffer to read the data into.
+ * @param size The amount of data to read.
+ * @retval 0 No error.
+ * @retval EIO The read did not complete.
+ */
+ int (*read) (const rtems_fdisk_segment_desc* sd,
+ uint32_t device,
+ uint32_t segment,
+ uint32_t offset,
+ void* buffer,
+ uint32_t size);
+
+ /**
+ * Write data from the buffer to the device. Return an errno
+ * error number if the device cannot be written to. A segment
+ * descriptor can describe more than segment in a device if the
+ * device has repeating segments. The segment number is the device
+ * segment to access and the segment descriptor must reference
+ * the segment being requested. For example the segment number must
+ * resided in the range [base, base + count).
+ *
+ * @param sd The segment descriptor.
+ * @param device The device to write data from.
+ * @param segment The segment within the device to write to.
+ * @param offset The offset in the segment to write.
+ * @param buffer The buffer to write the data from.
+ * @param size The amount of data to write.
+ * @retval 0 No error.
+ * @retval EIO The write did not complete or verify.
+ */
+ int (*write) (const rtems_fdisk_segment_desc* sd,
+ uint32_t device,
+ uint32_t segment,
+ uint32_t offset,
+ const void* buffer,
+ uint32_t size);
+
+ /**
+ * Blank a segment in the device. Return an errno error number
+ * if the device cannot be read or is not blank. A segment descriptor
+ * can describe more than segment in a device if the device has
+ * repeating segments. The segment number is the device segment to
+ * access and the segment descriptor must reference the segment
+ * being requested. For example the segment number must resided in
+ * the range [base, base + count).
+ *
+ * @param sd The segment descriptor.
+ * @param device The device to read data from.
+ * @param segment The segment within the device to read.
+ * @param offset The offset in the segment to checl.
+ * @param size The amount of data to check.
+ * @retval 0 No error.
+ * @retval EIO The segment is not blank.
+ */
+ int (*blank) (const rtems_fdisk_segment_desc* sd,
+ uint32_t device,
+ uint32_t segment,
+ uint32_t offset,
+ uint32_t size);
+
+ /**
+ * Verify data in the buffer to the data in the device. Return an
+ * errno error number if the device cannot be read. A segment
+ * descriptor can describe more than segment in a device if the
+ * device has repeating segments. The segment number is the
+ * segment to access and the segment descriptor must reference
+ * the device segment being requested. For example the segment number
+ * must resided in the range [base, base + count).
+ *
+ * @param sd The segment descriptor.
+ * @param device The device to verify data in.
+ * @param segment The segment within the device to verify.
+ * @param offset The offset in the segment to verify.
+ * @param buffer The buffer to verify the data in the device with.
+ * @param size The amount of data to verify.
+ * @retval 0 No error.
+ * @retval EIO The data did not verify.
+ */
+ int (*verify) (const rtems_fdisk_segment_desc* sd,
+ uint32_t device,
+ uint32_t segment,
+ uint32_t offset,
+ const void* buffer,
+ uint32_t size);
+
+ /**
+ * Erase the segment. Return an errno error number if the
+ * segment cannot be erased. A segment descriptor can describe
+ * more than segment in a device if the device has repeating
+ * segments. The segment number is the device segment to access and
+ * the segment descriptor must reference the segment being requested.
+ *
+ * @param sd The segment descriptor.
+ * @param device The device to erase the segment of.
+ * @param segment The segment within the device to erase.
+ * @retval 0 No error.
+ * @retval EIO The segment was not erased.
+ */
+ int (*erase) (const rtems_fdisk_segment_desc* sd,
+ uint32_t device,
+ uint32_t segment);
+
+ /**
+ * Erase the device. Return an errno error number if the
+ * segment cannot be erased. A segment descriptor can describe
+ * more than segment in a device if the device has repeating
+ * segments. The segment number is the segment to access and
+ * the segment descriptor must reference the segment being requested.
+ *
+ * @param sd The segment descriptor.
+ * @param device The device to erase.
+ * @retval 0 No error.
+ * @retval EIO The device was not erased.
+ */
+ int (*erase_device) (const struct rtems_fdisk_device_desc* dd,
+ uint32_t device);
+
+} rtems_fdisk_driver_handlers;
+
+/**
+ * Flash Device Descriptor holds the segments in a device. The
+ * placing of the segments in a device decriptor allows the
+ * low level driver to share the segment descriptors for a
+ * number of devices.
+ *
+ * Typically this structure is part of a table of segments in the
+ * device which is referenced in the flash disk configuration table.
+ * The reference is kept in the driver and used all the time to
+ * manage the flash device, therefore it must always exist.
+ */
+typedef struct rtems_fdisk_device_desc
+{
+ uint32_t segment_count; /**< Number of segments. */
+ const rtems_fdisk_segment_desc* segments; /**< Array of segments. */
+ const rtems_fdisk_driver_handlers* flash_ops; /**< Device handlers. */
+} rtems_fdisk_device_desc;
+
+/**
+ * RTEMS Flash Disk configuration table used to initialise the
+ * driver.
+ *
+ * The unavailable blocks count is the number of blocks less than the
+ * available number of blocks the file system is given. This means there
+ * will always be that number of blocks available when the file system
+ * thinks the disk is full. The compaction code needs blocks to compact
+ * with so you will never be able to have all the blocks allocated to the
+ * file system and be able to full the disk.
+ *
+ * The compacting segment count is the number of segments that are
+ * moved into a new segment. A high number will mean more segments with
+ * low active page counts and high used page counts will be moved into
+ * avaliable pages how-ever this extends the compaction time due to
+ * time it takes the erase the pages. There is no pont making this number
+ * greater than the maximum number of pages in a segment.
+ *
+ * The available compacting segment count is the level when compaction occurs
+ * when writing. If you set this to 0 then compaction will fail because
+ * there will be no segments to compact into.
+ *
+ * The info level can be 0 for off with error, and abort messages allowed.
+ * Level 1 is warning messages, level 1 is informational messages, and level 3
+ * is debugging type prints. The info level can be turned off with a compile
+ * time directive on the command line to the compiler of:
+ *
+ * -DRTEMS_FDISK_TRACE=0
+ */
+typedef struct rtems_flashdisk_config
+{
+ uint32_t block_size; /**< The block size. */
+ uint32_t device_count; /**< The number of devices. */
+ const rtems_fdisk_device_desc* devices; /**< The device descriptions. */
+ uint32_t flags; /**< Set of flags to control
+ driver. */
+ uint32_t unavail_blocks; /**< Number of blocks not
+ available to the file sys. */
+ uint32_t compact_segs; /**< Max number of segs to
+ compact in one pass. */
+ uint32_t avail_compact_segs; /**< The number of segments
+ when compaction occurs
+ when writing. */
+ uint32_t info_level; /**< Default info level. */
+} rtems_flashdisk_config;
+
+/*
+ * Driver flags.
+ */
+
+/**
+ * Leave the erasing of used segment to the background handler.
+ */
+#define RTEMS_FDISK_BACKGROUND_ERASE (1 << 0)
+
+/**
+ * Leave the compacting of of used segment to the background handler.
+ */
+#define RTEMS_FDISK_BACKGROUND_COMPACT (1 << 1)
+
+/**
+ * Check the pages during initialisation to see which pages are
+ * valid and which are not. This could slow down initialising the
+ * disk driver.
+ */
+#define RTEMS_FDISK_CHECK_PAGES (1 << 2)
+
+/**
+ * Blank check the flash device before writing to them. This is needed if
+ * you think you have a driver or device problem.
+ */
+#define RTEMS_FDISK_BLANK_CHECK_BEFORE_WRITE (1 << 3)
+
+/**
+ * Flash disk device driver initialization. Place in a table as the
+ * initialisation entry and remainder of the entries are the
+ * RTEMS block device generic handlers.
+ *
+ * @param major Flash disk major device number.
+ * @param minor Minor device number, not applicable.
+ * @param arg Initialization argument, not applicable.
+ * @return The rtems_device_driver is actually just
+ * rtems_status_code.
+ */
+rtems_device_driver
+rtems_fdisk_initialize (rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void* arg);
+
+/**
+ * External reference to the configuration. Please supply.
+ * Support is present in confdefs.h for providing this variable.
+ */
+extern const rtems_flashdisk_config rtems_flashdisk_configuration[];
+
+/**
+ * External reference to the number of configurations. Please supply.
+ * Support is present in confdefs.h for providing this variable.
+ */
+extern uint32_t rtems_flashdisk_configuration_size;
+
+#endif
diff --git a/cpukit/libblock/include/rtems/ide_part_table.h b/cpukit/libblock/include/rtems/ide_part_table.h
new file mode 100644
index 0000000000..c6fe587e02
--- /dev/null
+++ b/cpukit/libblock/include/rtems/ide_part_table.h
@@ -0,0 +1,217 @@
+/**
+ * @file rtems/ide_part_table.h
+ *
+ * Support for "MS-DOS-style" partition tables
+ */
+
+/*
+ * Copyright (C) 2002 OKTET Ltd., St.-Petersburg, Russia
+ *
+ * Author: Konstantin Abramenko <Konstantin.Abramenko@oktet.ru>
+ * Alexander Kukuta <Alexander.Kukuta@oktet.ru>
+ *
+ * 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.
+ *
+ * $Id$
+ *
+ *****************************************************************************/
+
+#ifndef _RTEMS_IDE_PART_TABLE_H
+#define _RTEMS_IDE_PART_TABLE_H
+
+#include <rtems/chain.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <rtems.h>
+#include <rtems/blkdev.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/bdbuf.h>
+#include <rtems/seterr.h>
+
+/* Minor base number for all logical devices */
+#define RTEMS_IDE_SECTOR_BITS 9
+#define RTEMS_IDE_SECTOR_SIZE 512
+#define RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE 16
+#define RTEMS_IDE_PARTITION_MAX_PARTITION_NUMBER 63
+#define RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER 4
+#define RTEMS_IDE_PARTITION_DEV_NAME_LENGTH_MAX 16
+
+#define RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_DATA1 0x55
+#define RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_DATA2 0xaa
+#define RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_OFFSET 0x1fe
+#define RTEMS_IDE_PARTITION_TABLE_OFFSET 0x1be
+#define RTEMS_IDE_PARTITION_TABLE_SIZE (4 * 16)
+#define RTEMS_IDE_PARTITION_BOOTABLE_OFFSET 0
+#define RTEMS_IDE_PARTITION_SYS_TYPE_OFFSET 4
+#define RTEMS_IDE_PARTITION_START_OFFSET 8
+#define RTEMS_IDE_PARTITION_SIZE_OFFSET 12
+
+/*
+ * Conversion from and to little-endian byte order. (no-op on i386/i486)
+ */
+
+#if (CPU_BIG_ENDIAN == TRUE)
+# define LE_TO_CPU_U16(v) CPU_swap_u16(v)
+# define LE_TO_CPU_U32(v) CPU_swap_u32(v)
+# define CPU_TO_LE_U16(v) CPU_swap_u16(v)
+# define CPU_TO_LE_U32(v) CPU_swap_u32(v)
+#else
+# define LE_TO_CPU_U16(v) (v)
+# define LE_TO_CPU_U32(v) (v)
+# define CPU_TO_LE_U16(v) (v)
+# define CPU_TO_LE_U32(v) (v)
+#endif
+
+
+/*
+ * sector_data_t --
+ * corresponds to the sector on the device
+ */
+typedef struct rtems_sector_data_s
+{
+ uint32_t sector_num; /* sector number on the device */
+ uint8_t data[0]; /* raw sector data */
+} rtems_sector_data_t;
+
+
+/*
+ * Enum partition types
+ * see list at http://ata-atapi.com/hiwtab.htm
+ *
+ * @todo Should these have RTEMS before them.
+ */
+enum {
+ EMPTY_PARTITION = 0x00,
+ DOS_FAT12_PARTITION = 0x01,
+ DOS_FAT16_PARTITION = 0x04,
+ EXTENDED_PARTITION = 0x05,
+ DOS_P32MB_PARTITION = 0x06,
+ FAT32_PARTITION = 0x0B,
+ FAT32_LBA_PARTITION = 0x0C,
+ FAT16_LBA_PARTITION = 0x0E,
+ DM6_PARTITION = 0x54,
+ EZD_PARTITION = 0x55,
+ DM6_AUX1PARTITION = 0x51,
+ DM6_AUX3PARTITION = 0x53,
+ LINUX_SWAP = 0x82,
+ LINUX_NATIVE = 0x83,
+ LINUX_EXTENDED = 0x85
+};
+
+
+/* Forward declaration */
+struct rtems_disk_desc_s;
+
+/*
+ * part_desc_t --
+ * contains all neccessary information about partition
+ */
+typedef struct rtems_part_desc_s {
+ uint8_t bootable; /* is the partition active */
+ uint8_t sys_type; /* type of partition */
+ uint8_t log_id; /* logical number of partition */
+ uint32_t start; /* first partition sector, in absolute
+ * numeration */
+ uint32_t size; /* size in sectors */
+ uint32_t end; /* last partition sector, end = start + size - 1 */
+ struct rtems_disk_desc_s *disk_desc; /* descriptor of disk, partition
+ * contains in */
+ struct rtems_part_desc_s *ext_part; /* extended partition containing this
+ * one */
+
+ /* partitions, containing in this one */
+ struct rtems_part_desc_s *sub_part[RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER];
+} rtems_part_desc_t;
+
+
+
+typedef struct rtems_disk_desc_s {
+ dev_t dev; /* device number */
+
+ /* device name in /dev filesystem */
+ char dev_name[RTEMS_IDE_PARTITION_DEV_NAME_LENGTH_MAX];
+
+ uint32_t sector_size; /* size of sector */
+ uint32_t sector_bits; /* the base-2 logarithm of sector_size */
+ uint32_t lba_size; /* total amount of sectors in lba address mode */
+ int last_log_id; /* used for logical disks enumerating */
+
+ /* primary partition descriptors */
+ rtems_part_desc_t *partitions[RTEMS_IDE_PARTITION_MAX_PARTITION_NUMBER];
+} rtems_disk_desc_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * rtems_ide_part_table_free --
+ * frees disk descriptor structure
+ *
+ * PARAMETERS:
+ * disk_desc - disc descriptor structure to free
+ *
+ * RETURNS:
+ * N/A
+ */
+/**
+ * @deprecated Use the @ref rtems_bdpart "block device partition module" instead.
+ */
+void rtems_ide_part_table_free(
+ rtems_disk_desc_t *disk_desc
+) RTEMS_COMPILER_DEPRECATED_ATTRIBUTE;
+
+
+/*
+ * rtems_ide_part_table_get --
+ * reads partition table structure from the device
+ * and creates disk description structure
+ *
+ * PARAMETERS:
+ * dev_name - path to physical device in /dev filesystem
+ * disk_desc - returned disc description structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if success, or -1 and corresponding errno else
+ */
+/**
+ * @deprecated Use the @ref rtems_bdpart "block device partition module" instead.
+ */
+rtems_status_code rtems_ide_part_table_get(
+ const char *dev_name,
+ rtems_disk_desc_t *disk_desc
+) RTEMS_COMPILER_DEPRECATED_ATTRIBUTE;
+
+
+/*
+ * rtems_ide_part_table_initialize --
+ * initializes logical devices on the physical IDE drive
+ *
+ * PARAMETERS:
+ * dev_name - path to physical device in /dev filesystem
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if success, or -1 and corresponding errno else
+ */
+/**
+ * @deprecated Use the @ref rtems_bdpart "block device partition module" instead.
+ */
+rtems_status_code rtems_ide_part_table_initialize(
+ char *dev_name
+) RTEMS_COMPILER_DEPRECATED_ATTRIBUTE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTEMS_IDE_PART_TABLE_H */
diff --git a/cpukit/libblock/include/rtems/media.h b/cpukit/libblock/include/rtems/media.h
new file mode 100644
index 0000000000..038357c16d
--- /dev/null
+++ b/cpukit/libblock/include/rtems/media.h
@@ -0,0 +1,521 @@
+/**
+ * @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.
+ *
+ * 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
+);
+
+/**
+ * @brief Sends an event message to the media server.
+ *
+ * @see See rtems_media_post_event().
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NO_MEMORY Not enough resources to notify the media server.
+ * @retval RTEMS_NOT_CONFIGURED Media server is not initialized.
+ */
+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 */
diff --git a/cpukit/libblock/include/rtems/nvdisk-sram.h b/cpukit/libblock/include/rtems/nvdisk-sram.h
new file mode 100644
index 0000000000..450cfd8602
--- /dev/null
+++ b/cpukit/libblock/include/rtems/nvdisk-sram.h
@@ -0,0 +1,25 @@
+/*
+ * $Id$
+ *
+ * RTEMS Project (http://www.rtems.org/)
+ *
+ * Copyright 2007 Chris Johns (chrisj@rtems.org)
+ */
+
+/**
+ * NV Disk Static RAM Device Driver.
+ *
+ * This driver maps an NV disk to static RAM. You can use this
+ */
+
+#if !defined (_RTEMS_NVDISK_SRAM_H_)
+#define _RTEMS_NVDISK_SRAM_H_
+
+#include <rtems/nvdisk.h>
+
+/**
+ * The handlers for the NV Disk SRAM driver.
+ */
+extern const rtems_nvdisk_driver_handlers rtems_nvdisk_sram_handlers;
+
+#endif
diff --git a/cpukit/libblock/include/rtems/nvdisk.h b/cpukit/libblock/include/rtems/nvdisk.h
new file mode 100644
index 0000000000..48d8ba0b16
--- /dev/null
+++ b/cpukit/libblock/include/rtems/nvdisk.h
@@ -0,0 +1,209 @@
+/*
+ * nvdisk.h -- Non-volatile disk block device implementation
+ *
+ * Copyright (C) 2007 Chris Johns
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * The Non-volatile disk provides a simple directly mapped disk
+ * driver with checksums for each. It is designed to provied a
+ * disk that can survive a restart. Examples are EEPROM devices
+ * which have byte writeable locations, or a battery backed up
+ * RAM disk.
+ *
+ * The low level driver provides the physical access to the
+ * hardware.
+ */
+#if !defined (_RTEMS_NVDISK_H_)
+#define _RTEMS_NVDISK_H_
+
+#include <stdint.h>
+#include <sys/ioctl.h>
+
+#include <rtems.h>
+
+/**
+ * The base name of the nv disks.
+ */
+#define RTEMS_NVDISK_DEVICE_BASE_NAME "/dev/nvd"
+
+/**
+ * NV disk specific ioctl request types. To use open the
+ * device and issue the ioctl call.
+ *
+ * @code
+ * int fd = open ("/dev/nvdisk0", O_WRONLY, 0);
+ * if (fd < 0)
+ * {
+ * printf ("driver open failed: %s\n", strerror (errno));
+ * exit (1);
+ * }
+ * if (ioctl (fd, RTEMS_NVDISK_IOCTL_ERASE_DISK) < 0)
+ * {
+ * printf ("driver erase failed: %s\n", strerror (errno));
+ * exit (1);
+ * }
+ * close (fd);
+ * @endcode
+ */
+#define RTEMS_NVDISK_IOCTL_ERASE_DISK _IO('B', 128)
+#define RTEMS_NVDISK_IOCTL_MONITORING _IO('B', 129)
+#define RTEMS_NVDISK_IOCTL_INFO_LEVEL _IO('B', 130)
+#define RTEMS_NVDISK_IOCTL_PRINT_STATUS _IO('B', 131)
+
+/**
+ * NV Disk Monitoring Data allows a user to obtain
+ * the current status of the disk.
+ */
+typedef struct rtems_nvdisk_monitor_data
+{
+ uint32_t block_size;
+ uint32_t block_count;
+ uint32_t page_count;
+ uint32_t pages_available;
+ uint32_t pages_used;
+ uint32_t info_level;
+} rtems_nvdisk_monitor_data;
+
+/**
+ * Return the number of kilo-bytes.
+ */
+#define RTEMS_NVDISK_KBYTES(_k) ((_k) * 1024)
+
+/**
+ * NV Low Level driver handlers.
+
+ * Typically this structure is part of a table of handlers in the
+ * device which is referenced in the nvdisk configuration table.
+ * The reference is kept in the driver and used all the time to
+ * manage the nv device, therefore it must always exist.
+ */
+typedef struct rtems_nvdisk_driver_handlers
+{
+ /**
+ * Read data from the device into the buffer. Return an errno
+ * error number if the data cannot be read.
+ *
+ * @param device The device to read data from.
+ * @param flags Device specific flags for the driver.
+ * @param base The base address of the device.
+ * @param offset The offset in the segment to read.
+ * @param buffer The buffer to read the data into.
+ * @param size The amount of data to read.
+ * @retval 0 No error.
+ * @retval EIO The read did not complete.
+ */
+ int (*read) (uint32_t device, uint32_t flags, void* base,
+ uint32_t offset, void* buffer, size_t size);
+
+ /**
+ * Write data from the buffer to the device. Return an errno
+ * error number if the device cannot be written to.
+ *
+ * @param device The device to write data to.
+ * @param flags Device specific flags for the driver.
+ * @param base The base address of the device.
+ * @param offset The offset in the device to write to.
+ * @param buffer The buffer to write the data from.
+ * @param size The amount of data to write.
+ * @retval 0 No error.
+ * @retval EIO The write did not complete or verify.
+ */
+ int (*write) (uint32_t device, uint32_t flags, void* base,
+ uint32_t offset, const void* buffer, size_t size);
+
+ /**
+ * Verify data in the buffer to the data in the device. Return an
+ * errno error number if the device cannot be read or the data verified.
+ *
+ * @param device The device to verify the data with.
+ * @param flags Device specific flags for the driver.
+ * @param base The base address of the device.
+ * @param offset The offset in the device to verify.
+ * @param buffer The buffer to verify the data in the device with.
+ * @param size The amount of data to verify.
+ * @retval 0 No error.
+ * @retval EIO The data did not verify.
+ */
+ int (*verify) (uint32_t device, uint32_t flags, void* base,
+ uint32_t offset, const void* buffer, size_t size);
+
+} rtems_nvdisk_driver_handlers;
+
+/**
+ * NV Device Descriptor holds the description of a device that is
+ * part of the NV disk.
+ *
+ * Typically this structure is part of a table of the device which
+ * is referenced in the nvdisk configuration table.
+ * The reference is kept in the driver and used all the time to
+ * manage the nv device, therefore it must always exist.
+ */
+typedef struct rtems_nvdisk_device_desc
+{
+ uint32_t flags; /**< Private user flags. */
+ void* base; /**< Base address of the device. */
+ uint32_t size; /**< Size of the device. */
+ const rtems_nvdisk_driver_handlers* nv_ops; /**< Device handlers. */
+} rtems_nvdisk_device_desc;
+
+/**
+ * RTEMS Non-Volatile Disk configuration table used to initialise the
+ * driver.
+ */
+typedef struct rtems_nvdisk_config
+{
+ uint32_t block_size; /**< The block size. */
+ uint32_t device_count; /**< The number of devices. */
+ const rtems_nvdisk_device_desc* devices; /**< The device descriptions. */
+ uint32_t flags; /**< Set of flags to control
+ driver. */
+ uint32_t info_level; /**< Default info level. */
+} rtems_nvdisk_config;
+
+/*
+ * Driver flags.
+ */
+
+/**
+ * Check the pages during initialisation to see which pages are
+ * valid and which are not. This could slow down initialising the
+ * disk driver.
+ */
+#define RTEMS_NVDISK_CHECK_PAGES (1 << 0)
+
+/**
+ * Non-volatile disk device driver initialization. Place in a table as the
+ * initialisation entry and remainder of the entries are the RTEMS block
+ * device generic handlers.
+ *
+ * @param major NV disk major device number.
+ * @param minor Minor device number, not applicable.
+ * @param arg Initialization argument, not applicable.
+ * @return The rtems_device_driver is actually just
+ * rtems_status_code.
+ */
+rtems_device_driver
+rtems_nvdisk_initialize (rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void* arg);
+
+/**
+ * External reference to the configuration. Please supply.
+ * Support is present in confdefs.h for providing this variable.
+ */
+extern const rtems_nvdisk_config rtems_nvdisk_configuration[];
+
+/**
+ * External reference to the number of configurations. Please supply.
+ * Support is present in confdefs.h for providing this variable.
+ */
+extern uint32_t rtems_nvdisk_configuration_size;
+
+#endif
diff --git a/cpukit/libblock/include/rtems/ramdisk.h b/cpukit/libblock/include/rtems/ramdisk.h
new file mode 100644
index 0000000000..71efc9fda0
--- /dev/null
+++ b/cpukit/libblock/include/rtems/ramdisk.h
@@ -0,0 +1,243 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_ramdisk
+ *
+ * @brief RAM disk block device API.
+ */
+
+/*
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#ifndef _RTEMS_RAMDISK_H
+#define _RTEMS_RAMDISK_H
+
+
+#include <rtems.h>
+#include <rtems/blkdev.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup rtems_ramdisk RAM Disk Device
+ *
+ * @ingroup rtems_blkdev
+ *
+ * @{
+ */
+
+/**
+ * @name Static Configuration
+ *
+ * @{
+ */
+
+/**
+ * @brief RAM disk configuration table entry.
+ */
+typedef struct rtems_ramdisk_config {
+ /**
+ * @brief RAM disk block size.
+ */
+ uint32_t block_size;
+
+ /**
+ * @brief Number of blocks on this RAM disk.
+ */
+ rtems_blkdev_bnum block_num;
+
+ /**
+ * @brief RAM disk location or @c NULL if RAM disk memory should be allocated
+ * dynamically.
+ */
+ void *location;
+} rtems_ramdisk_config;
+
+/**
+ * @brief External reference to the RAM disk configuration table describing
+ * each RAM disk in the system.
+ *
+ * The configuration table is provided by the application.
+ */
+extern rtems_ramdisk_config rtems_ramdisk_configuration [];
+
+/**
+ * @brief External reference the size of the RAM disk configuration table @ref
+ * rtems_ramdisk_configuration.
+ *
+ * The configuration table size is provided by the application.
+ */
+extern size_t rtems_ramdisk_configuration_size;
+
+/**
+ * @brief RAM disk driver initialization entry point.
+ */
+rtems_device_driver ramdisk_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+
+/**
+ * RAM disk driver table entry.
+ */
+#define RAMDISK_DRIVER_TABLE_ENTRY \
+ { \
+ .initialization_entry = ramdisk_initialize, \
+ RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
+ }
+
+#define RAMDISK_DEVICE_BASE_NAME "/dev/rd"
+
+/** @} */
+
+/**
+ * @name Runtime Configuration
+ *
+ * @{
+ */
+
+/**
+ * @brief RAM disk descriptor.
+ */
+typedef struct ramdisk {
+ /**
+ * @brief RAM disk block size, the media size.
+ */
+ uint32_t block_size;
+
+ /**
+ * @brief Number of blocks on this RAM disk.
+ */
+ rtems_blkdev_bnum block_num;
+
+ /**
+ * @brief RAM disk memory area.
+ */
+ void *area;
+
+ /**
+ * @brief RAM disk is initialized.
+ */
+ bool initialized;
+
+ /**
+ * @brief Indicates if memory is allocated by malloc() for this RAM disk.
+ */
+ bool malloced;
+
+ /**
+ * @brief Trace enable.
+ */
+ bool trace;
+} ramdisk;
+
+extern const rtems_driver_address_table ramdisk_ops;
+
+int ramdisk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
+
+/**
+ * @brief Allocates and initializes a RAM disk descriptor.
+ *
+ * The block size will be @a block_size. The block count will be @a
+ * block_count. The disk storage area begins at @a area_begin. If @a
+ * area_begin is @c NULL, the memory will be allocated and zeroed. Sets the
+ * trace enable to @a trace.
+ *
+ * @return Pointer to allocated and initialized ramdisk structure, or @c NULL
+ * if no memory is available.
+ *
+ * @note
+ * Runtime configuration example:
+ * @code
+ * #include <rtems.h>
+ * #include <rtems/libio.h>
+ * #include <rtems/ramdisk.h>
+ *
+ * rtems_status_code create_ramdisk(
+ * const char *disk_name_path,
+ * uint32_t block_size,
+ * rtems_blkdev_bnum block_count
+ * )
+ * {
+ * rtems_status_code sc = RTEMS_SUCCESSFUL;
+ * rtems_device_major_number major = 0;
+ * ramdisk *rd = NULL;
+ * dev_t dev = 0;
+ *
+ * sc = rtems_io_register_driver(0, &ramdisk_ops, &major);
+ * if (sc != RTEMS_SUCCESSFUL) {
+ * return RTEMS_UNSATISFIED;
+ * }
+ *
+ * rd = ramdisk_allocate(NULL, block_size, block_count, false);
+ * if (rd == NULL) {
+ * rtems_io_unregister_driver(major);
+ *
+ * return RTEMS_UNSATISFIED;
+ * }
+ *
+ * dev = rtems_filesystem_make_dev_t(major, 0);
+ *
+ * sc = rtems_disk_create_phys(
+ * dev,
+ * block_size,
+ * block_count,
+ * ramdisk_ioctl,
+ * rd,
+ * disk_name_path
+ * );
+ * if (sc != RTEMS_SUCCESSFUL) {
+ * ramdisk_free(rd);
+ * rtems_io_unregister_driver(major);
+ *
+ * return RTEMS_UNSATISFIED;
+ * }
+ *
+ * return RTEMS_SUCCESSFUL;
+ * }
+ * @endcode
+ */
+ramdisk *ramdisk_allocate(
+ void *area_begin,
+ uint32_t block_size,
+ rtems_blkdev_bnum block_count,
+ bool trace
+);
+
+void ramdisk_free(ramdisk *rd);
+
+/**
+ * @brief Allocates, initializes and registers a RAM disk.
+ *
+ * The block size will be @a block_size. The block count will be @a
+ * block_count. The disk storage will be allocated. Sets the trace enable to
+ * @a trace. Registers a device node with disk name path @a disk. The
+ * registered device number will be returned in @a dev.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_UNSATISFIED Something is wrong.
+ */
+rtems_status_code ramdisk_register(
+ uint32_t block_size,
+ rtems_blkdev_bnum block_count,
+ bool trace,
+ const char *disk,
+ dev_t *dev
+);
+
+/** @} */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif