static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, int chunkInNAND, __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 (data && doErrorCorrection) { /* Do ECC correction */ /* Todo handle any errors */ int eccResult1, eccResult2; __u8 calcEcc[3]; yaffs_ECCCalculate(data, calcEcc); eccResult1 = yaffs_ECCCorrect(data, spare->ecc1, calcEcc); yaffs_ECCCalculate(&data[256], calcEcc); eccResult2 = yaffs_ECCCorrect(&data[256], spare->ecc2, calcEcc); if (eccResult1 > 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>yaffs ecc error fix performed on chunk %d:0" TENDSTR), chunkInNAND)); dev->eccFixed++; } else if (eccResult1 < 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>yaffs ecc error unfixed on chunk %d:0" TENDSTR), chunkInNAND)); dev->eccUnfixed++; } if (eccResult2 > 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>yaffs ecc error fix performed on chunk %d:1" TENDSTR), chunkInNAND)); dev->eccFixed++; } else if (eccResult2 < 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>yaffs ecc error unfixed on chunk %d:1" TENDSTR), chunkInNAND)); dev->eccUnfixed++; } if (eccResult1 || eccResult2) { /* We had a data problem on this page */ yaffs_HandleReadDataError(dev, chunkInNAND); } if (eccResult1 < 0 || eccResult2 < 0) *eccResult = YAFFS_ECC_RESULT_UNFIXED; else if (eccResult1 > 0 || eccResult2 > 0) *eccResult = YAFFS_ECC_RESULT_FIXED; else *eccResult = YAFFS_ECC_RESULT_NO_ERROR; } } else { /* 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); memcpy(spare, &nspare, sizeof(yaffs_Spare)); if (data && doErrorCorrection) { if (nspare.eccres1 > 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>mtd ecc error fix performed on chunk %d:0" TENDSTR), chunkInNAND)); } else if (nspare.eccres1 < 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>mtd ecc error unfixed on chunk %d:0" TENDSTR), chunkInNAND)); } if (nspare.eccres2 > 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>mtd ecc error fix performed on chunk %d:1" TENDSTR), chunkInNAND)); } else if (nspare.eccres2 < 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>mtd ecc error unfixed on chunk %d:1" TENDSTR), chunkInNAND)); } if (nspare.eccres1 || nspare.eccres2) { /* We had a data problem on this page */ yaffs_HandleReadDataError(dev, chunkInNAND); } if (nspare.eccres1 < 0 || nspare.eccres2 < 0) *eccResult = YAFFS_ECC_RESULT_UNFIXED; else if (nspare.eccres1 > 0 || nspare.eccres2 > 0) *eccResult = YAFFS_ECC_RESULT_FIXED; else *eccResult = YAFFS_ECC_RESULT_NO_ERROR; } } return retVal; }
static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, int chunkInNAND, __u8 * data, yaffs_Spare * spare, yaffs_ECCResult * eccResult, int doErrorCorrection) { int retVal; yaffs_Spare localSpare; dev->nPageReads++; if (!spare && data) { spare = &localSpare; } if (!dev->useNANDECC) { retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare); if (data && doErrorCorrection) { int eccResult1, eccResult2; __u8 calcEcc[3]; yaffs_ECCCalculate(data, calcEcc); eccResult1 = yaffs_ECCCorrect(data, spare->ecc1, calcEcc); yaffs_ECCCalculate(&data[256], calcEcc); eccResult2 = yaffs_ECCCorrect(&data[256], spare->ecc2, calcEcc); if (eccResult1 > 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>yaffs ecc error fix performed on chunk %d:0" TENDSTR), chunkInNAND)); dev->eccFixed++; } else if (eccResult1 < 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>yaffs ecc error unfixed on chunk %d:0" TENDSTR), chunkInNAND)); dev->eccUnfixed++; } if (eccResult2 > 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>yaffs ecc error fix performed on chunk %d:1" TENDSTR), chunkInNAND)); dev->eccFixed++; } else if (eccResult2 < 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>yaffs ecc error unfixed on chunk %d:1" TENDSTR), chunkInNAND)); dev->eccUnfixed++; } if (eccResult1 || eccResult2) { yaffs_HandleReadDataError(dev, chunkInNAND); } if (eccResult1 < 0 || eccResult2 < 0) *eccResult = YAFFS_ECC_RESULT_UNFIXED; else if (eccResult1 > 0 || eccResult2 > 0) *eccResult = YAFFS_ECC_RESULT_FIXED; else *eccResult = YAFFS_ECC_RESULT_NO_ERROR; } } else { struct yaffs_NANDSpare nspare; retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, (yaffs_Spare *) & nspare); memcpy(spare, &nspare, sizeof(yaffs_Spare)); if (data && doErrorCorrection) { if (nspare.eccres1 > 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>mtd ecc error fix performed on chunk %d:0" TENDSTR), chunkInNAND)); } else if (nspare.eccres1 < 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>mtd ecc error unfixed on chunk %d:0" TENDSTR), chunkInNAND)); } if (nspare.eccres2 > 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>mtd ecc error fix performed on chunk %d:1" TENDSTR), chunkInNAND)); } else if (nspare.eccres2 < 0) { T(YAFFS_TRACE_ERROR, (TSTR ("**>>mtd ecc error unfixed on chunk %d:1" TENDSTR), chunkInNAND)); } if (nspare.eccres1 || nspare.eccres2) { yaffs_HandleReadDataError(dev, chunkInNAND); } if (nspare.eccres1 < 0 || nspare.eccres2 < 0) *eccResult = YAFFS_ECC_RESULT_UNFIXED; else if (nspare.eccres1 > 0 || nspare.eccres2 > 0) *eccResult = YAFFS_ECC_RESULT_FIXED; else *eccResult = YAFFS_ECC_RESULT_NO_ERROR; } } return retVal; }