📄 yaffs_tagscompat.c
字号:
{
dev->nBlockErasures++;
return dev->eraseBlockInNAND(dev,blockInNAND);
}
int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
{
return dev->initialiseNAND(dev);
}
#endif
#if 0
static int yaffs_WriteNewChunkToNAND(struct yaffs_DeviceStruct *dev, const __u8 *data, yaffs_Spare *spare,int useReserve)
{
int chunk;
int writeOk = 1;
int attempts = 0;
unsigned char rbData[YAFFS_BYTES_PER_CHUNK];
yaffs_Spare rbSpare;
do{
chunk = yaffs_AllocateChunk(dev,useReserve);
if(chunk >= 0)
{
// First check this chunk is erased...
#ifndef CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
writeOk = yaffs_CheckChunkErased(dev,chunk);
#endif
if(!writeOk)
{
T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs chunk %d was not erased" TENDSTR),chunk));
}
else
{
writeOk = yaffs_WriteChunkToNAND(dev,chunk,data,spare);
}
attempts++;
if(writeOk)
{
// Readback & verify
// If verify fails, then delete this chunk and try again
// To verify we compare everything except the block and
// page status bytes.
// NB We check a raw read without ECC correction applied
yaffs_ReadChunkFromNAND(dev,chunk,rbData,&rbSpare,0);
#ifndef CONFIG_YAFFS_DISABLE_WRITE_VERIFY
if(!yaffs_VerifyCompare(data,rbData,spare,&rbSpare))
{
// Didn't verify
T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs write verify failed on chunk %d" TENDSTR), chunk));
writeOk = 0;
}
#endif
}
if(writeOk)
{
// Copy the data into the write buffer.
// NB We do this at the end to prevent duplicates in the case of a write error.
//Todo
yaffs_HandleWriteChunkOk(dev,chunk,data,spare);
}
else
{
yaffs_HandleWriteChunkError(dev,chunk);
}
}
} while(chunk >= 0 && ! writeOk);
if(attempts > 1)
{
T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs write required %d attempts" TENDSTR),attempts));
dev->nRetriedWrites+= (attempts - 1);
}
return chunk;
}
#endif
///
// Functions for robustisizing
//
//
#if 0
static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND)
{
// Ding the blockStatus in the first two pages of the block.
yaffs_Spare spare;
memset(&spare, 0xff,sizeof(yaffs_Spare));
spare.blockStatus = 0;
// TODO change this retirement marking for other NAND types
yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL , &spare);
yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1, NULL , &spare);
yaffs_GetBlockInfo(dev,blockInNAND)->blockState = YAFFS_BLOCK_STATE_DEAD;
dev->nRetiredBlocks++;
}
#endif
#if 0
static int yaffs_RewriteBufferedBlock(yaffs_Device *dev)
{
dev->doingBufferedBlockRewrite = 1;
//
// Remove erased chunks
// Rewrite existing chunks to a new block
// Set current write block to the new block
dev->doingBufferedBlockRewrite = 0;
return 1;
}
#endif
static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND)
{
int blockInNAND = chunkInNAND/dev->nChunksPerBlock;
// Mark the block for retirement
yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1;
T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>>Block %d marked for retirement" TENDSTR),blockInNAND));
//TODO
// Just do a garbage collection on the affected block then retire the block
// NB recursion
}
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)
{
int blockInNAND = chunkInNAND/dev->nChunksPerBlock;
// Mark the block for retirement
yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1;
// Delete the chunk
yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__);
}
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 ||
s0->tagByte0 != s1->tagByte0 ||
s0->tagByte1 != s1->tagByte1 ||
s0->tagByte2 != s1->tagByte2 ||
s0->tagByte3 != s1->tagByte3 ||
s0->tagByte4 != s1->tagByte4 ||
s0->tagByte5 != s1->tagByte5 ||
s0->tagByte6 != s1->tagByte6 ||
s0->tagByte7 != s1->tagByte7 ||
s0->ecc1[0] != s1->ecc1[0] ||
s0->ecc1[1] != s1->ecc1[1] ||
s0->ecc1[2] != s1->ecc1[2] ||
s0->ecc2[0] != s1->ecc2[0] ||
s0->ecc2[1] != s1->ecc2[1] ||
s0->ecc2[2] != s1->ecc2[2] )
{
return 0;
}
return 1;
}
#if 0
typedef struct
{
unsigned validMarker0;
unsigned chunkUsed; // Status of the chunk: used or unused
unsigned objectId; // If 0 then this is not part of an object (unused)
unsigned chunkId; // If 0 then this is a header
unsigned byteCount; // Only valid for data chunks
// The following stuff only has meaning when we read
yaffs_ECCResult eccResult; // Only valid when we read.
unsigned blockBad; // Only valid on reading
// YAFFS 1 stuff
unsigned chunkDeleted; // The chunk is marked deleted
unsigned serialNumber; // Yaffs1 2-bit serial number
// YAFFS2 stuff
unsigned sequenceNumber; // The sequence number of this block
unsigned validMarker1;
} yaffs_ExtendedTags;
typedef struct
{
unsigned chunkId:20;
unsigned serialNumber:2;
unsigned byteCount:10;
unsigned objectId:18;
unsigned ecc:12;
unsigned unusedStuff:2;
} yaffs_Tags;
#endif
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)
{
spare.pageStatus = 0;
}
else
{
tags.objectId = eTags->objectId;
tags.chunkId = eTags->chunkId;
tags.byteCount = eTags->byteCount;
tags.serialNumber = eTags->serialNumber;
yaffs_LoadTagsIntoSpare(&spare,&tags);
}
return yaffs_WriteChunkToNAND(dev,chunkInNAND,data,&spare);
}
int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *eTags)
{
yaffs_Spare spare;
yaffs_Tags tags;
yaffs_ECCResult eccResult;
if(yaffs_ReadChunkFromNAND(dev,chunkInNAND,data,&spare,&eccResult,1))
{
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
return YAFFS_OK;
}
else
{
return YAFFS_FAIL;
}
}
int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockInNAND)
{
yaffs_Spare spare;
memset(&spare, 0xff,sizeof(yaffs_Spare));
spare.blockStatus = 0;
yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL , &spare);
yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1, NULL , &spare);
return YAFFS_OK;
}
int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
{
yaffs_Spare spare0,spare1;
static yaffs_Spare spareFF;
static int init;
yaffs_ECCResult dummy;
if(!init)
{
memset(&spareFF,0xFF,sizeof(spareFF));
init = 1;
}
*sequenceNumber = 0;
yaffs_ReadChunkFromNAND(dev,blockNo * dev->nChunksPerBlock,NULL,&spare0,&dummy,1);
yaffs_ReadChunkFromNAND(dev,blockNo * dev->nChunksPerBlock + 1,NULL,&spare1,&dummy,1);
if(yaffs_CountBits(spare0.blockStatus & spare1.blockStatus) < 7)
*state = YAFFS_BLOCK_STATE_DEAD;
else if(memcmp(&spareFF,&spare0,sizeof(spareFF)) == 0)
*state = YAFFS_BLOCK_STATE_EMPTY;
else
*state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
return YAFFS_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -