Index: cpukit/ChangeLog
===================================================================
--- cpukit/ChangeLog	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/ChangeLog	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -1,2 +1,27 @@
+2009-08-05	Chris Johns <chrisj@rtems.org>
+
+	* libmisc/dummy/dummy-networking.c: New.  
+	* libmisc/dummy/dummy.c, libmisc/Makefile.am: Move
+	trhe networking configuration into a separate file so
+	configuration varations do not cause conflicts.
+	* score/inline/rtems/score/object.inl,
+	score/include/rtems/score/object.h: Remove warnings.
+	* score/inline/rtems/score/object.inl: Add _Chain_First,
+	_Chain_Last, _Chain_Mext, and _Chain_Previous.
+	* sapi/inline/rtems/chain.inl: Add rtems_chain_first,
+	rtems_chain_last, rtems_chain_mext, and rtems_chain_previous.
+	* libblock/include/rtems/diskdevs.h: Remove the bdbuf pool id and
+	block_size_log2. Add media_block_size.
+	* libblock/src/diskdevs.c: Remove size restrictions on block
+	size. Add media block size initialisation. Remove comment to clean
+	up the bdbuf cache.
+	* libblock/src/blkdev.c: Remove references to
+	block_size_log2. Allow any block size.
+	* libblock/include/rtems/bdbuf.h, libblock/src/bdbuf.c: Remove all
+	references to pools and make the cache handle demand driver
+	variable buffer size allocation. Added worker threads support the
+	swapout task.
+	* sapi/include/confdefs.h: Updated the bdbuf configutation.
+	
 2009-08-04	Joel Sherrill <joel.sherrill@OARcorp.com>
 
Index: cpukit/libblock/include/rtems/bdbuf.h
===================================================================
--- cpukit/libblock/include/rtems/bdbuf.h	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/libblock/include/rtems/bdbuf.h	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -11,7 +11,8 @@
  * Author: Victor V. Vengerov <vvv@oktet.ru>
  *
- * Copyright (C) 2008 Chris Johns <chrisj@rtems.org>
+ * 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.
  *
  * @(#) bdbuf.h,v 1.9 2005/02/02 00:06:18 joel Exp
@@ -45,6 +46,31 @@
  * the drivers and fast cache look up using an AVL tree.
  *
- * The buffers are held in pools based on size. Each pool has buffers and the
- * buffers follow this state machine:
+ * 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 minumum
+ * 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 minium 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
@@ -83,12 +109,12 @@
  * 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 pool's modified list and a hold timer
+ * 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 complete. Buffers are often repeatable
- * 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.
+ * 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 mulitple block reads and writes. Multiple block reads or
@@ -104,9 +130,19 @@
  * the file system.
  *
- * The pool has the following lists of buffers:
+ * The cache has the following lists of buffers:
  *  - @c ready: Empty buffers created when the pool is initialised.
  *  - @c modified: Buffers waiting to be written to disk.
  *  - @c sync: Buffers to be synced to disk.
  *  - @c lru: Accessed buffers released in least recently used order.
+ *
+ * The cache scans the ready list then the LRU list for a suitable buffer in
+ * this order. 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 ready 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.
  *
  * @{
@@ -129,12 +165,18 @@
 
 /**
+ * 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
+ * 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 in the BD onto a number of lists. */
+  rtems_chain_node link;       /**< Link the BD onto a number of lists. */
 
   struct rtems_bdbuf_avl_node
@@ -155,81 +197,29 @@
   volatile rtems_bdbuf_buf_state state;  /**< State of the buffer. */
 
-  volatile uint32_t waiters;    /**< The number of threads waiting on this
-                                 * buffer. */
-  rtems_bdpool_id pool;         /**< Identifier of buffer pool to which this buffer
-                                    belongs */
-
-  volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer
-                                 * has been held in the cache modified. */
+  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. */
 } rtems_bdbuf_buffer;
 
 /**
- * The groups of the blocks with the same size are collected in a pool. Note
- * that a several of the buffer's groups with the same size can exists.
- */
-typedef struct rtems_bdbuf_pool
+ * 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
 {
-  uint32_t            blksize;           /**< The size of the blocks (in bytes) */
-  uint32_t            nblks;             /**< Number of blocks in this pool */
-
-  uint32_t            flags;             /**< Configuration flags */
-
-  rtems_id            lock;              /**< The pool lock. Lock this data and
-                                          * all BDs. */
-  rtems_id            sync_lock;         /**< Sync calls lock writes. */
-  bool                sync_active;       /**< True if a sync is active. */
-  rtems_id            sync_requester;    /**< The sync requester. */
-  dev_t               sync_device;       /**< The device to sync */
-
-  rtems_bdbuf_buffer* tree;             /**< Buffer descriptor lookup AVL tree
-                                         * root */
-  rtems_chain_control ready;            /**< Free buffers list (or read-ahead) */
-  rtems_chain_control lru;              /**< Last recently used list */
-  rtems_chain_control modified;         /**< Modified buffers list */
-  rtems_chain_control sync;             /**< Buffers to sync list */
-
-  rtems_id            access;           /**< Obtain if waiting for a buffer in the
-                                         * ACCESS state. */
-  volatile uint32_t   access_waiters;   /**< Count of access blockers. */
-  rtems_id            transfer;         /**< Obtain if waiting for a buffer in the
-                                         * TRANSFER state. */
-  volatile uint32_t   transfer_waiters; /**< Count of transfer blockers. */
-  rtems_id            waiting;          /**< Obtain if waiting for a buffer and the
-                                         * none are available. */
-  volatile uint32_t   wait_waiters;     /**< Count of waiting blockers. */
-
-  rtems_bdbuf_buffer* bds;              /**< Pointer to table of buffer descriptors
-                                         * allocated for this buffer pool. */
-  void*               buffers;          /**< The buffer's memory. */
-} rtems_bdbuf_pool;
-
-/**
- * Configuration structure describes block configuration (size, amount, memory
- * location) for buffering layer pool.
- */
-typedef struct rtems_bdbuf_pool_config {
-  int            size;      /**< Size of block */
-  int            num;       /**< Number of blocks of appropriate size */
-  unsigned char* mem_area;  /**< Pointer to the blocks location or NULL, in this
-                             * case memory for blocks will be allocated by
-                             * Buffering Layer with the help of RTEMS partition
-                             * manager */
-} rtems_bdbuf_pool_config;
-
-/**
- * External reference to the pool configuration table describing each pool in
- * the system.
- *
- * The configuration table is provided by the application.
- */
-extern rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[];
-
-/**
- * External reference the size of the pool configuration table
- * @ref rtems_bdbuf_pool_configuration.
- *
- * The configuration table size is provided by the application.
- */
-extern size_t rtems_bdbuf_pool_configuration_size;
+  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. */
+};
 
 /**
@@ -238,9 +228,24 @@
  */
 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. */
+  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. */
+  uint32_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;
 
@@ -250,5 +255,5 @@
  * The configuration is provided by the application.
  */
-extern rtems_bdbuf_config rtems_bdbuf_configuration;
+extern const rtems_bdbuf_config rtems_bdbuf_configuration;
 
 /**
@@ -279,9 +284,33 @@
 
 /**
+ * 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. Buffers will be allocated accoriding to the
- * configuration table, each entry describes the size of block and the size of
- * the pool. After initialization all blocks is placed into the ready state.
- * lists.
+ * neccessary) buffers. After initialization all blocks is placed into the
+ * ready state.
  *
  * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
@@ -396,11 +425,10 @@
 /**
  * Synchronize all modified buffers for this device with the disk and wait
- * until the transfers have completed. The sync mutex for the pool is locked
+ * 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 attached to a single pool will
- * be handled sequentially. A nested call will be blocked until the first sync
- * request has complete. This is only true for device using the same pool.
+ * @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
@@ -411,43 +439,4 @@
 rtems_status_code
 rtems_bdbuf_syncdev (dev_t dev);
-
-/**
- * Find first appropriate buffer pool. This primitive returns the index of
- * first buffer pool which block size is greater than or equal to specified
- * size.
- *
- * @param block_size Requested block size
- * @param pool The pool to use for the requested pool size.
- *
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- *         successfully or error code if error is occured)
- * @retval RTEMS_INVALID_SIZE The specified block size is invalid (not a power
- *         of 2)
- * @retval RTEMS_NOT_DEFINED The buffer pool for this or greater block size
- *         is not configured.
- */
-rtems_status_code
-rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool);
-
-/**
- * Obtain characteristics of buffer pool with specified number.
- *
- * @param pool Buffer pool number
- * @param block_size Block size for which buffer pool is configured returned
- *                   there
- * @param blocks Number of buffers in buffer pool.
- *
- * RETURNS:
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- *         successfully or error code if error is occured)
- * @retval RTEMS_INVALID_SIZE The appropriate buffer pool is not configured.
- *
- * @note Buffer pools enumerated continuously starting from 0.
- */
-rtems_status_code rtems_bdbuf_get_pool_info(
-  rtems_bdpool_id pool,
-  uint32_t *block_size,
-  uint32_t *blocks
-);
 
 /** @} */
Index: cpukit/libblock/include/rtems/diskdevs.h
===================================================================
--- cpukit/libblock/include/rtems/diskdevs.h	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/libblock/include/rtems/diskdevs.h	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -20,11 +20,4 @@
 #include <rtems/libio.h>
 #include <stdlib.h>
-
-/**
- * @ingroup rtems_bdbuf
- *
- * Buffer pool identifier.
- */
-typedef int rtems_bdpool_id;
 
 #include <rtems/blkdev.h>
@@ -108,17 +101,14 @@
    * Device block size in bytes.
    *
-   * This is the minimum transfer unit and must be power of two.
+   * This is the minimum transfer unit. It can be any size.
    */
   uint32_t block_size;
 
   /**
-   * Binary logarithm of the block size.
-   */
-  uint32_t block_size_log2;
-
-  /**
-   * Buffer pool assigned to this disk.
-   */
-  rtems_bdpool_id pool;
+   * Device media block size in bytes.
+   *
+   * This is the media transfer unit the hardware defaults to.
+   */
+  uint32_t media_block_size;
 
   /**
Index: cpukit/libblock/src/bdbuf.c
===================================================================
--- cpukit/libblock/src/bdbuf.c	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/libblock/src/bdbuf.c	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -16,5 +16,5 @@
  *         Alexander Kukuta <kam@oktet.ru>
  *
- * Copyright (C) 2008 Chris Johns <chrisj@rtems.org>
+ * Copyright (C) 2008,2009 Chris Johns <chrisj@rtems.org>
  *    Rewritten to remove score mutex access. Fixes many performance
  *    issues.
@@ -45,13 +45,87 @@
 #include "rtems/bdbuf.h"
 
-/**
- * The BD buffer context.
- */
-typedef struct rtems_bdbuf_context {
-  rtems_bdbuf_pool* pool;      /*< Table of buffer pools */
-  int               npools;    /*< Number of entries in pool table */
-  rtems_id          swapout;   /*< Swapout task ID */
-  bool              swapout_enabled;
-} rtems_bdbuf_context;
+/*
+ * Simpler label for this file.
+ */
+#define bdbuf_config rtems_bdbuf_configuration
+
+/**
+ * A swapout transfer transaction data. This data is passed to a worked thread
+ * to handle the write phase of the transfer.
+ */
+typedef struct rtems_bdbuf_swapout_transfer
+{
+  rtems_chain_control   bds;       /**< The transfer list of BDs. */
+  dev_t                 dev;       /**< The device the transfer is for. */
+  rtems_blkdev_request* write_req; /**< The write request array. */
+} rtems_bdbuf_swapout_transfer;
+
+/**
+ * Swapout worker thread. These are available to take processing from the
+ * main swapout thread and handle the I/O operation.
+ */
+typedef struct rtems_bdbuf_swapout_worker
+{
+  rtems_chain_node             link;     /**< The threads sit on a chain when
+                                          * idle. */
+  rtems_id                     id;       /**< The id of the task so we can wake
+                                          * it. */
+  volatile bool                enabled;  /**< The worked is enabled. */
+  rtems_bdbuf_swapout_transfer transfer; /**< The transfer data for this
+                                          * thread. */
+} rtems_bdbuf_swapout_worker;
+
+/**
+ * The BD buffer cache.
+ */
+typedef struct rtems_bdbuf_cache
+{
+  rtems_id            swapout;           /**< Swapout task ID */
+  volatile bool       swapout_enabled;   /**< Swapout is only running if
+                                          * enabled. Set to false to kill the
+                                          * swap out task. It deletes itself. */
+  rtems_chain_control swapout_workers;   /**< The work threads for the swapout
+                                          * task. */
+  
+  rtems_bdbuf_buffer* bds;               /**< Pointer to table of buffer
+                                          * descriptors. */
+  void*               buffers;           /**< The buffer's memory. */
+  size_t              buffer_min_count;  /**< Number of minimum size buffers
+                                          * that fit the buffer memory. */
+  size_t              max_bds_per_group; /**< The number of BDs of minimum
+                                          * buffer size that fit in a group. */
+  uint32_t            flags;             /**< Configuration flags. */
+
+  rtems_id            lock;              /**< The cache lock. It locks all
+                                          * cache data, BD and lists. */
+  rtems_id            sync_lock;         /**< Sync calls block writes. */
+  volatile bool       sync_active;       /**< True if a sync is active. */
+  volatile rtems_id   sync_requester;    /**< The sync requester. */
+  volatile dev_t      sync_device;       /**< The device to sync and -1 not a
+                                          * device sync. */
+
+  rtems_bdbuf_buffer* tree;              /**< Buffer descriptor lookup AVL tree
+                                          * root. There is only one. */
+  rtems_chain_control ready;             /**< Free buffers list, read-ahead, or
+                                          * resized group buffers. */
+  rtems_chain_control lru;               /**< Least recently used list */
+  rtems_chain_control modified;          /**< Modified buffers list */
+  rtems_chain_control sync;              /**< Buffers to sync list */
+
+  rtems_id            access;            /**< Obtain if waiting for a buffer in
+                                          * the ACCESS state. */
+  volatile uint32_t   access_waiters;    /**< Count of access blockers. */
+  rtems_id            transfer;          /**< Obtain if waiting for a buffer in
+                                          * the TRANSFER state. */
+  volatile uint32_t   transfer_waiters;  /**< Count of transfer blockers. */
+  rtems_id            waiting;           /**< Obtain if waiting for a buffer
+                                          * and the none are available. */
+  volatile uint32_t   wait_waiters;      /**< Count of waiting blockers. */
+
+  size_t              group_count;       /**< The number of groups. */
+  rtems_bdbuf_group*  groups;            /**< The groups. */
+  
+  bool                initialised;       /**< Initialised state. */
+} rtems_bdbuf_cache;
 
 /**
@@ -61,16 +135,20 @@
   (((uint32_t)'B' << 24) | ((uint32_t)(n) & (uint32_t)0x00FFFFFF))
 
-#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY RTEMS_BLKDEV_FATAL_ERROR(1)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SWAPOUT     RTEMS_BLKDEV_FATAL_ERROR(2)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK   RTEMS_BLKDEV_FATAL_ERROR(3)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(4)
-#define RTEMS_BLKDEV_FATAL_BDBUF_POOL_LOCK   RTEMS_BLKDEV_FATAL_ERROR(5)
-#define RTEMS_BLKDEV_FATAL_BDBUF_POOL_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(6)
-#define RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAIT   RTEMS_BLKDEV_FATAL_ERROR(7)
-#define RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAKE   RTEMS_BLKDEV_FATAL_ERROR(8)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE     RTEMS_BLKDEV_FATAL_ERROR(9)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM    RTEMS_BLKDEV_FATAL_ERROR(10)
-#define BLKDEV_FATAL_BDBUF_SWAPOUT_RE        RTEMS_BLKDEV_FATAL_ERROR(11)
-#define BLKDEV_FATAL_BDBUF_SWAPOUT_TS        RTEMS_BLKDEV_FATAL_ERROR(12)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY  RTEMS_BLKDEV_FATAL_ERROR(1)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SWAPOUT      RTEMS_BLKDEV_FATAL_ERROR(2)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK    RTEMS_BLKDEV_FATAL_ERROR(3)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK  RTEMS_BLKDEV_FATAL_ERROR(4)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_LOCK   RTEMS_BLKDEV_FATAL_ERROR(5)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(6)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_1 RTEMS_BLKDEV_FATAL_ERROR(7)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_2 RTEMS_BLKDEV_FATAL_ERROR(8)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_3 RTEMS_BLKDEV_FATAL_ERROR(9)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAKE   RTEMS_BLKDEV_FATAL_ERROR(10)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE      RTEMS_BLKDEV_FATAL_ERROR(11)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM     RTEMS_BLKDEV_FATAL_ERROR(12)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_CREATE RTEMS_BLKDEV_FATAL_ERROR(13)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_START  RTEMS_BLKDEV_FATAL_ERROR(14)
+#define BLKDEV_FATAL_BDBUF_SWAPOUT_RE         RTEMS_BLKDEV_FATAL_ERROR(15)
+#define BLKDEV_FATAL_BDBUF_SWAPOUT_TS         RTEMS_BLKDEV_FATAL_ERROR(16)
 
 /**
@@ -92,5 +170,5 @@
  * @warning Priority inheritance is on.
  */
-#define RTEMS_BDBUF_POOL_LOCK_ATTRIBS \
+#define RTEMS_BDBUF_CACHE_LOCK_ATTRIBS \
   (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
    RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
@@ -104,5 +182,5 @@
  *          IDLE task which can cause unsual side effects.
  */
-#define RTEMS_BDBUF_POOL_WAITER_ATTRIBS \
+#define RTEMS_BDBUF_CACHE_WAITER_ATTRIBS \
   (RTEMS_PRIORITY | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
    RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
@@ -114,7 +192,7 @@
 
 /**
- * The context of buffering layer.
- */
-static rtems_bdbuf_context rtems_bdbuf_ctx;
+ * The Buffer Descriptor cache.
+ */
+static rtems_bdbuf_cache bdbuf_cache;
 
 /**
@@ -637,68 +715,68 @@
 
 /**
- * Get the pool for the device.
- *
- * @param pid Physical disk device.
- */
-static rtems_bdbuf_pool*
-rtems_bdbuf_get_pool (const rtems_bdpool_id pid)
-{
-  return &rtems_bdbuf_ctx.pool[pid];
-}
-
-/**
- * Lock the pool. A single task can nest calls.
- *
- * @param pool The pool to lock.
+ * Lock the mutex. A single task can nest calls.
+ *
+ * @param lock The mutex to lock.
+ * @param fatal_error_code The error code if the call fails.
  */
 static void
-rtems_bdbuf_lock_pool (rtems_bdbuf_pool* pool)
-{
-  rtems_status_code sc = rtems_semaphore_obtain (pool->lock,
+rtems_bdbuf_lock (rtems_id lock, uint32_t fatal_error_code)
+{
+  rtems_status_code sc = rtems_semaphore_obtain (lock,
                                                  RTEMS_WAIT,
                                                  RTEMS_NO_TIMEOUT);
   if (sc != RTEMS_SUCCESSFUL)
-    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_LOCK);
-}
-
-/**
- * Unlock the pool.
- *
- * @param pool The pool to unlock.
+    rtems_fatal_error_occurred (fatal_error_code);
+}
+
+/**
+ * Unlock the mutex.
+ *
+ * @param lock The mutex to unlock.
+ * @param fatal_error_code The error code if the call fails.
  */
 static void
-rtems_bdbuf_unlock_pool (rtems_bdbuf_pool* pool)
-{
-  rtems_status_code sc = rtems_semaphore_release (pool->lock);
+rtems_bdbuf_unlock (rtems_id lock, uint32_t fatal_error_code)
+{
+  rtems_status_code sc = rtems_semaphore_release (lock);
   if (sc != RTEMS_SUCCESSFUL)
-    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_UNLOCK);
-}
-
-/**
- * Lock the pool's sync. A single task can nest calls.
- *
- * @param pool The pool's sync to lock.
+    rtems_fatal_error_occurred (fatal_error_code);
+}
+
+/**
+ * Lock the cache. A single task can nest calls.
  */
 static void
-rtems_bdbuf_lock_sync (rtems_bdbuf_pool* pool)
-{
-  rtems_status_code sc = rtems_semaphore_obtain (pool->sync_lock,
-                                                 RTEMS_WAIT,
-                                                 RTEMS_NO_TIMEOUT);
-  if (sc != RTEMS_SUCCESSFUL)
-    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK);
-}
-
-/**
- * Unlock the pool's sync.
- *
- * @param pool The pool's sync to unlock.
+rtems_bdbuf_lock_cache (void)
+{
+  rtems_bdbuf_lock (bdbuf_cache.lock, RTEMS_BLKDEV_FATAL_BDBUF_CACHE_LOCK);
+}
+
+/**
+ * Unlock the cache.
  */
 static void
-rtems_bdbuf_unlock_sync (rtems_bdbuf_pool* pool)
-{
-  rtems_status_code sc = rtems_semaphore_release (pool->sync_lock);
-  if (sc != RTEMS_SUCCESSFUL)
-    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK);
+rtems_bdbuf_unlock_cache (void)
+{
+  rtems_bdbuf_unlock (bdbuf_cache.lock, RTEMS_BLKDEV_FATAL_BDBUF_CACHE_UNLOCK);
+}
+
+/**
+ * Lock the cache's sync. A single task can nest calls.
+ */
+static void
+rtems_bdbuf_lock_sync (void)
+{
+  rtems_bdbuf_lock (bdbuf_cache.sync_lock, RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK);
+}
+
+/**
+ * Unlock the cache's sync lock. Any blocked writers are woken.
+ */
+static void
+rtems_bdbuf_unlock_sync (void)
+{
+  rtems_bdbuf_unlock (bdbuf_cache.sync_lock,
+                      RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK);
 }
 
@@ -709,20 +787,18 @@
  * tasks that could be waiting.
  *
- * While we have the pool locked we can try and claim the semaphore and
- * therefore know when we release the lock to the pool we will block until the
+ * While we have the cache locked we can try and claim the semaphore and
+ * therefore know when we release the lock to the cache we will block until the
  * semaphore is released. This may even happen before we get to block.
  *
  * A counter is used to save the release call when no one is waiting.
  *
- * The function assumes the pool is locked on entry and it will be locked on
+ * The function assumes the cache is locked on entry and it will be locked on
  * exit.
  *
- * @param pool The pool to wait for a buffer to return.
  * @param sema The semaphore to block on and wait.
  * @param waiters The wait counter for this semaphore.
  */
 static void
-rtems_bdbuf_wait (rtems_bdbuf_pool* pool, rtems_id* sema,
-                  volatile uint32_t* waiters)
+rtems_bdbuf_wait (rtems_id* sema, volatile uint32_t* waiters)
 {
   rtems_status_code sc;
@@ -735,13 +811,11 @@
 
   /*
-   * Disable preemption then unlock the pool and block.
-   * There is no POSIX condition variable in the core API so
-   * this is a work around.
+   * Disable preemption then unlock the cache and block.  There is no POSIX
+   * condition variable in the core API so this is a work around.
    *
-   * The issue is a task could preempt after the pool is unlocked
-   * because it is blocking or just hits that window, and before
-   * this task has blocked on the semaphore. If the preempting task
-   * flushes the queue this task will not see the flush and may
-   * block for ever or until another transaction flushes this
+   * The issue is a task could preempt after the cache is unlocked because it is
+   * blocking or just hits that window, and before this task has blocked on the
+   * semaphore. If the preempting task flushes the queue this task will not see
+   * the flush and may block for ever or until another transaction flushes this
    * semaphore.
    */
@@ -749,22 +823,22 @@
 
   if (sc != RTEMS_SUCCESSFUL)
-    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAIT);
-  
-  /*
-   * Unlock the pool, wait, and lock the pool when we return.
-   */
-  rtems_bdbuf_unlock_pool (pool);
+    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_1);
+  
+  /*
+   * Unlock the cache, wait, and lock the cache when we return.
+   */
+  rtems_bdbuf_unlock_cache ();
 
   sc = rtems_semaphore_obtain (*sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   
   if (sc != RTEMS_UNSATISFIED)
-    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAIT);
-  
-  rtems_bdbuf_lock_pool (pool);
+    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_2);
+  
+  rtems_bdbuf_lock_cache ();
 
   sc = rtems_task_mode (prev_mode, RTEMS_ALL_MODE_MASKS, &prev_mode);
 
   if (sc != RTEMS_SUCCESSFUL)
-    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAIT);
+    rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_3);
   
   *waiters -= 1;
@@ -788,5 +862,5 @@
   
     if (sc != RTEMS_SUCCESSFUL)
-      rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAKE);
+      rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAKE);
   }
 }
@@ -794,8 +868,8 @@
 /**
  * Add a buffer descriptor to the modified list. This modified list is treated
- * a litte differently to the other lists. To access it you must have the pool
+ * a litte differently to the other lists. To access it you must have the cache
  * locked and this is assumed to be the case on entry to this call.
  *
- * If the pool has a device being sync'ed and the bd is for that device the
+ * If the cache has a device being sync'ed and the bd is for that device the
  * call must block and wait until the sync is over before adding the bd to the
  * modified list. Once a sync happens for a device no bd's can be added the
@@ -807,28 +881,26 @@
  * active.
  *
- * @param pool The pool the bd belongs to.
- * @param bd The bd to queue to the pool's modified list.
+ * @param bd The bd to queue to the cache's modified list.
  */
 static void
-rtems_bdbuf_append_modified (rtems_bdbuf_pool* pool, rtems_bdbuf_buffer* bd)
-{
-  /*
-   * If the pool has a device being sync'ed check if this bd is for that
-   * device. If it is unlock the pool and block on the sync lock. once we have
-   * the sync lock reelase it.
-   *
-   * If the 
-   */
-  if (pool->sync_active && (pool->sync_device == bd->dev))
-  {
-    rtems_bdbuf_unlock_pool (pool);
-    rtems_bdbuf_lock_sync (pool);
-    rtems_bdbuf_unlock_sync (pool);
-    rtems_bdbuf_lock_pool (pool);
+rtems_bdbuf_append_modified (rtems_bdbuf_buffer* bd)
+{
+  /*
+   * If the cache has a device being sync'ed check if this bd is for that
+   * device. If it is unlock the cache and block on the sync lock. Once we have
+   * the sync lock release it.
+   */
+  if (bdbuf_cache.sync_active && (bdbuf_cache.sync_device == bd->dev))
+  {
+    rtems_bdbuf_unlock_cache ();
+    /* Wait for the sync lock */
+    rtems_bdbuf_lock_sync ();
+    rtems_bdbuf_unlock_sync ();
+    rtems_bdbuf_lock_cache ();
   }
       
   bd->state = RTEMS_BDBUF_STATE_MODIFIED;
 
-  rtems_chain_append (&pool->modified, &bd->link);
+  rtems_chain_append (&bdbuf_cache.modified, &bd->link);
 }
 
@@ -839,5 +911,5 @@
 rtems_bdbuf_wake_swapper (void)
 {
-  rtems_status_code sc = rtems_event_send (rtems_bdbuf_ctx.swapout,
+  rtems_status_code sc = rtems_event_send (bdbuf_cache.swapout,
                                            RTEMS_BDBUF_SWAPOUT_SYNC);
   if (sc != RTEMS_SUCCESSFUL)
@@ -846,261 +918,385 @@
 
 /**
- * Initialize single buffer pool.
- *
- * @param config Buffer pool configuration
- * @param pid Pool number
- *
- * @return RTEMS_SUCCESSFUL, if buffer pool initialized successfully, or error
- *         code if error occured.
- */
-static rtems_status_code
-rtems_bdbuf_initialize_pool (rtems_bdbuf_pool_config* config,
-                             rtems_bdpool_id          pid)
-{
-  int                 rv = 0;
-  unsigned char*      buffer = config->mem_area;
-  rtems_bdbuf_pool*   pool;
+ * Compute the number of BDs per group for a given buffer size.
+ *
+ * @param size The buffer size. It can be any size and we scale up.
+ */
+static size_t
+rtems_bdbuf_bds_per_group (size_t size)
+{
+  size_t bufs_per_size;
+  size_t bds_per_size;
+  
+  if (size > rtems_bdbuf_configuration.buffer_max)
+    return 0;
+  
+  bufs_per_size = ((size - 1) / bdbuf_config.buffer_min) + 1;
+  
+  for (bds_per_size = 1;
+       bds_per_size < bufs_per_size;
+       bds_per_size <<= 1)
+    ;
+
+  return bdbuf_cache.max_bds_per_group / bds_per_size;
+}
+
+/**
+ * Reallocate a group. The BDs currently allocated in the group are removed
+ * from the ALV tree and any lists then the new BD's are prepended to the ready
+ * list of the cache.
+ *
+ * @param group The group to reallocate.
+ * @param new_bds_per_group The new count of BDs per group.
+ */
+static void
+rtems_bdbuf_group_realloc (rtems_bdbuf_group* group, size_t new_bds_per_group)
+{
   rtems_bdbuf_buffer* bd;
+  int                 b;
+  size_t              bufs_per_bd;
+
+  bufs_per_bd = bdbuf_cache.max_bds_per_group / group->bds_per_group;
+  
+  for (b = 0, bd = group->bdbuf;
+       b < group->bds_per_group;
+       b++, bd += bufs_per_bd)
+  {
+    if ((bd->state == RTEMS_BDBUF_STATE_CACHED) ||
+        (bd->state == RTEMS_BDBUF_STATE_MODIFIED) ||
+        (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD))
+    {
+      if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
+        rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
+      rtems_chain_extract (&bd->link);
+    }
+  }
+  
+  group->bds_per_group = new_bds_per_group;
+  bufs_per_bd = bdbuf_cache.max_bds_per_group / new_bds_per_group;
+  
+  for (b = 0, bd = group->bdbuf;
+       b < group->bds_per_group;
+       b++, bd += bufs_per_bd)
+    rtems_chain_prepend (&bdbuf_cache.ready, &bd->link);
+}
+
+/**
+ * Get the next BD from the list. This call assumes the cache is locked.
+ *
+ * @param bds_per_group The number of BDs per block we are need.
+ * @param list The list to find the BD on.
+ * @return The next BD if found or NULL is none are available.
+ */
+static rtems_bdbuf_buffer*
+rtems_bdbuf_get_next_bd (size_t               bds_per_group,
+                         rtems_chain_control* list)
+{
+  rtems_chain_node* node = rtems_chain_first (list);
+  while (!rtems_chain_is_tail (list, node))
+  {
+    rtems_bdbuf_buffer* bd = (rtems_bdbuf_buffer*) node;
+
+    /*
+     * If this bd is already part of a group that supports the same number of
+     * BDs per group return it. If the bd is part of another group check the
+     * number of users and if 0 we can take this group and resize it.
+     */
+    if (bd->group->bds_per_group == bds_per_group)
+    {
+      rtems_chain_extract (node);
+      bd->group->users++;
+      return bd;
+    }
+
+    if (bd->group->users == 0)
+    {
+      /*
+       * We use the group to locate the start of the BDs for this group.
+       */
+      rtems_bdbuf_group_realloc (bd->group, bds_per_group);
+      bd = (rtems_bdbuf_buffer*) rtems_chain_get (&bdbuf_cache.ready);
+      return bd;
+    }
+
+    node = rtems_chain_next (node);
+  }
+  
+  return NULL;
+}
+
+/**
+ * Initialise the cache.
+ *
+ * @return rtems_status_code The initialisation status.
+ */
+rtems_status_code
+rtems_bdbuf_init (void)
+{
+  rtems_bdbuf_group*  group;
+  rtems_bdbuf_buffer* bd;
+  uint8_t*            buffer;
+  int                 b;
+  int                 cache_aligment;
   rtems_status_code   sc;
-  uint32_t            b;
-  int                 cache_aligment = 32 /* FIXME rtems_cache_get_data_line_size() */;
-
-  /* For unspecified cache alignments we use the CPU alignment */
+
+#if RTEMS_BDBUF_TRACE
+  rtems_bdbuf_printf ("init\n");
+#endif
+
+  /*
+   * Check the configuration table values.
+   */
+  if ((bdbuf_config.buffer_max % bdbuf_config.buffer_min) != 0)
+    return RTEMS_INVALID_NUMBER;
+  
+  /*
+   * We use a special variable to manage the initialisation incase we have
+   * completing threads doing this. You may get errors if the another thread
+   * makes a call and we have not finished initialisation.
+   */
+  if (bdbuf_cache.initialised)
+    return RTEMS_RESOURCE_IN_USE;
+
+  bdbuf_cache.initialised = true;
+  
+  /*
+   * For unspecified cache alignments we use the CPU alignment.
+   */
+  cache_aligment = 32; /* FIXME rtems_cache_get_data_line_size() */
   if (cache_aligment <= 0)
-  {
     cache_aligment = CPU_ALIGNMENT;
-  }
-
-  pool = rtems_bdbuf_get_pool (pid);
-  
-  pool->blksize        = config->size;
-  pool->nblks          = config->num;
-  pool->flags          = 0;
-  pool->sync_active    = false;
-  pool->sync_device    = -1;
-  pool->sync_requester = 0;
-  pool->tree           = NULL;
-  pool->buffers        = NULL;
-
-  rtems_chain_initialize_empty (&pool->ready);
-  rtems_chain_initialize_empty (&pool->lru);
-  rtems_chain_initialize_empty (&pool->modified);
-  rtems_chain_initialize_empty (&pool->sync);
-
-  pool->access           = 0;
-  pool->access_waiters   = 0;
-  pool->transfer         = 0;
-  pool->transfer_waiters = 0;
-  pool->waiting          = 0;
-  pool->wait_waiters     = 0;
-  
-  /*
-   * Allocate memory for buffer descriptors
-   */
-  pool->bds = calloc (config->num, sizeof (rtems_bdbuf_buffer));
-  
-  if (!pool->bds)
+
+  bdbuf_cache.sync_active    = false;
+  bdbuf_cache.sync_device    = -1;
+  bdbuf_cache.sync_requester = 0;
+  bdbuf_cache.tree           = NULL;
+
+  rtems_chain_initialize_empty (&bdbuf_cache.swapout_workers);
+  rtems_chain_initialize_empty (&bdbuf_cache.ready);
+  rtems_chain_initialize_empty (&bdbuf_cache.lru);
+  rtems_chain_initialize_empty (&bdbuf_cache.modified);
+  rtems_chain_initialize_empty (&bdbuf_cache.sync);
+
+  bdbuf_cache.access           = 0;
+  bdbuf_cache.access_waiters   = 0;
+  bdbuf_cache.transfer         = 0;
+  bdbuf_cache.transfer_waiters = 0;
+  bdbuf_cache.waiting          = 0;
+  bdbuf_cache.wait_waiters     = 0;
+
+  /*
+   * Create the locks for the cache.
+   */
+  sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 'l'),
+                               1, RTEMS_BDBUF_CACHE_LOCK_ATTRIBS, 0,
+                               &bdbuf_cache.lock);
+  if (sc != RTEMS_SUCCESSFUL)
+  {
+    bdbuf_cache.initialised = false;
+    return sc;
+  }
+
+  rtems_bdbuf_lock_cache ();
+  
+  sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 's'),
+                               1, RTEMS_BDBUF_CACHE_LOCK_ATTRIBS, 0,
+                               &bdbuf_cache.sync_lock);
+  if (sc != RTEMS_SUCCESSFUL)
+  {
+    rtems_bdbuf_unlock_cache ();
+    rtems_semaphore_delete (bdbuf_cache.lock);
+    bdbuf_cache.initialised = false;
+    return sc;
+  }
+  
+  sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 'a'),
+                               0, RTEMS_BDBUF_CACHE_WAITER_ATTRIBS, 0,
+                               &bdbuf_cache.access);
+  if (sc != RTEMS_SUCCESSFUL)
+  {
+    rtems_semaphore_delete (bdbuf_cache.sync_lock);
+    rtems_bdbuf_unlock_cache ();
+    rtems_semaphore_delete (bdbuf_cache.lock);
+    bdbuf_cache.initialised = false;
+    return sc;
+  }
+
+  sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 't'),
+                               0, RTEMS_BDBUF_CACHE_WAITER_ATTRIBS, 0,
+                               &bdbuf_cache.transfer);
+  if (sc != RTEMS_SUCCESSFUL)
+  {
+    rtems_semaphore_delete (bdbuf_cache.access);
+    rtems_semaphore_delete (bdbuf_cache.sync_lock);
+    rtems_bdbuf_unlock_cache ();
+    rtems_semaphore_delete (bdbuf_cache.lock);
+    bdbuf_cache.initialised = false;
+    return sc;
+  }
+
+  sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 'w'),
+                               0, RTEMS_BDBUF_CACHE_WAITER_ATTRIBS, 0,
+                               &bdbuf_cache.waiting);
+  if (sc != RTEMS_SUCCESSFUL)
+  {
+    rtems_semaphore_delete (bdbuf_cache.transfer);
+    rtems_semaphore_delete (bdbuf_cache.access);
+    rtems_semaphore_delete (bdbuf_cache.sync_lock);
+    rtems_bdbuf_unlock_cache ();
+    rtems_semaphore_delete (bdbuf_cache.lock);
+    bdbuf_cache.initialised = false;
+    return sc;
+  }
+  
+  /*
+   * Allocate the memory for the buffer descriptors.
+   */
+  bdbuf_cache.bds = calloc (sizeof (rtems_bdbuf_buffer),
+                            bdbuf_config.size / bdbuf_config.buffer_min);
+  if (!bdbuf_cache.bds)
+  {
+    rtems_semaphore_delete (bdbuf_cache.transfer);
+    rtems_semaphore_delete (bdbuf_cache.access);
+    rtems_semaphore_delete (bdbuf_cache.sync_lock);
+    rtems_bdbuf_unlock_cache ();
+    rtems_semaphore_delete (bdbuf_cache.lock);
+    bdbuf_cache.initialised = false;
     return RTEMS_NO_MEMORY;
-
-  /*
-   * Allocate memory for buffers if required.  The pool memory will be cache
-   * aligned.  It is possible to free the memory allocated by rtems_memalign()
-   * with free().
-   */
-  if (buffer == NULL)
-  {
-    rv = rtems_memalign ((void **) &buffer,
-                         cache_aligment,
-                         config->num * config->size);
-    if (rv != 0)
-    {
-      free (pool->bds);
-      return RTEMS_NO_MEMORY;
-    }
-    pool->buffers = buffer;
-  }
-
-  for (b = 0, bd = pool->bds;
-       b < pool->nblks;
-       b++, bd++, buffer += pool->blksize)
+  }
+
+  /*
+   * Compute the various number of elements in the cache.
+   */
+  bdbuf_cache.buffer_min_count =
+    bdbuf_config.size / bdbuf_config.buffer_min;
+  bdbuf_cache.max_bds_per_group =
+    bdbuf_config.buffer_max / bdbuf_config.buffer_min;
+  bdbuf_cache.group_count =
+    bdbuf_cache.buffer_min_count / bdbuf_cache.max_bds_per_group;
+
+  /*
+   * Allocate the memory for the buffer descriptors.
+   */
+  bdbuf_cache.groups = calloc (sizeof (rtems_bdbuf_group),
+                               bdbuf_cache.group_count);
+  if (!bdbuf_cache.groups)
+  {
+    free (bdbuf_cache.bds);
+    rtems_semaphore_delete (bdbuf_cache.transfer);
+    rtems_semaphore_delete (bdbuf_cache.access);
+    rtems_semaphore_delete (bdbuf_cache.sync_lock);
+    rtems_bdbuf_unlock_cache ();
+    rtems_semaphore_delete (bdbuf_cache.lock);
+    bdbuf_cache.initialised = false;
+    return RTEMS_NO_MEMORY;
+  }
+  
+  /*
+   * Allocate memory for buffer memory. The buffer memory will be cache
+   * aligned. It is possible to free the memory allocated by rtems_memalign()
+   * with free(). Return 0 if allocated.
+   */
+  if (rtems_memalign ((void **) &bdbuf_cache.buffers,
+                      cache_aligment,
+                      bdbuf_cache.buffer_min_count * bdbuf_config.buffer_min) != 0)
+  {
+    free (bdbuf_cache.groups);
+    free (bdbuf_cache.bds);
+    rtems_semaphore_delete (bdbuf_cache.transfer);
+    rtems_semaphore_delete (bdbuf_cache.access);
+    rtems_semaphore_delete (bdbuf_cache.sync_lock);
+    rtems_bdbuf_unlock_cache ();
+    rtems_semaphore_delete (bdbuf_cache.lock);
+    bdbuf_cache.initialised = false;
+    return RTEMS_NO_MEMORY;
+  }
+
+  /*
+   * The cache is empty after opening so we need to add all the buffers to it
+   * and initialise the groups.
+   */
+  for (b = 0, group = bdbuf_cache.groups,
+         bd = bdbuf_cache.bds, buffer = bdbuf_cache.buffers;
+       b < bdbuf_cache.buffer_min_count;
+       b++, bd++, buffer += bdbuf_config.buffer_min)
   {
     bd->dev        = -1;
-    bd->block      = 0;
+    bd->group      = group;
     bd->buffer     = buffer;
     bd->avl.left   = NULL;
     bd->avl.right  = NULL;
     bd->state      = RTEMS_BDBUF_STATE_EMPTY;
-    bd->pool       = pid;
     bd->error      = 0;
     bd->waiters    = 0;
     bd->hold_timer = 0;
     
-    rtems_chain_append (&pool->ready, &bd->link);
-  }
-
-  sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 'L'),
-                               1, RTEMS_BDBUF_POOL_LOCK_ATTRIBS, 0,
-                               &pool->lock);
-  if (sc != RTEMS_SUCCESSFUL)
-  {
-    free (pool->buffers);
-    free (pool->bds);
-    return sc;
-  }
-
-  sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 'S'),
-                               1, RTEMS_BDBUF_POOL_LOCK_ATTRIBS, 0,
-                               &pool->sync_lock);
-  if (sc != RTEMS_SUCCESSFUL)
-  {
-    rtems_semaphore_delete (pool->lock);
-    free (pool->buffers);
-    free (pool->bds);
-    return sc;
-  }
-  
-  sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 'a'),
-                               0, RTEMS_BDBUF_POOL_WAITER_ATTRIBS, 0,
-                               &pool->access);
-  if (sc != RTEMS_SUCCESSFUL)
-  {
-    rtems_semaphore_delete (pool->sync_lock);
-    rtems_semaphore_delete (pool->lock);
-    free (pool->buffers);
-    free (pool->bds);
-    return sc;
-  }
-
-  sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 't'),
-                               0, RTEMS_BDBUF_POOL_WAITER_ATTRIBS, 0,
-                               &pool->transfer);
-  if (sc != RTEMS_SUCCESSFUL)
-  {
-    rtems_semaphore_delete (pool->access);
-    rtems_semaphore_delete (pool->sync_lock);
-    rtems_semaphore_delete (pool->lock);
-    free (pool->buffers);
-    free (pool->bds);
-    return sc;
-  }
-
-  sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 'w'),
-                               0, RTEMS_BDBUF_POOL_WAITER_ATTRIBS, 0,
-                               &pool->waiting);
-  if (sc != RTEMS_SUCCESSFUL)
-  {
-    rtems_semaphore_delete (pool->transfer);
-    rtems_semaphore_delete (pool->access);
-    rtems_semaphore_delete (pool->sync_lock);
-    rtems_semaphore_delete (pool->lock);
-    free (pool->buffers);
-    free (pool->bds);
-    return sc;
-  }
-
-  return RTEMS_SUCCESSFUL;
-}
-
-/**
- * Free resources allocated for buffer pool with specified number.
- *
- * @param pid Buffer pool number
- *
- * @retval RTEMS_SUCCESSFUL
- */
-static rtems_status_code
-rtems_bdbuf_release_pool (rtems_bdpool_id pid)
-{
-  rtems_bdbuf_pool* pool = rtems_bdbuf_get_pool (pid);
-  
-  rtems_bdbuf_lock_pool (pool);
-
-  rtems_semaphore_delete (pool->waiting);
-  rtems_semaphore_delete (pool->transfer);
-  rtems_semaphore_delete (pool->access);
-  rtems_semaphore_delete (pool->lock);
-  
-  free (pool->buffers);
-  free (pool->bds);
-  
-  return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code
-rtems_bdbuf_init (void)
-{
-  rtems_bdpool_id   p;
-  rtems_status_code sc;
-
-#if RTEMS_BDBUF_TRACE
-  rtems_bdbuf_printf ("init\n");
-#endif
-
-  if (rtems_bdbuf_pool_configuration_size <= 0)
-    return RTEMS_INVALID_SIZE;
-
-  if (rtems_bdbuf_ctx.npools)
-    return RTEMS_RESOURCE_IN_USE;
-
-  rtems_bdbuf_ctx.npools = rtems_bdbuf_pool_configuration_size;
-
-  /*
-   * Allocate memory for buffer pool descriptors
-   */
-  rtems_bdbuf_ctx.pool = calloc (rtems_bdbuf_pool_configuration_size,
-                                 sizeof (rtems_bdbuf_pool));
-  
-  if (rtems_bdbuf_ctx.pool == NULL)
-    return RTEMS_NO_MEMORY;
-
-  /*
-   * Initialize buffer pools and roll out if something failed,
-   */
-  for (p = 0; p < rtems_bdbuf_ctx.npools; p++)
-  {
-    sc = rtems_bdbuf_initialize_pool (&rtems_bdbuf_pool_configuration[p], p);
-    if (sc != RTEMS_SUCCESSFUL)
-    {
-      rtems_bdpool_id j;
-      for (j = 0; j < p - 1; j++)
-        rtems_bdbuf_release_pool (j);
-      return sc;
-    }
-  }
-
-  /*
-   * Create and start swapout task
-   */
-
-  rtems_bdbuf_ctx.swapout_enabled = true;
+    rtems_chain_append (&bdbuf_cache.ready, &bd->link);
+
+    if ((b % bdbuf_cache.max_bds_per_group) ==
+        (bdbuf_cache.max_bds_per_group - 1))
+      group++;
+  }
+
+  for (b = 0,
+         group = bdbuf_cache.groups,
+         bd = bdbuf_cache.bds;
+       b < bdbuf_cache.group_count;
+       b++,
+         group++,
+         bd += bdbuf_cache.max_bds_per_group)
+  {
+    group->bds_per_group = bdbuf_cache.max_bds_per_group;
+    group->users = 0;
+    group->bdbuf = bd;
+  }
+         
+  /*
+   * Create and start swapout task. This task will create and manage the worker
+   * threads.
+   */
+  bdbuf_cache.swapout_enabled = true;
   
   sc = rtems_task_create (rtems_build_name('B', 'S', 'W', 'P'),
-                          (rtems_bdbuf_configuration.swapout_priority ?
-                           rtems_bdbuf_configuration.swapout_priority :
+                          (bdbuf_config.swapout_priority ?
+                           bdbuf_config.swapout_priority :
                            RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT),
                           SWAPOUT_TASK_STACK_SIZE,
                           RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
                           RTEMS_LOCAL | RTEMS_NO_FLOATING_POINT,
-                          &rtems_bdbuf_ctx.swapout);
+                          &bdbuf_cache.swapout);
   if (sc != RTEMS_SUCCESSFUL)
   {
-    for (p = 0; p < rtems_bdbuf_ctx.npools; p++)
-      rtems_bdbuf_release_pool (p);
-    free (rtems_bdbuf_ctx.pool);
+    free (bdbuf_cache.buffers);
+    free (bdbuf_cache.groups);
+    free (bdbuf_cache.bds);
+    rtems_semaphore_delete (bdbuf_cache.transfer);
+    rtems_semaphore_delete (bdbuf_cache.access);
+    rtems_semaphore_delete (bdbuf_cache.sync_lock);
+    rtems_bdbuf_unlock_cache ();
+    rtems_semaphore_delete (bdbuf_cache.lock);
+    bdbuf_cache.initialised = false;
     return sc;
   }
 
-  sc = rtems_task_start (rtems_bdbuf_ctx.swapout,
+  sc = rtems_task_start (bdbuf_cache.swapout,
                          rtems_bdbuf_swapout_task,
-                         (rtems_task_argument) &rtems_bdbuf_ctx);
+                         (rtems_task_argument) &bdbuf_cache);
   if (sc != RTEMS_SUCCESSFUL)
   {
-    rtems_task_delete (rtems_bdbuf_ctx.swapout);
-    for (p = 0; p < rtems_bdbuf_ctx.npools; p++)
-      rtems_bdbuf_release_pool (p);
-    free (rtems_bdbuf_ctx.pool);
+    rtems_task_delete (bdbuf_cache.swapout);
+    free (bdbuf_cache.buffers);
+    free (bdbuf_cache.groups);
+    free (bdbuf_cache.bds);
+    rtems_semaphore_delete (bdbuf_cache.transfer);
+    rtems_semaphore_delete (bdbuf_cache.access);
+    rtems_semaphore_delete (bdbuf_cache.sync_lock);
+    rtems_bdbuf_unlock_cache ();
+    rtems_semaphore_delete (bdbuf_cache.lock);
+    bdbuf_cache.initialised = false;
     return sc;
   }
 
+  rtems_bdbuf_unlock_cache ();
+  
   return RTEMS_SUCCESSFUL;
 }
