📄 saftl.c
字号:
{
DBG_PRINT_ERR(FLZONE_TL,"Debug: Too many blocks in the quick mount area.\r\n");
return FALSE;
}
}
/* Check quick mount validity and load general information sector */
if(fCheckOnly == FALSE)
{
flashPtr->args.startSector = ((FLDword)(volPrmPtr->firstQuickMountUnit + wIdx)) <<
volPrmPtr->sectorsInUnitBits;
}
else
{
flashPtr->args.startSector = ((FLDword)(volPrmPtr->firstQuickMountUnit + wIdx)) <<
(flashPtr->erasableBlockSizeBits-FL_SECTOR_SIZE_BITS);
if((volPrmPtr->flash->flashTechnology & FL_SUPPORT_MLC) &&
(volPrmPtr->MTDFlags & MTD_REL_MODE ) )
{
flashPtr->args.startSector <<= 1;
}
}
flashPtr->args.noOfSectors = 1;
flashPtr->args.readMainBuf = (fCheckOnly == TRUE) ? saftlBuffer :
volPrmPtr->foldingBuffer;
flashPtr->args.opFlags = MTD_DATA | volPrmPtr->MTDFlags;
status = flashPtr->flashRead(flashPtr);
if(status != flOK)
return FALSE;
info = (CNANDQuickMountInfo FAR1 *)flashPtr->args.readMainBuf;
if(info->endianValidation != SAFTL_ENDIAN_VALIDATION_MARK)
{
DBG_PRINT_WRN(FLZONE_TL,"Quick mount data is invalid.\r\n");
DBG_PRINT_WRN_PRM(FLZONE_TL,(FLTXT("Mark is 0x%lx instead of 0x%lx.\r\n"),(FLDword)info->endianValidation,(FLDword)SAFTL_ENDIAN_VALIDATION_MARK));
return FALSE;
}
if(info->quickMountVersion != SAFTL_QUICK_MOUNT_VERSION)
{
DBG_PRINT_WRN(FLZONE_TL,"Quick mount data is not compatible with current TrueFFS version.\r\n");
DBG_PRINT_WRN_PRM(FLZONE_TL,(FLTXT("TrueFFS quick mount version is 0x%lx while the version on the flash is 0x%lx.\r\n"),(FLDword)SAFTL_QUICK_MOUNT_VERSION,(FLDword)info->endianValidation));
return FALSE;
}
if(fCheckOnly == TRUE)
return TRUE;
if(info->noOfCachedUnits != volPrmPtr->noOfCachedUnits)
{
DBG_PRINT_WRN(FLZONE_TL,"Quick mount data was not loaded , because the number of cached units does not fit the number currently allocated.\r\n");
DBG_PRINT_WRN_PRM(FLZONE_TL,(FLTXT("There are %u allocated units while there are %u stored units.\r\n"),volPrmPtr->noOfCachedUnits,(FLWord)info->noOfCachedUnits ));
return FALSE;
}
/* Store current volPrmPtr record */
tffscpy(bSavedCnandPtr,volPrmPtr,sizeof(Cnand));
/* Load volume information from the quick mount data */
volPrmPtr->neededFreeUnits = (FLByte)info->neededFreeUnits;
volPrmPtr->freeUnits = (FLWord)info->freeUnits;
volPrmPtr->roverUnit = (FLWord)info->roverUnit;
volPrmPtr->bootUnits = (FLWord)info->bootUnits;
volPrmPtr->multiUnitListHead = (FLWord)info->multiUnitListHead;
volPrmPtr->multiUnitListTail = (FLWord)info->multiUnitListTail;
volPrmPtr->singleUnitListHead = (FLWord)info->singleUnitListHead;
volPrmPtr->singleUnitListTail = (FLWord)info->singleUnitListTail;
volPrmPtr->freeCacheUnitList = (FLWord)info->freeCacheUnitList;
volPrmPtr->wearLevel.alarm = (FLWord)info->alarm;
volPrmPtr->wearLevel.currUnit = (FLWord)info->currUnit;
volPrmPtr->eraseSum = info->eraseSum;
volPrmPtr->noOfUsedUnits = (FLWord)info->noOfUsedUnits;
#ifndef TL_NO_STATISTICS
volPrmPtr->sectorsRead = info->sectorsRead;
volPrmPtr->sectorsWritten = info->sectorsWritten;
volPrmPtr->sectorsDeleted = info->sectorsDeleted;
volPrmPtr->parasiteWritesFromOldest = info->parasiteWritesFromOldest;
volPrmPtr->parasiteWritesFromOldest = info->parasiteWritesFromOldest;
volPrmPtr->unitsFoldedFromOldest = info->unitsFoldedFromOldest;
volPrmPtr->unitsFoldedFromNewest = info->unitsFoldedFromNewest;
#endif /* FL_NO_STATISTICS */
flashPtr->args.startSector++; /* Skip first sector */
/* Load unit cache */
status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->CT ,
volPrmPtr->noOfCachedUnits * sizeof(CNANDCache));
/* Load sector cache */
if(status == flOK)
status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->sectors ,
(volPrmPtr->noOfCachedUnits << volPrmPtr->sectorsInUnitBits)
* sizeof(FLWord));
/* Load VUT table */
if(status == flOK)
status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->VUT ,
volPrmPtr->noOfVirtualUnits * sizeof(FLWord));
/* Load CLT table */
if(status == flOK)
status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->CLT ,
volPrmPtr->noOfUnits * sizeof(FLByte));
/* Load LUT table */
if(status == flOK)
status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->LUT ,
volPrmPtr->noOfUnits * sizeof(FLWord));
if(status != flOK)
{
/* RE-store volPrmPtr record */
tffscpy(volPrmPtr,bSavedCnandPtr,sizeof(Cnand));
DBG_PRINT_WRN(FLZONE_TL,"Failed getting quick mount information.\r\n");
DBG_PRINT_WRN_PRM(FLZONE_TL,(FLTXT("With status status %d.\r\n"),status));
return FALSE;
}
volPrmPtr->fIsQuickMountValid = TRUE; /* Prevent re-writing of the quick mount */
return TRUE;
}
#ifndef FL_READ_ONLY
/*----------------------------------------------------------------------*/
/* s t o r e Q u i c k M o u n t B u f f e r */
/* */
/* Store a RAM table to the quick mount area. */
/* */
/* Notes */
/* The routine uses both saftlBuffer + all of volPrmPtr->foldingBuffer */
/* */
/* Parameters: */
/* volPrmPtr : Pointer identifying drive */
/* volPrmPtr->flash->args.startSector : Flash address to write to */
/* volPrmPtr->flash->args.writeMainBuf : Location in internal buffer */
/* bufPtr : Pointer to read the data to */
/* endBufPtr : Pointer to end of internal buffer (minus 512) */
/* dwSize : Size to write in bytes */
/* */
/* Returns: */
/* flOK if the data was successfully loaded. */
/* Any other value for failure. */
/*----------------------------------------------------------------------*/
static FLStatus storeQuickMountBuffer(Cnand * volPrmPtr,
FLByte FAR1 * bufPtr,
FLByte FAR1 * endBufPtr,
FLDword dwSize)
{
FLFlash * flashPtr = volPrmPtr->flash;
FLDword dwEndAddress = flashPtr->args.startSector +
((dwSize+FL_SECTOR_MASK)>>FL_SECTOR_SIZE_BITS);
FLDword dwUnitSectorMask = (1L << volPrmPtr->sectorsInUnitBits) - 1;
FLDword dwUnitOffset;
FLDword dwNoneFullSector = (dwSize & FL_SECTOR_MASK) ? dwEndAddress - 1 :
SAFTL_INVALID_SECTOR_NO;
FLByte bNoOfSkippedUnits = 0;
while(flashPtr->args.startSector < dwEndAddress)
{
/* Copy the data to intenal buffer and pad with 0's if neccesary */
if(flashPtr->args.startSector == dwNoneFullSector)
{
tffsset((void FAR1 *)flashPtr->args.writeMainBuf,00,FL_SECTOR_SIZE);
tffscpy((void FAR1 *)flashPtr->args.writeMainBuf,bufPtr,(dwSize & FL_SECTOR_MASK));
}
else /* A full 512 bytes of data - can be read directly to the buffer */
{
tffscpy((void FAR1 *)flashPtr->args.writeMainBuf,bufPtr,FL_SECTOR_SIZE);
bufPtr = BYTE_ADD_FAR(bufPtr,FL_SECTOR_SIZE);
}
/* Check if internal buffer is full - need to write */
if(flashPtr->args.writeMainBuf != endBufPtr)
{
/* Buffer is not full yet , copy the data and continue */
flashPtr->args.writeMainBuf = BYTE_ADD_FAR(flashPtr->args.writeMainBuf,FL_SECTOR_SIZE);
flashPtr->args.startSector++;
}
else /* The intenal buffer is full - write the data */
{
/* Write to the begining of the page */
flashPtr->args.startSector -= (volPrmPtr->foldingBufferSize >> FL_SECTOR_SIZE_BITS) - 1;
flashPtr->args.writeMainBuf = volPrmPtr->foldingBuffer;
/* Make sure it is on a good unit */
if((flashPtr->args.startSector & dwUnitSectorMask) == 0)
{
/* Find next good block */
dwUnitOffset = (flashPtr->args.startSector >> volPrmPtr->sectorsInUnitBits) -
volPrmPtr->firstQuickMountUnit;
while ((saftlBuffer[dwUnitOffset] != BBT_GOOD_UNIT) ||
(bNoOfSkippedUnits != 0 ) )
{
switch(saftlBuffer[dwUnitOffset])
{
case BBT_UNAVAIL_UNIT:
bNoOfSkippedUnits = flashPtr->args.noOfSkippedUnits;
/* No break */
case BBT_BAD_UNIT:
break;
default: /* BBT_GOOD_UNIT */
bNoOfSkippedUnits--;
break;
}
if(dwUnitOffset >= FL_SECTOR_SIZE)
return flGeneralFailure;
dwEndAddress += volPrmPtr->sectorsInUnit;
dwNoneFullSector += volPrmPtr->sectorsInUnit;
dwUnitOffset++;
}
flashPtr->args.startSector = (dwUnitOffset + (FLDword)volPrmPtr->firstQuickMountUnit)
<< volPrmPtr->sectorsInUnitBits;
}
checkStatus(flashPtr->flashWrite(flashPtr))
flashPtr->args.startSector += volPrmPtr->foldingBufferSize >> FL_SECTOR_SIZE_BITS;
} /* End if - internal buffer is full */
} /* End loop over give buffer */
return flOK;
}
/*----------------------------------------------------------------------*/
/* s t o r e E n t i r e Q u i c k M o u n t I n f o */
/* */
/* Save the quick mount information from the RAM tables to the flash. */
/* */
/* Parameters: */
/* volPrmPtr : Pointer identifying drive */
/* */
/* Returns: */
/* flOK if data was written properly. Any other value for failure */
/*----------------------------------------------------------------------*/
static FLStatus storeEntireQuickMountInfo(Cnand *volPrmPtr)
{
FLFlash * flashPtr = volPrmPtr->flash;
CNANDQuickMountInfo * info = (CNANDQuickMountInfo *)volPrmPtr->foldingBuffer;
FLStatus status;
/* Last internal buffer location , before writing */
FLByte FAR1 * endBufPtr = BYTE_ADD_FAR(volPrmPtr->foldingBuffer,
volPrmPtr->foldingBufferSize - FL_SECTOR_SIZE);
FLWord wCachedUnits = volPrmPtr->noOfCachedUnits;
if((volPrmPtr->volumeFlags & SAFTL_QUICK_MOUNT) == 0)
return flOK;
/* Find the first good unit of the partition */
checkStatus(discardQuickMountInfo(volPrmPtr));
/* Prepare for writing the quick mount data */
flashPtr->args.startSector = 1L + ((FLDword)volPrmPtr->firstQuickMountUnit <<
volPrmPtr->sectorsInUnitBits);
flashPtr->args.noOfSectors = volPrmPtr->foldingBufferSize >> FL_SECTOR_SIZE_BITS;
flashPtr->args.writeMainBuf = BYTE_ADD_FAR(volPrmPtr->foldingBuffer,FL_SECTOR_SIZE);
flashPtr->args.extraBuf = (FLByte FAR1 *)volPrmPtr->myHeaders;
flashPtr->args.opFlags = MTD_DATA | MTD_EXTRA | volPrmPtr->MTDFlags;
/* Build volume information sector */
tffsset(volPrmPtr->myHeaders,0,volPrmPtr->sectorsInUnit * sizeof(CNANDSectorHeader));
tffsset(volPrmPtr->foldingBuffer,0,FL_SECTOR_SIZE);
info->quickMountVersion = SAFTL_QUICK_MOUNT_VERSION;
info->endianValidation = SAFTL_ENDIAN_VALIDATION_MARK;
info->noOfCachedUnits = (FLDword) volPrmPtr->noOfCachedUnits;
info->neededFreeUnits = (FLDword) volPrmPtr->neededFreeUnits;
info->freeUnits = (FLDword) volPrmPtr->freeUnits;
info->roverUnit = (FLDword) volPrmPtr->roverUnit;
info->bootUnits = (FLDword) volPrmPtr->bootUnits;
info->multiUnitListHead = (FLDword) volPrmPtr->multiUnitListHead;
info->multiUnitListTail = (FLDword) volPrmPtr->multiUnitListTail;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -