📄 smt_fat.c
字号:
if(bArea != SMT_AREA_2) // ECC value is taken out from
{ // - "ECC Area-1" or "ECC Area-2".
ulEccVal = (unsigned long)(pChkBuff->stDatBuff.bEcc1[0]);
ulEccVal |= (unsigned long)(pChkBuff->stDatBuff.bEcc1[1] << 8);
ulEccVal |= (unsigned long)(pChkBuff->stDatBuff.bEcc1[2] << 16);
}
else
{
ulEccVal = (unsigned long)(pChkBuff->stDatBuff.bEcc2[0]);
ulEccVal |= (unsigned long)(pChkBuff->stDatBuff.bEcc2[1] << 8);
ulEccVal |= (unsigned long)(pChkBuff->stDatBuff.bEcc2[2] << 16);
}
return(ulEccVal);
}
/************************************************************************
* smtRdSect
* Type : int
* Ret val : Error Code
* Argument : unsigned long ulLogSct ... Logic sector address
* unsigned long ulDatSiz ... Read data size
* char *pBuffer ... Read data buffer
* Function : This function reads data for the size from specified
* sector.
************************************************************************/
int smtRdSect(
unsigned char bDrvNum, // Drive number(dummy)
unsigned long ulLogSct, // Logic sector address
unsigned long ulDatSiz, // Read data size
unsigned char *pBuffer // Read data buffer
)
{
unsigned long ulLogBlk; // Logic block address
unsigned long ulPhyBlk; // Physics block address
unsigned long ulPhySct; // Physics sector address
unsigned long ulPage; // Page address
ulDatSiz /= smt_pDevInf->pSizeInf->uwDatSize; // Data are read in sector unit.
while(ulDatSiz > 0) // When an error occurs, it evacuate
{ // - in another block in the block unit.
ulLogBlk = ulLogSct / smt_pDevInf->pSizeInf->uwBlkSize;
ulPhyBlk = smtChgPhyNum(ulLogBlk);
ulPhySct = ulLogSct % smt_pDevInf->pSizeInf->uwBlkSize;
ulPage = smtChgPgNum(ulLogBlk / SMT_LZN_MAX, ulPhyBlk, ulPhySct);
if(smtPageReadWrap(SMT_C_DREAD_1, 0x00, ulPage, pBuffer) != SMT_E_SUCCESS)
{
smtErrInf.iSmtErr = SMT_E_PAGREAD;
return(SMT_E_FAILURE);
}
pBuffer += smt_pDevInf->pSizeInf->uwDatSize;
ulLogSct++;
ulDatSiz--;
}
return(SMT_E_SUCCESS);
}
/************************************************************************
* smtWtSect
* Type : int
* Ret val : Error code
* Argument : unsigned long ulLogSct ... Logic sector address
* unsigned long ulDatSiz ... Write data size
* char *pBuffer ... Write data buffer
* Function : This function writes data for the size in specified
* sector.
************************************************************************/
int smtWtSect(
unsigned char bDrvNum, // Drive number(dummy)
unsigned long ulLogSct, // Logic sector address
unsigned long ulDatSiz, // Write data size
unsigned char *pBuffer, // Wrire data buffer
unsigned char bVerify // Verify option flag
)
{
int iLoop, iLoopLmt; // Loop counter
unsigned char bIndex; // Zone index
unsigned char bOvrWrtFlg; // Over write flag
unsigned char bBlkGetFlg; // New block get flag
unsigned long ulZone; // Zone address
unsigned long ulLogBlk; // Logic block address
unsigned long ulPhySct; // Physics sector address
unsigned long ulEndSct; // End physics sector address
unsigned long ulOldPhyBlk; // Old physics block address
unsigned long ulNewPhyBlk; // New physics block address
unsigned long ulErsPhyBlk; // Erase physics block address
unsigned long ulPage; // Page address
int iRetVal;
unsigned int *pReadPnt; // Data compare pointer
struct SMT_BLKCOPY_PARAMS stBCParams; // Block copy function parameters
////////////////
// INITIALIZE //
////////////////
bOvrWrtFlg = SMT_FALSE; // Each address is calculated.
bBlkGetFlg = SMT_FALSE; // Each address is calculated.
ulErsPhyBlk = 0x00000000; // Erase Block address clear
ulLogBlk = ulLogSct / smt_pDevInf->pSizeInf->uwBlkSize;
ulPhySct = ulLogSct % smt_pDevInf->pSizeInf->uwBlkSize;
ulEndSct = ulPhySct + ulDatSiz / smt_pDevInf->pSizeInf->uwDatSize;
ulZone = ulLogBlk / SMT_LZN_MAX;
if(!ulZone)
{
bIndex = 0;
}
else
{
bIndex = 1;
}
/////////////////
// SECTOR LOOP // // Data are written in sector unit.
///////////////// // When an error occurs, it evacuate
ulOldPhyBlk = smtChgPhyNum(ulLogBlk); // - in another block in the block unit.
while((ulPhySct < ulEndSct)&&(ulPhySct < smt_pDevInf->pSizeInf->uwBlkSize))
{
if(!(smtBlkTbl[bIndex].bBlkChkInf[(ulLogBlk % SMT_LZN_MAX) / 8] & SMT_M_MASK(ulLogBlk % 8)))
{
////////////////////
// NEW DATA WRITE //
//////////////////// // Data are written in the new block.
for(iLoop = 0 ; iLoop <= SMT_BLKTRY_MAX ; iLoop++)
{
if(smtGetFreeBlk(ulZone, &ulNewPhyBlk) != SMT_E_SUCCESS)
{
return(SMT_E_FAILURE);
}
bBlkGetFlg = SMT_TRUE; // Indicate Got new block
ulOldPhyBlk = ulNewPhyBlk;
smtSetProlDat(ulLogBlk, pBuffer);
ulPage = smtChgPgNum(ulZone, ulNewPhyBlk, ulPhySct);
if(pSmt_PageProgram(0x00, ulPage, pBuffer, bVerify) != SMT_E_SUCCESS)
{
if(smtEntryBadBlk(ulZone, ulNewPhyBlk) != SMT_E_SUCCESS)
{
return(SMT_E_FAILURE);
}
continue;
}
if(smtWtBlkAddr(ulZone, ulNewPhyBlk, ulLogBlk) != SMT_E_SUCCESS)
{
if(smtEntryBadBlk(ulZone, ulNewPhyBlk) != SMT_E_SUCCESS)
{
return(SMT_E_FAILURE);
}
continue;
}
smtBlkTbl[bIndex].bBlkCnvInf[ulLogBlk % SMT_LZN_MAX] = SMT_M_BYTE(ulNewPhyBlk, 0);
smtBlkTbl[bIndex].bBlkChkInf[(ulLogBlk % SMT_LZN_MAX) / 8] |= SMT_M_MASK(ulLogBlk % 8);
break;
}
if(iLoop > SMT_BLKTRY_MAX) // Retry over?
{
smtErrInf.iSmtErr = SMT_E_SCTWRTE; // Set Sector Write error
return(SMT_E_FAILURE);
}
}
else
{
/////////////////////
// DATA OVER WRITE // // Appropriate sector is written after it is
///////////////////// // - copied on the new block when sector isn't being erased.
if(bOvrWrtFlg != SMT_TRUE && bBlkGetFlg != SMT_TRUE)
{
ulPage = smtChgPgNum(ulZone, ulOldPhyBlk, ulPhySct);
if(smtPageReadWrap(SMT_C_DREAD_1, 0x00, ulPage, smtRead.bBuff) != SMT_E_SUCCESS)
{
return(SMT_E_FAILURE);
}
pReadPnt = (unsigned int *)smtRead.bBuff; // The existence of the data is monitored.
iLoopLmt = smt_pDevInf->pSizeInf->uwDatSize / sizeof(unsigned int);
for(iLoop = 0 ; iLoop < iLoopLmt ; iLoop++)
{
if(*pReadPnt++ != 0xffffffff)
{
break;
}
}
if(iLoop < iLoopLmt)
{ // The one except for appropriate sector
bOvrWrtFlg = SMT_TRUE; // is copied on another block.
stBCParams.ulLogBlk = ulLogBlk; // Set block Copy parameters
stBCParams.ulFirstBlk = ulOldPhyBlk;
stBCParams.ulExceptSct = ulPhySct;
stBCParams.bValidBlkFlag = SMT_BLKMV_FIRST;
stBCParams.bVerify = bVerify;
iRetVal = smtBlockCopy(&stBCParams);
if(iRetVal != SMT_E_SUCCESS)
{
return(iRetVal);
}
if(!ulErsPhyBlk)
{
ulErsPhyBlk = ulOldPhyBlk;
}
ulOldPhyBlk = stBCParams.ulDestBlk;
}
}
smtSetProlDat(ulLogBlk, pBuffer);
ulPage = smtChgPgNum(ulZone, ulOldPhyBlk, ulPhySct);
if(pSmt_PageProgram(0x00, ulPage, pBuffer, bVerify) != SMT_E_SUCCESS)
{
if(smtWtEvac(ulLogBlk, ulPhySct, pBuffer, bVerify) != SMT_E_SUCCESS)
{
return(SMT_E_FAILURE);
}
ulOldPhyBlk = smtChgPhyNum(ulLogBlk);
}
}
ulPhySct++;
pBuffer += smt_pDevInf->pSizeInf->uwDatSize;
}
/////////////////////
// OLD BLOCK ERASE //
/////////////////////
if(bOvrWrtFlg != SMT_TRUE) // When data are replaced, an old block is erased.
{
return(SMT_E_SUCCESS);
}
if(ulPhySct < smt_pDevInf->pSizeInf->uwBlkSize)
{
if(smtDupliSect(ulZone, ulOldPhyBlk, ulErsPhyBlk, ulPhySct,
smt_pDevInf->pSizeInf->uwBlkSize - 1, bVerify) != SMT_E_SUCCESS)
{
stBCParams.ulLogBlk = ulLogBlk; // Set block Copy parameters
stBCParams.ulFirstBlk = ulOldPhyBlk;
stBCParams.ulLatterBlk = ulErsPhyBlk;
stBCParams.ulExceptSct = ulPhySct;
stBCParams.bValidBlkFlag = SMT_BLKMV_BOTH | SMT_BLKMV_RECOVER;
stBCParams.bVerify = bVerify;
iRetVal = smtBlockCopy(&stBCParams);
if(iRetVal != SMT_E_SUCCESS)
{
return(iRetVal);
}
}
}
ulPage = smtChgPgNum(ulZone, ulErsPhyBlk, 0x00);
if(pSmt_BlockErase(ulPage) == SMT_E_SUCCESS)
{
smtBlkTbl[bIndex].bBlkPhyInf[ulErsPhyBlk / 8] |= SMT_M_MASK(ulErsPhyBlk % 8);
}
return(SMT_E_SUCCESS);
}
/************************************************************************
* smtWtEvac
* Type : int
* Ret val : Error code
* Argument : unsigned long ulLogBlk ... Logic block address
* unsigned long ulPhySct ... Physics sector address
* : unsigned char *pBuffer ... target data
* : unsigned char bVerify ... Verify flag
* Function : This function copies normal data from the error block
* on another block.
************************************************************************/
int smtWtEvac(
unsigned long ulLogBlk,
unsigned long ulPhySct,
unsigned char *pBuffer,
unsigned char bVerify
)
{
unsigned long ulZone; // Zone address
unsigned long ulPhyBlk; // Physics block address
unsigned long ulNewPhyBlk; // New physics block address
unsigned long ulPage; // Page address
int iRetVal; // Return code
int iLoop; // Loop counter
struct SMT_BLKCOPY_PARAMS stBCParams; // Block copy function parameters
ulPhyBlk = smtChgPhyNum(ulLogBlk); // The data which aren't unusual are copied
ulZone = ulLogBlk / SMT_LZN_MAX;
for(iLoop = 0 ; iLoop < SMT_BLKTRY_MAX ; iLoop++) // - on another block.
{ // Information on "Bad Block" is written in the unusual block.
stBCParams.ulLogBlk = ulLogBlk;
stBCParams.ulFirstBlk = ulPhyBlk;
stBCParams.ulExceptSct = ulPhySct;
stBCParams.bValidBlkFlag = SMT_BLKMV_FIRST;
stBCParams.bVerify = bVerify;
iRetVal = smtBlockCopy(&stBCParams);
if(iRetVal != SMT_E_SUCCESS)
{
return(iRetVal);
}
smtSetProlDat(ulLogBlk, pBuffer);
ulPage = smtChgPgNum(ulZone, stBCParams.ulDestBlk, ulPhySct);
if(pSmt_PageProgram(0x00, ulPage, pBuffer, bVerify) != SMT_E_SUCCESS)
{
if(smtEntryBadBlk(ulZone, ulNewPhyBlk) != SMT_E_SUCCESS)
{
return(SMT_E_FAILURE);
}
continue;
}
if(smtEntryBadBlk(ulZone, ulPhyBlk) != SMT_E_SUCCESS)
{
return(SMT_E_FAILURE);
}
break;
}
if(iLoop <= SMT_BLKTRY_MAX)
{
return(SMT_E_SUCCESS);
}
else
{
smtErrInf.iSmtErr = SMT_E_SCTWRTE; // Set Sector Write error
return(SMT_E_FAILURE);
}
}
/************************************************************************
* smtChkRdDat
* Type : int
* Ret val : Error code
* Argument : unsigned char *pBuff ... Check data buffer
* Function : This function check the good reason of the reading data.
************************************************************************/
int smtChkRdDat(
unsigned char *pBuff // Check data buffer
)
{
int iRetVal; // Return value
int iLoop; // Loop counter
int iZero; // Zero counter
int iEccVal; // ECC value
int iResult1; // Data area-1 check result
int iResult2; // Data area-2 check result
union SMT_PROLIX_BUFF *pProlBuff; // Data buffer pointer
iRetVal = SMT_E_SUCCESS; // Return value is initialized.
//////////////////////////////
/// DATA STATUS AREA CHECK ///
//////////////////////////////
iZero = 0; // The validity of the data is checked
iLoop = 0; // - referring to "Data Status Area".
while(iLoop < 8)
{
if(!(smtProlBuff.stDatBuff.bDatSts & SMT_M_MASK(iLoop)))
{
if(++iZero >= 4)
{
smtErrInf.iSmtErr = SMT_E_PHYSFMT;
return(SMT_E_FAILURE);
}
}
iLoop++;
}
//////////////////////
/// ECC AREA CHECK /// // The ECC check of the data is done.
////////////////////// // When there is a bit error, a bit is modified,
#ifdef L05DMT
iEccVal= SMT_M_ECCVALA1;
#else
iEccVal = smtGetEccVal(smtProlBuff.bFlatBuff, SMT_AREA_1); // - and an error is returned.
#endif
iResult1 = smtChkEccVal(pBuff, SMT_AREA_1, iEccVal);
if(iResult1 != SMT_E_SUCCESS)
{
iResult1 = smtErrInf.iSmtErr;
}
#ifdef L05DMT
iEccVal= SMT_M_ECCVALA2;
#else
iEccVal = smtGetEccVal(smtProlBuff.bFlatBuff, SMT_AREA_2); // - and an error is returned.
#endif
iResult2 = smtChkEccVal(pBuff, SMT_AREA_2, iEccVal);
if(iResult2 != SMT_E_SUCCESS)
{
iResult2 = smtErrInf.iSmtErr;
}
if((iResult1 == SMT_E_ECCFAIL)||(iResult2 == SMT_E_ECCFAIL))
{
smtErrInf.iSmtErr = SMT_E_ECCFAIL;
iRetVal = SMT_E_FAILURE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -