diff options
Diffstat (limited to 'ecos/packages/services/blib/current')
| -rw-r--r-- | ecos/packages/services/blib/current/ChangeLog | 49 | ||||
| -rw-r--r-- | ecos/packages/services/blib/current/cdl/blib.cdl | 71 | ||||
| -rw-r--r-- | ecos/packages/services/blib/current/include/blib.h | 308 | ||||
| -rw-r--r-- | ecos/packages/services/blib/current/src/blib.c | 665 |
4 files changed, 1093 insertions, 0 deletions
diff --git a/ecos/packages/services/blib/current/ChangeLog b/ecos/packages/services/blib/current/ChangeLog new file mode 100644 index 0000000..ba22370 --- /dev/null +++ b/ecos/packages/services/blib/current/ChangeLog @@ -0,0 +1,49 @@ +2005-07-30 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/blib.c: made the types consistent to fix compiler warnings. + +2004-08-09 Savin Zlobec <savin@elatec.si> + + * inc/blib.h: + Extended the API with cyg_blib_get_block_size and + cyg_blib_get_block_size_log2 functions. + +2004-06-28 Savin Zlobec <savin@elatec.si> + + * inc/blib.h: + * src/blib.c: + Implemented block memory pool without using the cyg_mempool_fix_* + API - blib is now free of kernel dependencies. + +2003-09-01 Savin Zlobec <savin@elatec.si> + + * cdl/blib.cdl: + * inc/blib.h: + * src/blib.c: + A block access and cache library. + + + +//=========================================================================== +// ####GPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 or (at your option) any +// later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., 51 Franklin Street, +// Fifth Floor, Boston, MA 02110-1301, USA. +// ------------------------------------------- +// ####GPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/ecos/packages/services/blib/current/cdl/blib.cdl b/ecos/packages/services/blib/current/cdl/blib.cdl new file mode 100644 index 0000000..fbf366b --- /dev/null +++ b/ecos/packages/services/blib/current/cdl/blib.cdl @@ -0,0 +1,71 @@ +# ==================================================================== +# +# blib.cdl +# +# Block cache and access library configuration data +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2003 Free Software Foundation, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later +## version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License +## along with eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): savin +# Contributors: +# Date: 2003-08-29 +# +#####DESCRIPTIONEND#### +# ==================================================================== + +cdl_package CYGPKG_BLOCK_LIB { + display "Block cache and access library" + define_header blib.h + include_dir blib + + requires CYGPKG_ISOINFRA + requires CYGPKG_MEMALLOC + requires CYGPKG_LINUX_COMPAT + requires CYGPKG_ERROR + + compile -library=libextras.a blib.c + + cdl_option CYGIMP_BLOCK_LIB_STATISTICS { + display "Block access statistics support" + flavor bool + default_value 1 + description "This option enables statistics for + block access operations." + } +} + +# ==================================================================== +# End of blib.cdl diff --git a/ecos/packages/services/blib/current/include/blib.h b/ecos/packages/services/blib/current/include/blib.h new file mode 100644 index 0000000..8790299 --- /dev/null +++ b/ecos/packages/services/blib/current/include/blib.h @@ -0,0 +1,308 @@ +#ifndef CYGONCE_BLIB_H +#define CYGONCE_BLIB_H +//========================================================================== +// +// blib.h +// +// Block cache and access library +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): savin +// Date: 2003-08-29 +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <cyg/infra/cyg_type.h> +#include <cyg/io/io.h> + +#include <linux/rbtree.h> +#include <linux/list.h> + +// -------------------------------------------------------------------- + +typedef int (*cyg_blib_bread_fn) ( + void*, // private data + void*, // block buffer + cyg_uint32*, // number of blocks to read + cyg_uint32 // starting block number +); + +typedef int (*cyg_blib_bwrite_fn) ( + void*, // private data + const void*, // block buffer + cyg_uint32*, // number of blocks to write + cyg_uint32 // starting block number +); + +typedef struct { + cyg_uint32 n_gets; // number of block gets + cyg_uint32 n_reads; // number of block reads + cyg_uint32 n_writes; // number of block writes +} cyg_blib_stat_t; + +typedef struct { + void *priv; // private data + struct list_head list_head; // head of block list + struct rb_root rb_root; // block red-black tree root + cyg_uint32 block_size; // block size + cyg_uint32 block_size_log2; // block size log2 + cyg_uint8 *mem_base; // memory base + cyg_uint32 mem_size; // memory size + struct list_head free_list_head; // list of free blocks + cyg_blib_bread_fn bread_fn; // block read function + cyg_blib_bwrite_fn bwrite_fn; // block write function +#ifdef CYGIMP_BLOCK_LIB_STATISTICS + cyg_blib_stat_t stat; // statistics +#endif +} cyg_blib_t; + +// -------------------------------------------------------------------- + +// -------------------------------------------------------------------- +// Creates a block lib instance +// +// priv_data - private data to pass to bread_fn and bwrite_fn +// mem_base - block cache memory base +// mem_size - block cache memory size +// block_size - block size +// bread_fn - function which reads blocks +// bwrite_fn - function which writes blocks +// bl - block lib instance space holder +// +// returns ENOERR if create succeded +// + +int cyg_blib_create(void *priv_data, + void *mem_base, + cyg_uint32 mem_size, + cyg_uint32 block_size, + cyg_blib_bread_fn bread_fn, + cyg_blib_bwrite_fn bwrite_fn, + cyg_blib_t *bl); + +// -------------------------------------------------------------------- +// Creates a block lib instance on top of IO system +// (cyg_io_bread and cyg_io_bwrite) +// +// handle - cyg_io_handle_t +// mem_base - block cache memory base +// mem_size - block cache memory size +// block_size - block size +// bl - block lib instance space holder +// +// returns ENOERR if create succeded +// + +int cyg_blib_io_create(cyg_io_handle_t handle, + void *mem_base, + cyg_uint32 mem_size, + cyg_uint32 block_size, + cyg_blib_t *bl); + +// -------------------------------------------------------------------- +// Deletes a block lib instance +// +// bl - block lib instance +// +// The block cache is synced before +// +// returns ENOERR if delete succeded +// + +int cyg_blib_delete(cyg_blib_t *bl); + +// -------------------------------------------------------------------- +// Reads a number of blocks +// +// bl - block lib instance +// buf - block buffer ptr +// len - number of blocks to read +// pos - starting block number +// +// returns ENOERR if read succeded +// + +int cyg_blib_bread(cyg_blib_t *bl, + void *buf, + cyg_uint32 *len, + cyg_uint32 pos); + +// -------------------------------------------------------------------- +// Writes a number of blocks +// +// bl - block lib instance +// buf - block buffer ptr +// len - number of blocks to write +// pos - starting block number +// +// returns ENOERR if write succeded +// + +int cyg_blib_bwrite(cyg_blib_t *bl, + const void *buf, + cyg_uint32 *len, + cyg_uint32 pos); + +// -------------------------------------------------------------------- +// Reads data +// +// bl - block lib instance +// buf - data buffer ptr +// len - number of bytes to read +// bnum - starting block number +// pos - starting position inside starting block +// +// returns ENOERR if read succeded +// +// The block number is automatically adjusted if +// position is greater than block size +// + +int cyg_blib_read(cyg_blib_t *bl, + void *buf, + cyg_uint32 *len, + cyg_uint32 bnum, + cyg_uint32 pos); + +// -------------------------------------------------------------------- +// Writes data +// +// bl - block lib instance +// buf - data buffer ptr +// len - number of bytes to write +// bnum - starting block number +// pos - starting position inside starting block +// +// returns ENOERR if write succeded +// +// The block number is automatically adjusted if +// position is greater than block size +// + +int cyg_blib_write(cyg_blib_t *bl, + const void *buf, + cyg_uint32 *len, + cyg_uint32 bnum, + cyg_uint32 pos); + +// -------------------------------------------------------------------- +// Syncs block cache - ie write modified blocks +// +// bl - block lib instance +// +// returns ENOERR if sync succeded +// + +int cyg_blib_sync(cyg_blib_t *bl); + +// -------------------------------------------------------------------- +// Syncs block - ie write if modified +// +// bl - block lib instance +// num - block number to sync +// +// returns ENOERR if sync succeded +// + +int cyg_blib_sync_block(cyg_blib_t *bl, cyg_uint32 num); + +// -------------------------------------------------------------------- +// Flushes block cache +// +// bl - block lib instance +// +// returns ENOERR if flush succeded +// +// The block cache is synced before +// + +int cyg_blib_flush(cyg_blib_t *bl); + +// -------------------------------------------------------------------- +// Sets block size +// +// bl - block lib instance +// block_size - new block size +// +// returns ENOERR if set succeded +// +// The block cache is synced before +// + +int cyg_blib_set_block_size(cyg_blib_t *bl, cyg_uint32 block_size); + +// -------------------------------------------------------------------- +// Gets block size +// +// bl - block lib instance +// +// returns the current block size + +static inline cyg_uint32 cyg_blib_get_block_size(cyg_blib_t *bl) +{ + return bl->block_size; +} + +// -------------------------------------------------------------------- +// Gets log2 of block size +// +// bl - block lib instance +// +// returns log2 of the current block size + +static inline cyg_uint32 cyg_blib_get_block_size_log2(cyg_blib_t *bl) +{ + return bl->block_size_log2; +} + +// -------------------------------------------------------------------- +// Gets block cache statistics +// +// bl - block lib instance +// +// returns ENOERR if get succeded +// + +int cyg_blib_get_stat(cyg_blib_t *bl, cyg_blib_stat_t *stat); + +#endif // CYGONCE_BLIB_H + +// -------------------------------------------------------------------- +// EOF blib.h diff --git a/ecos/packages/services/blib/current/src/blib.c b/ecos/packages/services/blib/current/src/blib.c new file mode 100644 index 0000000..43187c7 --- /dev/null +++ b/ecos/packages/services/blib/current/src/blib.c @@ -0,0 +1,665 @@ +//========================================================================== +// +// blib.c +// +// Block cache and access library +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): savin +// Date: 2003-08-29 +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <cyg/io/io.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> // assertion support +#include <cyg/infra/diag.h> // diagnostic output +#include <blib/blib.h> + +#include <string.h> // memcpy + +#include <linux/rbtree.h> +#include <linux/list.h> + +// -------------------------------------------------------------------- + +//#define DEBUG 1 + +#ifdef DEBUG +# define D(_args_) diag_printf _args_ +#else +# define D(_args_) CYG_EMPTY_STATEMENT +#endif + +#define ALIGN(_x_) (((_x_) + (CYGARC_ALIGNMENT-1)) & ~(CYGARC_ALIGNMENT-1)) + +#ifdef CYGIMP_BLOCK_LIB_STATISTICS + +#define STAT_INIT(_bl_) do { \ + bl->stat.n_gets = 0; \ + bl->stat.n_reads = 0; \ + bl->stat.n_writes = 0; \ + } while (0) + +#define STAT(_bl_, _group_) \ + ((_bl_)->stat._group_++) + +#else // CYGIMP_BLOCK_LIB_STATISTICS + +#define STAT_INIT(_bl_) CYG_EMPTY_STATEMENT +#define STAT(_bl_, _group_) CYG_EMPTY_STATEMENT + +#endif // not CYGIMP_BLOCK_LIB_STATISTICS + +// -------------------------------------------------------------------- + +typedef struct { + struct list_head list_node; // list node + struct rb_node rb_node; // red-black tree node + cyg_uint32 num; // block number + cyg_bool modified; // is this block data modified (needs write) + cyg_uint8 data[0]; // block data +} blib_block_t; + +// -------------------------------------------------------------------- + +static blib_block_t * +rb_find_block(cyg_blib_t *bl, cyg_uint32 num) +{ + struct rb_node *node = bl->rb_root.rb_node; + blib_block_t *block = NULL; + + while (NULL != node) + { + block = rb_entry(node, blib_block_t, rb_node); + + if (block->num == num) + return block; + + node = (block->num > num) ? node->rb_left : node->rb_right; + } + return NULL; +} + +static void +rb_add_block(cyg_blib_t *bl, blib_block_t *block) +{ + struct rb_node *node = bl->rb_root.rb_node; + + if (NULL == node) + { + rb_link_node(&block->rb_node, NULL, &bl->rb_root.rb_node); + } + else + { + struct rb_node **link; + blib_block_t *b = NULL; + + while (NULL != node) + { + b = rb_entry(node, blib_block_t, rb_node); + + CYG_ASSERTC(b->num != block->num); + + link = (b->num > block->num) ? &node->rb_left : &node->rb_right; + node = *link; + } + rb_link_node(&block->rb_node, &b->rb_node, link); + } + rb_insert_color(&block->rb_node, &bl->rb_root); +} + +static __inline__ void +rb_del_block(cyg_blib_t *bl, blib_block_t *block) +{ + rb_erase(&block->rb_node, &bl->rb_root); +} + +// -------------------------------------------------------------------- + +static __inline__ void +list_add_block(cyg_blib_t *bl, blib_block_t *block) +{ + list_add(&block->list_node, &bl->list_head); +} + +static __inline__ void +list_del_block(cyg_blib_t *bl, blib_block_t *block) +{ + list_del(&block->list_node); +} + +static __inline__ blib_block_t * +list_get_first_block(cyg_blib_t *bl) +{ + return(list_entry(bl->list_head.next, blib_block_t, list_node)); +} + +static __inline__ blib_block_t * +list_get_last_block(cyg_blib_t *bl) +{ + return(list_entry(bl->list_head.prev, blib_block_t, list_node)); +} + +static void +list_move_block_to_head(cyg_blib_t *bl, blib_block_t *block) +{ + list_del(&block->list_node); + list_add(&block->list_node, &bl->list_head); +} + +// -------------------------------------------------------------------- + +static __inline__ void +free_block(cyg_blib_t *bl, blib_block_t *block) +{ + list_add(&block->list_node, &bl->free_list_head); +} + +static __inline__ blib_block_t * +alloc_block(cyg_blib_t *bl) +{ + if ( !list_empty(&bl->free_list_head) ) + { + blib_block_t *new; + + new = list_entry(bl->free_list_head.next, blib_block_t, list_node); + list_del(bl->free_list_head.next); + + return new; + } + else + return NULL; +} + +static void +init_block_mem_pool(cyg_blib_t *bl) +{ + cyg_uint8 *block_mem; + cyg_uint32 avail_mem_size, block_mem_size; + + INIT_LIST_HEAD(&bl->free_list_head); + + block_mem = bl->mem_base; + avail_mem_size = bl->mem_size; + block_mem_size = ALIGN(sizeof(blib_block_t) + bl->block_size); + + while (avail_mem_size >= block_mem_size) + { + blib_block_t *block = (blib_block_t *)block_mem; + + list_add(&block->list_node, &bl->free_list_head); + + block_mem += block_mem_size; + avail_mem_size -= block_mem_size; + } +} + +// -------------------------------------------------------------------- + +static cyg_uint32 +get_val_log2(cyg_uint32 val) +{ + cyg_uint32 i, log2; + + i = val; + log2 = 0; + while (0 == (i & 1)) + { + i >>= 1; + log2++; + } + if (i != 1) + return 0; + else + return log2; +} + +static int +blib_sync_block(cyg_blib_t *bl, blib_block_t *block) +{ + int ret = ENOERR; + + if (block->modified) + { + cyg_uint32 len = 1; + + D(("blib writting block=%d\n", block->num)); + + STAT(bl, n_writes); + + ret = bl->bwrite_fn(bl->priv, (void *)block->data, &len, block->num); + + if (ENOERR == ret) + block->modified = false; + } + return ret; +} + +static int +blib_sync(cyg_blib_t *bl) +{ + struct list_head *node = bl->list_head.next; + blib_block_t *block; + int ret = ENOERR; + + D(("blib cache sync\n")); + + while (node != &bl->list_head) + { + block = list_entry(node, blib_block_t, list_node); + + ret = blib_sync_block(bl, block); + if (ENOERR != ret) + break; + + node = node->next; + } + return ret; +} + +static int +blib_get_block(cyg_blib_t *bl, + cyg_uint32 num, + cyg_bool read_data, + blib_block_t **dblock) +{ + blib_block_t *block = NULL; + int ret = ENOERR; + cyg_uint32 len; + + D(("blib get block=%d\n", num)); + + STAT(bl, n_gets); + + // first check if the most recently used block is the requested block, + // this can improve performance when using byte access functions + if (!list_empty(&bl->list_head)) + { + blib_block_t *first_block = list_get_first_block(bl); + if (first_block->num == num) + block = first_block; + else + block = rb_find_block(bl, num); + } + + if (NULL != block) + { + D(("blib block=%d found in cache\n", num)); + + list_move_block_to_head(bl, block); + *dblock = block; + return ret; + } + + D(("blib block=%d NOT found in cache\n", num)); + + block = alloc_block(bl); + + if (NULL == block) + { + CYG_ASSERTC(!list_empty(&bl->list_head)); + + block = list_get_last_block(bl); + + D(("blib reusing block=%d space\n", block->num)); + + ret = blib_sync_block(bl, block); + if (ENOERR != ret) + return ret; + + list_del_block(bl, block); + rb_del_block(bl, block); + } + + block->num = num; + block->modified = false; + + if (read_data) + { + D(("blib reading block=%d\n", block->num)); + + STAT(bl, n_reads); + + len = 1; + ret = bl->bread_fn(bl->priv, (void *)block->data, &len, block->num); + if (ENOERR != ret) + { + free_block(bl, block); + return ret; + } + } + rb_add_block(bl, block); + list_add_block(bl, block); + + *dblock = block; + return ret; +} + +static int +blib_init_cache(cyg_blib_t *bl, + void *mem_base, + cyg_uint32 mem_size, + cyg_uint32 block_size, + cyg_bool reinit) +{ + int ret = ENOERR; + + if (reinit) + { + ret = blib_sync(bl); + if (ENOERR != ret) + return ret; + } + + bl->rb_root = RB_ROOT; + INIT_LIST_HEAD(&bl->list_head); + + bl->mem_base = mem_base; + bl->mem_size = mem_size; + bl->block_size = block_size; + + bl->block_size_log2 = get_val_log2(block_size); + if (0 == bl->block_size_log2) + return -EINVAL; + + init_block_mem_pool(bl); + + STAT_INIT(bl); + + return ret; +} + +// -------------------------------------------------------------------- + +static int +io_bread(void *priv, void *buf, cyg_uint32 *len, cyg_uint32 pos) +{ + return cyg_io_bread((cyg_io_handle_t)priv, buf, len, pos); +} + +static int +io_bwrite(void *priv, const void *buf, cyg_uint32 *len, cyg_uint32 pos) +{ + return cyg_io_bwrite((cyg_io_handle_t)priv, buf, len, pos); +} + +// -------------------------------------------------------------------- + +int +cyg_blib_create(void *priv_data, + void *mem_base, + cyg_uint32 mem_size, + cyg_uint32 block_size, + cyg_blib_bread_fn bread_fn, + cyg_blib_bwrite_fn bwrite_fn, + cyg_blib_t *bl) +{ + int ret; + + bl->priv = priv_data; + bl->bread_fn = bread_fn; + bl->bwrite_fn = bwrite_fn; + + ret = blib_init_cache(bl, mem_base, mem_size, block_size, false); + return ret; +} + +int +cyg_blib_io_create(cyg_io_handle_t handle, + void *mem_base, + cyg_uint32 mem_size, + cyg_uint32 block_size, + cyg_blib_t *bl) +{ + return cyg_blib_create((void *)handle, mem_base, mem_size, block_size, + io_bread, io_bwrite, bl); +} + +int +cyg_blib_delete(cyg_blib_t *bl) +{ + return blib_sync(bl); +} + +int +cyg_blib_bread(cyg_blib_t *bl, + void *buf, + cyg_uint32 *len, + cyg_uint32 pos) +{ + blib_block_t *block; + cyg_int32 size = *len; + cyg_int32 bnum = pos; + cyg_uint8 *bbuf = buf; + Cyg_ErrNo ret = ENOERR; + + D(("blib bread block=%d len=%d buf=%p\n", pos, *len, buf)); + + while (size > 0) + { + ret = blib_get_block(bl, bnum, true, &block); + if (ENOERR != ret) + break; + + memcpy((void *)bbuf, (void *)block->data, bl->block_size); + + bbuf += bl->block_size; + bnum++; + size--; + } + *len -= size; + return ret; +} + +int +cyg_blib_bwrite(cyg_blib_t *bl, + const void *buf, + cyg_uint32 *len, + cyg_uint32 pos) +{ + blib_block_t *block; + cyg_int32 size = *len; + cyg_int32 bnum = pos; + cyg_uint8 *bbuf = (cyg_uint8 * const) buf; + Cyg_ErrNo ret = ENOERR; + + D(("blib bwrite block=%d len=%d buf=%p\n", pos, *len, buf)); + + while (size > 0) + { + ret = blib_get_block(bl, bnum, false, &block); + if (ENOERR != ret) + break; + + memcpy((void *)block->data, (void *)bbuf, bl->block_size); + block->modified = true; + + bbuf += bl->block_size; + bnum++; + size--; + } + *len -= size; + return ret; +} + +int +cyg_blib_read(cyg_blib_t *bl, + void *buf, + cyg_uint32 *len, + cyg_uint32 bnum, + cyg_uint32 pos) +{ + blib_block_t *block; + cyg_uint8 *bbuf = buf; + cyg_int32 size = *len; + Cyg_ErrNo ret = ENOERR; + + size = *len; + + if (pos >= bl->block_size) + { + bnum += pos >> bl->block_size_log2; + pos = pos & (bl->block_size - 1); + } + + D(("blib read len=%d pos=%d bnum=%d\n", *len, pos, bnum)); + + while (size > 0) + { + cyg_uint32 csize; + + if ((size + pos) > bl->block_size) + csize = bl->block_size - pos; + else + csize = size; + + ret = blib_get_block(bl, bnum, true, &block); + if (ENOERR != ret) + break; + + memcpy((void *)bbuf, (void *)(block->data+pos), csize); + + bbuf += csize; + size -= csize; + pos = 0; + bnum++; + } + *len -= size; + return ret; +} + +int +cyg_blib_write(cyg_blib_t *bl, + const void *buf, + cyg_uint32 *len, + cyg_uint32 bnum, + cyg_uint32 pos) +{ + blib_block_t *block; + cyg_uint8 *bbuf = (cyg_uint8 * const) buf; + cyg_int32 size = *len; + Cyg_ErrNo ret = ENOERR; + + size = *len; + + if (pos >= bl->block_size) + { + bnum += pos >> bl->block_size_log2; + pos = pos & (bl->block_size - 1); + } + + D(("blib write len=%d pos=%d bnum=%d\n", *len, pos, bnum)); + + while (size > 0) + { + cyg_uint32 csize; + + if ((size + pos) > bl->block_size) + csize = bl->block_size - pos; + else + csize = size; + + if (0 == pos && csize == bl->block_size) + ret = blib_get_block(bl, bnum, false, &block); + else + ret = blib_get_block(bl, bnum, true, &block); + if (ENOERR != ret) + break; + + memcpy((void *)(block->data+pos), (void *)bbuf, csize); + block->modified = true; + + bbuf += csize; + size -= csize; + pos = 0; + bnum++; + } + *len -= size; + return ret; +} + +int +cyg_blib_sync(cyg_blib_t *bl) +{ + return blib_sync(bl); +} + +int +cyg_blib_sync_block(cyg_blib_t *bl, cyg_uint32 num) +{ + blib_block_t *block = rb_find_block(bl, num); + + if (NULL != block) + return blib_sync_block(bl, block); + else + return -EINVAL; +} + +int +cyg_blib_flush(cyg_blib_t *bl) +{ + return blib_init_cache(bl, bl->mem_base, bl->mem_size, + bl->block_size, true); +} + +int +cyg_blib_set_block_size(cyg_blib_t *bl, cyg_uint32 block_size) +{ + return blib_init_cache(bl, bl->mem_base, bl->mem_size, + block_size, true); +} + +int +cyg_blib_get_stat(cyg_blib_t *bl, cyg_blib_stat_t *stat) +{ +#ifdef CYGIMP_BLOCK_LIB_STATISTICS + *stat = bl->stat; + return ENOERR; +#else + stat->n_gets = 0; + stat->n_reads = 0; + stat->n_writes = 0; + return -EINVAL; +#endif +} + +// -------------------------------------------------------------------- +// EOF blib.c |
