Tweaks to YaffsTuning doc.
[yaffs2.git] / yaffs_tagscompat.c
index 2cf783e65a9bf998ba53df8c9738fbe9350124e5..1ab054faf61743f8e99e600f83ce78a3f5168a57 100644 (file)
@@ -1,31 +1,31 @@
 /*
- * YAFFS: Yet another FFS. A NAND-flash specific file system. 
- * yaffs_tagscompat.h: Tags compatability layer to use YAFFS1 formatted NAND.
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  *
- * Copyright (C) 2002 Aleph One Ltd.
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
  *
  * Created by Charles Manning <charles@aleph1.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * $Id: yaffs_tagscompat.c,v 1.7 2005-09-20 23:12:38 charles Exp $
  */
 
 #include "yaffs_guts.h"
 #include "yaffs_tagscompat.h"
 #include "yaffs_ecc.h"
+#include "yaffs_getblockinfo.h"
+#include "yaffs_trace.h"
 
-static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
+static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND);
 #ifdef NOTYET
-static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND);
-static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
-                                    const __u8 * data,
-                                    const yaffs_Spare * spare);
-static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
-                                   const yaffs_Spare * spare);
-static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND);
+static void yaffs_CheckWrittenBlock(yaffs_Device *dev, int chunkInNAND);
+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND,
+                                    const __u8 *data,
+                                    const yaffs_Spare *spare);
+static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND,
+                                   const yaffs_Spare *spare);
+static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND);
 #endif
 
 static const char yaffs_countBitsTable[256] = {
@@ -47,7 +47,7 @@ static const char yaffs_countBitsTable[256] = {
        4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
 };
 
-static int yaffs_CountBits(__u8 x)
+int yaffs_CountBits(__u8 x)
 {
        int retVal;
        retVal = yaffs_countBitsTable[x];
@@ -56,13 +56,13 @@ static int yaffs_CountBits(__u8 x)
 
 /********** Tags ECC calculations  *********/
 
-void yaffs_CalcECC(const __u8 * data, yaffs_Spare * spare)
+void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare)
 {
        yaffs_ECCCalculate(data, spare->ecc1);
        yaffs_ECCCalculate(&data[256], spare->ecc2);
 }
 
-void yaffs_CalcTagsECC(yaffs_Tags * tags)
+void yaffs_CalcTagsECC(yaffs_Tags *tags)
 {
        /* Calculate an ecc */
 
@@ -76,9 +76,8 @@ void yaffs_CalcTagsECC(yaffs_Tags * tags)
        for (i = 0; i < 8; i++) {
                for (j = 1; j & 0xff; j <<= 1) {
                        bit++;
-                       if (b[i] & j) {
+                       if (b[i] & j)
                                ecc ^= bit;
-                       }
                }
        }
 
@@ -86,7 +85,7 @@ void yaffs_CalcTagsECC(yaffs_Tags * tags)
 
 }
 
-int yaffs_CheckECCOnTags(yaffs_Tags * tags)
+int yaffs_CheckECCOnTags(yaffs_Tags *tags)
 {
        unsigned ecc = tags->ecc;
 
@@ -117,8 +116,8 @@ int yaffs_CheckECCOnTags(yaffs_Tags * tags)
 
 /********** Tags **********/
 
-static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr,
-                                   yaffs_Tags * tagsPtr)
+static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr,
+                               yaffs_Tags *tagsPtr)
 {
        yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;
 
@@ -134,8 +133,8 @@ static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr,
        sparePtr->tagByte7 = tu->asBytes[7];
 }
 
-static void yaffs_GetTagsFromSpare(yaffs_Device * dev, 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;
@@ -150,53 +149,49 @@ static void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr,
        tu->asBytes[7] = sparePtr->tagByte7;
 
        result = yaffs_CheckECCOnTags(tagsPtr);
-       if (result > 0) {
+       if (result > 0)
                dev->tagsEccFixed++;
-       } else if (result < 0) {
+       else if (result < 0)
                dev->tagsEccUnfixed++;
-       }
 }
 
-static void yaffs_SpareInitialise(yaffs_Spare * spare)
+static void yaffs_SpareInitialise(yaffs_Spare *spare)
 {
        memset(spare, 0xFF, sizeof(yaffs_Spare));
 }
 
 static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,
-                                 int chunkInNAND, const __u8 * data,
-                                 yaffs_Spare * spare)
+                               int chunkInNAND, const __u8 *data,
+                               yaffs_Spare *spare)
 {
-       if (chunkInNAND < dev->startBlock * dev->nChunksPerBlock) {
+       if (chunkInNAND < dev->param.startBlock * dev->param.nChunksPerBlock) {
                T(YAFFS_TRACE_ERROR,
                  (TSTR("**>> yaffs chunk %d is not valid" TENDSTR),
                   chunkInNAND));
                return YAFFS_FAIL;
        }
 
-       dev->nPageWrites++;
-       return dev->writeChunkToNAND(dev, chunkInNAND, data, spare);
+       return dev->param.writeChunkToNAND(dev, chunkInNAND, data, spare);
 }
 
 static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
                                   int chunkInNAND,
-                                  __u8 * data,
-                                  yaffs_Spare * spare,
-                                  yaffs_ECCResult * eccResult,
+                                  __u8 *data,
+                                  yaffs_Spare *spare,
+                                  yaffs_ECCResult *eccResult,
                                   int doErrorCorrection)
 {
        int retVal;
        yaffs_Spare localSpare;
 
-       dev->nPageReads++;
-
        if (!spare && data) {
                /* If we don't have a real spare, then we use a local one. */
                /* Need this for the calculation of the ecc */
                spare = &localSpare;
        }
 
-       if (!dev->useNANDECC) {
-               retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare);
+       if (!dev->param.useNANDECC) {
+               retVal = dev->param.readChunkFromNAND(dev, chunkInNAND, data, spare);
                if (data && doErrorCorrection) {
                        /* Do ECC correction */
                        /* Todo handle any errors */
@@ -254,9 +249,11 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
                /* Must allocate enough memory for spare+2*sizeof(int) */
                /* for ecc results from device. */
                struct yaffs_NANDSpare nspare;
-               retVal =
-                   dev->readChunkFromNAND(dev, chunkInNAND, data,
-                                          (yaffs_Spare *) & nspare);
+
+               memset(&nspare, 0, sizeof(nspare));
+
+               retVal = dev->param.readChunkFromNAND(dev, chunkInNAND, data,
+                                       (yaffs_Spare *) &nspare);
                memcpy(spare, &nspare, sizeof(yaffs_Spare));
                if (data && doErrorCorrection) {
                        if (nspare.eccres1 > 0) {
@@ -304,15 +301,14 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
 static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
                                  int chunkInNAND)
 {
-
-       static int init = 0;
+       static int init;
        static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK];
        static __u8 data[YAFFS_BYTES_PER_CHUNK];
        /* Might as well always allocate the larger size for */
-       /* dev->useNANDECC == true; */
+       /* dev->param.useNANDECC == true; */
        static __u8 spare[sizeof(struct yaffs_NANDSpare)];
 
-       dev->readChunkFromNAND(dev, chunkInNAND, data, (yaffs_Spare *) spare);
+       dev->param.readChunkFromNAND(dev, chunkInNAND, data, (yaffs_Spare *) spare);
 
        if (!init) {
                memset(cmpbuf, 0xff, YAFFS_BYTES_PER_CHUNK);
@@ -333,12 +329,12 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
  * Functions for robustisizing
  */
 
-static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND)
+static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND)
 {
-       int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
+       int blockInNAND = chunkInNAND / dev->param.nChunksPerBlock;
 
        /* Mark the block for retirement */
-       yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
+       yaffs_GetBlockInfo(dev, blockInNAND + dev->blockOffset)->needsRetiring = 1;
        T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
          (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND));
 
@@ -350,24 +346,24 @@ static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND)
 }
 
 #ifdef NOTYET
-static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND)
+static void yaffs_CheckWrittenBlock(yaffs_Device *dev, int chunkInNAND)
 {
 }
 
-static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
-                                    const __u8 * data,
-                                    const yaffs_Spare * spare)
+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND,
+                                    const __u8 *data,
+                                    const yaffs_Spare *spare)
 {
 }
 
-static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
-                                   const yaffs_Spare * spare)
+static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND,
+                                   const yaffs_Spare *spare)
 {
 }
 
-static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND)
+static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND)
 {
-       int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
+       int blockInNAND = chunkInNAND / dev->param.nChunksPerBlock;
 
        /* Mark the block for retirement */
        yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
@@ -375,8 +371,8 @@ static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND)
        yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
 }
 
-static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1,
-                              const yaffs_Spare * s0, const yaffs_Spare * s1)
+static int yaffs_VerifyCompare(const __u8 *d0, const __u8 *d1,
+                              const yaffs_Spare *s0, const yaffs_Spare *s1)
 {
 
        if (memcmp(d0, d1, YAFFS_BYTES_PER_CHUNK) != 0 ||
@@ -400,28 +396,35 @@ static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1,
 }
 #endif                         /* NOTYET */
 
-int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
-                                                   int chunkInNAND,
-                                                   const __u8 * data,
-                                                   const yaffs_ExtendedTags *
-                                                   eTags)
+int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev,
+                                               int chunkInNAND,
+                                               const __u8 *data,
+                                               const yaffs_ExtendedTags *eTags)
 {
        yaffs_Spare spare;
        yaffs_Tags tags;
 
        yaffs_SpareInitialise(&spare);
 
-       if (eTags->chunkDeleted) {
+       if (eTags->chunkDeleted)
                spare.pageStatus = 0;
-       else {
+       else {
                tags.objectId = eTags->objectId;
                tags.chunkId = eTags->chunkId;
-               tags.byteCount = eTags->byteCount;
+
+               tags.byteCountLSB = eTags->byteCount & 0x3ff;
+
+               if (dev->nDataBytesPerChunk >= 1024)
+                       tags.byteCountMSB = (eTags->byteCount >> 10) & 3;
+               else
+                       tags.byteCountMSB = 3;
+
+
                tags.serialNumber = eTags->serialNumber;
 
-               if (!dev->useNANDECC && data) {
+               if (!dev->param.useNANDECC && data)
                        yaffs_CalcECC(data, &spare);
-               }
+
                yaffs_LoadTagsIntoSpare(&spare, &tags);
 
        }
@@ -429,15 +432,15 @@ int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
        return yaffs_WriteChunkToNAND(dev, chunkInNAND, data, &spare);
 }
 
-int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
+int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev,
                                                     int chunkInNAND,
-                                                    __u8 * data,
-                                                    yaffs_ExtendedTags * eTags)
+                                                    __u8 *data,
+                                                    yaffs_ExtendedTags *eTags)
 {
 
        yaffs_Spare spare;
        yaffs_Tags tags;
-       yaffs_ECCResult eccResult;
+       yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_UNKNOWN;
 
        static yaffs_Spare spareFF;
        static int init;
@@ -455,20 +458,26 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
                        int deleted =
                            (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0;
 
-                       yaffs_GetTagsFromSpare(dev, &spare, &tags);
-
                        eTags->chunkDeleted = deleted;
-                       eTags->objectId = tags.objectId;
-                       eTags->chunkId = tags.chunkId;
-                       eTags->byteCount = tags.byteCount;
-                       eTags->serialNumber = tags.serialNumber;
                        eTags->eccResult = eccResult;
                        eTags->blockBad = 0;    /* We're reading it */
                        /* therefore it is not a bad block */
-
                        eTags->chunkUsed =
                            (memcmp(&spareFF, &spare, sizeof(spareFF)) !=
                             0) ? 1 : 0;
+
+                       if (eTags->chunkUsed) {
+                               yaffs_GetTagsFromSpare(dev, &spare, &tags);
+
+                               eTags->objectId = tags.objectId;
+                               eTags->chunkId = tags.chunkId;
+                               eTags->byteCount = tags.byteCountLSB;
+
+                               if (dev->nDataBytesPerChunk >= 1024)
+                                       eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10);
+
+                               eTags->serialNumber = tags.serialNumber;
+                       }
                }
 
                return YAFFS_OK;
@@ -487,9 +496,9 @@ int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
 
        spare.blockStatus = 'Y';
 
-       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL,
+       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->param.nChunksPerBlock, NULL,
                               &spare);
-       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1,
+       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->param.nChunksPerBlock + 1,
                               NULL, &spare);
 
        return YAFFS_OK;
@@ -497,9 +506,9 @@ int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
 }
 
 int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
-                                         int blockNo, yaffs_BlockState *
-                                         state,
-                                         int *sequenceNumber)
+                                         int blockNo,
+                                         yaffs_BlockState *state,
+                                         __u32 *sequenceNumber)
 {
 
        yaffs_Spare spare0, spare1;
@@ -514,9 +523,9 @@ int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
 
        *sequenceNumber = 0;
 
-       yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock, NULL,
+       yaffs_ReadChunkFromNAND(dev, blockNo * dev->param.nChunksPerBlock, NULL,
                                &spare0, &dummy, 1);
-       yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock + 1, NULL,
+       yaffs_ReadChunkFromNAND(dev, blockNo * dev->param.nChunksPerBlock + 1, NULL,
                                &spare1, &dummy, 1);
 
        if (yaffs_CountBits(spare0.blockStatus & spare1.blockStatus) < 7)