# HG changeset patch # User Michael Spacefalcon # Date 1388030399 0 # Node ID 6f4a12b4582f51ee041766bf974f80146eb1f144 # Parent 2abe6ade042d6c2f4595eeacdd4ebf7a203e6963 gsm-fw FFS: starting to integrate C code diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/Makefile Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,18 @@ +CC= arm-elf-gcc +CFLAGS= -O2 -fno-builtin -mthumb-interwork -mthumb +LD= arm-elf-ld + +OBJS= drv.o + +HDRS= core.h drv.h ffs.h ffs_api.h ffs_env.h ffs_pool_size.h ffstrace.h \ + intctl.h ramffs.h + +all: xipcode.o + +${OBJS}: ${HDRS} + +xipcode.o: ${OBJS} + ${LD} -r -o $@ ${OBJS} + +clean: + rm -f *.[oa] *errs diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/core.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/core.h Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,579 @@ +/****************************************************************************** + * Flash File System (ffs) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * ffs core functions + * + * $Id: core.h 1.80.1.15.1.36 Thu, 08 Jan 2004 15:05:23 +0100 tsj $ + * + ******************************************************************************/ + +#if (TARGET == 1) +#include "../../riviera/rv/rv_defined_swe.h" +#endif + +/****************************************************************************** + * Compile option switches + ******************************************************************************/ + +// FFS compiled with extra test functionality +#define FFS_TEST 1 + +// Default max number of simultaneous open files +#ifdef RVM_MSFE_SWE +#define FFS_FD_MAX 20 +#else +#define FFS_FD_MAX 4 +#endif + +#define FFS_RECLAIM_NEW 1 + +/****************************************************************************** + * Compile constants + ******************************************************************************/ + +// FFS API version (in four-digit BCD format) +#define FFS_API_VERSION ((uint16) 0x0642) + +// FFS_DRV_VERSION is in drv.h + +// TMFFS protocol version is in tmffs.h + +// Magic for determining (formatted) file system version. First two digits +// represent major version, bottom two digits represent minor version. An +// ffs code compiled for one major version X is compatible with any other +// format version with major = X. Minor version is incremented when adding +// new features that does not break compatibility. +#define FFS_FORMAT_VERSION (0x0210) +#define BLOCK_MAGIC_LOW ('f'<<8|'F') // "Ffs#" +#define BLOCK_MAGIC_HIGH ('#'<<8|'s') +#define BLOCK_MAGIC ((BLOCK_MAGIC_HIGH << 8)|(BLOCK_MAGIC_LOW)) + +// Absolute maximum number of inodes allowed +#define FFS_INODES_MAX 2048 + +// Default maximum number of inodes allowed +#define FFS_INODES_MAX_DEFAULT 1024 + +// Default number of path components (limit due to recursiveness of +// inodes_reclaim()) +#define FFS_PATH_DEPTH_MAX 6 + +// Maximum number of blocks (flash sectors) in a ffs system. FFS_BLOCKS_MAX +// must be >= the number of blocks in the largest flash device memory +// map. It is used to allocate the number of entries in the static bstat +// array. +#define FFS_BLOCKS_MAX 128 +// Default size of journal file (represented as 256'ths of the blocksize) +#define FFS_JOURNAL_SIZE_IN256THS 16 // one 16'ths of the block size. + +// Without the min size will the maximum of files (fs.blocks_files_max) in +// one block be 32 files if the blocksize is 8kB! +#define FFS_JOURNAL_SIZE_MIN 1024 + +#define FFS_JOURNAL_NAME ".journal" + +// Default max size of file name (excluding null terminator) +#define FFS_FILENAME_MAX 20 + +// Maximum distance in age between youngest and oldest blocks +#define FFS_DAGE_MAX 256 +#define FFS_DAGE_GAIN_MIN (FFS_DAGE_MAX / 4) +#define FFS_DAGE_EARLY_WIDTH 64 + +// Offset on file descriptors +#define FFS_FD_OFFSET '1' + +// Macros to set flags and test bits in flash memory words (negative logic) +#define BIT_SET(value, bits) ((value) & (~bits)) +#define IS_BIT_SET(value, bits) (~(value) & (bits)) + +// Number of free inodes and journal entries to keep for "emergencies" +#define FFS_INODES_MARGIN 4 +#define FFS_JOURNAL_MARGIN 4 + + +/****************************************************************************** + * Macros used in both drv.c and core.c + ******************************************************************************/ + +// Convert a offset_t value to a block index +#define offset2block(offset) (((uint32) offset) >> dev.binfo[0].size_ld) + +// Convert between offset and address +#define offset2addr(offset) (dev.base + (offset)) + +// Size of a block +#define blocksize(block) (1 << dev.binfo[block].size_ld) + +// Test if flag is set +#define is_open_option(options, flags) ((options & flags) == flags) + +// Amount of reserved space. +#define RESERVED_LOW 2 * fs.journal_size +#define RESERVED_NONE 0 + +// We have to saturate because a recently reclaimed inodes block could +// theoretically possess a high age +#define saturate_dage(dage) (dage > (2*FFS_DAGE_MAX) ? (2*FFS_DAGE_MAX) : dage) + +/****************************************************************************** + * External declarations + ******************************************************************************/ + +extern struct fs_s fs; +extern struct block_stat_s bstat[FFS_BLOCKS_MAX]; + +extern struct ffs_stats_s stats; + +extern const struct block_info_s *binfo; + + +/****************************************************************************** + * Block Types + ******************************************************************************/ + +// Block age, ie. number of times block has been erased +typedef uint16 age_t; + +// Maximum age a block can have +#define BLOCK_AGE_MAX 0xFFFF + +// ffs block status flags. These are stored in the first 2 bytes of +// the ffs block in the flash sector. +enum BLOCK_FLAGS { + BF_LOST = 0x80, // block is lost and will soon be erased + BF_FREE = 0x40, // free (preformatted and with block magic) + BF_DATA = 0x02, // data + BF_CLEANING = 0x01, // block is being cleaned + BF_INODES = 0x10, // block contains inodes + BF_COPYING = 0x04 // block is a coming inodes block +}; +enum BLOCK_STATES { + BF_IS_EMPTY = ~(0), + BF_IS_FREE = ~(BF_FREE), + BF_IS_DATA = ~(BF_FREE | BF_DATA), + BF_IS_CLEANING = ~(BF_FREE | BF_DATA | BF_CLEANING), + BF_IS_COPYING = ~(BF_FREE | BF_COPYING), + BF_IS_INODES = ~(BF_FREE | BF_COPYING | BF_INODES), + BF_IS_INODES_LOST = ~(BF_FREE | BF_COPYING | BF_INODES | BF_LOST) +}; + +// Header of each FFS block +struct block_header_s { + uint16 magic_low; // 32-bit magic number + uint16 magic_high; + uint16 version; // FFS_FORMAT_VERSION used for formatting + age_t age; // number of times this block has been erased + uint16 flags; // status flags of this block (BLOCK_FLAGS) + uint16 reserved0; + uint16 reserved1; + uint16 reserved2; +}; + +// Important the below define MUST fit to the size of the header that is written +#define BHEADER_SIZE sizeof(struct block_header_s) + +#define OLD_BLOCK_MAGIC_LOW ('S'<<8|'F') // "FS" +#define OLD_FFS_FORMAT_VERSION (0x0100) // 1.00 (in four-digit BCD format) + +// Old header of each FFS block. From old/previous FFS format version +struct block_header_old_s { + uint8 flags; + uint8 copied; + uint8 magicflags; + uint8 reserved0; + uint16 magic_low; + uint16 magic_high; + uint16 reserved1; + uint16 reserved2; +}; + +// Block status. This struct holds the status of one ffs block This relation +// is always valid: = + + . The block size +// is obtained from the corresponding block_info structure. and +// variables always holds a value which is a multiple of +// FFS_GRANULARITY. For inodes, is number of inodes in active use, +// is number of deleted/lost inodes, is the index of the +// first free inode. +struct block_stat_s { + blocksize_t used; // number of used bytes + blocksize_t lost; // number of lost bytes + uint16 flags; // flash block flags (first 16 bits of each block) + uint16 objects; // number of valid objects +}; + + +/****************************************************************************** + * Object Types + ******************************************************************************/ + +// This enum MUST be in sync with the one in ffs.h. +enum OBJECT_TYPE_E { + // remaining filetypes are in ffs.h + OT_ERASED = 0, + OT_NULL = 7, + OT_MASK = 7, + OT_MAX = 4 +}; + +// This enum MUST be in sync with the one in ffs.h. +enum OBJECT_FLAGS_E { + // remaining object flags are in ffs.h + OF_UNDEF0 = 1<<5, + OF_UNDEF1 = 1<<6, + OF_EXACT = 1<<7, // used by control()/update_commit() interaction. This + // is *not* an object flag! + OF_ALL = OF_READONLY, // all flags allowed to be changed by user + OF_MASK = 0xF0 +}; + +struct inode_s { + uint16 size; + uint8 reserved; // size extension? + objflags_t flags; + iref_t child; // link to first inode in dir (this inode is a dir) + iref_t sibling; // link to next inode in same directory + location_t location; // location of object + uint16 sequence; // + uint16 updates; // times this object has been updated +}; + +struct file_descriptor_s { + char *buf; // Write buffer + iref_t seghead; // First chunk. Contain file name and optional data + iref_t wch; // Inode of work chunk (if chunk is read to buf) + int fp; // File pointer + int wfp; // Work file pointer always points to start of wch + int size; // Size of object (all chunks and data from buf) + int8 options; // Open options + int dirty; // Indicate if buf contain valid data or not +}; + + +/****************************************************************************** + * Journal types and global fs structure + ******************************************************************************/ + +enum JOURNAL_FLAGS { + JOURNAL_WRITING = 0x02, // journal is being written to journal file + JOURNAL_READY = 0x04, // journal has been written to journal file + JOURNAL_DONE = 0x08 // journal has been written to ffs +}; + +enum JOURNAL_STATES { + JOURNAL_IS_EMPTY = ~(0), + JOURNAL_IS_WRITING = ~(JOURNAL_WRITING), + JOURNAL_IS_READY = ~(JOURNAL_WRITING | JOURNAL_READY), + JOURNAL_IS_DONE = ~(JOURNAL_WRITING | JOURNAL_READY | JOURNAL_DONE) +}; + +// Journal entry structure. Note that the state byte *MUST* be the first +// byte of the structure! +struct journal_s { + uint8 state; // state of journal entry. + objflags_t flags; // type of object + iref_t i; // iref of object + iref_t diri; // iref of object that is this object's parent/sibling + iref_t oldi; // iref of object being replaced (only for updates) + location_t location; // object's location + uint16 size; // object's size + iref_t repli; // inode which is replaced +}; + +// Main ffs info struct (initialised by ffs_initialize()) +struct fs_s { + struct inode_s *inodes_addr; // base address of inodes + iref_t root; // iref of root directory + bref_t inodes; // index into bstat containing inode block + bref_t newinodes; // index into bstat containing new inode block + bref_t blocks_free_min; // Number of spare blocks (0 or 1) + int filesize_max; // Max size of object data + int reserved_space; // Byte size of space reserved for journal relocation + iref_t inodes_max; // Max number of inodes possible + iref_t inodes_high; // number of inodes triggering an inodes_reclaim() + iref_t objects_max; // Max number of objects (valid inodes) allowed + age_t age_max; // Max block age found by blocks_fsck() + iref_t block_files_max; // max number of files in a block + iref_t block_files_reserved; // Reserved for journals + uint16 format; // FFS version as formatted in flash blocks + uint16 sequence; // Object sequence number (for debug only) + effs_t initerror; // ffs_initialize() return code + uint8 lost_threshold; // Threshold percentage for data block reclaim + uint8 flags; // Global FFS options/flags + uint8 filename_max; // Max length of a filename + uint8 path_depth_max; // Max path componenents allowed + uint8 numfds; // Mumber of available file descriptors + uint8 testflags; + int8 journal_depth; // Current journal nesting depth (0 or 1) + iref_t ijournal; // iref of journal file + uint32 journal_size; // Byte size of journal file + uint32 journal_pos; // Byte offset to first free entry in journal file + struct journal_s journal; + uint8 fd_max; // number of max available file descriptors + int fd_buf_size; // size of stream buffer + struct file_descriptor_s fd[FFS_FD_MAX]; + struct journal_s ojournal; // "Old" journal + int link_child; // Link child in journal or not + iref_t i_backup; // Used by ffs_file_write() + int chunk_size_max; // Max size of one chunk + int chunk_size_min; // Min size of one chunk + uint32 debug[4]; +}; + +// This is the layout of the FFS performance statistics file. The file is +// created with the name ".statistics" in the root directory at format. It +// is updated after each data and inodes reclaim (after writing the file +// that provoked the reclaim). The file is only updated if it exists, so if +// the user does not want the file, she can erase it after the initial +// format. FIXME: The use of the .statistics file is not yet implemented +struct ffs_stats_s { + uint32 data_allocated; // implemented + + struct { // Not yet implemented + uint32 created; + uint32 updated; + uint32 read; + } files; + struct { // Not yet implemented + uint32 written[2]; + uint32 read[2]; + } bytes; + struct { + uint32 most_lost; // Block candidate + uint32 most_unused; // Block candidate + uint32 youngest; // Block candidate + uint32 valid[2]; // Amount of valid reclaimed data + uint32 lost[2]; // Amount of lost reclaimed data + } drec; + struct { + uint32 num; // Number of inode reclaims + uint32 valid; // Number of valid reclaimed inodes + uint32 lost; // Number of lost reclaimed inodes + } irec; +}; +extern struct ffs_stats_s stats; + + +/****************************************************************************** + * Miscellaneous types + ******************************************************************************/ + +// only used with (FFS_TEST == 1) +enum TEST_RECOVERY { + JOURNAL_TEST_BASE = 0x10, + JOURNAL_TEST_EMPTY, + JOURNAL_TEST_WRITING, + JOURNAL_TEST_READY, + JOURNAL_TEST_COMMITTING, + JOURNAL_TEST_COMMITTED, + JOURNAL_TEST_DONE, + BLOCK_COMMIT_BASE = 0x20, + BLOCK_COMMIT_BEFORE, + BLOCK_COMMIT_NO_VALID, + BLOCK_COMMIT_OLD_FREE, + BLOCK_COMMIT_AFTER, + BLOCK_RECLAIM_BASE = 0x40, + BLOCK_RECLAIM_ALLOC, + BLOCK_RECLAIM_CLEANING, + BLOCK_RECLAIM_NO_CLEAN, + BLOCK_RECOVER_OBJECTS +}; + +enum FLASH_DATA { + FLASH_NULL8 = 0xFF, + FLASH_NULL16 = 0xFFFF, + FLASH_NULL32 = 0xFFFFFFFFL, + IREF_NULL = FLASH_NULL16 +}; + + +// This enum MUST be in sync with the one in ffs.h. +enum OBJECT_CONTROL { + // remaining object control codes are in ffs.h + OC_FS_FLAGS = 80, + OC_TRACE_INIT = 82, + OC_DEV_MANUFACT = 88, + OC_DEV_DEVICE = 89, + + OC_DEBUG_FIRST = 120, + OC_DEBUG_0 = 120, + OC_DEBUG_1 = 121, + OC_DEBUG_2 = 122, + OC_DEBUG_3 = 123, + OC_DEBUG_LAST = 123, + + OC_FS_TESTFLAGS = 127 +}; + +enum FS_FLAGS { + FS_DIR_DATA = 0x01 // allow directory objects to contain data. +}; + +enum RECLAIM_CANDIDATE { + MOST_LOST, + MOST_UNUSED, + YOUNGEST +}; + +/****************************************************************************** + * Macros + ******************************************************************************/ + +// Convert between location and offset +#define location2offset(location) ((location) << dev.atomlog2) +#define offset2location(offset) (((uint32) offset) >> dev.atomlog2) + +// test if object is of a specific type +#define is_object(objp, type) (((objp)->flags & OT_MASK) == (type)) + +// test if object is valid (directory, file or symlink) +#define is_object_valid(ip) ((ip->flags & OT_MASK) <= OT_MAX && (ip->flags & OT_MASK) != OT_ERASED) + +// test if block is in a specific state +#define is_block(block, state) (bstat[block].flags == (uint16) (state)) + +// test if block has certain flags set +#define is_block_flag(block, bits) (IS_BIT_SET(bstat[block].flags, (bits))) + +// convert an object's data address to the address of the object's name +#define addr2name(addr) (addr) + +// Convert a size to an aligned size +#define atomalign(size) (((size) + dev.atomsize-1) & ~dev.atomnotmask) +#define wordalign(size) (((size) + 3) & ~3) +#define halfwordalign(size) (((size) + 1) & ~1) + +#define inode_addr(i) (fs.inodes_addr + i) + +#define JOURNAL_POS_INITIAL (wordalign(2 + sizeof(FFS_JOURNAL_NAME) + 1)) + + +/****************************************************************************** + * Function prototypes + ******************************************************************************/ + +// Helper functions + +effs_t is_filename(const char *s); +int ffs_strlen(const char *s); +int ffs_strcmp(const char *s, const char *p); +char *addr2data(const char *addr, const struct inode_s *ip); + +int object_datasize(iref_t i); +iref_t is_readonly(iref_t i, const char *name); +iref_t dir_traverse(iref_t i, iref_t *entries); + +bref_t block_alloc(bref_t n, uint16 flags); +bref_t block_alloc_try(bref_t *n); +void block_flags_write(uint8 block, uint8 flags); + +offset_t data_alloc(int size); +offset_t data_alloc_try(int size); +offset_t data_reserved_alloc(int size); + +iref_t inode_alloc(void); + +effs_t is_fd_valid(fd_t fdi); +effs_t is_offset_in_buf(int offset, fd_t fdi); + +iref_t chunk_alloc(int realsize, int is_journal, offset_t *offset); + +iref_t inode_alloc_try(void); +fd_t get_fdi(iref_t i); + +offset_t data_prealloc(int realsize); + +// Functions used by API + +effs_t object_update(iref_t oldi); +iref_t object_create(const char *name, const char *buf, int size, + iref_t dir); +int file_read(const char *name, void *addr, int size); +int stream_read(fd_t fdi, void *src, int size); +int object_read(const char *name, char *buf, int size, int linkflag); + +iref_t object_stat(const char *name, struct xstat_s *stat, + int linkflag, int fdi, int extended); +effs_t object_remove(iref_t i); +iref_t object_rename(iref_t oldi, const char *newname, iref_t newdir); +effs_t object_control(iref_t i, int8 action, int value); +int object_truncate(const char *pathname, fd_t fdi, offset_t length); +iref_t object_lookup(const char *path, char **leaf, iref_t *dir); +iref_t object_lookup_once(const char *path, char **leaf, iref_t *dir); +iref_t dir_open(const char *name); +iref_t dir_next (iref_t dir, iref_t i, char *name, int8 size); + + +// Journalling + +void journal_begin(iref_t oldi); +void journal_end(uint8 type); +void journal_commit(uint8 type); +int journal_push(void); +int journal_pop(void); +iref_t journal_create(iref_t oldi); +effs_t journal_init(iref_t i); + + +// Format, Init and Reclaim + +void block_preformat(bref_t b, age_t age); +effs_t fs_preformat(void); +effs_t is_formattable(int8 flag); +effs_t fs_format(const char *fsname_and_options); + +effs_t ffs_initialize(void); +void fs_params_init(const char *p); +blocksize_t block_used(bref_t b); + +effs_t ffs_begin(void); +int ffs_end(int error); + +int block_reclaim(bref_t b); +int blocks_reclaim(void); +void block_commit(void); + +iref_t data_reclaim(int space); +int data_reclaim_try(int space); +iref_t data_block_reclaim(bref_t b, int reclaim_candidate); +iref_t object_relocate(iref_t oldi); +iref_t block_clean(bref_t b); + +void block_free(bref_t block); + +void inodes_set(iref_t i); +effs_t inodes_reclaim(void); + +int reclaim(void); + +// Internally used functions + +effs_t file_read_int(const char *path, void *src, int size); +effs_t file_update(const char *path, void *src, int size); + +int statistics_file_create(void); +int statistics_write(void); +void statistics_init(void); +void statistics_update_drec(int valid, int lost, int candidate); +void statistics_update_irec(int valid, int lost); + +// Chunk Operations +iref_t segment_create(const char *buf, int size, iref_t dir); +int segment_datasize(const struct inode_s *ip); +int segment_read(iref_t i, char *buf, int size, int offset); +iref_t segment_next(iref_t i); +iref_t segment_traverse(iref_t i, iref_t *entries); +int segfile_seek(iref_t in_i, int in_pos, + iref_t *out_i, int *out_pos_i); +iref_t chunk_traverse(iref_t i); +effs_t datasync(fd_t fdi); +// debug/test functions + +void tr_bstat(void); +void tr_fd(fd_t fdi); + +// These prototypes really belong in ffs.h but as they have not been +// implemented, we will not show these prototypes to application +// programmers. +effs_t fcntl(fd_t fd, int8 action, uint32 *param); diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/drv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/drv.c Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,423 @@ +/****************************************************************************** + * Flash File System (ffs) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * ffs low level flash driver + * + * $Id: drv.c 1.30.1.6.1.51.1.1.1.13.1.11 Tue, 06 Jan 2004 14:36:52 +0100 tsj $ + * + ******************************************************************************/ + +#include "../../include/config.h" +#include "ffs.h" +#include "drv.h" +#include "ffstrace.h" +#include "intctl.h" +#include "ramffs.h" +#include + + +/****************************************************************************** + * Macros + ******************************************************************************/ + +#define addr2offset(address) ( (int) (address) - (int) dev.base ) + + +/****************************************************************************** + * Generic Driver Functions + ******************************************************************************/ + +// Note: This function is designed for little-endian memory addressing! +void ffsdrv_write_byte(void *dst, uint8 value) +{ + uint16 halfword; + + tw(tr(TR_FUNC, TrDrvWrite, "ffsdrv_write_byte(0x%05x, 0x%x)\n", + (int) (addr2offset(dst)), value)); + ttw(str(TTrDrvWrite, "wb" NL)); + + if ((int) dst & 1) + halfword = (value << 8) | *((uint8 *) dst - 1); + else + halfword = (*((uint8 *) dst + 1) << 8) | (value); + + ffsdrv.write_halfword((uint16 *) ((int) dst & ~1), halfword); +} + +void ffsdrv_generic_write(void *dst, const void *src, uint16 size) +{ + uint8 *mydst = dst; + const uint8 *mysrc = src; + + if (size > 0) + { + if ((unsigned int) mydst & 1) { + ffsdrv_write_byte(mydst++, *mysrc++); + size--; + } + while (size >= 2) { + ffsdrv.write_halfword((uint16 *) mydst, + mysrc[0] | (mysrc[1] << 8)); + size -= 2; + mysrc += 2; + mydst += 2; + } + if (size == 1) + ffsdrv_write_byte(mydst++, *mysrc++); + } +} + +/****************************************************************************** + * Dummy Functions + ******************************************************************************/ + +int ffsdrv_null_init(void) +{ + ttw(ttr(TTrDrvOther, "ffsdrv_null_init()" NL)); + + return 0; +} + +void ffsdrv_null_erase(uint8 block) +{ + ttw(ttr(TTrDrvErase, "ffsdrv_null_erase(%d)" NL, block)); +} + +void ffsdrv_null_write_halfword(volatile uint16 *addr, uint16 value) +{ + ttw(ttr(TTrDrvWrite, "ffsdrv_null_write_halfword(0x%x, 0x%x)" NL, addr, value)); +} + +void ffsdrv_null_write(void *dst, const void *src, uint16 size) +{ + ttw(ttr(TTrDrvWrite, "ffsdrv_null_write(0x%x, 0x%x, %d)" NL, dst, src, size)); +} + +void ffsdrv_null_erase_suspend(void) +{ + ttw(str(TTrDrvErase, "ffsdrv_null_erase_suspend()" NL)); +} + +void ffsdrv_null_erase_resume(void) +{ + ttw(str(TTrDrvErase, "ffsdrv_null_erase_resume()" NL)); +} + +void ffsdrv_null_write_end(void) +{ + ttw(str(TTrDrvWrite, "ffsdrv_null_write_end()" NL)); +} + +void ffsdrv_null_erase_end(void) +{ + ttw(str(TTrDrvErase, "ffsdrv_null_erase_end()" NL)); +} + +/* + * FreeCalypso change from TI: we only compile one flash "driver" type + * based on the build configuration. + */ + +#if FFS_IN_RAM + +/****************************************************************************** + * RAM Family Functions + ******************************************************************************/ + +struct block_info_s ramffs_block_info[RAMFFS_NBLOCKS]; + +int ffsdrv_ram_init(void) +{ + unsigned i; + uint32 offset; + + ttw(ttr(TTrDrvOther, "ffsdrv_ram_init()" NL)); + memset(_RAMFFS_area, 0xFF, RAMFFS_TOTAL_SIZE); + offset = 0; + for (i = 0; i < RAMFFS_NBLOCKS; i++) { + ramffs_block_info[i].offset = offset; + ramffs_block_info[i].size_ld = RAMFFS_BLKSIZE_LOG2; + offset += RAMFFS_BLKSIZE_BYTES; + } + return 0; +} + +void ffsdrv_ram_write_halfword(volatile uint16 *dst, uint16 value) +{ + *dst = value; +} + +#if 0 +/* duplicates ffsdrv_generic_write */ +void ffsdrv_ram_write(void *dst, const void *src, uint16 size) +{ + uint8 *mydst = dst; + const uint8 *mysrc = src; + + if (size == 0) + return; + else if (size == 1) + ffsdrv_write_byte(mydst, *mysrc); + else { + if ((int) mydst & 1) { + ffsdrv_write_byte(mydst++, *mysrc++); + size--; + } + while (size >= 2) { + ffsdrv_ram_write_halfword((uint16 *) mydst, mysrc[0]|(mysrc[1] << 8)); + size -= 2; + mysrc += 2; + mydst += 2; + } + if (size == 1) + ffsdrv_write_byte(mydst++, *mysrc++); + } +} +#endif + +void ffsdrv_ram_erase(uint8 block) +{ + int i; + char *addr; + + addr = block2addr(block); + + for (i = 0; i < (1 << dev.binfo[block].size_ld); i++) { + *addr++ = 0xFF; + } +} + +const struct ffsdrv_s ffsdrv = { + ffsdrv_ram_init, + ffsdrv_ram_erase, + ffsdrv_ram_write_halfword, + ffsdrv_generic_write, + ffsdrv_null_write_end, + ffsdrv_null_erase_suspend, + ffsdrv_null_erase_resume +}; + +#elif CONFIG_FLASH_WRITE + +/****************************************************************************** + * AMD Dual/Multi Bank Driver Functions + ******************************************************************************/ + +// All erase and write operations are performed atomically (interrupts +// disabled). Otherwise we cannot trust the value of dev.state and we cannot +// determine exactly how many of the command words have already been +// written. + +// in ffs_end() when we resume an erasure that was previously suspended, how +// does that affect multiple tasks doing that simultaneously? + +void ffsdrv_amd_write_end(void); +void ffsdrv_amd_erase_end(void); + +void ffsdrv_amd_write_halfword(volatile uint16 *addr, uint16 value) +{ + volatile char *flash = dev.base; + uint32 cpsr; + + tlw(led_on(LED_WRITE)); + ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value)); + + dev.addr = addr; + dev.data = value; + + if (~*addr & value) { + ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value)); + return; + } + + cpsr = int_disable(); + tlw(led_toggle(LED_WRITE_SUSPEND)); + dev.state = DEV_WRITE; + flash[0xAAAA] = 0xAA; // unlock cycle 1 + flash[0x5555] = 0x55; // unlock cycle 2 + flash[0xAAAA] = 0xA0; + *addr = value; + int_enable(cpsr); + tlw(led_toggle(LED_WRITE_SUSPEND)); + + ffsdrv_amd_write_end(); +} + +#if 0 +/* duplicates ffsdrv_generic_write */ +void ffsdrv_amd_write(void *dst, const void *src, uint16 size) +{ + uint8 *mydst = dst; + const uint8 *mysrc = src; + + if (size > 0) + { + if ((unsigned int) mydst & 1) { + ffsdrv_write_byte(mydst++, *mysrc++); + size--; + } + while (size >= 2) { + ffsdrv_amd_write_halfword((uint16 *) mydst, + mysrc[0] | (mysrc[1] << 8)); + size -= 2; + mysrc += 2; + mydst += 2; + } + if (size == 1) + ffsdrv_write_byte(mydst++, *mysrc++); + } +} +#endif + +void ffsdrv_amd_write_end(void) +{ + while ((*dev.addr ^ dev.data) & 0x80) + tlw(led_toggle(LED_WRITE_SUSPEND)); + + dev.state = DEV_READ; + + tlw(led_off(LED_WRITE)); +} + +void ffsdrv_amd_erase(uint8 block) +{ + volatile char *flash = dev.base; + uint32 cpsr; + + tlw(led_on(LED_ERASE)); + ttw(ttr(TTrDrvErase, "e(%d)" NL, block)); + + dev.addr = (uint16 *) block2addr(block); + + cpsr = int_disable(); + dev.state = DEV_ERASE; + flash[0xAAAA] = 0xAA; // unlock cycle 1 + flash[0x5555] = 0x55; // unlock cycle 2 + flash[0xAAAA] = 0x80; + flash[0xAAAA] = 0xAA; // unlock cycle 1 + flash[0x5555] = 0x55; // unlock cycle 2 + *dev.addr = 0x30; // AMD erase sector command + int_enable(cpsr); + + ffsdrv_amd_erase_end(); +} + +void ffsdrv_amd_erase_end(void) +{ + while ((*dev.addr & 0x80) == 0) + ; + + dev.state = DEV_READ; + + tlw(led_off(LED_ERASE)); +} + +void ffsdrv_amd_erase_suspend(void) +{ + uint32 cpsr; + + tlw(led_on(LED_ERASE_SUSPEND)); + ttw(str(TTrDrvErase, "es" NL)); + + // if erase has finished then all is ok + if (*dev.addr & 0x80) { + ffsdrv_amd_erase_end(); + tlw(led_off(LED_ERASE_SUSPEND)); + return; + } + + // NOTEME: As there is no way to be absolutely certain that erase + // doesn't finish between last poll and the following erase suspend + // command, we assume that the erase suspend is safe even though the + // erase IS actually already finished. + + cpsr = int_disable(); + dev.state = DEV_ERASE_SUSPEND; + *dev.addr = 0xB0; + + // Wait for erase suspend to finish + while ((*dev.addr & 0x80) == 0) + ; + + int_enable(cpsr); +} + +void ffsdrv_amd_erase_resume(void) +{ + uint32 cpsr; + + ttw(str(TTrDrvErase, "er" NL)); + + // NOTEME: See note in erase_suspend()... We assume that the erase + // resume is safe even though the erase IS actually already finished. + cpsr = int_disable(); + dev.state = DEV_ERASE; + *dev.addr = 0x30; + int_enable(cpsr); + + tlw(led_off(LED_ERASE_SUSPEND)); +} + +const struct ffsdrv_s ffsdrv = { + ffsdrv_null_init, + ffsdrv_amd_erase, + ffsdrv_amd_write_halfword, + ffsdrv_generic_write, + ffsdrv_amd_write_end, + ffsdrv_amd_erase_suspend, + ffsdrv_amd_erase_resume +}; + +#else + +/* + * This part will get compiled if we have real FFS (FFS_IN_RAM=0), + * but not allowed to write to flash (CONFIG_FLASH_WRITE=0). + */ + +const struct ffsdrv_s ffsdrv = { + ffsdrv_null_init, + ffsdrv_null_erase, + ffsdrv_null_write_halfword, + ffsdrv_null_write, + ffsdrv_null_write_end, + ffsdrv_null_erase_suspend, + ffsdrv_null_erase_resume +}; + +#endif + + +/****************************************************************************** + * Initialization + * + * Significantly simplified in FreeCalypso. + * + ******************************************************************************/ + +effs_t ffsdrv_init(void) +{ + int error; + + tw(tr(TR_BEGIN, TrDrvInit, "drv_init() {\n")); + ttw(str(TTrDrvOther, "ffsdrv_init() {" NL)); + + dev.state = DEV_READ; + dev.atomlog2 = FFS_ATOM_LOG2; + dev.atomsize = 1 << dev.atomlog2; + dev.atomnotmask = dev.atomsize - 1; + + error = ffsdrv.init(); + + tw(tr(TR_FUNC, TrDrvInit, "dev.binfo = 0x%x\n", (unsigned int) dev.binfo)); + tw(tr(TR_FUNC, TrDrvInit, "dev.base = 0x%x\n", (unsigned int) dev.base)); + tw(tr(TR_FUNC, TrDrvInit, "dev.numblocks = %d\n", dev.numblocks)); + tw(tr(TR_FUNC, TrDrvInit, "dev.blocksize = %d\n", dev.blocksize)); + tw(tr(TR_FUNC, TrDrvInit, "dev.atomlog2/atomsize/atomnotmask = %d/%d/%x\n", + dev.atomlog2, dev.atomsize, dev.atomnotmask)); + tw(tr(TR_END, TrDrvInit, "} %d\n", error)); + ttw(ttr(TTrDrvOther, "} %d" NL, error)); + + return error; +} diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/drv.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/drv.h Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,187 @@ +/****************************************************************************** + * Flash File System (ffs) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * ffs low level flash driver + * + * $Id: drv.h 1.15.1.25.1.1.1.20 Mon, 17 Nov 2003 08:51:37 +0100 tsj $ + * + ******************************************************************************/ + +#ifndef TARGET +#define TARGET 1 +#define _RVF 1 +#endif + +/****************************************************************************** + * Compile constants + ******************************************************************************/ + +// FFS driver version (in four-digit BCD format). Format is MMID, where MM +// is major revision number, incremented e.g. for major revision or support +// for new flash family/driver. I is minor revision that is incremented for +// minor changes or when a bug is corrected. D is incremented when support +// of another device is added. +#define FFS_DRV_VERSION ((uint16) 0x1011) + +// Default Allocation granularity of ffs data sectors (as power of two) +#define FFS_ATOM_LOG2 4 + + +/****************************************************************************** + * Macros + ******************************************************************************/ + +// Convert between address and block index. Only works if all blocks are the +// same size! +#define block2addr(block) (dev.base + dev.binfo[block].offset) + +// Note that it is *VERY* important that pointers to hardware and flash are +// declared volatile, otherwise the compiler optimizes some reads and writes +// out and this results in non-working code! +#define FLASH_WRITE_HALFWORD(addr, data) *(volatile uint16 *) (addr) = (data) +#define FLASH_READ_HALFWORD(addr) *((volatile uint16 *) (addr)) + +#if (TARGET == 1) + +#include "../../include/config.h" +#include "../../bsp/mem.h" +#if (CHIPSET == 12) + #include "sys_inth.h" +#else +#include "../../bsp/inth.h" +#endif + +#if (CHIPSET == 3) +#define INT_REQUESTED (*(volatile uint16 *) INTH_IT_REG) & \ + ~(*(volatile uint16 *) INTH_MASK_REG) +#elif (CHIPSET == 4 || CHIPSET == 5 || CHIPSET == 6 || CHIPSET == 7 || CHIPSET == 8 || CHIPSET == 9 || CHIPSET == 10 || CHIPSET == 11) +#define INT_REQUESTED ((*(volatile uint16 *) INTH_IT_REG1) & \ + ~(*(volatile uint16 *) INTH_MASK_REG1)) || \ + ((*(volatile uint16 *) INTH_IT_REG2) & \ + ~(*(volatile uint16 *) INTH_MASK_REG2)) +#elif (CHIPSET == 12) +#define INT_REQUESTED ((*(volatile uint16 *) C_INTH_IT_REG1) & \ + ~(*(volatile uint16 *) C_INTH_MASK_REG1)) || \ + ((*(volatile uint16 *) C_INTH_IT_REG2) & \ + ~(*(volatile uint16 *) C_INTH_MASK_REG2)) +#endif +#endif // (TARGET == 1) + + +/****************************************************************************** + * Types + ******************************************************************************/ + +// Flash driver identifiers. +enum FFS_DRIVER { + FFS_DRIVER_NULL = 0, // Null driver + + FFS_DRIVER_AMD = 2, // AMD dual/multi-bank driver + FFS_DRIVER_AMD_SB = 3, // AMD single-bank driver + + FFS_DRIVER_SST = 8, // SST dual/multi-bank driver + FFS_DRIVER_SST_SB = 9, // SST single-bank driver + + FFS_DRIVER_INTEL = 16, // Intel dual/multi-bank driver + FFS_DRIVER_INTEL_SB = 17, // Intel single-bank driver + + FFS_DRIVER_AMD_PSEUDO_SB = 32, // Test driver + FFS_DRIVER_TEST = 34, // Test driver + + FFS_DRIVER_RAM = 64 // Ram driver +}; + + +// Manufacturer identifiers. These should never have to be changed. They are +// ordered in alphabetically ascending order. +enum FFS_MANUFACTURER { + MANUFACT_AMD = 0x01, + MANUFACT_ATMEL = 0x1F, + MANUFACT_FUJITSU = 0x04, + MANUFACT_INTEL = 0x89, + MANUFACT_MXIC = 0xC2, + MANUFACT_SAMSUNG = 0xEC, + MANUFACT_SHARP = 0xB0, + MANUFACT_SST = 0xBF, + MANUFACT_TOSHIBA = 0x98, + MANUFACT_RAM = 0xFE, // Ram + MANUFACT_TEST = 0x54 // 'T'est manufacturer +}; + + +// Flash block information for one ffs block (flash sector). Note that the +// ffs block definition might be of a smaller size then the physical flash +// sector. The ffs blocks must be defined in ascending order of addresses. +struct block_info_s { + uint32 offset; + uint8 size_ld; // log2 of block size + uint8 unused1; + uint8 unused2; + uint8 unused3; +}; + + +// General flash information for one flash device +struct flash_info_s { + const struct block_info_s *binfo; // block info array for this device + char *base; // base flash address of ffs blocks + uint16 manufact; // read with flash A0 = 0 + uint16 device; // read with flash A0 = 1 + uint8 driver; // flash driver type + uint8 numblocks; // number of blocks defined for use by ffs +}; +extern const struct flash_info_s flash_info[]; + +enum DEVICE_STATE { + DEV_READ, + DEV_ERASE, + DEV_ERASE_SUSPEND, + DEV_WRITE +}; + + +// Note that it is *VERY* important that pointers to hardware and flash are +// declared volatile, otherwise the compiler optimizes some reads and writes +// out and this results in non-working code! +struct dev_s { + char *base; // base flash address of ffs blocks + struct block_info_s *binfo; + uint16 manufact; + uint16 device; + volatile uint16 *addr; // address being written or erased + uint16 data; // data currently being written (dev.state = WRITE) + uint32 blocksize; + uint8 blocksize_ld; + uint8 atomlog2; + uint8 driver; + uint8 state; // state of device (DEVICE_STATE) + uint8 numblocks; + uint8 atomsize; + uint8 atomnotmask; +}; +extern struct dev_s dev; + + +// Flash low level driver function pointers +struct ffsdrv_s { + int (* init)(void); + void (* erase)(uint8 block); + void (* write_halfword)(volatile uint16 *dst, uint16 value); + void (* write)(void *dst, const void *src, uint16 size); + void (* write_end)(void); + void (* erase_suspend)(void); + void (* erase_resume)(void); +}; +extern const struct ffsdrv_s ffsdrv; /* const added for FreeCalypso */ + + +/****************************************************************************** + * Function Prototypes + ******************************************************************************/ + +void ffsdrv_write_byte(void *dst, uint8 value); +effs_t ffsdrv_init(void); + +//extern int ffs_ram_image_address; +// We do it in a different way in FreeCalypso diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/ffs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/ffs.h Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,406 @@ +/****************************************************************************** + * Flash File System (ffs) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * FFS Types and globals + * + * $Id: ffs.h 1.19.1.45.1.26 Mon, 28 Apr 2003 11:27:14 +0200 cm $ + * + ******************************************************************************/ + +#ifndef _FFS_H_ +#define _FFS_H_ + +#ifndef TARGET +#define TARGET 1 +#define _RVF 1 +#endif + +#ifdef _RVF +#include "../../riviera/rvf/rvf_api.h" +#include "../../riviera/rvm/rvm_use_id_list.h" +#endif + +/****************************************************************************** + * Types + ******************************************************************************/ + +#ifndef BASIC_TYPES +#define BASIC_TYPES +typedef signed char int8; +typedef unsigned char uint8; +typedef signed short int16; +typedef unsigned short uint16; +typedef signed int int32; +typedef unsigned int uint32; +#endif + +#if (TARGET == 1) +// Unique message offset returned in the header of each mail (msg_id). +#define FFS_MESSAGE_OFFSET BUILD_MESSAGE_OFFSET(FFS_USE_ID) +#endif + +typedef int8 effs_t; // error type +//typedef int effs_t; +typedef int32 req_id_t; // request id +typedef int32 offset_t; // offset from first address of ffs. +typedef uint32 location_t; // object location offset +typedef int32 blocksize_t; // can hold size of a block +typedef uint8 objflags_t; // object flags +typedef uint8 objtype_t; // object type + +typedef int16 iref_t; // inode reference +typedef int8 bref_t; // block reference + +typedef int32 fd_t; // file descriptor +typedef uint16 ffs_options_t; // option flags to open() and file_write() + +// For directory operations +struct dir_s { + iref_t this; // iref of dir that was opened + iref_t index; // last inode returned by ffs_readdir() +}; + +// File stat structure +struct stat_s { + objtype_t type; + objflags_t flags; + iref_t inode; + int size; // size of data space occupied by object +}; + +// File xstat structure +struct xstat_s { + objtype_t type; + objflags_t flags; + iref_t inode; + int size; // size of data space occupied by object + int space; // size of physical data space occupied by object + location_t location; + uint8 reserved; // only for debug + bref_t block; // only for debug + uint16 sequence; // only for debug + uint16 updates; // only for debug +}; + +#if (TARGET == 0) +// Only use to run on PC and not in target. Must be syncron with the typedef +// from rv_general.h +typedef void (*CALLBACK_FUNC)(void *); + +typedef uint16 T_RVF_ADDR_ID; + +/* define return_path */ +typedef struct +{ + T_RVF_ADDR_ID addr_id; + void (*callback_func)(void *); +} T_RV_RETURN; + +/* Define the header of each message used in Riviera. */ +typedef struct { + uint32 msg_id; + void (*callback_func)(void *); + T_RVF_ADDR_ID src_addr_id; + T_RVF_ADDR_ID dest_addr_id; +} T_RV_HDR; + +// Used riviera types +typedef uint16 UINT16; +typedef int8 INT8; + +#endif + +// Confirm mail sent from FFS task to caller (application) +struct ffs_file_cnf_s { + T_RV_HDR header; + int error; // error code of FFS operation + req_id_t request_id; // Unique id number + char *path; // path name of object operation was performed on +}; + +struct ffs_stream_cnf_s { + T_RV_HDR header; + int error; // error code of FFS operation + req_id_t request_id; // Unique id number + fd_t fdi; // file descriptor +}; + +/****************************************************************************** + * RVF Types + ******************************************************************************/ + +typedef ffs_options_t T_FFS_OPEN_FLAGS; +typedef int T_FFS_SIZE; +typedef offset_t T_FFS_OFFSET; +typedef effs_t T_FFS_RET; +typedef req_id_t T_FFS_REQ_ID; +typedef int T_FFS_WHENCE; +typedef fd_t T_FFS_FD; +typedef objtype_t T_FFS_OBJECT_TYPE; +typedef objflags_t T_FFS_FLAGS; +typedef struct stat_s T_FFS_STAT; +typedef struct xstat_s T_FFS_XSTAT; +typedef struct dir_s T_FFS_DIR; +typedef struct ffs_file_cnf_s T_FFS_FILE_CNF; +typedef struct ffs_stream_cnf_s T_FFS_STREAM_CNF; + +/****************************************************************************** + * Errors + ******************************************************************************/ + +enum FFS_ERRORS { + EFFS_OK = 0, /* ok */ + EFFS_NODEVICE = -1, /* flash device unknown */ + EFFS_CORRUPTED = -2, /* filesystem corrupted!? */ + EFFS_NOPREFORMAT = -3, /* ffs not preformatted */ + EFFS_NOFORMAT = -4, /* ffs not formatted */ + EFFS_BADFORMAT = -5, /* incompatible ffs version, re-format needed */ + EFFS_MAGIC = -6, /* bad magic */ + EFFS_AGAIN = -7, /* not ready, try again later */ + EFFS_NOSYS = -8, /* function not implemented */ + EFFS_DRIVER = -9, /* ffs device driver error */ + + EFFS_NOSPACE = -10, /* out of data space */ + EFFS_FSFULL = -11, /* file system full, no free inodes */ + EFFS_BADNAME = -12, /* bad filename */ + EFFS_NOTFOUND = -13, /* object not found */ + EFFS_EXISTS = -14, /* object exists */ + EFFS_ACCESS = -15, /* access permission violation */ + EFFS_NAMETOOLONG = -16, /* filename too long */ + EFFS_INVALID = -17, /* invalid argument */ + EFFS_DIRNOTEMPTY = -18, /* directory not empty */ + EFFS_NOTADIR = -19, /* object is not a directory */ + EFFS_SPARE = -20, /* SPARE */ + EFFS_FILETOOBIG = -21, /* file too big */ + EFFS_NOTAFILE = -22, /* object is not a file */ + EFFS_PATHTOODEEP = -23, /* path too deep */ + + EFFS_NUMFD = -24, /* Max number of open files reached */ + EFFS_BADFD = -25, /* Bad file descriptor */ + EFFS_BADOP = -26, /* Bad operation */ + EFFS_LOCKED = -27, /* The file is locked */ + + EFFS_TOOBIG = -30, /* too big (tmffs buffer overflow) */ + EFFS_MEMORY = -31, /* out of memory */ + EFFS_MSGSEND = -32, /* message send failed */ + + /* debug errors */ + + EFFS_SIBLINGLOOP = -40, /* directory sibling loop */ + EFFS_NOBLOCKS = -41, /* No more blocks!? */ + EFFS_DBR = -42, /* Data reclaim did not finish!? */ + EFFS_RECLAIMLOOP = -43 /* Data reclaim loop */ +}; + + +/****************************************************************************** + * Enumerations + ******************************************************************************/ + +enum FFS_OBJECT_CONTROL_ACTION { + OC_FLAGS = 1 +}; + +enum FFS_OBJECT_TYPE { + OT_FILE = 1, + OT_DIR = 2, + OT_LINK = 3, + OT_SEGMENT = 4 +}; + +enum FFS_OBJECT_FLAGS { + OF_READONLY = 1<<4 // object cannot be modified +}; + +enum FFS_OPEN { + FFS_O_EMPTY = 0x00, // Okay? + FFS_O_CREATE = 0x01, + FFS_O_APPEND = 0x02, + FFS_O_EXCL = 0x04, + FFS_O_TRUNC = 0x08, + FFS_O_RDONLY = 0x10, + FFS_O_WRONLY = 0x20, + FFS_O_RDWR = FFS_O_RDONLY | FFS_O_WRONLY +}; + +enum FFS_SEEK { + FFS_SEEK_SET = 0, + FFS_SEEK_CUR = 1, + FFS_SEEK_END = 2 +}; + +// FIXME: debug indices to go into core.h +enum FFS_QUERY { // data size, description + Q_BYTES_FREE = 1, // 4, number of free bytes in FFS + Q_BYTES_USED = 2, // 4, number of used bytes in FFS + Q_BYTES_LOST = 3, // 4, number of lost bytes in FFS + Q_BYTES_MAX = 4, // 4, number of max available bytes in FFS + Q_BYTES_FREE_RAW = 5, // 4, number of free raw bytes in FFS (used internal) + + Q_FD_BUF_SIZE = 10, // 4, size of buffer used by stream functions + + Q_TM_BUFADDR = 11, // 4, testmode buffer addr + Q_TM_BUFSIZE = 12, // 4, testmode ffs buffer size + Q_DEV_BASE = 13, // 4, FFS device base address + Q_CHUNK_SIZE_MAX = 14, // 4, max size of chunks made by non stream fkt. + + // FFS versions + Q_FFS_API_VERSION = 16, // 2, FFS API Version + Q_FFS_DRV_VERSION = 17, // 2, FFS Driver Version + Q_FFS_REVISION = 18, // 2, FFS Revision (from PRCS) + Q_FFS_FORMAT_READ = 19, // 2, FFS version as read from ffs + Q_FFS_LASTERROR = 20, // 2, FFS last error (from init) + Q_FFS_FORMAT_WRITE = 21, // 2, FFS version as written to ffs on format + Q_FFS_TM_VERSION = 22, // 2, FFS Testmode version + + // File system queries + Q_FILENAME_MAX = 24, // 2, max filename length + Q_PATH_DEPTH_MAX = 25, // 2, max path/directory nesting depth + Q_FD_MAX = 26, // 2, max numbers of simultaneous open files + + Q_OBJECTS_FREE = 32, // 2, number of objects that can be created + Q_INODES_USED = 33, // 2, number of inodes used + Q_INODES_LOST = 34, // 2, number of inodes lost + Q_OBJECTS_USED = 33, // 2, DEPRECATED: old name for Q_INODES_USED + Q_OBJECTS_LOST = 34, // 2, DEPRECATED: old name for Q_INODES_LOST + Q_OBJECTS_MAX = 35, // 2, max number of valid objects allowed + Q_INODES_MAX = 36, // 2, physical total max number of inodes + Q_INODES_HIGH = 37, // 2, watermark for when inodes will be reclaimed + Q_LOST_HIGH = 38, // 2, watermark for when data block will be reclaimed + + // Device queries + Q_DEV_MANUFACTURER = 48, // 2, flash manufacturer ID + Q_DEV_DEVICE = 49, // 2, flash device ID + Q_DEV_BLOCKS = 50, // 2, number of FFS blocks in device + Q_DEV_ATOMSIZE = 51, // 2, atomsize used by FFS for this device + Q_DEV_DRIVER = 52, // 2, flash device driver + + // All queries below here are for debug purpose only, are unsupported + // and can change at any time without notice! + + // Miscellaneous/Internal + Q_BLOCKS_FREE_MIN = 64, // 2, Number of spare blocks (0 or 1) + + Q_BLOCKS_FREE = 70, // 2, number of free blocks + + // Debug queries + Q_FS_FLAGS = 80, + Q_FS_INODES = 81, + Q_FS_ROOT = 82, + + Q_OBJECTS_TOTAL = 90, // 2, Accumulated number of valid objects + Q_TOTAL_OBJECTS = 90, // 2, DEPRECATED: old name for Q_OBJECTS_TOTAL + + Q_STATS_FIRST = 100, + Q_STATS_DRECLAIMS = 100, + Q_STATS_IRECLAIMS = 101, + Q_STATS_BRECLAIMS = 102, + Q_STATS_DATA_RECLAIMED = 103, + Q_STATS_INODES_RECLAIMED = 104, + Q_STATS_DATA_ALLOCATED = 105, + + Q_REQUEST_ID_LAST = 110, + + Q_DEBUG_FIRST = 120, + Q_DEBUG_0 = 120, + Q_DEBUG_1 = 121, + Q_DEBUG_2 = 122, + Q_DEBUG_3 = 123, + Q_DEBUG_LAST = 127, + + // individual lines of the bstat array can be returned by the following + // id plus the bstat index of the line wanted. + Q_BSTAT = -128 +}; + + +/****************************************************************************** + * Function prototypes + ******************************************************************************/ + +// Call-back function prototypes +T_FFS_REQ_ID ffs_fcreate_nb(const char *name, void *addr, T_FFS_SIZE size, + T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_fupdate_nb(const char *name, void *addr, T_FFS_SIZE size, + T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_fwrite_nb(const char *name, void *addr, T_FFS_SIZE size, + T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_file_write_nb(const char *name, void *addr, T_FFS_SIZE size, + T_FFS_OPEN_FLAGS flags, T_RV_RETURN *cp); + +T_FFS_REQ_ID ffs_mkdir_nb(const char *name, T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_symlink_nb(const char *name, const char *actualpath, + T_RV_RETURN *cp); + +T_FFS_REQ_ID ffs_remove_nb(const char *namestruct, T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_fcontrol_nb(const char *pathname, INT8 action, int param, + T_RV_RETURN *cp); + +T_FFS_REQ_ID ffs_rename_nb(const char *oldname, const char *newname, + T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_preformat_nb(UINT16 magic, T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_format_nb(const char *name, UINT16 magic, T_RV_RETURN *cp); + +T_FFS_REQ_ID ffs_open_nb(const char *name, T_FFS_OPEN_FLAGS option, + T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_close_nb(T_FFS_FD fdi, T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_write_nb(T_FFS_FD fdi, void *src, T_FFS_SIZE size, + T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_seek_nb(T_FFS_FD fdi, T_FFS_SIZE offset, T_FFS_WHENCE whence + , T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_truncate_nb(const char *path, T_FFS_OFFSET length, + T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_ftruncate_nb(T_FFS_FD fdi, T_FFS_OFFSET length, + T_RV_RETURN *cp); +T_FFS_REQ_ID ffs_fdatasync_nb(T_FFS_FD fdi, T_RV_RETURN *cp); + +// No-call-back function prototypes +T_FFS_RET ffs_fcreate(const char *name, void *addr, T_FFS_SIZE size); +T_FFS_RET ffs_fupdate(const char *name, void *addr, T_FFS_SIZE size); +T_FFS_RET ffs_fwrite(const char *name, void *addr, T_FFS_SIZE size); +T_FFS_RET ffs_file_write(const char *name, void *addr, T_FFS_SIZE size, + T_FFS_OPEN_FLAGS flags); +T_FFS_SIZE ffs_fread(const char *name, void *addr, T_FFS_SIZE size); +T_FFS_SIZE ffs_file_read(const char *name, void *addr, T_FFS_SIZE size); + +T_FFS_RET ffs_mkdir(const char *name); +T_FFS_SIZE ffs_opendir(const char *name, T_FFS_DIR *dir); +T_FFS_SIZE ffs_readdir (T_FFS_DIR *dir, char *name, T_FFS_SIZE size); + +T_FFS_RET ffs_symlink(const char *name, const char *actualpath); +T_FFS_SIZE ffs_readlink(const char *name, char *addr, T_FFS_SIZE size); + +T_FFS_RET ffs_stat(const char *name, T_FFS_STAT *stat); +T_FFS_RET ffs_linkstat(const char *name, T_FFS_STAT *stat); +T_FFS_RET ffs_lstat(const char *name, T_FFS_STAT *stat); +T_FFS_RET ffs_xlstat(const char *name, T_FFS_XSTAT *stat); +T_FFS_RET ffs_fstat(T_FFS_FD fdi, T_FFS_STAT *stat); + +T_FFS_RET ffs_remove(const char *name); +T_FFS_RET ffs_fcontrol(const char *pathname, INT8 action, int param); + + +T_FFS_RET ffs_rename(const char *oldname, const char *newname); + +T_FFS_RET ffs_query(INT8 query, void *p); + +T_FFS_RET ffs_preformat(UINT16 magic); +T_FFS_RET ffs_format(const char *name, UINT16 magic); + +T_FFS_FD ffs_open(const char *name, T_FFS_OPEN_FLAGS option); +T_FFS_RET ffs_close(T_FFS_FD fdi); +T_FFS_SIZE ffs_write(T_FFS_FD fdi, void *src, T_FFS_SIZE amount); +T_FFS_SIZE ffs_seek(T_FFS_FD fdi, T_FFS_SIZE offset, T_FFS_WHENCE whence); +T_FFS_SIZE ffs_read(T_FFS_FD fdi, void *src, T_FFS_SIZE size); + +T_FFS_RET ffs_truncate(const char *path, T_FFS_OFFSET length); + +T_FFS_RET ffs_ftruncate(T_FFS_FD fdi, T_FFS_OFFSET length); + +T_FFS_RET ffs_fdatasync(T_FFS_FD fdi); + +// This function is to be implemented by user. It is defined in cfgffs.c. +extern T_FFS_RET ffs_is_modifiable(const char *name); + +#endif //_FFS_H_ diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/ffs_api.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/ffs_api.h Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,28 @@ +/****************************************************************************/ +/* */ +/* File Name: ffs_api.h */ +/* */ +/* */ +/* Version 0.1 */ +/* */ +/* Date Modification */ +/* ------------------------------------ */ +/* 28 January 2002 Create */ +/* */ +/* Author Stephanie Gerthoux */ +/* */ +/* (C) Copyright 2002 by Texas Instruments Incorporated, All Rights Reserved*/ +/****************************************************************************/ + +#ifndef _FFS_API_H_ +#define _FFS_API_H_ + +#include "ffs.h" + +/****************************************************************************** + * Types + ******************************************************************************/ + + #define FFS_OBJECT_TYPE T_FFS_OBJECT_TYPE + +#endif diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/ffs_env.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/ffs_env.h Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,58 @@ +/****************************************************************************/ +/* */ +/* File Name: ffs_env.h */ +/* */ +/* Purpose: This file contains prototypes for RV manager related */ +/* functions used to get info, start and stop the ffs block. */ +/* */ +/* Version 0.1 */ +/* */ +/* Date Modification */ +/* ------------------------------------ */ +/* 10/24/2000 Create */ +/* */ +/* Author Pascal Puel */ +/* */ +/* This code is in the public domain per the order of the Supreme */ +/* Revolutionary Command. */ +/****************************************************************************/ +#ifndef __FFS_ENV_H_ +#define __FFS_ENV_H_ + + +#include "../../riviera/rvm/rvm_gen.h" +#include "ffs_pool_size.h" /* Stack & Memory Bank sizes definitions */ + + +/* FFS mailbox */ +#define FFS_MAILBOX RVF_TASK_MBOX_0 + +/* min mem size: fd_max * fd_buf_size + 1k */ +/* memory bank size and watermark */ +#define FFS_MB_PRIM_SIZE FFS_MB1_SIZE + +#define FFS_MB_PRIM_WATERMARK (FFS_MB_PRIM_SIZE - 3000) + + +typedef struct { + T_RVF_MB_ID mbid; + T_RVF_ADDR_ID addr_id; +} T_FFS_TASK_INFO; + +extern T_FFS_TASK_INFO ffs_task_info; + +/* generic functions declarations */ +T_RVM_RETURN ffs_get_info (T_RVM_INFO_SWE *infoSWE); +T_RVM_RETURN ffs_set_info(T_RVF_ADDR_ID addr_id, + T_RV_RETURN ReturnPath[], + T_RVF_MB_ID mbId[], + T_RVM_RETURN (*callBackFct)(T_RVM_NAME SWEntName, + T_RVM_RETURN errorCause, + T_RVM_ERROR_TYPE errorType, + T_RVM_STRING errorMsg)); +T_RVM_RETURN ffs_init (void); +T_RVM_RETURN ffs_start (void); +T_RVM_RETURN ffs_stop (void); +T_RVM_RETURN ffs_kill (void); + +#endif /*__FFS_ENV_H_*/ diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/ffs_pool_size.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/ffs_pool_size.h Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,52 @@ +/** + * @file ffs_pool_size.h + * + * Declarations of: + * - the memory bank sizes and their watermark + * - the SWE stack size + * - the pool size needed (generally the sum of memory bank and stack sizes) + * + * @author Vincent Oberle + * @version 0.1 + */ + +/* + * History: + * + * Date Author Modification + * ------------------------------------------------------------------- + * 07/08/2003 Vincent Oberle Extracted from rvf_pool_size.h + * 09/03/2004 Tommy Jensen Split pool size into several defines + * + * This code is in the public domain per the order of the + * Supreme Revolutionary Command. + */ + +#ifndef __FFS_POOL_SIZE_H_ +#define __FFS_POOL_SIZE_H_ + +#include "../../include/config.h" +#include "../../riviera/rv/rv_defined_swe.h" + +/* + * Values used in ffs_env.h + */ +#define FFS_STACK_SIZE (1024) +#define FFS_MAILBUF_SIZE (1024) // Default: Max 20 pending FFS mails. +#define FFS_TESTBUF_SIZE (0) // Must be set to zero + +#if (!GSMLITE) +#ifdef RVM_MSFE_SWE + #define FFS_STREAMBUF_SIZE (40960) +#else + #define FFS_STREAMBUF_SIZE (8192) +#endif // RVM_MSFE_SWE +#else + #define FFS_STREAMBUF_SIZE (4096) +#endif // GSMLITE + +#define FFS_MB1_SIZE (FFS_STREAMBUF_SIZE + FFS_MAILBUF_SIZE + FFS_TESTBUF_SIZE) +#define FFS_POOL_SIZE (FFS_STACK_SIZE + FFS_MB1_SIZE) + + +#endif /*__FFS_POOL_SIZE_H_*/ diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/ffstrace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/ffstrace.h Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,154 @@ +/****************************************************************************** + * Flash File System (ffs) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * ffs tracing + * + * $Id: ffstrace.h 1.38.1.4 Wed, 14 Aug 2002 13:02:34 +0200 tsj $ + * + ******************************************************************************/ + + +/****************************************************************************** + ** Common Tracing and logging + *****************************************************************************/ + +int tr_query(int mask); + + +/****************************************************************************** + ** Target Tracing + ******************************************************************************/ + +#if (TARGET == 1) + +#define tw(contents) +#define ttw(contents) contents +#define tlw(contents) +#define NL +void ttr_init(unsigned int mask); +void ttr(unsigned trmask, char *format, ...); +void str(unsigned mask, char *string); + +void led_config(unsigned char n); +void led_set(unsigned char n); +void led_counter(unsigned char n); +void led_on(unsigned char n); +void led_off(unsigned char n); +void led_toggle(unsigned char n); + +enum TargetTraceMask { + TTrTest = 0x00000001, + TTrTestInfo = 0x00000002, + + TTrApi = 0x00000010, + TTrDrvWrite = 0x00000020, + TTrDrvErase = 0x00000040, + TTrDrvOther = 0x00000080, + + TTrInit = 0x00000100, + TTrInitLow = 0x00000200, + TTrFormat = 0x00000400, + + TTrObj = 0x00001000, + TTrInode = 0x00002000, + TTrData = 0x00004000, + TTrMisc = 0x00008000, + + TTrRec = 0x00020000, + TTrPcmRead = 0x00040000, + TTrPcmWrite = 0x00080000, + + TTrTask = 0x00100000, + TTrTaskLow = 0x00200000, + TTrBstat = 0x00400000, + + TTrTmffs = 0x08000000, + + TTrTaskDelays = 0x10000000, + TTrFatal = 0x80000000, + + TTrAll = 0xFFFFFFFF +}; + +enum { + LED_INIT = 0, + LED_DRV_INIT = 1, + LED_BLOCKS_FSCK = 2, + LED_INODES_FSCK = 3, + LED_WRITE_SUSPEND = 4, + LED_WRITE = 5, + LED_ERASE_SUSPEND = 6, + LED_ERASE = 7 +}; + + +/****************************************************************************** + ** PC Tracing + ******************************************************************************/ + +#else // (TARGET == 1) + +void tr_init(unsigned int mask, int spaces, char *filename); +void tr(int type, unsigned int mask, char *format, ...); + + +//void tr_init(int mask, int level,int spaces, char *filename); +//void tr(int level, int type, char *format, ...); +#define tw(contents) contents +#define ttw(contents) +#define tlw(contents) + +#define led_config(n) +#define led_set(n) +#define led_counter(n) +#define led_on(n) +#define led_off(n) + +enum SimulationTraceMask { + TrTest = 0x00000001, + TrTestHigh = 0x00000002, + TrTestLow = 0x00000004, + TrApi = 0x00000008, + + TrBstat = 0x00000010, + TrFormat = 0x00000020, + TrFsck = 0x00000040, + TrFsckLow = 0x00000080, + + TrObject = 0x00000100, // object_create/remove/read/stat, etc. + TrLookup = 0x00000200, + TrDirLow = 0x00000400, + TrDirHigh = 0x00000800, + + TrBlock = 0x00001000, // block_alloc/free, etc. + TrInode = 0x00002000, // inode_alloc, etc. + TrData = 0x00004000, // data_alloc + + TrIReclaim = 0x00010000, + TrDReclaim = 0x00020000, + TrReclaimLow = 0x00040000, + TrJournal = 0x00080000, + + TrDrvInit = 0x00100000, + TrDrvWrite = 0x00200000, + TrDrvErase = 0x00400000, + + TrOther = 0x01000000, // object_control, query, etc. + TrUtil = 0x02000000, + TrTmffs = 0x03000000, + TrServer = 0x08000000, + + TrTrace = 0x80000000, + TrAll = 0xFFFFFFFF +}; + +enum TRACE_TYPES { + TR_BEGIN = 0x100, + TR_END = 0x200, + TR_FUNC = 0x400, + TR_NULL = 0x800 +}; + + +#endif // (TARGET == 1) diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/intctl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/intctl.h Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,21 @@ +/* + * The int_disable() and int_enable() calls in TI's FFS code are nothing + * more than TCT_Control_Interrupts() aka NU_Control_Interrupts(). + * TI's original code used assembly (proprietary toolchain asm syntax and + * ABI semantics) to make the needed Thumb->ARM calls; we don't need such + * idiocy in FreeCalypso, so we have turned int_disable() and int_enable() + * into simple inline functions. + */ + +#include "ffs.h" +#include "../../nucleus/nucleus.h" + +static inline uint32 int_disable(void) +{ + return NU_Control_Interrupts(NU_DISABLE_INTERRUPTS); +} + +static inline void int_enable(uint32 tmp) +{ + NU_Control_Interrupts(tmp); +} diff -r 2abe6ade042d -r 6f4a12b4582f gsm-fw/services/ffs/ramffs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/ramffs.h Thu Dec 26 03:59:59 2013 +0000 @@ -0,0 +1,16 @@ +/* + * This FFS implementation header file is a FreeCalypso addition. + * Here we have some preprocessor magic and extern declarations + * for the FFS-in-RAM configuration which are needed at both + * "flash driver" and "FFS configuration" abstraction levels. + */ + +#include "../../include/config.h" +#if FFS_IN_RAM + +#define RAMFFS_BLKSIZE_BYTES (1 << RAMFFS_BLKSIZE_LOG2) +#define RAMFFS_TOTAL_SIZE (RAMFFS_BLKSIZE_BYTES * RAMFFS_NBLOCKS) + +extern char _RAMFFS_area[RAMFFS_TOTAL_SIZE]; + +#endif /* FFS_IN_RAM */