@@ -1109,27 +1305,27 @@
  * Get a buffer for this device and block. This function returns a buffer once
  * placed into the AVL tree. If no buffer is available and it is not a read
- * ahead request and no buffers are waiting to the written to disk wait until
- * one is available. If buffers are waiting to be written to disk and non are
- * available expire the hold timer and wake the swap out task. If the buffer is
- * for a read ahead transfer return NULL if there is not buffer or it is in the
- * cache.
- *
- * The AVL tree of buffers for the pool is searched and if not located check
- * obtain a buffer and insert it into the AVL tree. Buffers are first obtained
- * from the ready list until all empty/ready buffers are used. Once all buffers
- * are in use buffers are taken from the LRU list with the least recently used
- * buffer taken first. A buffer taken from the LRU list is removed from the AVL
- * tree. The ready list or LRU list buffer is initialised to this device and
- * block. If no buffers are available due to the ready and LRU lists being
- * empty a check is made of the modified list. Buffers may be queued waiting
- * for the hold timer to expire. These buffers should be written to disk and
- * returned to the LRU list where they can be used rather than this call
- * blocking. If buffers are on the modified list the max. write block size of
- * buffers have their hold timer expired and the swap out task woken. The
- * caller then blocks on the waiting semaphore and counter. When buffers return
- * from the upper layers (access) or lower driver (transfer) the blocked caller
- * task is woken and this procedure is repeated. The repeat handles a case of a
- * another thread pre-empting getting a buffer first and adding it to the AVL
- * tree.
+ * ahead request and no buffers are waiting to the written to disk wait until a
+ * buffer is available. If buffers are waiting to be written to disk and none
+ * are available expire the hold timer's of the queued buffers and wake the
+ * swap out task. If the buffer is for a read ahead transfer return NULL if
+ * there are no buffers available or the buffer is already in the cache.
+ *
+ * The AVL tree of buffers for the cache is searched and if not found obtain a
+ * buffer and insert it into the AVL tree. Buffers are first obtained from the
+ * ready list until all empty/ready buffers are used. Once all buffers are in
+ * use the LRU list is searched for a buffer of the same group size or a group
+ * that has no active buffers in use. A buffer taken from the LRU list is
+ * removed from the AVL tree and assigned the new block number. The ready or
+ * LRU list buffer is initialised to this device and block. If no buffers are
+ * available due to the ready and LRU lists being empty a check is made of the
+ * modified list. Buffers may be queued waiting for the hold timer to
+ * expire. These buffers should be written to disk and returned to the LRU list
+ * where they can be used. If buffers are on the modified list the max. write
+ * block size of buffers have their hold timer's expired and the swap out task
+ * woken. The caller then blocks on the waiting semaphore and counter. When
+ * buffers return from the upper layers (access) or lower driver (transfer) the
+ * blocked caller task is woken and this procedure is repeated. The repeat
+ * handles a case of a another thread pre-empting getting a buffer first and
+ * adding it to the AVL tree.
  *
  * A buffer located in the AVL tree means it is already in the cache and maybe
@@ -1143,35 +1339,43 @@
  * and return to the user.
  *
- * This function assumes the pool the buffer is being taken from is locked and
- * it will make sure the pool is locked when it returns. The pool will be
+ * This function assumes the cache the buffer is being taken from is locked and
+ * it will make sure the cache is locked when it returns. The cache will be
  * unlocked if the call could block.
  *
- * @param pdd The physical disk device
- * @param pool The pool reference
- * @param block Absolute media block number
- * @param read_ahead The get is for a read ahead buffer
- *
- * @return RTEMS status code ( if operation completed successfully or error
+ * Variable sized buffer is handled by groups. A group is the size of the
+ * maximum buffer that can be allocated. The group can size in multiples of the
+ * minimum buffer size where the mulitples are 1,2,4,8, etc. If the buffer is
+ * found in the AVL tree the number of BDs in the group is check and if
+ * different the buffer size for the block has changed. The buffer needs to be
+ * invalidated.
+ *
+ * @param dd The disk device. Has the configured block size.
+ * @param bds_per_group The number of BDs in a group for this block.
+ * @param block Absolute media block number for the device
+ * @param read_ahead The get is for a read ahead buffer if true
+ * @return RTEMS status code (if operation completed successfully or error
  *         code if error is occured)
  */
 static rtems_bdbuf_buffer*
-rtems_bdbuf_get_buffer (rtems_disk_device* pdd,
-                        rtems_bdbuf_pool*  pool,
+rtems_bdbuf_get_buffer (rtems_disk_device* dd,
+                        size_t             bds_per_group,
                         rtems_blkdev_bnum  block,
                         bool               read_ahead)
 {
-  dev_t               device = pdd->dev;
+  dev_t               device = dd->dev;
   rtems_bdbuf_buffer* bd;
   bool                available;
-
+  
   /*
    * Loop until we get a buffer. Under load we could find no buffers are
    * available requiring this task to wait until some become available before
-   * proceeding. There is no timeout. If the call is to block and the buffer is
-   * for a read ahead buffer return NULL.
+   * proceeding. There is no timeout. If this call is to block and the buffer
+   * is for a read ahead buffer return NULL. The read ahead is nice but not
+   * that important.
    *
    * The search procedure is repeated as another thread could have pre-empted
    * us while we waited for a buffer, obtained an empty buffer and loaded the
-   * AVL tree with the one we are after.
+   * AVL tree with the one we are after. In this case we move down and wait for
+   * the buffer to return to the cache.
    */
   do
@@ -1180,5 +1384,5 @@
      * Search for buffer descriptor for this dev/block key.
      */
-    bd = rtems_bdbuf_avl_search (&pool->tree, device, block);
+    bd = rtems_bdbuf_avl_search (&bdbuf_cache.tree, device, block);
 
     /*
@@ -1195,17 +1399,20 @@
     {
       /*
-       * Assign new buffer descriptor from the empty list if one is present. If
-       * the empty queue is empty get the oldest buffer from LRU list. If the
+       * Assign new buffer descriptor from the ready list if one is present. If
+       * the ready queue is empty get the oldest buffer from LRU list. If the
        * LRU list is empty there are no available buffers check the modified
        * list.
        */
-      if (rtems_chain_is_empty (&pool->ready))
+      bd = rtems_bdbuf_get_next_bd (bds_per_group, &bdbuf_cache.ready);
+
+      if (!bd)
       {
         /*
-         * No unsed or read-ahead buffers.
+         * No unused or read-ahead buffers.
          *
          * If this is a read ahead buffer just return. No need to place further
          * pressure on the cache by reading something that may be needed when
-         * we have data in the cache that was needed and may still be.
+         * we have data in the cache that was needed and may still be in the
+         * future.
          */
         if (read_ahead)
@@ -1215,5 +1422,5 @@
          * Check the LRU list.
          */
-        bd = (rtems_bdbuf_buffer *) rtems_chain_get (&pool->lru);
+        bd = rtems_bdbuf_get_next_bd (bds_per_group, &bdbuf_cache.lru);
         
         if (bd)
@@ -1222,5 +1429,5 @@
            * Remove the buffer from the AVL tree.
            */
-          if (rtems_bdbuf_avl_remove (&pool->tree, bd) != 0)
+          if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
             rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
         }
@@ -1230,18 +1437,20 @@
            * If there are buffers on the modified list expire the hold timer
            * and wake the swap out task then wait else just go and wait.
+           *
+           * The check for an empty list is made so the swapper is only woken
+           * when if timers are changed.
            */
-          if (!rtems_chain_is_empty (&pool->modified))
+          if (!rtems_chain_is_empty (&bdbuf_cache.modified))
           {
-            rtems_chain_node* node = rtems_chain_head (&pool->modified);
+            rtems_chain_node* node = rtems_chain_first (&bdbuf_cache.modified);
             uint32_t          write_blocks = 0;
             
-            node = node->next;
-            while ((write_blocks < rtems_bdbuf_configuration.max_write_blocks) &&
-                   !rtems_chain_is_tail (&pool->modified, node))
+            while ((write_blocks < bdbuf_config.max_write_blocks) &&
+                   !rtems_chain_is_tail (&bdbuf_cache.modified, node))
             {
               rtems_bdbuf_buffer* bd = (rtems_bdbuf_buffer*) node;
               bd->hold_timer = 0;
               write_blocks++;
-              node = node->next;
+              node = rtems_chain_next (node);
             }
 
@@ -1250,14 +1459,15 @@
           
           /*
-           * Wait for a buffer to be returned to the pool. The buffer will be
+           * Wait for a buffer to be returned to the cache. The buffer will be
            * placed on the LRU list.
            */
-          rtems_bdbuf_wait (pool, &pool->waiting, &pool->wait_waiters);
+          rtems_bdbuf_wait (&bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
         }
       }
       else
       {
-        bd = (rtems_bdbuf_buffer *) rtems_chain_get (&(pool->ready));
-
+        /*
+         * We have a new buffer for this block.
+         */
         if ((bd->state != RTEMS_BDBUF_STATE_EMPTY) &&
             (bd->state != RTEMS_BDBUF_STATE_READ_AHEAD))
@@ -1266,5 +1476,5 @@
         if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)
         {
-          if (rtems_bdbuf_avl_remove (&pool->tree, bd) != 0)
+          if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
             rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
         }
@@ -1281,8 +1491,22 @@
         bd->waiters   = 0;
 
-        if (rtems_bdbuf_avl_insert (&pool->tree, bd) != 0)
+        if (rtems_bdbuf_avl_insert (&bdbuf_cache.tree, bd) != 0)
           rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
 
         return bd;
+      }
+    }
+    else
+    {
+      /*
+       * We have the buffer for the block from the cache. Check if the buffer
+       * in the cache is the same size and the requested size we are after.
+       */
+      if (bd->group->bds_per_group != bds_per_group)
+      {
+        bd->state = RTEMS_BDBUF_STATE_EMPTY;
+        rtems_chain_extract (&bd->link);
+        rtems_chain_prepend (&bdbuf_cache.ready, &bd->link);
+        bd = NULL;
       }
     }
@@ -1315,5 +1539,6 @@
       case RTEMS_BDBUF_STATE_ACCESS_MODIFIED:
         bd->waiters++;
-        rtems_bdbuf_wait (pool, &pool->access, &pool->access_waiters);
+        rtems_bdbuf_wait (&bdbuf_cache.access,
+                          &bdbuf_cache.access_waiters);
         bd->waiters--;
         break;
@@ -1322,5 +1547,6 @@
       case RTEMS_BDBUF_STATE_TRANSFER:
         bd->waiters++;
-        rtems_bdbuf_wait (pool, &pool->transfer, &pool->transfer_waiters);
+        rtems_bdbuf_wait (&bdbuf_cache.transfer,
+                          &bdbuf_cache.transfer_waiters);
         bd->waiters--;
         break;
@@ -1345,23 +1571,31 @@
 {
   rtems_disk_device*  dd;
-  rtems_bdbuf_pool*   pool;
   rtems_bdbuf_buffer* bd;
-
-  /*
-   * Do not hold the pool lock when obtaining the disk table.
+  size_t              bds_per_group;
+
+  if (!bdbuf_cache.initialised)
+    return RTEMS_NOT_CONFIGURED;
+
+  /*
+   * Do not hold the cache lock when obtaining the disk table.
    */
   dd = rtems_disk_obtain (device);
-  if (dd == NULL)
+  if (!dd)
     return RTEMS_INVALID_ID;
 
   if (block >= dd->size)
+  {
+    rtems_disk_release (dd);
+    return RTEMS_INVALID_ADDRESS;
+  }
+
+  bds_per_group = rtems_bdbuf_bds_per_group (dd->block_size);
+  if (!bds_per_group)
   {
     rtems_disk_release (dd);
     return RTEMS_INVALID_NUMBER;
   }
-
-  pool = rtems_bdbuf_get_pool (dd->phys_dev->pool);
-  
-  rtems_bdbuf_lock_pool (pool);
+  
+  rtems_bdbuf_lock_cache ();
 
 #if RTEMS_BDBUF_TRACE
@@ -1370,5 +1604,5 @@
 #endif
 
-  bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool, block + dd->start, false);
+  bd = rtems_bdbuf_get_buffer (dd, bds_per_group, block + dd->start, false);
 
   if (bd->state == RTEMS_BDBUF_STATE_MODIFIED)
@@ -1376,11 +1610,11 @@
   else
     bd->state = RTEMS_BDBUF_STATE_ACCESS;
-  
-  rtems_bdbuf_unlock_pool (pool);
+
+  rtems_bdbuf_unlock_cache ();
 
   rtems_disk_release(dd);
 
   *bdp = bd;
-  
+
   return RTEMS_SUCCESSFUL;
 }
