*** empty log message ***
[yaffs/.git] / yaffs_guts.c
index eaa18fda50db7701b6235d0621ff51cb7141d41f..bfe10b74deb2aa6140d47fe876831f1a2b695ad2 100644 (file)
@@ -14,6 +14,8 @@
  */
  //yaffs_guts.c
 
+const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.10 2002-09-27 20:50:50 charles Exp $";
+
 #include "yportenv.h"
 
 #include "yaffsinterface.h"
@@ -63,7 +65,7 @@ static int yaffs_CountBits(__u8 x)
 // Local prototypes
 static int yaffs_CheckObjectHashSanity(yaffs_Device *dev);
 static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr);
-static void yaffs_GetTagsFromSpare(yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr);
+static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr);
 static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkInNAND, int inScan);
 
 static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type);
@@ -178,19 +180,23 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8
                 if(eccResult1>0)
                 {
                        T((TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND));
+                       dev->eccFixed++;
                 }
                 else if(eccResult1<0)
                 {
                        T((TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND));
+                       dev->eccUnfixed++;
                 }
                 
                 if(eccResult2>0)
                 {
                        T((TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND));
+                       dev->eccFixed++;
                 }
                 else if(eccResult2<0)
                 {
                        T((TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND));
+                       dev->eccUnfixed++;
                 }
                 
                 if(eccResult1 || eccResult2)
@@ -488,7 +494,7 @@ void yaffs_CalcTagsECC(yaffs_Tags *tags)
        
 }
 
-void yaffs_CheckECCOnTags(yaffs_Tags *tags)
+int  yaffs_CheckECCOnTags(yaffs_Tags *tags)
 {
        unsigned ecc = tags->ecc;
        
@@ -496,9 +502,9 @@ void yaffs_CheckECCOnTags(yaffs_Tags *tags)
        
        ecc ^= tags->ecc;
        
-       if(ecc)
+       if(ecc && ecc <= 64)
        {
-               // Needs fixing
+               // TODO: Handle the failure better. Retire?
                unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes;
 
                ecc--;
@@ -507,7 +513,17 @@ void yaffs_CheckECCOnTags(yaffs_Tags *tags)
                
                // Now recvalc the ecc
                yaffs_CalcTagsECC(tags);
+               
+               return 1; // recovered error
+       }
+       else if(ecc)
+       {
+               // Wierd ecc failure value
+               // TODO Need to do somethiong here
+               return -1; //unrecovered error
        }
+       
+       return 0;
 }
 
 
@@ -1867,7 +1883,8 @@ int  yaffs_GarbageCollectBlock(yaffs_Device *dev,int block)
                        
                        yaffs_ReadChunkFromNAND(dev,oldChunk,buffer, &spare,1);
                        
-                       yaffs_GetTagsFromSpare(&spare,&tags);
+                       yaffs_GetTagsFromSpare(dev,&spare,&tags);
+                       
                        tags.serialNumber++;
                        yaffs_LoadTagsIntoSpare(&spare,&tags);
 
@@ -2020,9 +2037,10 @@ static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr)
        sparePtr->tagByte7 = tu->asBytes[7];
 }
 
-static void yaffs_GetTagsFromSpare(yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr)
+static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr)
 {
        yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;
+       int result;
 
        tu->asBytes[0]= sparePtr->tagByte0;
        tu->asBytes[1]= sparePtr->tagByte1;
@@ -2033,7 +2051,15 @@ static void yaffs_GetTagsFromSpare(yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr)
        tu->asBytes[6]= sparePtr->tagByte6;
        tu->asBytes[7]= sparePtr->tagByte7;
        
-       yaffs_CheckECCOnTags(tagsPtr);
+       result =  yaffs_CheckECCOnTags(tagsPtr);
+       if(result> 0)
+       {
+               dev->tagsEccFixed++;
+       }
+       else if(result <0)
+       {
+               dev->tagsEccUnfixed++;
+       }
 }
 
 static void yaffs_SpareInitialise(yaffs_Spare *spare)
@@ -2049,7 +2075,7 @@ static int yaffs_ReadChunkTagsFromNAND(yaffs_Device *dev,int chunkInNAND, yaffs_
                if(yaffs_ReadChunkFromNAND(dev,chunkInNAND,NULL,&spare,1) == YAFFS_OK)
                {
                        *chunkDeleted = (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0;
-                       yaffs_GetTagsFromSpare(&spare,tags);
+                       yaffs_GetTagsFromSpare(dev,&spare,tags);
                        return YAFFS_OK;
                }
                else
@@ -2798,9 +2824,9 @@ int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nB
        
 #ifdef CONFIG_YAFFS_SHORT_OP_CACHE
        yaffs_ChunkCache *cache;
-#else
-       __u8 localBuffer[YAFFS_BYTES_PER_CHUNK];
 #endif
+
+       __u8 localBuffer[YAFFS_BYTES_PER_CHUNK];
        
        int chunk;
        int start;
@@ -2849,8 +2875,15 @@ int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nB
                }
                else
                {
+#ifdef WIN32
+                       // Under WinCE can't do direct transfer. Need to use a local buffer.
+                       // This is because we otherwise screw up WinCE's memory mapper
+                       yaffs_ReadChunkDataFromObject(in,chunk,localBuffer);
+                       memcpy(buffer,localBuffer,YAFFS_BYTES_PER_CHUNK);
+#else
                        // A full chunk. Read directly into the supplied buffer.
                        yaffs_ReadChunkDataFromObject(in,chunk,buffer);
+#endif
                }
                
                n -= nToCopy;
@@ -2914,8 +2947,16 @@ int yaffs_WriteDataToFile(yaffs_Object *in,const __u8 * buffer, __u32 offset, in
                }
                else
                {
+                       
+#ifdef WIN32
+                       // Under WinCE can't do direct transfer. Need to use a local buffer.
+                       // This is because we otherwise screw up WinCE's memory mapper
+                       memcpy(localBuffer,buffer,YAFFS_BYTES_PER_CHUNK);
+                       chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,localBuffer,YAFFS_BYTES_PER_CHUNK,0);
+#else
                        // A full chunk. Write directly from the supplied buffer.
                        chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,buffer,YAFFS_BYTES_PER_CHUNK,0);
+#endif
                        //T(("Write to chunk %d %d\n",chunk,chunkWritten));
                }
                
@@ -3432,7 +3473,7 @@ static int yaffs_Scan(yaffs_Device *dev)
 
                        
                        // This block looks ok, now what's in this chunk?
-                       yaffs_GetTagsFromSpare(&spare,&tags);
+                       yaffs_GetTagsFromSpare(dev,&spare,&tags);
                        
                        if(yaffs_CountBits(spare.pageStatus) < 6)
                        {
@@ -4038,6 +4079,10 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        dev->nDeletedFiles = 0;
        dev->nBackgroundDeletions=0;
        dev->nUnlinkedFiles = 0;
+       dev->eccFixed=0;
+       dev->eccUnfixed=0;
+       dev->tagsEccFixed=0;
+       dev->tagsEccUnfixed=0;
        
        yaffs_InitialiseBlocks(dev,nBlocks);