From 3d5f3cc536fd1e1c2ce477c4f3ba5147eb8678be Mon Sep 17 00:00:00 2001 From: charles Date: Fri, 13 Dec 2002 00:13:06 +0000 Subject: [PATCH] *** empty log message *** --- Makefile | 4 +- utils/Makefile | 6 + utils/mkyaffs | Bin 16029 -> 16029 bytes utils/mkyaffs.c | 4 +- utils/mkyaffsimage.c | 34 +- yaffs_guts.c | 57 ++- yaffs_guts.h | 1123 +++++++++++++++++++++--------------------- yaffs_mtdif.c | 52 +- 8 files changed, 668 insertions(+), 612 deletions(-) diff --git a/Makefile b/Makefile index 633c1b1..21d4b59 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # -# $Id: Makefile,v 1.8 2002-11-26 01:15:37 charles Exp $ +# $Id: Makefile,v 1.9 2002-12-13 00:13:06 charles Exp $ # ## Change or override KERNELDIR to your kernel @@ -46,6 +46,8 @@ USE_MTD = -DCONFIG_YAFFS_MTD_ENABLED # CONFIG_YAFFS_USE_NANDECC # This enables the ECC functions of the generic MTD-NAND driver. # This will not work if you are using the old mtd. +# +# NB UseNANDECC does not work at present with yaffsram. USE_NANDECC = -DCONFIG_YAFFS_USE_NANDECC diff --git a/utils/Makefile b/utils/Makefile index a628641..1e0d432 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -17,6 +17,8 @@ KERNELDIR = /usr/src/kernel-headers-2.4.18 CFLAGS = -I$(KERNELDIR)/include -I.. -O2 -Wall +CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations +CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline MKYAFFSOBJS = mkyaffs.o @@ -38,5 +40,9 @@ $(MKYAFFSOBJS): %.o: %.c mkyaffs: $(MKYAFFSOBJS) gcc -o $@ $(MKYAFFSOBJS) +nand_ecc.c: + ln -s ../nand_ecc.c nand_ecc.c + + clean: rm -f $(MKYAFFSOBJS) $(MKYAFFSIMAGEOBJS) core diff --git a/utils/mkyaffs b/utils/mkyaffs index 644ea3b8700b2469f3a9e8c111e9f5aa981e646f..5ed31f26b564af6b8a6523109ab970bf6083aa4f 100755 GIT binary patch delta 34 ocmbPRJGXYjM@~^w1tS9kBV9uvGFC7!urf5ZGBDfB#x>mp0KSU}dH?_b delta 34 pcmbPRJGXYjM@~@_1tS9kBV9uST>~Qp10yR#Ln|ZG&1_uLO#r?;33dPg diff --git a/utils/mkyaffs.c b/utils/mkyaffs.c index 53055b3..8b7350d 100644 --- a/utils/mkyaffs.c +++ b/utils/mkyaffs.c @@ -34,7 +34,7 @@ #include #include -const char *mkyaffs_c_version = "$Id: mkyaffs.c,v 1.4 2002-10-02 02:11:25 charles Exp $"; +const char *mkyaffs_c_version = "$Id: mkyaffs.c,v 1.5 2002-12-13 00:13:06 charles Exp $"; // countBits is a quick way of counting the number of bits in a byte. // ie. countBits[n] holds the number of 1 bits in a byte with the value n. @@ -74,7 +74,7 @@ int main(int argc, char **argv) { unsigned long addr; unsigned long offset; - int bs, fd, i; + int fd; int img=-1; int imglen = 0; struct mtd_oob_buf oob = {0, 16, (unsigned char *) &oobbuf}; diff --git a/utils/mkyaffsimage.c b/utils/mkyaffsimage.c index b71cf92..814e2af 100644 --- a/utils/mkyaffsimage.c +++ b/utils/mkyaffsimage.c @@ -33,7 +33,7 @@ #define MAX_OBJECTS 10000 -const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.5 2002-11-28 07:24:32 charles Exp $"; +const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.6 2002-12-13 00:13:06 charles Exp $"; // External functions for ECC on data void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); @@ -59,7 +59,7 @@ static int outFile; static int error; -int obj_compare(const void *a, const void * b) +static int obj_compare(const void *a, const void * b) { objItem *oa, *ob; @@ -75,7 +75,7 @@ int obj_compare(const void *a, const void * b) } -void add_obj_to_list(dev_t dev, ino_t ino, int obj) +static void add_obj_to_list(dev_t dev, ino_t ino, int obj) { if(n_obj < MAX_OBJECTS) { @@ -95,11 +95,11 @@ void add_obj_to_list(dev_t dev, ino_t ino, int obj) } -int find_obj_in_list(dev_t dev, ino_t ino) +static int find_obj_in_list(dev_t dev, ino_t ino) { objItem *i = NULL; objItem test; - + test.dev = dev; test.ino = ino; @@ -133,13 +133,13 @@ static __u16 yaffs_CalcNameSum(const char *name) } -void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) +static void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) { nand_calculate_ecc (data , spare->ecc1); nand_calculate_ecc (&data[256] , spare->ecc2); } -void yaffs_CalcTagsECC(yaffs_Tags *tags) +static void yaffs_CalcTagsECC(yaffs_Tags *tags) { // Todo don't do anything yet. Need to calculate ecc unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes; @@ -170,7 +170,7 @@ static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr) { yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr; - yaffs_CalcTagsECC(tagsPtr); + //yaffs_CalcTagsECC(tagsPtr); sparePtr->tagByte0 = tu->asBytes[0]; sparePtr->tagByte1 = tu->asBytes[1]; @@ -184,14 +184,14 @@ static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr) -int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) +static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) { yaffs_Tags t; yaffs_Spare s; - + error = write(outFile,data,512); if(error < 0) return error; - + memset(&t,0xff,sizeof (yaffs_Tags)); memset(&s,0xff,sizeof (yaffs_Spare)); @@ -210,7 +210,7 @@ int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) } -int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias) +static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias) { __u8 bytes[512]; @@ -258,13 +258,13 @@ int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int paren } -int process_directory(int parent, const char *path) +static int process_directory(int parent, const char *path) { DIR *dir; struct dirent *entry; - nDirectories++; + nDirectories++; dir = opendir(path); @@ -317,9 +317,9 @@ int process_directory(int parent, const char *path) char symname[500]; - memset(symname,0,500); + memset(symname,0, sizeof(symname)); - readlink(full_name,symname,499); + readlink(full_name,symname,sizeof(symname) -1); printf("symlink to \"%s\"\n",symname); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname); @@ -413,7 +413,7 @@ int main(int argc, char *argv[]) { printf("usage: mkyaffsimage dir image_file\n"); printf(" dir the directory tree to be converted\n"); - printf(" image_file the ouput file to hold the image\n"); + printf(" image_file the output file to hold the image\n"); exit(1); } diff --git a/yaffs_guts.c b/yaffs_guts.c index 2fddbc2..9ddabf6 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -14,7 +14,7 @@ */ //yaffs_guts.c -const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.14 2002-12-04 19:12:43 charles Exp $"; +const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.15 2002-12-13 00:13:06 charles Exp $"; #include "yportenv.h" @@ -190,12 +190,44 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, #ifndef CONFIG_YAFFS_USE_NANDECC - retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,spare); - if(data && doErrorCorrection) - { - // Hoosterman, we had a data problem on this page - yaffs_HandleReadDataError(dev,chunkInNAND); - } + retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,spare); + if(data && doErrorCorrection) + { + // Do ECC correction + //Todo handle any errors + nand_calculate_ecc(data,calcEcc); + eccResult1 = nand_correct_data (data,spare->ecc1, calcEcc); + nand_calculate_ecc(&data[256],calcEcc); + eccResult2 = nand_correct_data (&data[256],spare->ecc2, calcEcc); + + if(eccResult1>0) + { + T(YAFFS_TRACE_ERROR, (TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND)); + dev->eccFixed++; + } + else if(eccResult1<0) + { + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND)); + dev->eccUnfixed++; + } + + if(eccResult2>0) + { + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND)); + dev->eccFixed++; + } + else if(eccResult2<0) + { + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND)); + dev->eccUnfixed++; + } + + if(eccResult1 || eccResult2) + { + // Hoosterman, we had a data problem on this page + yaffs_HandleReadDataError(dev,chunkInNAND); + } + } #else retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare*)&nspare); memcpy (spare, &nspare, sizeof(yaffs_Spare)); @@ -1869,12 +1901,19 @@ static int yaffs_FindBlockForAllocation(yaffs_Device *dev) for(i = dev->startBlock; i <= dev->endBlock; i++) { - bi = yaffs_GetBlockInfo(dev,i); + dev->allocationBlockFinder++; + if(dev->allocationBlockFinder < dev->startBlock || + dev->allocationBlockFinder > dev->endBlock) + { + dev->allocationBlockFinder = dev->startBlock; + } + + bi = yaffs_GetBlockInfo(dev,dev->allocationBlockFinder); if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY) { bi->blockState = YAFFS_BLOCK_STATE_ALLOCATING; dev->nErasedBlocks--; - return i; + return dev->allocationBlockFinder; } } diff --git a/yaffs_guts.h b/yaffs_guts.h index 6130c4f..3ab41f7 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -1,561 +1,562 @@ -/* - * YAFFS: Yet another FFS. A NAND-flash specific file system. - * yaffs_guts.h: Configuration etc for yaffs_guts - * - * Copyright (C) 2002 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 as - * published by the Free Software Foundation. - * - * - * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. - * - * $Id: yaffs_guts.h,v 1.12 2002-11-26 01:15:37 charles Exp $ - */ - -#ifndef __YAFFS_GUTS_H__ -#define __YAFFS_GUTS_H__ - -#include "devextras.h" - - -#define YAFFS_OK 1 -#define YAFFS_FAIL 0 - -// Give us a Y=0x59, -// Give us an A=0x41, -// Give us an FF=0xFF -// Give us an S=0x53 -// And what have we got... -#define YAFFS_MAGIC 0x5941FF53 - -#define YAFFS_NTNODES_LEVEL0 16 -#define YAFFS_TNODES_LEVEL0_BITS 4 -#define YAFFS_TNODES_LEVEL0_MASK 0xf - -#define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2) -#define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1) -#define YAFFS_TNODES_INTERNAL_MASK 0x7 -#define YAFFS_TNODES_MAX_LEVEL 6 - -#define YAFFS_BYTES_PER_CHUNK 512 -#define YAFFS_CHUNK_SIZE_SHIFT 9 - -#define YAFFS_BYTES_PER_SPARE 16 - -#define YAFFS_CHUNKS_PER_BLOCK 32 -#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK) - -#define YAFFS_MAX_CHUNK_ID 0x000FFFFF - -#define YAFFS_UNUSED_OBJECT_ID 0x0003FFFF - -#define YAFFS_ALLOCATION_NOBJECTS 100 -#define YAFFS_ALLOCATION_NTNODES 100 -#define YAFFS_ALLOCATION_NLINKS 100 - -#define YAFFS_NOBJECT_BUCKETS 256 - - -#define YAFFS_RESERVED_BLOCKS 8 - -#define YAFFS_OBJECT_SPACE 0x40000 -#define YAFFS_MAX_NAME_LENGTH 255 -#define YAFFS_SHORT_NAME_LENGTH 15 - -#define YAFFS_MAX_ALIAS_LENGTH 159 - -#define YAFFS_OBJECTID_ROOT 1 -#define YAFFS_OBJECTID_LOSTNFOUND 2 -#define YAFFS_OBJECTID_UNLINKED 3 - -#define YAFFS_N_CACHE_CHUNKS 10 - -#ifdef CONFIG_YAFFS_WINCE - -// Force the short operation cache on for WinCE - -#define CONFIG_YAFFS_SHORT_OP_CACHE -#endif - - -// ChunkCache is used for short read/write operations. -typedef struct -{ - struct yaffs_ObjectStruct *object; - int chunkId; - int lastUse; - int dirty; - __u8 data[YAFFS_BYTES_PER_CHUNK]; -} yaffs_ChunkCache; - -// Tags structures in RAM -// NB This uses bitfield. Bitfields should not stradle a u32 boundary otherwise -// the structure size will get blown out. - -typedef struct -{ - unsigned chunkId:20; - unsigned serialNumber:2; - unsigned byteCount:10; - unsigned objectId:18; - unsigned ecc:12; - unsigned unusedStuff:2; -} yaffs_Tags; - -typedef union -{ - yaffs_Tags asTags; - __u8 asBytes[8]; -} yaffs_TagsUnion; - - -// Spare structure -typedef struct -{ - __u8 tagByte0; - __u8 tagByte1; - __u8 tagByte2; - __u8 tagByte3; - __u8 pageStatus; // set to 0 to delete the chunk - __u8 blockStatus; - __u8 tagByte4; - __u8 tagByte5; - __u8 ecc1[3]; - __u8 tagByte6; - __u8 tagByte7; - __u8 ecc2[3]; -} yaffs_Spare; - -// Block data in RAM - -typedef enum { - YAFFS_BLOCK_STATE_UddNKNOWN = 0, - YAFFS_BLOCK_STATE_SCANNING, // Used while the block is being scanned. - // NB Don't erase blocks while they're being scanned - - YAFFS_BLOCK_STATE_EMPTY, // This block is empty - - YAFFS_BLOCK_STATE_ALLOCATING, // This block is partially allocated. - // This is the one currently being used for page - // allocation. Should never be more than one of these - - - YAFFS_BLOCK_STATE_FULL, // All the pages in this block have been allocated. - // At least one page holds valid data. - - YAFFS_BLOCK_STATE_DIRTY, // All pages have been allocated and deleted. - // Erase me, reuse me. - - YAFFS_BLOCK_STATE_DEAD = 0x77 // This block has failed and is not in use - -} yaffs_BlockState; - - - - -typedef struct -{ - __u32 pageBits; // bitmap of pages in use - __u8 blockState; // One of the above block states - __u8 pagesInUse; // number of pages in use - __u8 needsRetiring:1; // Data has failed on this block, need to get valid data off - // and retire the block. -} yaffs_BlockInfo; - - -//////////////////// Object structure /////////////////////////// -// This is the object structure as stored on NAND - -typedef enum -{ - YAFFS_OBJECT_TYPE_UNKNOWN, - YAFFS_OBJECT_TYPE_FILE, - YAFFS_OBJECT_TYPE_SYMLINK, - YAFFS_OBJECT_TYPE_DIRECTORY, - YAFFS_OBJECT_TYPE_HARDLINK, - YAFFS_OBJECT_TYPE_SPECIAL -} yaffs_ObjectType; - -typedef struct -{ - yaffs_ObjectType type; - - // Apply to everything - int parentObjectId; - __u16 sum__NoLongerUsed; // checksum of name. Calc this off the name to prevent inconsistencies - char name[YAFFS_MAX_NAME_LENGTH + 1]; - - // Thes following apply to directories, files, symlinks - not hard links - __u32 st_mode; // protection - -#ifdef CONFIG_YAFFS_WINCE - __u32 notForWinCE[5]; -#else - __u32 st_uid; // user ID of owner - __u32 st_gid; // group ID of owner - __u32 st_atime; // time of last access - __u32 st_mtime; // time of last modification - __u32 st_ctime; // time of last change -#endif - - // File size applies to files only - int fileSize; - - // Equivalent object id applies to hard links only. - int equivalentObjectId; - - // Alias is for symlinks only. - char alias[YAFFS_MAX_ALIAS_LENGTH + 1]; - - __u32 st_rdev; // device stuff for block and char devices (maj/min) - -#ifdef CONFIG_YAFFS_WINCE - __u32 win_ctime[2]; - __u32 win_atime[2]; - __u32 win_mtime[2]; - __u32 roomToGrow[6]; -#else - __u32 roomToGrow[12]; -#endif - -} yaffs_ObjectHeader; - - - -//////////////////// Tnode /////////////////////////// - -union yaffs_Tnode_union -{ - union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL]; - __u16 level0[YAFFS_NTNODES_LEVEL0]; - -}; - -typedef union yaffs_Tnode_union yaffs_Tnode; - -struct yaffs_TnodeList_struct -{ - struct yaffs_TnodeList_struct *next; - yaffs_Tnode *tnodes; -}; - -typedef struct yaffs_TnodeList_struct yaffs_TnodeList; - - - -/////////////////// Object //////////////////////////////// -// An object can be one of: -// - a directory (no data, has children links -// - a regular file (data.... not prunes :->). -// - a symlink [symbolic link] (the alias). -// - a hard link - - -typedef struct -{ - __u32 fileSize; - __u32 scannedFileSize; - int topLevel; - yaffs_Tnode *top; -} yaffs_FileStructure; - -typedef struct -{ - struct list_head children; // list of child links -} yaffs_DirectoryStructure; - -typedef struct -{ - char *alias; -} yaffs_SymLinkStructure; - -typedef struct -{ - struct yaffs_ObjectStruct *equivalentObject; - __u32 equivalentObjectId; -} yaffs_HardLinkStructure; - -typedef union -{ - yaffs_FileStructure fileVariant; - yaffs_DirectoryStructure directoryVariant; - yaffs_SymLinkStructure symLinkVariant; - yaffs_HardLinkStructure hardLinkVariant; -} yaffs_ObjectVariant; - - -struct yaffs_ObjectStruct -{ - __u8 deleted: 1; // This should only apply to unlinked files. - __u8 unlinked: 1; // An unlinked file. The file should be in the unlinked pseudo directory. - __u8 fake:1; // A fake object has no presence on NAND. - __u8 renameAllowed:1; - __u8 unlinkAllowed:1; - __u8 dirty:1; // the object needs to be written to flash - __u8 valid:1; // When the file system is being loaded up, this - // object might be created before the data - // is available (ie. file data records appear before the header). - __u8 serial; // serial number of chunk in NAND. Store here so we don't have to - // read back the old one to update. - __u16 sum; // sum of the name to speed searching - - struct yaffs_DeviceStruct *myDev; // The device I'm on - - - struct list_head hashLink; // list of objects in this hash bucket - - - struct list_head hardLinks; // all the equivalent hard linked objects - // live on this list - // directory structure stuff - struct yaffs_ObjectStruct *parent; //my parent directory - struct list_head siblings; // siblings in a directory - // also used for linking up the free list - - // Where's my data in NAND? - int chunkId; // where it lives - - int nDataChunks; - - __u32 objectId; // the object id value - - - __u32 st_mode; // protection - -#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM - char shortName[YAFFS_SHORT_NAME_LENGTH+1]; -#endif - -#ifdef CONFIG_YAFFS_WINCE - __u32 inUse; - - __u32 win_ctime[2]; - __u32 win_mtime[2]; - __u32 win_atime[2]; -#else - __u32 st_uid; // user ID of owner - __u32 st_gid; // group ID of owner - __u32 st_atime; // time of last access - __u32 st_mtime; // time of last modification - __u32 st_ctime; // time of last change - __u32 st_rdev; // device stuff for block and char devices -#endif - - - - -#ifdef __KERNEL__ - struct inode *myInode; -#endif - - - - yaffs_ObjectType variantType; - - yaffs_ObjectVariant variant; - -}; - - - -typedef struct yaffs_ObjectStruct yaffs_Object; - - -struct yaffs_ObjectList_struct -{ - yaffs_Object *objects; - struct yaffs_ObjectList_struct *next; -}; - -typedef struct yaffs_ObjectList_struct yaffs_ObjectList; - -typedef struct -{ - struct list_head list; - int count; -} yaffs_ObjectBucket; - - -//////////////////// Device //////////////////////////////// - -struct yaffs_DeviceStruct -{ - // Entry parameters set up way early. Yaffs sets up the rest. - int startBlock; // Start block we're allowed to use - int endBlock; // End block we're allowed to use - __u16 chunkGroupBits; // 0 for devices <= 32MB. else log2(nchunks) - 16 - __u16 chunkGroupSize; // == 2^^chunkGroupBits - - - void *genericDevice; // Pointer to device context - // On an mtd this holds the mtd pointer. - -#ifdef __KERNEL__ - - struct semaphore sem;// Semaphore for waiting on erasure. - struct semaphore grossLock; // Gross locking semaphore - -#endif - - - // NAND access functions (Must be set before calling YAFFS) - - int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare); - int (*readChunkFromNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare); - int (*eraseBlockInNAND)(struct yaffs_DeviceStruct *dev,int blockInNAND); - int (*initialiseNAND)(struct yaffs_DeviceStruct *dev); - -#ifdef __KERNEL__ - void (*putSuperFunc)(struct super_block *sb); -#endif - - // Runtime parameters. - yaffs_BlockInfo *blockInfo; - int nErasedBlocks; - int allocationBlock; - __u32 allocationPage; - - // Runtime state - int nTnodesCreated; - yaffs_Tnode *freeTnodes; - int nFreeTnodes; - yaffs_TnodeList *allocatedTnodeList; - - - int nObjectsCreated; - yaffs_Object *freeObjects; - int nFreeObjects; - - yaffs_ObjectList *allocatedObjectList; - - yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS]; - - int nFreeChunks; - - int currentDirtyChecker; // Used to find current dirtiest block - - int garbageCollectionRequired; - - // Operations since mount - int nPageWrites; - int nPageReads; - int nBlockErasures; - int nGCCopies; - int garbageCollections; - int nRetriedWrites; - int nRetiredBlocks; - int eccFixed; - int eccUnfixed; - int tagsEccFixed; - int tagsEccUnfixed; - - yaffs_Object *rootDir; - yaffs_Object *lostNFoundDir; - - // Buffer areas for storing data to recover from write failures - __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK]; - yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK]; - int bufferedBlock; // Which block is buffered here? - int doingBufferedBlockRewrite; - - int blockSelectedForGC; - -#ifdef CONFIG_YAFFS_SHORT_OP_CACHE - yaffs_ChunkCache srCache[YAFFS_N_CACHE_CHUNKS]; - int srLastUse; -#endif - int cacheHits; - - // Stuff for background deletion and unlinked files. - yaffs_Object *unlinkedDir; // Directory where unlinked and deleted files live. - yaffs_Object *unlinkedDeletion; // Current file being background deleted. - int nDeletedFiles; // Count of files awaiting deletion; - int nUnlinkedFiles; // Count of unlinked files. - int nBackgroundDeletions; // Count of background deletions. - - __u8 *localBuffer; - -}; - -typedef struct yaffs_DeviceStruct yaffs_Device; - - - -//////////// YAFFS Functions ////////////////// - -int yaffs_GutsInitialise(yaffs_Device *dev); -void yaffs_Deinitialise(yaffs_Device *dev); - -int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev); - - -// Rename -int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object *newDir, const char *newName); - -// generic Object functions -int yaffs_Unlink(yaffs_Object *dir, const char *name); -int yaffs_DeleteFile(yaffs_Object *obj); - -// Object access functions. -int yaffs_GetObjectName(yaffs_Object *obj,char *name,int buffSize); -int yaffs_GetObjectFileLength(yaffs_Object *obj); -int yaffs_GetObjectInode(yaffs_Object *obj); -unsigned yaffs_GetObjectType(yaffs_Object *obj); -int yaffs_GetObjectLinkCount(yaffs_Object *obj); - -// Change inode attributes -int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr); -int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr); - -// File operations -int yaffs_ReadDataFromFile(yaffs_Object *obj, __u8 *buffer, __u32 offset, int nBytes); -int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, __u32 offset, int nBytes); -int yaffs_ResizeFile(yaffs_Object *obj, int newSize); - -yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid); -int yaffs_FlushFile(yaffs_Object *obj); - - -// Directory operations -yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid); -yaffs_Object *yaffs_FindObjectByName(yaffs_Object *theDir,const char *name); -int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,int (*fn)(yaffs_Object *)); - -yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,__u32 number); - -// Link operations -yaffs_Object *yaffs_Link(yaffs_Object *parent, const char *name, yaffs_Object *equivalentObject); - -yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj); - -// Symlink operations -yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const char *name, __u32 mode, __u32 uid, __u32 gid, const char *alias); -char *yaffs_GetSymlinkAlias(yaffs_Object *obj); - -// Special inodes (fifos, sockets and devices) -yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid,__u32 rdev); - - -// Special directories -yaffs_Object *yaffs_Root(yaffs_Device *dev); -yaffs_Object *yaffs_LostNFound(yaffs_Device *dev); - -#ifdef CONFIG_YAFFS_WINCE -// CONFIG_YAFFS_WINCE special stuff -void yfsd_WinFileTimeNow(__u32 target[2]); -#endif - - -// Debug dump -int yaffs_DumpObject(yaffs_Object *obj); - - -void yaffs_GutsTest(yaffs_Device *dev); - - -#endif +/* + * YAFFS: Yet another FFS. A NAND-flash specific file system. + * yaffs_guts.h: Configuration etc for yaffs_guts + * + * Copyright (C) 2002 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. + * + * $Id: yaffs_guts.h,v 1.13 2002-12-13 00:13:06 charles Exp $ + */ + +#ifndef __YAFFS_GUTS_H__ +#define __YAFFS_GUTS_H__ + +#include "devextras.h" + + +#define YAFFS_OK 1 +#define YAFFS_FAIL 0 + +// Give us a Y=0x59, +// Give us an A=0x41, +// Give us an FF=0xFF +// Give us an S=0x53 +// And what have we got... +#define YAFFS_MAGIC 0x5941FF53 + +#define YAFFS_NTNODES_LEVEL0 16 +#define YAFFS_TNODES_LEVEL0_BITS 4 +#define YAFFS_TNODES_LEVEL0_MASK 0xf + +#define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2) +#define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1) +#define YAFFS_TNODES_INTERNAL_MASK 0x7 +#define YAFFS_TNODES_MAX_LEVEL 6 + +#define YAFFS_BYTES_PER_CHUNK 512 +#define YAFFS_CHUNK_SIZE_SHIFT 9 + +#define YAFFS_BYTES_PER_SPARE 16 + +#define YAFFS_CHUNKS_PER_BLOCK 32 +#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK) + +#define YAFFS_MAX_CHUNK_ID 0x000FFFFF + +#define YAFFS_UNUSED_OBJECT_ID 0x0003FFFF + +#define YAFFS_ALLOCATION_NOBJECTS 100 +#define YAFFS_ALLOCATION_NTNODES 100 +#define YAFFS_ALLOCATION_NLINKS 100 + +#define YAFFS_NOBJECT_BUCKETS 256 + + +#define YAFFS_RESERVED_BLOCKS 8 + +#define YAFFS_OBJECT_SPACE 0x40000 +#define YAFFS_MAX_NAME_LENGTH 255 +#define YAFFS_SHORT_NAME_LENGTH 15 + +#define YAFFS_MAX_ALIAS_LENGTH 159 + +#define YAFFS_OBJECTID_ROOT 1 +#define YAFFS_OBJECTID_LOSTNFOUND 2 +#define YAFFS_OBJECTID_UNLINKED 3 + +#define YAFFS_N_CACHE_CHUNKS 10 + +#ifdef CONFIG_YAFFS_WINCE + +// Force the short operation cache on for WinCE + +#define CONFIG_YAFFS_SHORT_OP_CACHE +#endif + + +// ChunkCache is used for short read/write operations. +typedef struct +{ + struct yaffs_ObjectStruct *object; + int chunkId; + int lastUse; + int dirty; + __u8 data[YAFFS_BYTES_PER_CHUNK]; +} yaffs_ChunkCache; + +// Tags structures in RAM +// NB This uses bitfield. Bitfields should not stradle a u32 boundary otherwise +// the structure size will get blown out. + +typedef struct +{ + unsigned chunkId:20; + unsigned serialNumber:2; + unsigned byteCount:10; + unsigned objectId:18; + unsigned ecc:12; + unsigned unusedStuff:2; +} yaffs_Tags; + +typedef union +{ + yaffs_Tags asTags; + __u8 asBytes[8]; +} yaffs_TagsUnion; + + +// Spare structure +typedef struct +{ + __u8 tagByte0; + __u8 tagByte1; + __u8 tagByte2; + __u8 tagByte3; + __u8 pageStatus; // set to 0 to delete the chunk + __u8 blockStatus; + __u8 tagByte4; + __u8 tagByte5; + __u8 ecc1[3]; + __u8 tagByte6; + __u8 tagByte7; + __u8 ecc2[3]; +} yaffs_Spare; + +// Block data in RAM + +typedef enum { + YAFFS_BLOCK_STATE_UddNKNOWN = 0, + YAFFS_BLOCK_STATE_SCANNING, // Used while the block is being scanned. + // NB Don't erase blocks while they're being scanned + + YAFFS_BLOCK_STATE_EMPTY, // This block is empty + + YAFFS_BLOCK_STATE_ALLOCATING, // This block is partially allocated. + // This is the one currently being used for page + // allocation. Should never be more than one of these + + + YAFFS_BLOCK_STATE_FULL, // All the pages in this block have been allocated. + // At least one page holds valid data. + + YAFFS_BLOCK_STATE_DIRTY, // All pages have been allocated and deleted. + // Erase me, reuse me. + + YAFFS_BLOCK_STATE_DEAD = 0x77 // This block has failed and is not in use + +} yaffs_BlockState; + + + + +typedef struct +{ + __u32 pageBits; // bitmap of pages in use + __u8 blockState; // One of the above block states + __u8 pagesInUse; // number of pages in use + __u8 needsRetiring:1; // Data has failed on this block, need to get valid data off + // and retire the block. +} yaffs_BlockInfo; + + +//////////////////// Object structure /////////////////////////// +// This is the object structure as stored on NAND + +typedef enum +{ + YAFFS_OBJECT_TYPE_UNKNOWN, + YAFFS_OBJECT_TYPE_FILE, + YAFFS_OBJECT_TYPE_SYMLINK, + YAFFS_OBJECT_TYPE_DIRECTORY, + YAFFS_OBJECT_TYPE_HARDLINK, + YAFFS_OBJECT_TYPE_SPECIAL +} yaffs_ObjectType; + +typedef struct +{ + yaffs_ObjectType type; + + // Apply to everything + int parentObjectId; + __u16 sum__NoLongerUsed; // checksum of name. Calc this off the name to prevent inconsistencies + char name[YAFFS_MAX_NAME_LENGTH + 1]; + + // Thes following apply to directories, files, symlinks - not hard links + __u32 st_mode; // protection + +#ifdef CONFIG_YAFFS_WINCE + __u32 notForWinCE[5]; +#else + __u32 st_uid; // user ID of owner + __u32 st_gid; // group ID of owner + __u32 st_atime; // time of last access + __u32 st_mtime; // time of last modification + __u32 st_ctime; // time of last change +#endif + + // File size applies to files only + int fileSize; + + // Equivalent object id applies to hard links only. + int equivalentObjectId; + + // Alias is for symlinks only. + char alias[YAFFS_MAX_ALIAS_LENGTH + 1]; + + __u32 st_rdev; // device stuff for block and char devices (maj/min) + +#ifdef CONFIG_YAFFS_WINCE + __u32 win_ctime[2]; + __u32 win_atime[2]; + __u32 win_mtime[2]; + __u32 roomToGrow[6]; +#else + __u32 roomToGrow[12]; +#endif + +} yaffs_ObjectHeader; + + + +//////////////////// Tnode /////////////////////////// + +union yaffs_Tnode_union +{ + union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL]; + __u16 level0[YAFFS_NTNODES_LEVEL0]; + +}; + +typedef union yaffs_Tnode_union yaffs_Tnode; + +struct yaffs_TnodeList_struct +{ + struct yaffs_TnodeList_struct *next; + yaffs_Tnode *tnodes; +}; + +typedef struct yaffs_TnodeList_struct yaffs_TnodeList; + + + +/////////////////// Object //////////////////////////////// +// An object can be one of: +// - a directory (no data, has children links +// - a regular file (data.... not prunes :->). +// - a symlink [symbolic link] (the alias). +// - a hard link + + +typedef struct +{ + __u32 fileSize; + __u32 scannedFileSize; + int topLevel; + yaffs_Tnode *top; +} yaffs_FileStructure; + +typedef struct +{ + struct list_head children; // list of child links +} yaffs_DirectoryStructure; + +typedef struct +{ + char *alias; +} yaffs_SymLinkStructure; + +typedef struct +{ + struct yaffs_ObjectStruct *equivalentObject; + __u32 equivalentObjectId; +} yaffs_HardLinkStructure; + +typedef union +{ + yaffs_FileStructure fileVariant; + yaffs_DirectoryStructure directoryVariant; + yaffs_SymLinkStructure symLinkVariant; + yaffs_HardLinkStructure hardLinkVariant; +} yaffs_ObjectVariant; + + +struct yaffs_ObjectStruct +{ + __u8 deleted: 1; // This should only apply to unlinked files. + __u8 unlinked: 1; // An unlinked file. The file should be in the unlinked pseudo directory. + __u8 fake:1; // A fake object has no presence on NAND. + __u8 renameAllowed:1; + __u8 unlinkAllowed:1; + __u8 dirty:1; // the object needs to be written to flash + __u8 valid:1; // When the file system is being loaded up, this + // object might be created before the data + // is available (ie. file data records appear before the header). + __u8 serial; // serial number of chunk in NAND. Store here so we don't have to + // read back the old one to update. + __u16 sum; // sum of the name to speed searching + + struct yaffs_DeviceStruct *myDev; // The device I'm on + + + struct list_head hashLink; // list of objects in this hash bucket + + + struct list_head hardLinks; // all the equivalent hard linked objects + // live on this list + // directory structure stuff + struct yaffs_ObjectStruct *parent; //my parent directory + struct list_head siblings; // siblings in a directory + // also used for linking up the free list + + // Where's my data in NAND? + int chunkId; // where it lives + + int nDataChunks; + + __u32 objectId; // the object id value + + + __u32 st_mode; // protection + +#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM + char shortName[YAFFS_SHORT_NAME_LENGTH+1]; +#endif + +#ifdef CONFIG_YAFFS_WINCE + __u32 inUse; + + __u32 win_ctime[2]; + __u32 win_mtime[2]; + __u32 win_atime[2]; +#else + __u32 st_uid; // user ID of owner + __u32 st_gid; // group ID of owner + __u32 st_atime; // time of last access + __u32 st_mtime; // time of last modification + __u32 st_ctime; // time of last change + __u32 st_rdev; // device stuff for block and char devices +#endif + + + + +#ifdef __KERNEL__ + struct inode *myInode; +#endif + + + + yaffs_ObjectType variantType; + + yaffs_ObjectVariant variant; + +}; + + + +typedef struct yaffs_ObjectStruct yaffs_Object; + + +struct yaffs_ObjectList_struct +{ + yaffs_Object *objects; + struct yaffs_ObjectList_struct *next; +}; + +typedef struct yaffs_ObjectList_struct yaffs_ObjectList; + +typedef struct +{ + struct list_head list; + int count; +} yaffs_ObjectBucket; + + +//////////////////// Device //////////////////////////////// + +struct yaffs_DeviceStruct +{ + // Entry parameters set up way early. Yaffs sets up the rest. + int startBlock; // Start block we're allowed to use + int endBlock; // End block we're allowed to use + __u16 chunkGroupBits; // 0 for devices <= 32MB. else log2(nchunks) - 16 + __u16 chunkGroupSize; // == 2^^chunkGroupBits + + + void *genericDevice; // Pointer to device context + // On an mtd this holds the mtd pointer. + +#ifdef __KERNEL__ + + struct semaphore sem;// Semaphore for waiting on erasure. + struct semaphore grossLock; // Gross locking semaphore + +#endif + + + // NAND access functions (Must be set before calling YAFFS) + + int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare); + int (*readChunkFromNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare); + int (*eraseBlockInNAND)(struct yaffs_DeviceStruct *dev,int blockInNAND); + int (*initialiseNAND)(struct yaffs_DeviceStruct *dev); + +#ifdef __KERNEL__ + void (*putSuperFunc)(struct super_block *sb); +#endif + + // Runtime parameters. + yaffs_BlockInfo *blockInfo; + int nErasedBlocks; + int allocationBlock; + __u32 allocationPage; + int allocationBlockFinder; + + // Runtime state + int nTnodesCreated; + yaffs_Tnode *freeTnodes; + int nFreeTnodes; + yaffs_TnodeList *allocatedTnodeList; + + + int nObjectsCreated; + yaffs_Object *freeObjects; + int nFreeObjects; + + yaffs_ObjectList *allocatedObjectList; + + yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS]; + + int nFreeChunks; + + int currentDirtyChecker; // Used to find current dirtiest block + + int garbageCollectionRequired; + + // Operations since mount + int nPageWrites; + int nPageReads; + int nBlockErasures; + int nGCCopies; + int garbageCollections; + int nRetriedWrites; + int nRetiredBlocks; + int eccFixed; + int eccUnfixed; + int tagsEccFixed; + int tagsEccUnfixed; + + yaffs_Object *rootDir; + yaffs_Object *lostNFoundDir; + + // Buffer areas for storing data to recover from write failures + __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK]; + yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK]; + int bufferedBlock; // Which block is buffered here? + int doingBufferedBlockRewrite; + + int blockSelectedForGC; + +#ifdef CONFIG_YAFFS_SHORT_OP_CACHE + yaffs_ChunkCache srCache[YAFFS_N_CACHE_CHUNKS]; + int srLastUse; +#endif + int cacheHits; + + // Stuff for background deletion and unlinked files. + yaffs_Object *unlinkedDir; // Directory where unlinked and deleted files live. + yaffs_Object *unlinkedDeletion; // Current file being background deleted. + int nDeletedFiles; // Count of files awaiting deletion; + int nUnlinkedFiles; // Count of unlinked files. + int nBackgroundDeletions; // Count of background deletions. + + __u8 *localBuffer; + +}; + +typedef struct yaffs_DeviceStruct yaffs_Device; + + + +//////////// YAFFS Functions ////////////////// + +int yaffs_GutsInitialise(yaffs_Device *dev); +void yaffs_Deinitialise(yaffs_Device *dev); + +int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev); + + +// Rename +int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object *newDir, const char *newName); + +// generic Object functions +int yaffs_Unlink(yaffs_Object *dir, const char *name); +int yaffs_DeleteFile(yaffs_Object *obj); + +// Object access functions. +int yaffs_GetObjectName(yaffs_Object *obj,char *name,int buffSize); +int yaffs_GetObjectFileLength(yaffs_Object *obj); +int yaffs_GetObjectInode(yaffs_Object *obj); +unsigned yaffs_GetObjectType(yaffs_Object *obj); +int yaffs_GetObjectLinkCount(yaffs_Object *obj); + +// Change inode attributes +int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr); +int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr); + +// File operations +int yaffs_ReadDataFromFile(yaffs_Object *obj, __u8 *buffer, __u32 offset, int nBytes); +int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, __u32 offset, int nBytes); +int yaffs_ResizeFile(yaffs_Object *obj, int newSize); + +yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid); +int yaffs_FlushFile(yaffs_Object *obj); + + +// Directory operations +yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid); +yaffs_Object *yaffs_FindObjectByName(yaffs_Object *theDir,const char *name); +int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,int (*fn)(yaffs_Object *)); + +yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,__u32 number); + +// Link operations +yaffs_Object *yaffs_Link(yaffs_Object *parent, const char *name, yaffs_Object *equivalentObject); + +yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj); + +// Symlink operations +yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const char *name, __u32 mode, __u32 uid, __u32 gid, const char *alias); +char *yaffs_GetSymlinkAlias(yaffs_Object *obj); + +// Special inodes (fifos, sockets and devices) +yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid,__u32 rdev); + + +// Special directories +yaffs_Object *yaffs_Root(yaffs_Device *dev); +yaffs_Object *yaffs_LostNFound(yaffs_Device *dev); + +#ifdef CONFIG_YAFFS_WINCE +// CONFIG_YAFFS_WINCE special stuff +void yfsd_WinFileTimeNow(__u32 target[2]); +#endif + + +// Debug dump +int yaffs_DumpObject(yaffs_Object *obj); + + +void yaffs_GutsTest(yaffs_Device *dev); + + +#endif diff --git a/yaffs_mtdif.c b/yaffs_mtdif.c index 4d31736..5505d55 100644 --- a/yaffs_mtdif.c +++ b/yaffs_mtdif.c @@ -13,7 +13,7 @@ * */ -const char *yaffs_mtdif_c_version = "$Id: yaffs_mtdif.c,v 1.4 2002-11-26 01:15:37 charles Exp $"; +const char *yaffs_mtdif_c_version = "$Id: yaffs_mtdif.c,v 1.5 2002-12-13 00:13:06 charles Exp $"; #ifdef CONFIG_YAFFS_MTD_ENABLED @@ -23,76 +23,84 @@ const char *yaffs_mtdif_c_version = "$Id: yaffs_mtdif.c,v 1.4 2002-11-26 01:15:3 #include "linux/mtd/mtd.h" #include "linux/types.h" +#include "linux/time.h" #ifndef CONFIG_YAFFS_USE_OLD_MTD #include "linux/mtd/nand.h" #endif - int nandmtd_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_Spare *spare) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); size_t dummy; + int retval = 0; loff_t addr = ((loff_t)chunkInNAND) * YAFFS_BYTES_PER_CHUNK; - __u8 *spareAsBytes = (__u8 *)spare; #ifndef CONFIG_YAFFS_USE_OLD_MTD if(data && spare) { #ifdef CONFIG_YAFFS_USE_NANDECC - mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_YAFFS_OOB); + retval = mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_YAFFS_OOB); #else - mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB); + retval = mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB); #endif } else { #endif if(data) - mtd->write(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data); + retval = mtd->write(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data); if(spare) - mtd->write_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes); + retval = mtd->write_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes); #ifndef CONFIG_YAFFS_USE_OLD_MTD } #endif - return YAFFS_OK; + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; } - int nandmtd_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); size_t dummy; + int retval = 0; loff_t addr = ((loff_t)chunkInNAND) * YAFFS_BYTES_PER_CHUNK; __u8 *spareAsBytes = (__u8 *)spare; - #ifndef CONFIG_YAFFS_USE_OLD_MTD if(data && spare) { #ifdef CONFIG_YAFFS_USE_NANDECC - mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_YAFFS_OOB); + u8 tmpSpare[ YAFFS_BYTES_PER_SPARE + (2*sizeof(int)) ]; + retval = mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,tmpSpare,NAND_YAFFS_OOB); + memcpy(spareAsBytes, tmpSpare, YAFFS_BYTES_PER_SPARE); #else - mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB); + retval = mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB); #endif } else { #endif if(data) - mtd->read(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data); + retval = mtd->read(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data); if(spare) - mtd->read_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes); + retval = mtd->read_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes); #ifndef CONFIG_YAFFS_USE_OLD_MTD } #endif - return YAFFS_OK; + + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; } @@ -105,10 +113,10 @@ static void nandmtd_EraseCallback(struct erase_info *ei) int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) { - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); __u32 addr = ((loff_t) blockNumber) * YAFFS_BYTES_PER_BLOCK; struct erase_info ei; + int retval = 0; ei.mtd = mtd; ei.addr = addr; @@ -122,14 +130,14 @@ int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) sema_init(&dev->sem,0); - mtd->erase(mtd,&ei); - + retval = mtd->erase(mtd,&ei); down(&dev->sem); // Wait for the erasure to complete - - //Todo, check result of erasure - - return YAFFS_OK; + + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; } int nandmtd_InitialiseNAND(yaffs_Device *dev) -- 2.30.2