📄 fmd.cpp
字号:
}
pBSPArgs->nfsblk = pLockInfo->StartBlock + pLockInfo->NumBlocks;
break;
case IOCTL_FMD_UNLOCK_BLOCKS:
RETAILMSG(1, (TEXT("IOCTL_FMD_UNLOCK_BLOCKS!!!!(0x%x,0x%x) \r\n"), pLockInfo->StartBlock, pLockInfo->NumBlocks));
RETAILMSG(1, (TEXT("S3C2440 Does not support IOCTL_FMD_UNLOCK_BLOCKS !!!! \r\n")));
return(FALSE);
/*
pLockInfo = (BlockLockInfo *)pInBuf;
RETAILMSG(1, (TEXT("IOCTL_FMD_UNLOCK_BLOCKS!!!!(0x%x,0x%x) \r\n"), pLockInfo->StartBlock, pLockInfo->NumBlocks));
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 ) // Large Block
{
if ( READ_REGISTER_BYTE(pNFSBLK) >> 5 > (ULONG)(pLockInfo->StartBlock - 1) )
WRITE_REGISTER_USHORT(pNFSBLK, (pLockInfo->StartBlock - 1)<<5 );
}
else // Small Block
{
if ( READ_REGISTER_BYTE(pNFSBLK) >> 5 > (ULONG)(pLockInfo->StartBlock - 1)*8 )
WRITE_REGISTER_USHORT(pNFSBLK, ((ULONG)(pLockInfo->StartBlock - 1)*8)<<5 );
}
pBSPArgs->nfsblk = pLockInfo->StartBlock - 1;
*/
break;
/*
case IOCTL_FMD_READ_RESERVED:
RETAILMSG(1,(TEXT("IOCTL_FMD_READ_RESERVED\r\n")));
return(FALSE);
break;
case IOCTL_FMD_WRITE_RESERVED:
RETAILMSG(1,(TEXT("IOCTL_FMD_WRITE_RESERVED\r\n")));
return(FALSE);
break;
case IOCTL_FMD_GET_RESERVED_TABLE:
RETAILMSG(1,(TEXT("IOCTL_FMD_GET_RESERVED_TABLE\r\n")));
return(FALSE);
break;
case IOCTL_FMD_SET_REGION_TABLE:
RETAILMSG(1,(TEXT("IOCTL_FMD_SET_REGION_TABLE\r\n")));
return(FALSE);
break;
case IOCTL_FMD_SET_SECTORSIZE:
RETAILMSG(1,(TEXT("IOCTL_FMD_SET_SECTORSIZE\r\n")));
return(FALSE);
break;
case IOCTL_FMD_RAW_WRITE_BLOCKS:
RETAILMSG(1,(TEXT("IOCTL_FMD_RAW_WRITE_BLOCKS\r\n")));
return(FALSE);
break;
case IOCTL_FMD_GET_RAW_BLOCK_SIZE:
RETAILMSG(1,(TEXT("IOCTL_FMD_GET_RAW_BLOCK_SIZE\r\n")));
return(FALSE);
break;
case IOCTL_FMD_GET_INFO:
RETAILMSG(1,(TEXT("IOCTL_FMD_GET_INFO\r\n")));
return(FALSE);
break;
*/
default:
RETAILMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
return(FALSE);
}
return TRUE;
}
#endif // NOSYSCALL
//------------------------------- Private Interface (NOT used by the FAL) --------------------------
// FMD_GetOEMReservedByte
//
// Retrieves the OEM reserved byte (for metadata) for the specified physical sector.
//
//
BOOL FMD_GetOEMReservedByte(SECTOR_ADDR physicalSectorAddr, PBYTE pOEMReserved)
{
if ( physicalSectorAddr < (unsigned)wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK ) // First NAND Flash
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
FMD_LB_GetOEMReservedByte( physicalSectorAddr, pOEMReserved, USE_NFCE);
else
FMD_SB_GetOEMReservedByte( physicalSectorAddr, pOEMReserved, USE_NFCE);
}
else
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
FMD_LB_GetOEMReservedByte( physicalSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK, pOEMReserved, USE_GPIO);
else
FMD_SB_GetOEMReservedByte( physicalSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK, pOEMReserved, USE_GPIO);
}
return TRUE;
}
// FMD_SetOEMReservedByte
//
// Sets the OEM reserved byte (for metadata) for the specified physical sector.
//
BOOL FMD_SetOEMReservedByte(SECTOR_ADDR physicalSectorAddr, BYTE bOEMReserved)
{
BOOL bRet = TRUE;
if ( physicalSectorAddr < (unsigned)wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK ) // First NAND Flash
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
bRet = FMD_LB_SetOEMReservedByte(physicalSectorAddr, bOEMReserved, USE_NFCE);
else
bRet = FMD_SB_SetOEMReservedByte(physicalSectorAddr, bOEMReserved, USE_NFCE);
}
else
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
bRet = FMD_LB_SetOEMReservedByte(physicalSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK, bOEMReserved, USE_GPIO);
else
bRet = FMD_SB_SetOEMReservedByte(physicalSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK, bOEMReserved, USE_GPIO);
}
return bRet;
}
//---------------------------------------- Helper Functions ----------------------------------------
// Interface function for testing purpose.
//
BOOL FMD_ReadSpare(DWORD dwStartPage, LPBYTE pBuff, DWORD dwNumPages)
{
RETAILMSG(1, (TEXT("FMD_ReadSpare Not Support !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n")));
return FALSE;
}
// Reset the chip
//
void SB_NF_Reset(int mode)
{
int i;
SetChipSelect(mode,LOW);
NF_CLEAR_RB();
NF_CMD(CMD_RESET);
for(i=0;i<10;i++); //tWB = 100ns. //??????
SetChipSelect(mode,HIGH);
}
/*
* NAND_SB_ReadSectorInfo
*
* Read SectorInfo out of the spare area. The current implementation only handles
* one sector at a time.
*/
void NAND_SB_ReadSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
BOOL bLastMode = SetKMode(TRUE);
// Chip enable
SetChipSelect(mode,LOW);
NF_CLEAR_RB();
// Write the command
NF_CMD(CMD_READ2);
// Write the address
NF_ADDR(0x00);
NF_ADDR(sectorAddr & 0xff);
NF_ADDR((sectorAddr >> 8) & 0xff);
if (SB_NEED_EXT_ADDR) {
NF_ADDR((sectorAddr >> 16) & 0xff);
}
// Wait for the Ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
// Read the SectorInfo data (we only need to read first 8 bytes)
pInfo->dwReserved1 = NF_DATA_R4();
// OEM byte
pInfo->bOEMReserved = (BYTE) NF_DATA_R();
// Read the bad block mark
pInfo->bBadBlock = (BYTE) NF_DATA_R();
// Second reserved field (WORD)
pInfo->wReserved2 = ((BYTE) NF_DATA_R() << 8);
pInfo->wReserved2 |= ((BYTE) NF_DATA_R());
SetChipSelect(mode,HIGH);
SetKMode(bLastMode);
}
/*
* NAND_SB_WriteSectorInfo
*
* Write SectorInfo out to the spare area. The current implementation only handles
* one sector at a time.
*/
BOOL NAND_SB_WriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
BOOL bRet = TRUE;
BOOL bLastMode = SetKMode(TRUE);
// Chip enable
SetChipSelect(mode,LOW);
NF_CLEAR_RB();
// Write the command
// First, let's point to the spare area
NF_CMD(CMD_READ2);
NF_CMD(CMD_WRITE);
// Write the address
NF_ADDR(0x00);
NF_ADDR(sectorAddr & 0xff);
NF_ADDR((sectorAddr >> 8) & 0xff);
if (SB_NEED_EXT_ADDR) {
NF_ADDR((sectorAddr >> 16) & 0xff);
}
// Now let's write the SectorInfo data
//
// Write the first reserved field (DWORD)
NF_DATA_W4( pInfo->dwReserved1 );
// Write OEM reserved flag
NF_DATA_W( (pInfo->bOEMReserved) );
// Write the bad block flag
NF_DATA_W( (pInfo->bBadBlock) );
// Write the second reserved field
NF_DATA_W( (pInfo->wReserved2 >> 8) & 0xff );
NF_DATA_W( (pInfo->wReserved2) );
// Issue the write complete command
NF_CMD(CMD_WRITE2);
// Check ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
if ( READ_REGISTER_USHORT(pNFSTAT) & STATUS_ILLACC )
{
RETAILMSG(1, (TEXT("NAND_WriteSectorInfo() ######## Error Programming page (Illigar Access) %d!\n"), sectorAddr));
WRITE_REGISTER_USHORT(pNFSTAT, STATUS_ILLACC); // Write 1 to clear.
bRet = FALSE;
}
else
{
// Check the status of program
NF_CMD(CMD_STATUS);
if(NF_DATA_R() & STATUS_ERROR) {
RETAILMSG(1, (TEXT("NAND_WriteSectorInfo() ######## Error Programming page %d!\n"), sectorAddr));
bRet = FALSE;
}
}
SetChipSelect(mode,HIGH);
SetKMode(bLastMode);
return bRet;
}
// FMD_SB_ReadSector
//
// Read the content of the sector.
//
// startSectorAddr: Starting page address
// pSectorBuff : Buffer for the data portion
// pSectorInfoBuff: Buffer for Sector Info structure
// dwNumSectors : Number of sectors
//
typedef union _ECCRegVal
{
DWORD dwECCVal;
BYTE bECCBuf[4];
} ECCRegVal;
BOOL FMD_SB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff,
PSectorInfo pSectorInfoBuff, DWORD dwNumSectors, int mode)
{
DWORD i;
BYTE eccBuf[8];
ECCRegVal eccRegVal;
// RETAILMSG(1, (TEXT("FMD::FMD_SB_ReadSector 0x%x \r\n"), startSectorAddr));
// RETAILMSG(1, (TEXT("startSectorAddr = 0x%x \r\n"), startSectorAddr));
// Sanity check
if (!pSectorBuff && !pSectorInfoBuff || dwNumSectors > 1) {
RETAILMSG(1, (TEXT("Invalid parameters!\n")));
return FALSE;
}
if(!pSectorBuff) {
// We are reading spare only
NAND_SB_ReadSectorInfo(startSectorAddr, pSectorInfoBuff, mode);
// There is no ECC for the sector info, so the read always succeed.
return TRUE;
}
BOOL bLastMode = SetKMode(TRUE);
// Initialize ECC register
NF_RSTECC();
NF_MECC_UnLock();
// Enable the chip
SetChipSelect(mode,LOW);
NF_CLEAR_RB();
// Issue command
NF_CMD(CMD_READ);
// Set up address
NF_ADDR(0x00);
NF_ADDR((startSectorAddr) & 0xff);
NF_ADDR((startSectorAddr >> 8) & 0xff);
if (SB_NEED_EXT_ADDR) {
NF_ADDR((startSectorAddr >> 16) & 0xff);
}
// RETAILMSG(1, (TEXT("1 \r\n")));
NF_DETECT_RB(); // Wait tR(max 12us)
// RETAILMSG(1, (TEXT("2 \r\n")));
// BUGBUG, because Media Player for Pocket PC sometimes pass us un-aligned buffer
// we have to waste cycle here to work around this problem
if( ((DWORD) pSectorBuff) & 0x3) {
for(i=0; i<SECTOR_SIZE; i++) {
pSectorBuff[i] = (BYTE) NF_DATA_R();
}
}
else {
// The right way.
ReadPage512(pSectorBuff, pNFDATA);
}
// Do the ECC thing here
// We read the ECC value from the ECC register pFNECC
NF_MECC_Lock();
eccRegVal.dwECCVal = NF_ECC();
// Read the SectorInfo data
if(pSectorInfoBuff) {
// Read the SectorInfo data (we only need to read first 8 bytes)
pSectorInfoBuff->dwReserved1 = NF_DATA_R4();
// OEM byte
pSectorInfoBuff->bOEMReserved = (BYTE) NF_DATA_R();
// Read the bad block mark
pSectorInfoBuff->bBadBlock = (BYTE) NF_DATA_R();
// Second reserved field (WORD)
pSectorInfoBuff->wReserved2 = ((BYTE) NF_DATA_R() << 8);
pSectorInfoBuff->wReserved2 |= ((BYTE) NF_DATA_R());
}
else {
// Advance the read pointer
for(i=0; i<sizeof(SectorInfo); i++) {
eccBuf[i] = (BYTE) NF_DATA_R();
}
}
// Verify the ECC values
//
// Read the ECC buffer
for(i=0; i<3; i++) {
eccBuf[i] = (BYTE) NF_DATA_R();
}
SetChipSelect(mode,HIGH);
// Copmare with the ECC generated from the HW
if(eccBuf[0] != eccRegVal.bECCBuf[0] ||
eccBuf[1] != eccRegVal.bECCBuf[1] ||
eccBuf[2] != eccRegVal.bECCBuf[2] ) {
RETAILMSG(1, (TEXT("FMD(FMD_SB_ReadSector): ECC ERROR - Page #: %d\r\n"), startSectorAddr));
// Now try to correct them
if(!ECC_CorrectData(pSectorBuff, eccBuf, eccRegVal.bECCBuf)) {
RETAILMSG(1, (TEXT("FMD: Unable to correct the ECC error - Page #: %d\r\n"),
startSectorAddr));
SetKMode(bLastMode);
return FALSE;
}
}
// RETAILMSG(1, (TEXT("FMD::FMD_SB_ReadSector -- \r\n")));
SetKMode(bLastMode);
return TRUE;
}
//
// SB_IsBlockBad
//
// Check to see if the given block is bad. A block is bad if the 517th byte on
// the first or second page is not 0xff.
//
// blockID: The block address. We need to convert this to page address
//
//
BOOL SB_IsBlockBad(BLOCK_ID blockID, int mode)
{
DWORD dwPageID = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK;
BOOL bRet = FALSE;
BYTE wFlag;
BOOL bLastMode = SetKMode(TRUE);
// Enable the chip
SetChipSelect(mode,LOW);
NF_CLEAR_RB();
// Issue the command
NF_CMD(CMD_READ2);
// Set up address
NF_ADDR(VALIDADDR);
NF_ADDR((dwPageID) & 0xff);
NF_ADDR((dwPageID >> 8) & 0xff);
if (SB_NEED_EXT_ADDR) {
NF_ADDR((dwPageID >> 16) & 0xff);
}
// Wait for Ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
// Now get the byte we want
wFlag = (BYTE) NF_DATA_R();
if(wFlag != 0xff) {
bRet = TRUE;
}
// Disable the chip
SetChipSelect(mode,HIGH);
SetKMode(bLastMode);
return bRet;
}
//
// FMD_SB_GetBlockStatus
//
// Returns the status of a block. The status information is stored in the spare area of the first sector for
// the respective block.
//
// A block is BAD if the bBadBlock byte on the first page is not equal to 0xff.
//
DWORD FMD_SB_GetBlockStatus(BLOCK_ID blockID, int mode)
{
SECTOR_ADDR sectorAddr = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK;
SectorInfo SI;
DWORD dwResult = 0;
if(!FMD_SB_ReadSector(sectorAddr, NULL, &SI, 1, mode))
{
return BLOCK_STATUS_UNKNOWN;
}
if(!(SI.bOEMReserved & OEM_BLOCK_READONLY))
{
dwResult |= BLOCK_STATUS_READONLY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -