Add unbuffered methods for accessing a KBlock.
authorbatt <batt@38d2e660-2303-0410-9eaa-f027e97ec537>
Sat, 3 Jul 2010 12:31:04 +0000 (12:31 +0000)
committerbatt <batt@38d2e660-2303-0410-9eaa-f027e97ec537>
Sat, 3 Jul 2010 12:31:04 +0000 (12:31 +0000)
Since some modules which will use KBlock use an
internal buffer, the buffered API supplied by KBlock
may be redundant.

Specifically, if a module (like the FatFS) has its
own internal block buffer, the buffer inside the KBlock
would be wasted.
In order to avoid this waste of RAM, this patch adds
an unbuffered and simplified version of the API.

All KBlocks will implement this unbuffered API, and
they will give the user the option of adding a software
emulated buffer at init time. In this way we can have both
APIs with no RAM wasting.

In order to simplify KBlock implementors' job, a series of
generic functions is supplied. If the device supports
only a few functions of the KBlock low level API, the missing
ones may be generated using the generic ones.

git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3991 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/io/kblock.c
bertos/io/kblock.h

index 65f427903a11ba018e92acbd1d2a2600bf57e8e1..fb70ef941083e9c3d87517b28ed1e880903b5b08 100644 (file)
 #define LOG_FORMAT LOG_FMT_VERBOSE
 
 #include <cfg/log.h>
+#include <string.h>
 
 INLINE size_t kblock_readDirect(struct KBlock *b, block_idx_t index, void *buf, size_t offset, size_t size)
 {
        KB_ASSERT_METHOD(b, readDirect);
+       ASSERT(index < b->blk_cnt);
        return b->priv.vt->readDirect(b, b->priv.blk_start + index, buf, offset, size);
 }
 
@@ -134,6 +136,7 @@ size_t kblock_write(struct KBlock *b, block_idx_t idx, const void *buf, size_t o
 {
        ASSERT(b);
        ASSERT(buf);
+       ASSERT(idx < b->blk_cnt);
        ASSERT(offset + size <= b->blk_size);
 
        LOG_INFO("blk_idx %d, offset %d, size %d\n", idx, offset, size);
@@ -148,6 +151,8 @@ size_t kblock_write(struct KBlock *b, block_idx_t idx, const void *buf, size_t o
 int kblock_copy(struct KBlock *b, block_idx_t idx1, block_idx_t idx2)
 {
        ASSERT(b);
+       ASSERT(idx1 < b->blk_cnt);
+       ASSERT(idx2 < b->blk_cnt);
 
        if (!kblock_loadPage(b, idx1))
                return EOF;
@@ -157,3 +162,50 @@ int kblock_copy(struct KBlock *b, block_idx_t idx1, block_idx_t idx2)
        return 0;
 }
 
+int kblock_swWriteBlock(struct KBlock *b, block_idx_t index, const void *buf)
+{
+       return (kblock_write(b, index, buf, 0, b->blk_size) == b->blk_size) ? 0 : EOF;
+}
+
+int kblock_swReadBlock(struct KBlock *b, block_idx_t index, void *buf)
+{
+       return (kblock_read(b, index, buf, 0, b->blk_size) == b->blk_size) ? 0 : EOF;
+}
+
+int kblock_swLoad(struct KBlock *b, block_idx_t index)
+{
+       return kblock_readBlock(b, index, b->priv.buf);
+}
+
+int kblock_swStore(struct KBlock *b, block_idx_t index)
+{
+       return kblock_writeBlock(b, index, b->priv.buf);
+}
+
+size_t kblock_swReadBuf(struct KBlock *b, void *buf, size_t offset, size_t size)
+{
+       ASSERT(buf);
+       ASSERT(offset + size <= b->blk_size);
+       
+       memcpy(buf, (uint8_t *)b->priv.buf + offset, size);
+       return size;
+}
+
+size_t kblock_swWriteBuf(struct KBlock *b, const void *buf, size_t offset, size_t size)
+{
+       ASSERT(buf);
+       ASSERT(offset + size <= b->blk_size);
+       memcpy((uint8_t *)b->priv.buf + offset, buf, size);
+       return size;
+}
+
+size_t kblock_swReadDirect(struct KBlock *b, block_idx_t index, void *buf, size_t offset, size_t size)
+{
+       ASSERT(buf);
+       ASSERT(index < b->blk_cnt);
+       
+       if (!kblock_loadPage(b, index))
+               return 0;
+               
+       return kblock_swReadBuf(b, buf, offset, size);
+}
\ No newline at end of file
index 4dffe18b198ed96d9c5bd3e7d747cdba10c7682b..abc0fcb28e0de43e29bef346a56465a3d555c073 100644 (file)
@@ -61,6 +61,10 @@ typedef size_t (* kblock_read_t)        (struct KBlock *b, void *buf, size_t off
 typedef size_t (* kblock_write_t)       (struct KBlock *b, const void *buf, size_t offset, size_t size);
 typedef int    (* kblock_load_t)        (struct KBlock *b, block_idx_t index);
 typedef int    (* kblock_store_t)       (struct KBlock *b, block_idx_t index);
+
+typedef int    (* kblock_write_block_t) (struct KBlock *b, block_idx_t index, const void *buf);
+typedef int    (* kblock_read_block_t)  (struct KBlock *b, block_idx_t index, void *buf);
+
 typedef int    (* kblock_error_t)       (struct KBlock *b);
 typedef int    (* kblock_clearerr_t)    (struct KBlock *b);
 typedef int    (* kblock_close_t)       (struct KBlock *b);
@@ -72,11 +76,15 @@ typedef int    (* kblock_close_t)       (struct KBlock *b);
 typedef struct KBlockVTable
 {
        kblock_read_direct_t readDirect;
-    kblock_read_t  readBuf;
+
+       kblock_read_t  readBuf;
        kblock_write_t writeBuf;
        kblock_load_t  load;
        kblock_store_t store;
-
+       
+       kblock_read_block_t readBlock;
+       kblock_write_block_t writeBlock;
+       
        kblock_error_t    error;    ///< \sa kblock_error()
        kblock_clearerr_t clearerr; ///< \sa kblock_clearerr()
 
@@ -84,6 +92,8 @@ typedef struct KBlockVTable
 } KBlockVTable;
 
 
+#define KB_BUFFERED BV(0)
+
 /**
  * KBlock private members.
  * These are the private members of the KBlock class, please do not
@@ -93,11 +103,12 @@ typedef struct KBlockPriv
 {
        DB(id_t type);         ///< Used to keep track, at runtime, of the class type.
        int flags;             ///< Status and error flags.
+       void *buf;
        block_idx_t blk_start; ///< Start block number when the device is trimmed. \sa kblock_trim()
        block_idx_t curr_blk;
        bool cache_dirty;
 
-       struct KBlockVTable *vt; ///< Virtual table of interface functions.
+       const struct KBlockVTable *vt; ///< Virtual table of interface functions.
 } KBlockPriv;
 
 /**
@@ -215,6 +226,31 @@ INLINE int kblock_close(struct KBlock *b)
        return b->priv.vt->close(b);
 }
 
+INLINE int kblock_writeBlock(struct KBlock *b, block_idx_t index, const void *buf)
+{
+       KB_ASSERT_METHOD(b, writeBlock);
+       ASSERT(index < b->blk_cnt);
+       return b->priv.vt->writeBlock(b, b->priv.blk_start + index, buf);
+}
+
+INLINE int kblock_readBlock(struct KBlock *b, block_idx_t index, void *buf)
+{
+       KB_ASSERT_METHOD(b, readDirect);
+       ASSERT(index < b->blk_cnt);
+       return b->priv.vt->readBlock(b, b->priv.blk_start + index, buf);
+}
+
+INLINE block_idx_t kblock_cachedBlock(struct KBlock *b)
+{
+       return b->priv.curr_blk;
+}
+
+INLINE bool kblock_buffered(struct KBlock *b)
+{
+       ASSERT(b);
+       return (b->priv.flags & KB_BUFFERED);
+}
+
 size_t kblock_read(struct KBlock *b, block_idx_t idx, void *buf, size_t offset, size_t size);
 
 int kblock_flush(struct KBlock *b);
@@ -223,4 +259,14 @@ size_t kblock_write(struct KBlock *b, block_idx_t idx, const void *buf, size_t o
 
 int kblock_copy(struct KBlock *b, block_idx_t idx1, block_idx_t idx2);
 
+
+int kblock_swWriteBlock(struct KBlock *b, block_idx_t index, const void *buf);
+int kblock_swReadBlock(struct KBlock *b, block_idx_t index, void *buf);
+
+size_t kblock_swReadDirect(struct KBlock *b, block_idx_t index, void *buf, size_t offset, size_t size);
+int kblock_swLoad(struct KBlock *b, block_idx_t index);
+int kblock_swStore(struct KBlock *b, block_idx_t index);
+size_t kblock_swReadBuf(struct KBlock *b, void *buf, size_t offset, size_t size);
+size_t kblock_swWriteBuf(struct KBlock *b, const void *buf, size_t offset, size_t size);
+
 #endif /* IO_KBLOCK_H */