@@ -1413,9 +1647,12 @@
 {
   rtems_disk_device*    dd;
-  rtems_bdbuf_pool*     pool;
   rtems_bdbuf_buffer*   bd = NULL;
   uint32_t              read_ahead_count;
   rtems_blkdev_request* req;
-  
+  size_t                bds_per_group;
+  
+  if (!bdbuf_cache.initialised)
+    return RTEMS_NOT_CONFIGURED;
+
   /*
    * @todo This type of request structure is wrong and should be removed.
@@ -1428,12 +1665,19 @@
 
   /*
-   * Do not hold the pool lock when obtaining the disk table.
+   * Do not hold the cache lock when obtaining the disk table.
    */
   dd = rtems_disk_obtain (device);
-  if (dd == NULL)
+  if (!dd)
     return RTEMS_INVALID_ID;
   
   if (block >= dd->size) {
     rtems_disk_release(dd);
+    return RTEMS_INVALID_NUMBER;
+  }
+  
+  bds_per_group = rtems_bdbuf_bds_per_group (dd->block_size);
+  if (!bds_per_group)
+  {
+    rtems_disk_release (dd);
     return RTEMS_INVALID_NUMBER;
   }
@@ -1458,7 +1702,5 @@
     read_ahead_count = dd->size - block;
 
-  pool = rtems_bdbuf_get_pool (dd->phys_dev->pool);
-
-  rtems_bdbuf_lock_pool (pool);
+  rtems_bdbuf_lock_cache ();
 
   while (req->bufnum < read_ahead_count)
@@ -1472,5 +1714,5 @@
      * caller.
      */
-    bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool,
+    bd = rtems_bdbuf_get_buffer (dd, bds_per_group,
                                  block + dd->start + req->bufnum,
                                  req->bufnum == 0 ? false : true);
@@ -1515,12 +1757,12 @@
   {
     /*
-     * Unlock the pool. We have the buffer for the block and it will be in the
+     * Unlock the cache. We have the buffer for the block and it will be in the
      * access or transfer state. We may also have a number of read ahead blocks
      * if we need to transfer data. At this point any other threads can gain
-     * access to the pool and if they are after any of the buffers we have they
-     * will block and be woken when the buffer is returned to the pool.
+     * access to the cache and if they are after any of the buffers we have
+     * they will block and be woken when the buffer is returned to the cache.
      *
      * If a transfer is needed the I/O operation will occur with pre-emption
-     * enabled and the pool unlocked. This is a change to the previous version
+     * enabled and the cache unlocked. This is a change to the previous version
      * of the bdbuf code.
      */
@@ -1536,5 +1778,5 @@
                          0, &out);
                          
-    rtems_bdbuf_unlock_pool (pool);
+    rtems_bdbuf_unlock_cache ();
 
     req->req = RTEMS_BLKDEV_REQ_READ;
@@ -1568,5 +1810,5 @@
     }
 
-    rtems_bdbuf_lock_pool (pool);
+    rtems_bdbuf_lock_cache ();
 
     for (b = 1; b < req->bufnum; b++)
@@ -1589,5 +1831,5 @@
     bd->state = RTEMS_BDBUF_STATE_ACCESS;
 
-  rtems_bdbuf_unlock_pool (pool);
+  rtems_bdbuf_unlock_cache ();
   rtems_disk_release (dd);
 
@@ -1600,12 +1842,11 @@
 rtems_bdbuf_release (rtems_bdbuf_buffer* bd)
 {
-  rtems_bdbuf_pool* pool;
+  if (!bdbuf_cache.initialised)
+    return RTEMS_NOT_CONFIGURED;
 
   if (bd == NULL)
     return RTEMS_INVALID_ADDRESS;
 
-  pool = rtems_bdbuf_get_pool (bd->pool);
-
-  rtems_bdbuf_lock_pool (pool);
+  rtems_bdbuf_lock_cache ();
 
 #if RTEMS_BDBUF_TRACE
@@ -1615,5 +1856,5 @@
   if (bd->state == RTEMS_BDBUF_STATE_ACCESS_MODIFIED)
   {
-    rtems_bdbuf_append_modified (pool, bd);
+    rtems_bdbuf_append_modified (bd);
   }
   else
@@ -1625,10 +1866,15 @@
      */
     if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)
-      rtems_chain_prepend (&pool->ready, &bd->link);
+      rtems_chain_prepend (&bdbuf_cache.ready, &bd->link);
     else
     {
       bd->state = RTEMS_BDBUF_STATE_CACHED;
-      rtems_chain_append (&pool->lru, &bd->link);
-    }
+      rtems_chain_append (&bdbuf_cache.lru, &bd->link);
+    }
+
+    /*
+     * One less user for the group of bds.
+     */
+    bd->group->users--;
   }
   
@@ -1638,20 +1884,20 @@
    */
   if (bd->waiters)
-    rtems_bdbuf_wake (pool->access, &pool->access_waiters);
+    rtems_bdbuf_wake (bdbuf_cache.access, &bdbuf_cache.access_waiters);
   else
   {
     if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)
     {
-      if (rtems_chain_has_only_one_node (&pool->ready))
-        rtems_bdbuf_wake (pool->waiting, &pool->wait_waiters);
+      if (rtems_chain_has_only_one_node (&bdbuf_cache.ready))
+        rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
     }
     else
     {
-      if (rtems_chain_has_only_one_node (&pool->lru))
-        rtems_bdbuf_wake (pool->waiting, &pool->wait_waiters);
-    }
-  }
-  
-  rtems_bdbuf_unlock_pool (pool);
+      if (rtems_chain_has_only_one_node (&bdbuf_cache.lru))
+        rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
+    }
+  }
+  
+  rtems_bdbuf_unlock_cache ();
 
   return RTEMS_SUCCESSFUL;
@@ -1661,12 +1907,11 @@
 rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd)
 {
-  rtems_bdbuf_pool* pool;
-
-  if (bd == NULL)
+  if (!bdbuf_cache.initialised)
+    return RTEMS_NOT_CONFIGURED;
+
+  if (!bd)
     return RTEMS_INVALID_ADDRESS;
 
-  pool = rtems_bdbuf_get_pool (bd->pool);
-
-  rtems_bdbuf_lock_pool (pool);
+  rtems_bdbuf_lock_cache ();
 
 #if RTEMS_BDBUF_TRACE
@@ -1676,10 +1921,10 @@
   bd->hold_timer = rtems_bdbuf_configuration.swap_block_hold;
   
-  rtems_bdbuf_append_modified (pool, bd);
+  rtems_bdbuf_append_modified (bd);
 
   if (bd->waiters)
-    rtems_bdbuf_wake (pool->access, &pool->access_waiters);
-  
-  rtems_bdbuf_unlock_pool (pool);
+    rtems_bdbuf_wake (bdbuf_cache.access, &bdbuf_cache.access_waiters);
+  
+  rtems_bdbuf_unlock_cache ();
 
   return RTEMS_SUCCESSFUL;
@@ -1689,6 +1934,5 @@
 rtems_bdbuf_sync (rtems_bdbuf_buffer* bd)
 {
-  rtems_bdbuf_pool* pool;
-  bool              available;
+  bool available;
 
 #if RTEMS_BDBUF_TRACE
@@ -1696,14 +1940,15 @@
 #endif
   
-  if (bd == NULL)
+  if (!bdbuf_cache.initialised)
+    return RTEMS_NOT_CONFIGURED;
+
+  if (!bd)
     return RTEMS_INVALID_ADDRESS;
 
-  pool = rtems_bdbuf_get_pool (bd->pool);
-
-  rtems_bdbuf_lock_pool (pool);
+  rtems_bdbuf_lock_cache ();
 
   bd->state = RTEMS_BDBUF_STATE_SYNC;
 
-  rtems_chain_append (&pool->sync, &bd->link);
+  rtems_chain_append (&bdbuf_cache.sync, &bd->link);
 
   rtems_bdbuf_wake_swapper ();
@@ -1725,5 +1970,5 @@
       case RTEMS_BDBUF_STATE_TRANSFER:
         bd->waiters++;
-        rtems_bdbuf_wait (pool, &pool->transfer, &pool->transfer_waiters);
+        rtems_bdbuf_wait (&bdbuf_cache.transfer, &bdbuf_cache.transfer_waiters);
         bd->waiters--;
         break;
@@ -1734,5 +1979,5 @@
   }
 
-  rtems_bdbuf_unlock_pool (pool);
+  rtems_bdbuf_unlock_cache ();
   
   return RTEMS_SUCCESSFUL;
@@ -1743,5 +1988,4 @@
 {
   rtems_disk_device*  dd;
-  rtems_bdbuf_pool*   pool;
   rtems_status_code   sc;
   rtems_event_set     out;
@@ -1751,36 +1995,37 @@
 #endif
 
-  /*
-   * Do not hold the pool lock when obtaining the disk table.
+  if (!bdbuf_cache.initialised)
+    return RTEMS_NOT_CONFIGURED;
+
+  /*
+   * Do not hold the cache lock when obtaining the disk table.
    */
   dd = rtems_disk_obtain (dev);
-  if (dd == NULL)
+  if (!dd)
     return RTEMS_INVALID_ID;
 
-  pool = rtems_bdbuf_get_pool (dd->pool);
-
-  /*
-   * Take the sync lock before locking the pool. Once we have the sync lock
-   * we can lock the pool. If another thread has the sync lock it will cause
-   * this thread to block until it owns the sync lock then it can own the
-   * pool. The sync lock can only be obtained with the pool unlocked.
-   */
-  
-  rtems_bdbuf_lock_sync (pool);
-  rtems_bdbuf_lock_pool (pool);  
-
-  /*
-   * Set the pool to have a sync active for a specific device and let the swap
+  /*
+   * Take the sync lock before locking the cache. Once we have the sync lock we
+   * can lock the cache. If another thread has the sync lock it will cause this
+   * thread to block until it owns the sync lock then it can own the cache. The
+   * sync lock can only be obtained with the cache unlocked.
+   */
+  
+  rtems_bdbuf_lock_sync ();
+  rtems_bdbuf_lock_cache ();  
+
+  /*
+   * Set the cache to have a sync active for a specific device and let the swap
    * out task know the id of the requester to wake when done.
    *
    * The swap out task will negate the sync active flag when no more buffers
-   * for the device are held on the modified for sync queues.
-   */
-  pool->sync_active    = true;
-  pool->sync_requester = rtems_task_self ();
-  pool->sync_device    = dev;
+   * for the device are held on the "modified for sync" queues.
+   */
+  bdbuf_cache.sync_active    = true;
+  bdbuf_cache.sync_requester = rtems_task_self ();
+  bdbuf_cache.sync_device    = dev;
   
   rtems_bdbuf_wake_swapper ();
-  rtems_bdbuf_unlock_pool (pool);
+  rtems_bdbuf_unlock_cache ();
   
   sc = rtems_event_receive (RTEMS_BDBUF_TRANSFER_SYNC,
@@ -1791,7 +2036,7 @@
     rtems_fatal_error_occurred (BLKDEV_FATAL_BDBUF_SWAPOUT_RE);
       
-  rtems_bdbuf_unlock_sync (pool);
-  
-  return rtems_disk_release(dd);
+  rtems_bdbuf_unlock_sync ();
+  
+  return rtems_disk_release (dd);
 }
 
@@ -1818,198 +2063,30 @@
 
 /**
- * Process the modified list of buffers. There us a sync or modified list that
- * needs to be handled.
- *
- * @param pid The pool id to process modified buffers on.
- * @param dev The device to handle. If -1 no device is selected so select the
- *            device of the first buffer to be written to disk.
- * @param chain The modified chain to process.
- * @param transfer The chain to append buffers to be written too.
- * @param sync_active If true this is a sync operation so expire all timers.
- * @param update_timers If true update the timers.
- * @param timer_delta It update_timers is true update the timers by this
- *                    amount.
+ * Swapout transfer to the driver. The driver will break this I/O into groups
+ * of consecutive write requests is multiple consecutive buffers are required
+ * by the driver.
+ *
+ * @param transfer The transfer transaction.
  */
 static void
-rtems_bdbuf_swapout_modified_processing (rtems_bdpool_id      pid,
-                                         dev_t*               dev,
-                                         rtems_chain_control* chain,
-                                         rtems_chain_control* transfer,
-                                         bool                 sync_active,
-                                         bool                 update_timers,
-                                         uint32_t             timer_delta)
-{
-  if (!rtems_chain_is_empty (chain))
-  {
-    rtems_chain_node* node = rtems_chain_head (chain);
-    node = node->next;
-
-    while (!rtems_chain_is_tail (chain, node))
-    {
-      rtems_bdbuf_buffer* bd = (rtems_bdbuf_buffer*) node;
-    
-      if (bd->pool == pid)
-      {
-        /*
-         * Check if the buffer's hold timer has reached 0. If a sync is active
-         * force all the timers to 0.
-         *
-         * @note Lots of sync requests will skew this timer. It should be based
-         *       on TOD to be accurate. Does it matter ?
-         */
-        if (sync_active)
-          bd->hold_timer = 0;
-  
-        if (bd->hold_timer)
-        {
-          if (update_timers)
-          {
-            if (bd->hold_timer > timer_delta)
-              bd->hold_timer -= timer_delta;
-            else
-              bd->hold_timer = 0;
-          }
-
-          if (bd->hold_timer)
-          {
-            node = node->next;
-            continue;
-          }
-        }
-
-        /*
-         * This assumes we can set dev_t to -1 which is just an
-         * assumption. Cannot use the transfer list being empty the sync dev
-         * calls sets the dev to use.
-         */
-        if (*dev == (dev_t)-1)
-          *dev = bd->dev;
-
-        if (bd->dev == *dev)
-        {
-          rtems_chain_node* next_node = node->next;
-          rtems_chain_node* tnode = rtems_chain_tail (transfer);
-    
-          /*
-           * The blocks on the transfer list are sorted in block order. This
-           * means multi-block transfers for drivers that require consecutive
-           * blocks perform better with sorted blocks and for real disks it may
-           * help lower head movement.
-           */
-
-          bd->state = RTEMS_BDBUF_STATE_TRANSFER;
-
-          rtems_chain_extract (node);
-
-          tnode = tnode->previous;
-          
-          while (node && !rtems_chain_is_head (transfer, tnode))
-          {
-            rtems_bdbuf_buffer* tbd = (rtems_bdbuf_buffer*) tnode;
-
-            if (bd->block > tbd->block)
-            {
-              rtems_chain_insert (tnode, node);
-              node = NULL;
-            }
-            else
-              tnode = tnode->previous;
-          }
-
-          if (node)
-            rtems_chain_prepend (transfer, node);
-          
-          node = next_node;
-        }
-        else
-        {
-          node = node->next;
-        }
-      }
-    }
-  }
-}
-
-/**
- * Process a pool's modified buffers. Check the sync list first then the
- * modified list extracting the buffers suitable to be written to disk. We have
- * a device at a time. The task level loop will repeat this operation while
- * there are buffers to be written. If the transfer fails place the buffers
- * back on the modified list and try again later. The pool is unlocked while
- * the buffers are being written to disk.
- *
- * @param pid The pool id to process modified buffers on.
- * @param timer_delta It update_timers is true update the timers by this
- *                    amount.
- * @param update_timers If true update the timers.
- * @param write_req The write request structure. There is only one.
- *
- * @retval true Buffers where written to disk so scan again.
- * @retval false No buffers where written to disk.
- */
-static bool
-rtems_bdbuf_swapout_pool_processing (rtems_bdpool_id       pid,
-                                     unsigned long         timer_delta,
-                                     bool                  update_timers,
-                                     rtems_blkdev_request* write_req)
-{
-  rtems_bdbuf_pool*   pool = rtems_bdbuf_get_pool (pid);
-  rtems_chain_control transfer;
-  dev_t               dev = -1;
+rtems_bdbuf_swapout_write (rtems_bdbuf_swapout_transfer* transfer)
+{
   rtems_disk_device*  dd;
-  bool                transfered_buffers = true;
-
-  rtems_chain_initialize_empty (&transfer);
-    
-  rtems_bdbuf_lock_pool (pool);
-
-  /*
-   * When the sync is for a device limit the sync to that device. If the sync
-   * is for a buffer handle process the devices in the order on the sync
-   * list. This means the dev is -1.
-   */
-  if (pool->sync_active)
-    dev = pool->sync_device;
-
-  /*
-   * If we have any buffers in the sync queue move them to the modified
-   * list. The first sync buffer will select the device we use.
-   */
-  rtems_bdbuf_swapout_modified_processing (pid, &dev,
-                                           &pool->sync, &transfer,
-                                           true, false,
-                                           timer_delta);
-
-  /*
-   * Process the pool's modified list.
-   */
-  rtems_bdbuf_swapout_modified_processing (pid, &dev,
-                                           &pool->modified, &transfer,
-                                           pool->sync_active,
-                                           update_timers,
-                                           timer_delta);
-
-  /*
-   * We have all the buffers that have been modified for this device so the
-   * pool can be unlocked because the state of each buffer has been set to
-   * TRANSFER.
-   */
-  rtems_bdbuf_unlock_pool (pool);
+  
+#if RTEMS_BDBUF_TRACE
+  rtems_bdbuf_printf ("swapout transfer: %08x\n", transfer->dev);
+#endif
 
   /*
    * If there are buffers to transfer to the media transfer them.
    */
-  if (rtems_chain_is_empty (&transfer))
-    transfered_buffers = false;
-  else
+  if (!rtems_chain_is_empty (&transfer->bds))
   {
     /*
-     * Obtain the disk device. The pool's mutex has been released to avoid a
+     * Obtain the disk device. The cache's mutex has been released to avoid a
      * dead lock.
      */
-    dd = rtems_disk_obtain (dev);
-    if (dd == NULL)
-       transfered_buffers = false;
-    else
+    dd = rtems_disk_obtain (transfer->dev);
+    if (dd)
     {
       /*
@@ -2028,12 +2105,12 @@
        * trouble waiting to happen.
        */
-      write_req->status = RTEMS_RESOURCE_IN_USE;
-      write_req->error = 0;
-      write_req->bufnum = 0;
-
-      while (!rtems_chain_is_empty (&transfer))
+      transfer->write_req->status = RTEMS_RESOURCE_IN_USE;
+      transfer->write_req->error = 0;
+      transfer->write_req->bufnum = 0;
+
+      while (!rtems_chain_is_empty (&transfer->bds))
       {
         rtems_bdbuf_buffer* bd =
-          (rtems_bdbuf_buffer*) rtems_chain_get (&transfer);
+          (rtems_bdbuf_buffer*) rtems_chain_get (&transfer->bds);
 
         bool write = false;
@@ -2046,19 +2123,28 @@
          */
         
-        if ((dd->capabilities & RTEMS_BLKDEV_CAP_MULTISECTOR_CONT) &&
-            write_req->bufnum &&
+#if RTEMS_BDBUF_TRACE
+        rtems_bdbuf_printf ("swapout write: bd:%d, bufnum:%d mode:%s\n",
+                            bd->block, transfer->write_req->bufnum,
+                            dd->phys_dev->capabilities &
+                            RTEMS_BLKDEV_CAP_MULTISECTOR_CONT ? "MULIT" : "SCAT");
+#endif
+
+        if ((dd->phys_dev->capabilities & RTEMS_BLKDEV_CAP_MULTISECTOR_CONT) &&
+            transfer->write_req->bufnum &&
             (bd->block != (last_block + 1)))
         {
-          rtems_chain_prepend (&transfer, &bd->link);
+          rtems_chain_prepend (&transfer->bds, &bd->link);
           write = true;
         }
         else
         {
-          write_req->bufs[write_req->bufnum].user   = bd;
-          write_req->bufs[write_req->bufnum].block  = bd->block;
-          write_req->bufs[write_req->bufnum].length = dd->block_size;
-          write_req->bufs[write_req->bufnum].buffer = bd->buffer;
-          write_req->bufnum++;
-          last_block = bd->block;
+          rtems_blkdev_sg_buffer* buf;
+          buf = &transfer->write_req->bufs[transfer->write_req->bufnum];
+          transfer->write_req->bufnum++;
+          buf->user   = bd;
+          buf->block  = bd->block;
+          buf->length = dd->block_size;
+          buf->buffer = bd->buffer;
+          last_block  = bd->block;
         }
 
@@ -2068,6 +2154,6 @@
          */
 
-        if (rtems_chain_is_empty (&transfer) ||
-            (write_req->bufnum >= rtems_bdbuf_configuration.max_write_blocks))
+        if (rtems_chain_is_empty (&transfer->bds) ||
+            (transfer->write_req->bufnum >= rtems_bdbuf_configuration.max_write_blocks))
           write = true;
 
@@ -2077,28 +2163,32 @@
           uint32_t b;
 
+#if RTEMS_BDBUF_TRACE
+          rtems_bdbuf_printf ("swapout write: writing bufnum:%d\n",
+                              transfer->write_req->bufnum);
+#endif
           /*
-           * Perform the transfer. No pool locks, no preemption, only the disk
+           * Perform the transfer. No cache locks, no preemption, only the disk
            * device is being held.
            */
-          result = dd->ioctl (dd->phys_dev->dev,
-                              RTEMS_BLKIO_REQUEST, write_req);
+          result = dd->phys_dev->ioctl (dd->phys_dev->dev,
+                                        RTEMS_BLKIO_REQUEST, transfer->write_req);
 
           if (result < 0)
           {
-            rtems_bdbuf_lock_pool (pool);
+            rtems_bdbuf_lock_cache ();
               
-            for (b = 0; b < write_req->bufnum; b++)
+            for (b = 0; b < transfer->write_req->bufnum; b++)
             {
-              bd = write_req->bufs[b].user;
+              bd = transfer->write_req->bufs[b].user;
               bd->state  = RTEMS_BDBUF_STATE_MODIFIED;
               bd->error = errno;
 
               /*
-               * Place back on the pools modified queue and try again.
+               * Place back on the cache's modified queue and try again.
                *
                * @warning Not sure this is the best option but I do not know
                *          what else can be done.
                */
-              rtems_chain_append (&pool->modified, &bd->link);
+              rtems_chain_append (&bdbuf_cache.modified, &bd->link);
             }
           }
@@ -2115,29 +2205,30 @@
               rtems_fatal_error_occurred (BLKDEV_FATAL_BDBUF_SWAPOUT_RE);
 
-            rtems_bdbuf_lock_pool (pool);
-
-            for (b = 0; b < write_req->bufnum; b++)
+            rtems_bdbuf_lock_cache ();
+
+            for (b = 0; b < transfer->write_req->bufnum; b++)
             {
-              bd = write_req->bufs[b].user;
+              bd = transfer->write_req->bufs[b].user;
               bd->state = RTEMS_BDBUF_STATE_CACHED;
               bd->error = 0;
-
-              rtems_chain_append (&pool->lru, &bd->link);
+              bd->group->users--;
+              
+              rtems_chain_append (&bdbuf_cache.lru, &bd->link);
               
               if (bd->waiters)
-                rtems_bdbuf_wake (pool->transfer, &pool->transfer_waiters);
+                rtems_bdbuf_wake (bdbuf_cache.transfer, &bdbuf_cache.transfer_waiters);
               else
               {
-                if (rtems_chain_has_only_one_node (&pool->lru))
-                  rtems_bdbuf_wake (pool->waiting, &pool->wait_waiters);
+                if (rtems_chain_has_only_one_node (&bdbuf_cache.lru))
+                  rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
               }
             }
           }
-
-          rtems_bdbuf_unlock_pool (pool);
-
-          write_req->status = RTEMS_RESOURCE_IN_USE;
-          write_req->error = 0;
-          write_req->bufnum = 0;
+              
+          rtems_bdbuf_unlock_cache ();
+
+          transfer->write_req->status = RTEMS_RESOURCE_IN_USE;
+          transfer->write_req->error = 0;
+          transfer->write_req->bufnum = 0;
         }
       }
@@ -2145,33 +2236,250 @@
       rtems_disk_release (dd);
     }
-  }
-
-  if (pool->sync_active && !  transfered_buffers)
-  {
-    rtems_id sync_requester = pool->sync_requester;
-    pool->sync_active = false;
-    pool->sync_requester = 0;
+    else
+    {
+      /*
+       * We have buffers but no device. Put the BDs back onto the
+       * ready queue and exit.
+       */
+      /* @todo fixme */
+    }
+  }
+}
+
+/**
+ * Process the modified list of buffers. There is a sync or modified list that
+ * needs to be handled so we have a common function to do the work.
+ *
+ * @param dev The device to handle. If -1 no device is selected so select the
+ *            device of the first buffer to be written to disk.
+ * @param chain The modified chain to process.
+ * @param transfer The chain to append buffers to be written too.
+ * @param sync_active If true this is a sync operation so expire all timers.
+ * @param update_timers If true update the timers.
+ * @param timer_delta It update_timers is true update the timers by this
+ *                    amount.
+ */
+static void
+rtems_bdbuf_swapout_modified_processing (dev_t*               dev,
+                                         rtems_chain_control* chain,
+                                         rtems_chain_control* transfer,
+                                         bool                 sync_active,
+                                         bool                 update_timers,
+                                         uint32_t             timer_delta)
+{
+  if (!rtems_chain_is_empty (chain))
+  {
+    rtems_chain_node* node = rtems_chain_head (chain);
+    node = node->next;
+
+    while (!rtems_chain_is_tail (chain, node))
+    {
+      rtems_bdbuf_buffer* bd = (rtems_bdbuf_buffer*) node;
+    
+      /*
+       * Check if the buffer's hold timer has reached 0. If a sync is active
+       * force all the timers to 0.
+       *
+       * @note Lots of sync requests will skew this timer. It should be based
+       *       on TOD to be accurate. Does it matter ?
+       */
+      if (sync_active)
+        bd->hold_timer = 0;
+  
+      if (bd->hold_timer)
+      {
+        if (update_timers)
+        {
+          if (bd->hold_timer > timer_delta)
+            bd->hold_timer -= timer_delta;
+          else
+            bd->hold_timer = 0;
+        }
+
+        if (bd->hold_timer)
+        {
+          node = node->next;
+          continue;
+        }
+      }
+
+      /*
+       * This assumes we can set dev_t to -1 which is just an
+       * assumption. Cannot use the transfer list being empty the sync dev
+       * calls sets the dev to use.
+       */
+      if (*dev == (dev_t)-1)
+        *dev = bd->dev;
+
+      if (bd->dev == *dev)
+      {
+        rtems_chain_node* next_node = node->next;
+        rtems_chain_node* tnode = rtems_chain_tail (transfer);
+    
+        /*
+         * The blocks on the transfer list are sorted in block order. This
+         * means multi-block transfers for drivers that require consecutive
+         * blocks perform better with sorted blocks and for real disks it may
+         * help lower head movement.
+         */
+
+        bd->state = RTEMS_BDBUF_STATE_TRANSFER;
+
+        rtems_chain_extract (node);
+
+        tnode = tnode->previous;
+          
+        while (node && !rtems_chain_is_head (transfer, tnode))
+        {
+          rtems_bdbuf_buffer* tbd = (rtems_bdbuf_buffer*) tnode;
+
+          if (bd->block > tbd->block)
+          {
+            rtems_chain_insert (tnode, node);
+            node = NULL;
+          }
+          else
+            tnode = tnode->previous;
+        }
+        
+        if (node)
+          rtems_chain_prepend (transfer, node);
+          
+        node = next_node;
+      }
+      else
+      {
+        node = node->next;
+      }
+    }
+  }
+}
+
+/**
+ * Process the cache's modified buffers. Check the sync list first then the
+ * modified list extracting the buffers suitable to be written to disk. We have
+ * a device at a time. The task level loop will repeat this operation while
+ * there are buffers to be written. If the transfer fails place the buffers
+ * back on the modified list and try again later. The cache is unlocked while
+ * the buffers are being written to disk.
+ *
+ * @param timer_delta It update_timers is true update the timers by this
+ *                    amount.
+ * @param update_timers If true update the timers.
+ * @param transfer The transfer transaction data.
+ *
+ * @retval true Buffers where written to disk so scan again.
+ * @retval false No buffers where written to disk.
+ */
+static bool
+rtems_bdbuf_swapout_processing (unsigned long                 timer_delta,
+                                bool                          update_timers,
+                                rtems_bdbuf_swapout_transfer* transfer)
+{
+  rtems_bdbuf_swapout_worker* worker;
+  bool                        transfered_buffers = false;
+
+  rtems_bdbuf_lock_cache ();
+
+  /*
+   * If a sync is active do not use a worker because the current code does not
+   * cleaning up after. We need to know the buffers have been written when
+   * syncing to release sync lock and currently worker threads do not return to
+   * here. We do not know the worker is the last in a sequence of sync writes
+   * until after we have it running so we do not know to tell it to release the
+   * lock. The simplest solution is to get the main swap out task perform all
+   * sync operations.
+   */
+  if (bdbuf_cache.sync_active)
+    worker = NULL;
+  else
+  {
+    worker = (rtems_bdbuf_swapout_worker*)
+      rtems_chain_get (&bdbuf_cache.swapout_workers);
+    if (worker)
+      transfer = &worker->transfer;
+  }
+  
+  rtems_chain_initialize_empty (&transfer->bds);
+  transfer->dev = -1;
+  
+  /*
+   * When the sync is for a device limit the sync to that device. If the sync
+   * is for a buffer handle process the devices in the order on the sync
+   * list. This means the dev is -1.
+   */
+  if (bdbuf_cache.sync_active)
+    transfer->dev = bdbuf_cache.sync_device;
+  
+  /*
+   * If we have any buffers in the sync queue move them to the modified
+   * list. The first sync buffer will select the device we use.
+   */
+  rtems_bdbuf_swapout_modified_processing (&transfer->dev,
+                                           &bdbuf_cache.sync,
+                                           &transfer->bds,
+                                           true, false,
+                                           timer_delta);
+
+  /*
+   * Process the cache's modified list.
+   */
+  rtems_bdbuf_swapout_modified_processing (&transfer->dev,
+                                           &bdbuf_cache.modified,
+                                           &transfer->bds,
+                                           bdbuf_cache.sync_active,
+                                           update_timers,
+                                           timer_delta);
+
+  /*
+   * We have all the buffers that have been modified for this device so the
+   * cache can be unlocked because the state of each buffer has been set to
+   * TRANSFER.
+   */
+  rtems_bdbuf_unlock_cache ();
+
+  /*
+   * If there are buffers to transfer to the media transfer them.
+   */
+  if (!rtems_chain_is_empty (&transfer->bds))
+  {
+    if (worker)
+    {
+      rtems_status_code sc = rtems_event_send (worker->id,
+                                               RTEMS_BDBUF_SWAPOUT_SYNC);
+      if (sc != RTEMS_SUCCESSFUL)
+        rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE);
+    }
+    else
+    {
+      rtems_bdbuf_swapout_write (transfer);
+    }
+    
+    transfered_buffers = true;
+  }
+   
+  if (bdbuf_cache.sync_active && !transfered_buffers)
+  {
+    rtems_id sync_requester;
+    rtems_bdbuf_lock_cache ();
+    sync_requester = bdbuf_cache.sync_requester;
+    bdbuf_cache.sync_active = false;
+    bdbuf_cache.sync_requester = 0;
+    rtems_bdbuf_unlock_cache ();
     if (sync_requester)
       rtems_event_send (sync_requester, RTEMS_BDBUF_TRANSFER_SYNC);
   }
   
-  return  transfered_buffers;
-}
-
-/**
- * Body of task which takes care on flushing modified buffers to the disk.
- *
- * @param arg The task argument which is the context.
- */
-static rtems_task
-rtems_bdbuf_swapout_task (rtems_task_argument arg)
-{
-  rtems_bdbuf_context*  context = (rtems_bdbuf_context*) arg;
-  rtems_blkdev_request* write_req;
-  uint32_t              period_in_ticks;
-  const uint32_t        period_in_msecs = rtems_bdbuf_configuration.swapout_period;
-  uint32_t              timer_delta;
-  rtems_status_code     sc;
-
+  return transfered_buffers;
+}
+
+/**
+ * Allocate the write request and initialise it for good measure.
+ *
+ * @return rtems_blkdev_request* The write reference memory.
+ */
+static rtems_blkdev_request*
+rtems_bdbuf_swapout_writereq_alloc (void)
+{
   /*
    * @note chrisj The rtems_blkdev_request and the array at the end is a hack.
@@ -2180,5 +2488,5 @@
    * is already part of the buffer structure.
    */
-  write_req =
+  rtems_blkdev_request* write_req =
     malloc (sizeof (rtems_blkdev_request) +
             (rtems_bdbuf_configuration.max_write_blocks *
@@ -2193,4 +2501,140 @@
   write_req->io_task = rtems_task_self ();
 
+  return write_req;
+}
+
+/**
+ * The swapout worker thread body.
+ *
+ * @param arg A pointer to the worker thread's private data.
+ * @return rtems_task Not used.
+ */
+static rtems_task
+rtems_bdbuf_swapout_worker_task (rtems_task_argument arg)
+{
+  rtems_bdbuf_swapout_worker* worker = (rtems_bdbuf_swapout_worker*) arg;
+
+  while (worker->enabled)
+  {
+    rtems_event_set   out;
+    rtems_status_code sc;
+    
+    sc = rtems_event_receive (RTEMS_BDBUF_SWAPOUT_SYNC,
+                              RTEMS_EVENT_ALL | RTEMS_WAIT,
+                              RTEMS_NO_TIMEOUT,
+                              &out);
+
+    if (sc != RTEMS_SUCCESSFUL)
+      rtems_fatal_error_occurred (BLKDEV_FATAL_BDBUF_SWAPOUT_RE);
+
+    rtems_bdbuf_swapout_write (&worker->transfer);
+
+    rtems_bdbuf_lock_cache ();
+
+    rtems_chain_initialize_empty (&worker->transfer.bds);
+    worker->transfer.dev = -1;
+
+    rtems_chain_append (&bdbuf_cache.swapout_workers, &worker->link);
+    
+    rtems_bdbuf_unlock_cache ();
+  }
+
+  free (worker->transfer.write_req);
+  free (worker);
+
+  rtems_task_delete (RTEMS_SELF);
+}
+
+/**
+ * Open the swapout worker threads.
+ */
+static void
+rtems_bdbuf_swapout_workers_open (void)
+{
+  rtems_status_code sc;
+  int               w;
+  
+  rtems_bdbuf_lock_cache ();
+  
+  for (w = 0; w < rtems_bdbuf_configuration.swapout_workers; w++)
+  {
+    rtems_bdbuf_swapout_worker* worker;
+
+    worker = malloc (sizeof (rtems_bdbuf_swapout_worker));
+    if (!worker)
+      rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM);
+
+    rtems_chain_append (&bdbuf_cache.swapout_workers, &worker->link);
+    worker->enabled = true;
+    worker->transfer.write_req = rtems_bdbuf_swapout_writereq_alloc ();
+    
+    rtems_chain_initialize_empty (&worker->transfer.bds);
+    worker->transfer.dev = -1;
+
+    sc = rtems_task_create (rtems_build_name('B', 'D', 'o', 'a' + w),
+                            (rtems_bdbuf_configuration.swapout_priority ?
+                             rtems_bdbuf_configuration.swapout_priority :
+                             RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT),
+                            SWAPOUT_TASK_STACK_SIZE,
+                            RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
+                            RTEMS_LOCAL | RTEMS_NO_FLOATING_POINT,
+                            &worker->id);
+    if (sc != RTEMS_SUCCESSFUL)
+      rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_CREATE);
+
+    sc = rtems_task_start (worker->id,
+                           rtems_bdbuf_swapout_worker_task,
+                           (rtems_task_argument) worker);
+    if (sc != RTEMS_SUCCESSFUL)
+      rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_START);
+  }
+  
+  rtems_bdbuf_unlock_cache ();
+}
+
+/**
+ * Close the swapout worker threads.
+ */
+static void
+rtems_bdbuf_swapout_workers_close (void)
+{
+  rtems_chain_node* node;
+  
+  rtems_bdbuf_lock_cache ();
+  
+  node = rtems_chain_first (&bdbuf_cache.swapout_workers);
+  while (!rtems_chain_is_tail (&bdbuf_cache.swapout_workers, node))
+  {
+    rtems_bdbuf_swapout_worker* worker = (rtems_bdbuf_swapout_worker*) node;
+    worker->enabled = false;
+    rtems_event_send (worker->id, RTEMS_BDBUF_SWAPOUT_SYNC);
+    node = rtems_chain_next (node);
+  }
+  
+  rtems_bdbuf_unlock_cache ();
+}
+
+/**
+ * Body of task which takes care on flushing modified buffers to the disk.
+ *
+ * @param arg A pointer to the global cache data. Use the global variable and
+ *            not this.
+ * @return rtems_task Not used.
+ */
+static rtems_task
+rtems_bdbuf_swapout_task (rtems_task_argument arg)
+{
+  rtems_bdbuf_swapout_transfer transfer;
+  uint32_t                     period_in_ticks;
+  const uint32_t               period_in_msecs = bdbuf_config.swapout_period;;
+  uint32_t                     timer_delta;
+
+  transfer.write_req = rtems_bdbuf_swapout_writereq_alloc ();
+  rtems_chain_initialize_empty (&transfer.bds);
+  transfer.dev = -1;
+
+  /*
+   * Localise the period.
+   */
   period_in_ticks = RTEMS_MICROSECONDS_TO_TICKS (period_in_msecs * 1000);
 
@@ -2200,7 +2644,13 @@
   timer_delta = period_in_msecs;
 
-  while (context->swapout_enabled)
-  {
-    rtems_event_set out;
+  /*
+   * Create the worker threads.
+   */
+  rtems_bdbuf_swapout_workers_open ();
+  
+  while (bdbuf_cache.swapout_enabled)
+  {
+    rtems_event_set   out;
+    rtems_status_code sc;
 
     /*
@@ -2211,5 +2661,5 @@
     /*
      * If we write buffers to any disk perform a check again. We only write a
-     * single device at a time and a pool may have more than one devices
+     * single device at a time and the cache may have more than one device's
      * buffers modified waiting to be written.
      */
@@ -2218,24 +2668,18 @@
     do
     {
-      rtems_bdpool_id pid;
-    
       transfered_buffers = false;
 
       /*
-       * Loop over each pool extacting all the buffers we find for a specific
-       * device. The device is the first one we find on a modified list of a
-       * pool. Process the sync queue of buffers first.
+       * Extact all the buffers we find for a specific device. The device is
+       * the first one we find on a modified list. Process the sync queue of
+       * buffers first.
        */
-      for (pid = 0; pid < context->npools; pid++)
+      if (rtems_bdbuf_swapout_processing (timer_delta,
+                                          update_timers,
+                                          &transfer))
       {
-        if (rtems_bdbuf_swapout_pool_processing (pid,
-                                                 timer_delta,
-                                                 update_timers,
-                                                 write_req))
-        {
-          transfered_buffers = true;
-        }
+        transfered_buffers = true;
       }
-
+      
       /*
        * Only update the timers once.
@@ -2254,66 +2698,9 @@
   }
 
-  free (write_req);
+  rtems_bdbuf_swapout_workers_close ();
+  
+  free (transfer.write_req);
 
   rtems_task_delete (RTEMS_SELF);
 }
 
-rtems_status_code
-rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool)
-{
-  rtems_bdbuf_pool* p;
-  rtems_bdpool_id   i;
-  rtems_bdpool_id   curid = -1;
-  bool              found = false;
-  uint32_t          cursize = UINT_MAX;
-  int               j;
-
-  for (j = block_size; (j != 0) && ((j & 1) == 0); j >>= 1);
-  if (j != 1)
-    return RTEMS_INVALID_SIZE;
-
-  for (i = 0; i < rtems_bdbuf_ctx.npools; i++)
-  {
-    p = rtems_bdbuf_get_pool (i);
-    if ((p->blksize >= block_size) &&
-        (p->blksize < cursize))
-    {
-      curid = i;
-      cursize = p->blksize;
-      found = true;
-    }
-  }
-
-  if (found)
-  {
-    if (pool != NULL)
-      *pool = curid;
-    return RTEMS_SUCCESSFUL;
-  }
-  else
-  {
-    return RTEMS_NOT_DEFINED;
-  }
-}
-
-rtems_status_code rtems_bdbuf_get_pool_info(
-  rtems_bdpool_id pool,
-  uint32_t *block_size,
-  uint32_t *blocks
-)
-{
-  if (pool >= rtems_bdbuf_ctx.npools)
-    return RTEMS_INVALID_NUMBER;
-
-  if (block_size != NULL)
-  {
-    *block_size = rtems_bdbuf_ctx.pool[pool].blksize;
-  }
-
-  if (blocks != NULL)
-  {
-    *blocks = rtems_bdbuf_ctx.pool[pool].nblks;
-  }
-
-  return RTEMS_SUCCESSFUL;
-}
Index: cpukit/libblock/src/blkdev.c
===================================================================
--- cpukit/libblock/src/blkdev.c	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/libblock/src/blkdev.c	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -38,5 +38,4 @@
 {
     rtems_libio_rw_args_t *args = arg;
-    int block_size_log2;
     int block_size;
     char         *buf;
@@ -52,5 +51,4 @@
         return RTEMS_INVALID_NUMBER;
 
-    block_size_log2 = dd->block_size_log2;
     block_size = dd->block_size;
 
@@ -59,6 +57,6 @@
     args->bytes_moved = 0;
 
-    block = args->offset >> block_size_log2;
-    blkofs = args->offset & (block_size - 1);
+    block = args->offset / block_size;
+    blkofs = args->offset % block_size;
 
     while (count > 0)
@@ -98,5 +96,4 @@
 {
     rtems_libio_rw_args_t *args = arg;
-    int           block_size_log2;
     uint32_t      block_size;
     char         *buf;
@@ -113,5 +110,4 @@
         return RTEMS_INVALID_NUMBER;
 
-    block_size_log2 = dd->block_size_log2;
     block_size = dd->block_size;
 
@@ -120,6 +116,6 @@
     args->bytes_moved = 0;
 
-    block = args->offset >> block_size_log2;
-    blkofs = args->offset & (block_size - 1);
+    block = args->offset / block_size;
+    blkofs = args->offset % block_size;
 
     while (count > 0)
Index: cpukit/libblock/src/diskdevs.c
===================================================================
--- cpukit/libblock/src/diskdevs.c	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/libblock/src/diskdevs.c	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -227,18 +227,10 @@
 )
 {
-    int bs_log2;
-    int i;
     rtems_disk_device *dd;
     rtems_status_code rc;
-    rtems_bdpool_id pool;
     rtems_device_major_number major;
     rtems_device_minor_number minor;
 
     rtems_filesystem_split_dev_t (dev, major, minor);
-
-
-    for (bs_log2 = 0, i = block_size; (i & 1) == 0; i >>= 1, bs_log2++);
-    if ((bs_log2 < 9) || (i != 1)) /* block size < 512 or not power of 2 */
-        return RTEMS_INVALID_NUMBER;
 
     rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
@@ -247,12 +239,4 @@
     diskdevs_protected = true;
 
-    rc = rtems_bdbuf_find_pool(block_size, &pool);
-    if (rc != RTEMS_SUCCESSFUL)
-    {
-        diskdevs_protected = false;
-        rtems_semaphore_release(diskdevs_mutex);
-        return rc;
-    }
-
     rc = create_disk(dev, name, &dd);
     if (rc != RTEMS_SUCCESSFUL)
@@ -267,8 +251,6 @@
     dd->start = 0;
     dd->size = disk_size;
-    dd->block_size = block_size;
-    dd->block_size_log2 = bs_log2;
+    dd->block_size = dd->media_block_size = block_size;
     dd->ioctl = handler;
-    dd->pool = pool;
 
     rc = rtems_io_register_name(name, major, minor);
@@ -334,5 +316,4 @@
   dd->size = size;
   dd->block_size = pdd->block_size;
-  dd->block_size_log2 = pdd->block_size_log2;
   dd->ioctl = pdd->ioctl;
 
@@ -556,5 +537,4 @@
     rc = rtems_semaphore_delete(diskdevs_mutex);
 
-    /* XXX bdbuf should be released too! */
     disk_io_initialized = 0;
     return rc;
Index: cpukit/libmisc/Makefile.am
===================================================================
--- cpukit/libmisc/Makefile.am	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/libmisc/Makefile.am	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -32,5 +32,5 @@
 
 noinst_LIBRARIES += libdummy.a
-libdummy_a_SOURCES = dummy/dummy.c
+libdummy_a_SOURCES = dummy/dummy.c dummy/dummy-networking.c
 
 ## dumpbuf
Index: cpukit/libmisc/dummy/dummy-networking.c
===================================================================
--- cpukit/libmisc/dummy/dummy-networking.c	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
+++ cpukit/libmisc/dummy/dummy-networking.c	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -0,0 +1,58 @@
+/*
+ *  Dummy configuration file
+ *
+ *  COPYRIGHT (c) 1989-2008.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  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$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+/* Loopback Network Configuration */
+#if defined(RTEMS_NETWORKING)
+  #include <rtems/rtems_bsdnet.h>
+  #include <sys/socket.h>
+  #include <netinet/in.h>
+
+  extern int rtems_bsdnet_loopattach(struct rtems_bsdnet_ifconfig *, int);
+
+  static struct rtems_bsdnet_ifconfig loopback_config = {
+      "lo0",                     /* name */
+      rtems_bsdnet_loopattach,   /* attach function */
+      NULL,                      /* link to next interface */
+      "127.0.0.1",               /* IP address */
+      "255.0.0.0",               /* IP net mask */
+      0,                         /* hardware_address */
+      0, 0, 0, 0,
+      0, 0, 0,
+      0
+  };
+
+  struct rtems_bsdnet_config rtems_bsdnet_config = {
+      &loopback_config,       /* Network interface */
+      NULL,                   /* Use fixed network configuration */
+      0,                      /* Default network task priority */
+      0,                      /* Default mbuf capacity */
+      0,                      /* Default mbuf cluster capacity */
+      "testSystem",           /* Host name */
+      "nowhere.com",          /* Domain name */
+      "127.0.0.1",            /* Gateway */
+      "127.0.0.1",            /* Log host */
+      {"127.0.0.1" },         /* Name server(s) */
+      {"127.0.0.1" },         /* NTP server(s) */
+      1,                      /* sb_efficiency */
+      0,                      /* udp_tx_buf_size */
+      0,                      /* udp_rx_buf_size */
+      0,                      /* tcp_tx_buf_size */
+      0                       /* tcp_rx_buf_size */
+  };
+#endif
Index: cpukit/libmisc/dummy/dummy.c
===================================================================
--- cpukit/libmisc/dummy/dummy.c	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/libmisc/dummy/dummy.c	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -37,42 +37,2 @@
 #include <rtems/confdefs.h>
 
-/* Loopback Network Configuration */
-#if defined(RTEMS_NETWORKING)
-  #include <rtems/rtems_bsdnet.h>
-  #include <sys/socket.h>
-  #include <netinet/in.h>
-
-  extern int rtems_bsdnet_loopattach(struct rtems_bsdnet_ifconfig *, int);
-
-  static struct rtems_bsdnet_ifconfig loopback_config = {
-      "lo0",                     /* name */
-      rtems_bsdnet_loopattach,   /* attach function */
-      NULL,                      /* link to next interface */
-      "127.0.0.1",               /* IP address */
-      "255.0.0.0",               /* IP net mask */
-      0,                         /* hardware_address */
-      0, 0, 0, 0,
-      0, 0, 0,
-      0
-  };
-
-  struct rtems_bsdnet_config rtems_bsdnet_config = {
-      &loopback_config,       /* Network interface */
-      NULL,                   /* Use fixed network configuration */
-      0,                      /* Default network task priority */
-      0,                      /* Default mbuf capacity */
-      0,                      /* Default mbuf cluster capacity */
-      "testSystem",           /* Host name */
-      "nowhere.com",          /* Domain name */
-      "127.0.0.1",            /* Gateway */
-      "127.0.0.1",            /* Log host */
-      {"127.0.0.1" },         /* Name server(s) */
-      {"127.0.0.1" },         /* NTP server(s) */
-      1,                      /* sb_efficiency */
-      0,                      /* udp_tx_buf_size */
-      0,                      /* udp_rx_buf_size */
-      0,                      /* tcp_tx_buf_size */
-      0                       /* tcp_rx_buf_size */
-  };
-#endif
-
Index: cpukit/sapi/include/confdefs.h
===================================================================
--- cpukit/sapi/include/confdefs.h	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/sapi/include/confdefs.h	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -728,30 +728,43 @@
                               RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT
   #endif
+  #ifndef CONFIGURE_SWAPOUT_WORKER_TASKS
+    #define CONFIGURE_SWAPOUT_WORKER_TASKS \
+                              RTEMS_BDBUF_SWAPOUT_WORKER_TASKS_DEFAULT
+  #endif
+  #ifndef CONFIGURE_SWAPOUT_WORKER_TASK_PRIORITY
+    #define CONFIGURE_SWAPOUT_WORKER_TASK_PRIORITY \
+                              RTEMS_BDBUF_SWAPOUT_WORKER_TASK_PRIORITY_DEFAULT
+  #endif
+  #ifndef CONFIGURE_BDBUF_CACHE_MEMORY_SIZE
+    #define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE \
+                              RTEMS_BDBUF_CACHE_MEMORY_SIZE_DEFAULT
+  #endif
+  #ifndef CONFIGURE_BDBUF_BUFFER_MIN_SIZE
+    #define CONFIGURE_BDBUF_BUFFER_MIN_SIZE \
+                              RTEMS_BDBUF_BUFFER_MIN_SIZE_DEFAULT
+  #endif
+  #ifndef CONFIGURE_BDBUF_BUFFER_MAX_SIZE
+    #define CONFIGURE_BDBUF_BUFFER_MAX_SIZE \
+                              RTEMS_BDBUF_BUFFER_MAX_SIZE_DEFAULT
+  #endif
   #ifdef CONFIGURE_INIT
-    rtems_bdbuf_config rtems_bdbuf_configuration = { 
+    const rtems_bdbuf_config rtems_bdbuf_configuration = { 
       CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS,
       CONFIGURE_BDBUF_MAX_WRITE_BLOCKS,
       CONFIGURE_SWAPOUT_TASK_PRIORITY,
       CONFIGURE_SWAPOUT_SWAP_PERIOD,
-      CONFIGURE_SWAPOUT_BLOCK_HOLD
+      CONFIGURE_SWAPOUT_BLOCK_HOLD,
+      CONFIGURE_SWAPOUT_WORKER_TASKS,
+      CONFIGURE_SWAPOUT_WORKER_TASK_PRIORITY,
+      CONFIGURE_BDBUF_CACHE_MEMORY_SIZE,
+      CONFIGURE_BDBUF_BUFFER_MIN_SIZE,
+      CONFIGURE_BDBUF_BUFFER_MAX_SIZE
     };
   #endif
-  #ifndef CONFIGURE_HAS_OWN_BDBUF_TABLE
-    #ifndef CONFIGURE_BDBUF_BUFFER_COUNT
-      #define CONFIGURE_BDBUF_BUFFER_COUNT 64
-    #endif
-
-    #ifndef CONFIGURE_BDBUF_BUFFER_SIZE
-      #define CONFIGURE_BDBUF_BUFFER_SIZE 512
-    #endif
-    #ifdef CONFIGURE_INIT
-      rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[] = {
-        {CONFIGURE_BDBUF_BUFFER_SIZE, CONFIGURE_BDBUF_BUFFER_COUNT, NULL}
-      };
-      size_t rtems_bdbuf_pool_configuration_size = 
-        (sizeof(rtems_bdbuf_pool_configuration) /
-         sizeof(rtems_bdbuf_pool_configuration[0]));
-    #endif /* CONFIGURE_INIT */
-  #endif /* CONFIGURE_HAS_OWN_BDBUF_TABLE        */
+  #if defined(CONFIGURE_HAS_OWN_BDBUF_TABLE) || \
+      defined(CONFIGURE_BDBUF_BUFFER_SIZE) || \
+      defined(CONFIGURE_BDBUF_BUFFER_COUNT)
+    #error BDBUF Cache does not use a buffer configuration table. Please remove.
+  #endif
 #endif /* CONFIGURE_APPLICATION_NEEDS_LIBBLOCK */
 
Index: cpukit/sapi/inline/rtems/chain.inl
===================================================================
--- cpukit/sapi/inline/rtems/chain.inl	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/sapi/inline/rtems/chain.inl	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -97,5 +97,5 @@
  *  @param[in] the_chain is the chain to be operated upon.
  *
- *  @return This method returns the permanent head node of the chain.
+ *  @return This method returns the permanent  node of the chain.
  */
 RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_head(
@@ -120,4 +120,54 @@
 {
   return _Chain_Tail( the_chain );
+}
+
+/**
+ *  @brief Return pointer to Chain's First node after the permanent head.
+ *
+ *  This function returns a pointer to the first node on the chain after the
+ *  head.
+ *
+ *  @param[in] the_chain is the chain to be operated upon.
+ *
+ *  @return This method returns the first node of the chain.
+ */
+RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_first(
+  rtems_chain_control *the_chain
+)
+{
+  return _Chain_First( the_chain );
+}
+
+/**
+ *  @brief Return pointer to Chain's Last node before the permanent tail.
+ *
+ *  This function returns a pointer to the last node on the chain just before
+ *  the tail.
+ *
+ *  @param[in] the_chain is the chain to be operated upon.
+ *
+ *  @return This method returns the last node of the chain.
+ */
+RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_last(
+  rtems_chain_control *the_chain
+)
+{
+  return _Chain_Last( the_chain );
+}
+
+/**
+ *  @brief Return pointer the next node from this node
+ *
+ *  This function returns a pointer to the next node after this node.
+ *
+ *  @param[in] the_node is the node to be operated upon.
+ *
+ *  @return This method returns the next node on the chain.
+ */
+RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_next(
+  rtems_chain_node *the_node
+)
+{
+  return _Chain_Next( the_node );
 }
 
Index: cpukit/score/include/rtems/score/object.h
===================================================================
--- cpukit/score/include/rtems/score/object.h	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/score/include/rtems/score/object.h	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -74,18 +74,18 @@
 typedef uint8_t    Objects_Maximum;
 
-#define OBJECTS_INDEX_START_BIT  0
-#define OBJECTS_API_START_BIT    8
-#define OBJECTS_CLASS_START_BIT 11
-
-#define OBJECTS_INDEX_MASK      (Objects_Id)0x00ff
-#define OBJECTS_API_MASK        (Objects_Id)0x0700
-#define OBJECTS_CLASS_MASK      (Objects_Id)0xF800
-
-#define OBJECTS_INDEX_VALID_BITS  (Objects_Id)0x00ff
-#define OBJECTS_API_VALID_BITS    (Objects_Id)0x0007
+#define OBJECTS_INDEX_START_BIT  0U
+#define OBJECTS_API_START_BIT    8U
+#define OBJECTS_CLASS_START_BIT 11U
+
+#define OBJECTS_INDEX_MASK      (Objects_Id)0x00ffU
+#define OBJECTS_API_MASK        (Objects_Id)0x0700U
+#define OBJECTS_CLASS_MASK      (Objects_Id)0xF800U
+
+#define OBJECTS_INDEX_VALID_BITS  (Objects_Id)0x00ffU
+#define OBJECTS_API_VALID_BITS    (Objects_Id)0x0007U
 /* OBJECTS_NODE_VALID_BITS should not be used with 16 bit Ids */
-#define OBJECTS_CLASS_VALID_BITS  (Objects_Id)0x001f
-
-#define OBJECTS_UNLIMITED_OBJECTS 0x8000
+#define OBJECTS_CLASS_VALID_BITS  (Objects_Id)0x001fU
+
+#define OBJECTS_UNLIMITED_OBJECTS 0x8000U
 
 #define OBJECTS_ID_INITIAL_INDEX  (0)
@@ -114,5 +114,5 @@
  *  the object Id.
  */
-#define OBJECTS_INDEX_START_BIT  0
+#define OBJECTS_INDEX_START_BIT  0U
 
 
@@ -121,5 +121,5 @@
  *  the object Id.
  */
-#define OBJECTS_NODE_START_BIT  16
+#define OBJECTS_NODE_START_BIT  16U
 
 /**
@@ -127,5 +127,5 @@
  *  the object Id.
  */
-#define OBJECTS_API_START_BIT   24
+#define OBJECTS_API_START_BIT   24U
 
 /**
@@ -133,25 +133,25 @@
  *  the object Id.
  */
-#define OBJECTS_CLASS_START_BIT 27
+#define OBJECTS_CLASS_START_BIT 27U
 
 /**
  *  This mask is used to extract the index portion of an object Id.
  */
-#define OBJECTS_INDEX_MASK      (Objects_Id)0x0000ffff
+#define OBJECTS_INDEX_MASK      (Objects_Id)0x0000ffffU
 
 /**
  *  This mask is used to extract the node portion of an object Id.
  */
-#define OBJECTS_NODE_MASK       (Objects_Id)0x00ff0000
+#define OBJECTS_NODE_MASK       (Objects_Id)0x00ff0000U
 
 /**
  *  This mask is used to extract the API portion of an object Id.
  */
-#define OBJECTS_API_MASK        (Objects_Id)0x07000000
+#define OBJECTS_API_MASK        (Objects_Id)0x07000000U
 
 /**
  *  This mask is used to extract the class portion of an object Id.
  */
-#define OBJECTS_CLASS_MASK      (Objects_Id)0xf8000000
+#define OBJECTS_CLASS_MASK      (Objects_Id)0xf8000000U
 
 /**
@@ -159,5 +159,5 @@
  *  are set after shifting to extract the index portion of an object Id.
  */
-#define OBJECTS_INDEX_VALID_BITS  (Objects_Id)0x0000ffff
+#define OBJECTS_INDEX_VALID_BITS  (Objects_Id)0x0000ffffU
 
 /**
@@ -165,5 +165,5 @@
  *  are set after shifting to extract the node portion of an object Id.
  */
-#define OBJECTS_NODE_VALID_BITS   (Objects_Id)0x000000ff
+#define OBJECTS_NODE_VALID_BITS   (Objects_Id)0x000000ffU
 
 /**
@@ -171,5 +171,5 @@
  *  are set after shifting to extract the API portion of an object Id.
  */
-#define OBJECTS_API_VALID_BITS    (Objects_Id)0x00000007
+#define OBJECTS_API_VALID_BITS    (Objects_Id)0x00000007U
 
 /**
@@ -177,5 +177,5 @@
  *  are set after shifting to extract the class portion of an object Id.
  */
-#define OBJECTS_CLASS_VALID_BITS  (Objects_Id)0x0000001f
+#define OBJECTS_CLASS_VALID_BITS  (Objects_Id)0x0000001fU
 
 /**
@@ -183,5 +183,5 @@
  *  table when specifying the number of configured objects.
  */
-#define OBJECTS_UNLIMITED_OBJECTS 0x80000000
+#define OBJECTS_UNLIMITED_OBJECTS 0x80000000U
 
 /**
@@ -193,5 +193,5 @@
  *  This is the highest value for the index portion of an object Id.
  */
-#define OBJECTS_ID_FINAL_INDEX    (0xffff)
+#define OBJECTS_ID_FINAL_INDEX    (0xffffU)
 #endif
 
@@ -337,5 +337,5 @@
   bool              auto_extend;
   /** This is the number of objects in a block. */
-  uint32_t          allocation_size;
+  Objects_Maximum   allocation_size;
   /** This is the size in bytes of each object instance. */
   size_t            size;
Index: cpukit/score/inline/rtems/score/chain.inl
===================================================================
--- cpukit/score/inline/rtems/score/chain.inl	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/score/inline/rtems/score/chain.inl	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -84,5 +84,5 @@
 /** @brief Return pointer to Chain Head
  *
- *  This function returns a pointer to the first node on the chain.
+ *  This function returns a pointer to the head node on the chain.
  *
  *  @param[in] the_chain is the chain to be operated upon.
@@ -110,4 +110,66 @@
 {
    return (Chain_Node *) &the_chain->permanent_null;
+}
+
+/** @brief Return pointer to Chain's First node
+ *
+ *  This function returns a pointer to the first node on the chain after the
+ *  head.
+ *
+ *  @param[in] the_chain is the chain to be operated upon.
+ *
+ *  @return This method returns the first node of the chain.
+ */
+RTEMS_INLINE_ROUTINE Chain_Node *_Chain_First(
+  Chain_Control *the_chain
+)
+{
+  return the_chain->first;
+}
+
+/** @brief Return pointer to Chain's Last node
+ *
+ *  This function returns a pointer to the last node on the chain just before
+ *  the tail.
+ *
+ *  @param[in] the_chain is the chain to be operated upon.
+ *
+ *  @return This method returns the last node of the chain.
+ */
+RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Last(
+  Chain_Control *the_chain
+)
+{
+  return the_chain->last;
+}
+
+/** @brief Return pointer the next node from this node
+ *
+ *  This function returns a pointer to the next node after this node.
+ *
+ *  @param[in] the_node is the node to be operated upon.
+ *
+ *  @return This method returns the next node on the chain.
+ */
+RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Next(
+  Chain_Node *the_node
+)
+{
+  return the_node->next;
+}
+
+/** @brief Return pointer the previous node from this node
+ *
+ *  This function returns a pointer to the previous node on this chain.
+ *
+ *  @param[in] the_node is the node to be operated upon.
+ *
+ *  @return This method returns the previous node on the chain.
+ */
+RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Previous(
+  Chain_Node *the_node
+)
+{
+  return the_node->previous;
 }
 
Index: cpukit/score/inline/rtems/score/object.inl
===================================================================
--- cpukit/score/inline/rtems/score/object.inl	(revision f14a21df691328cefa1464fc5ef13c0584bbfaf3)
+++ cpukit/score/inline/rtems/score/object.inl	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
@@ -112,5 +112,7 @@
 )
 {
-  return (id >> OBJECTS_INDEX_START_BIT) & OBJECTS_INDEX_VALID_BITS;
+  return
+    (Objects_Maximum)((id >> OBJECTS_INDEX_START_BIT) &
+                                          OBJECTS_INDEX_VALID_BITS);
 }
 
@@ -225,5 +227,5 @@
 RTEMS_INLINE_ROUTINE void _Objects_Set_local_object(
   Objects_Information *information,
-  uint16_t             index,
+  uint32_t             index,
   Objects_Control     *the_object
 )
