*/
//yaffs_guts.c
-const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.41 2005-04-24 08:54:36 charles Exp $";
+const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.42 2005-06-25 03:22:23 charles Exp $";
#include "yportenv.h"
static __inline __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk)
{
- if(blk < dev->startBlock || blk > dev->endBlock)
+ if(blk < dev->internalStartBlock || blk > dev->internalEndBlock)
{
T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),blk));
YBUG();
}
- return dev->chunkBits + (dev->chunkBitmapStride * (blk - dev->startBlock));
+ return dev->chunkBits + (dev->chunkBitmapStride * (blk - dev->internalStartBlock));
}
static __inline__ void yaffs_ClearChunkBits(yaffs_Device *dev,int blk)
// Function to manipulate block info
static __inline__ yaffs_BlockInfo* yaffs_GetBlockInfo(yaffs_Device *dev, int blk)
{
- if(blk < dev->startBlock || blk > dev->endBlock)
+ if(blk < dev->internalStartBlock || blk > dev->internalEndBlock)
{
T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),blk));
YBUG();
}
- return &dev->blockInfo[blk - dev->startBlock];
+ return &dev->blockInfo[blk - dev->internalStartBlock];
}
static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare)
{
- if(chunkInNAND < dev->startBlock * dev->nChunksPerBlock)
+ if(chunkInNAND < dev->internalStartBlock * dev->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->writeChunkToNAND(dev,chunkInNAND - dev->chunkOffset,data,spare);
}
if(!dev->useNANDECC)
{
- retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,spare);
+ retVal = dev->readChunkFromNAND(dev,chunkInNAND - dev->chunkOffset,data,spare);
if(data && doErrorCorrection)
{
// Do ECC correction
if(eccResult1>0)
{
- T(YAFFS_TRACE_ERROR, (TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND));
+ T(YAFFS_TRACE_ERROR, (TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND - dev->chunkOffset));
dev->eccFixed++;
}
else if(eccResult1<0)
{
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND));
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND - dev->chunkOffset));
dev->eccUnfixed++;
}
if(eccResult2>0)
{
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND));
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND - dev->chunkOffset));
dev->eccFixed++;
}
else if(eccResult2<0)
{
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND));
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND - dev->chunkOffset));
dev->eccUnfixed++;
}
{
// 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);
+ retVal = dev->readChunkFromNAND(dev,chunkInNAND - dev->chunkOffset,data,(yaffs_Spare*)&nspare);
memcpy (spare, &nspare, sizeof(yaffs_Spare));
if(data && doErrorCorrection)
{
if(nspare.eccres1>0)
{
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND));
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND - dev->chunkOffset));
}
else if(nspare.eccres1<0)
{
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND));
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND - dev->chunkOffset));
}
if(nspare.eccres2>0)
{
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND));
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND - dev->chunkOffset));
}
else if(nspare.eccres2<0)
{
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND));
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND - dev->chunkOffset));
}
if(nspare.eccres1 || nspare.eccres2)
// Might as well always allocate the larger size for dev->useNANDECC == true;
static __u8 spare[sizeof(struct yaffs_NANDSpare)];
- dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare *)spare);
+ dev->readChunkFromNAND(dev,chunkInNAND - dev->chunkOffset,data,(yaffs_Spare *)spare);
if(!init)
{
int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND)
{
dev->nBlockErasures++;
- return dev->eraseBlockInNAND(dev,blockInNAND);
+ return dev->eraseBlockInNAND(dev,blockInNAND - dev->blockOffset);
}
int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
pagesInUse = (aggressive)? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1;
if(aggressive)
{
- iterations = dev->endBlock - dev->startBlock + 1;
+ iterations = dev->internalEndBlock - dev->internalStartBlock + 1;
}
else
{
- iterations = dev->endBlock - dev->startBlock + 1;
+ iterations = dev->internalEndBlock - dev->internalStartBlock + 1;
iterations = iterations / 16;
if(iterations > 200)
{
for(i = 0; i <= iterations && pagesInUse > 0 ; i++)
{
b++;
- if ( b < dev->startBlock || b > dev->endBlock)
+ if ( b < dev->internalStartBlock || b > dev->internalEndBlock)
{
- b = dev->startBlock;
+ b = dev->internalStartBlock;
}
- if(b < dev->startBlock || b > dev->endBlock)
+ if(b < dev->internalStartBlock || b > dev->internalEndBlock)
{
T(YAFFS_TRACE_ERROR,(TSTR("**>> Block %d is not valid" TENDSTR),b));
YBUG();
// Find an empty block.
- for(i = dev->startBlock; i <= dev->endBlock; i++)
+ for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++)
{
dev->allocationBlockFinder++;
- if(dev->allocationBlockFinder <dev->startBlock || dev->allocationBlockFinder> dev->endBlock)
+ if(dev->allocationBlockFinder <dev->internalStartBlock || dev->allocationBlockFinder> dev->internalEndBlock)
{
- dev->allocationBlockFinder = dev->startBlock;
+ dev->allocationBlockFinder = dev->internalStartBlock;
}
bi = yaffs_GetBlockInfo(dev,dev->allocationBlockFinder);
// using yaffs_DeleteChunk
chunkId = yaffs_FindAndDeleteChunkInFile(in,i,NULL);
- if(chunkId < (dev->startBlock * 32) || chunkId >= ((dev->endBlock+1) * 32))
+ if(chunkId < (dev->internalStartBlock * 32) || chunkId >= ((dev->internalEndBlock+1) * 32))
{
//T(("Found daft chunkId %d for %d\n",chunkId,i));
}
// Scan all the blocks...
- for(blk = dev->startBlock; blk <= dev->endBlock; blk++)
+ for(blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++)
{
deleted = 0;
bi = yaffs_GetBlockInfo(dev,blk);
if( dev->nBytesPerChunk != YAFFS_BYTES_PER_CHUNK ||
dev->nChunksPerBlock < 2 ||
dev->nReservedBlocks < 2 ||
- dev->startBlock <= 0 ||
+ dev->startBlock < 0 ||
dev->endBlock <= 0 ||
dev->endBlock <= (dev->startBlock + dev->nReservedBlocks)
)
{
//these parameters must be set before stating yaffs
- // Other parameters startBlock,
+ // Other parameters internalStartBlock,
return YAFFS_FAIL;
}
}
dev->isMounted = 1;
-
- if(dev->startBlock <= 0 ||
+
+ if(dev->startBlock < 0 ||
(dev->endBlock - dev->startBlock) < 10)
{
T(YAFFS_TRACE_ALWAYS,(TSTR("startBlock %d or endBlock %d invalid\n" TENDSTR),
return YAFFS_FAIL;
}
- nBlocks = dev->endBlock - dev->startBlock + 1;
+
+ // Do we need to add an offset to use block 0?
+
+ dev->internalStartBlock = dev->startBlock;
+ dev->internalEndBlock = dev->endBlock;
+ dev->blockOffset = 0;
+ dev->chunkOffset = 0;
+
+ if(dev->startBlock == 0)
+ {
+ dev->internalStartBlock++;
+ dev->internalEndBlock++;
+ dev->blockOffset++;
+ dev->chunkOffset = dev->nChunksPerBlock;
+ }
+
+
+ nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
// OK now calculate a few things for the device
// Calculate chunkGroupBits.
- // We need to find the next power of 2 > than endBlock
+ // We need to find the next power of 2 > than internalEndBlock
- x = dev->nChunksPerBlock * (dev->endBlock+1);
+ x = dev->nChunksPerBlock * (dev->internalEndBlock+1);
for(bits = extraBits = 0; x > 1; bits++)
{
struct list_head *i;
yaffs_Object *l;
- for(nFree = 0, b = dev->startBlock; b <= dev->endBlock; b++)
+ for(nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock; b++)
{
blk = yaffs_GetBlockInfo(dev,b);