📄 fmd.cpp
字号:
// Special case to handle un-aligned buffer pointer.
if( ((DWORD) pSectorBuff) & 0x3)
{
WrPage512Unalign (pSectorBuff,(PULONG)&s2440NAND->NFDATA);
}
else
{
WrPage512(pSectorBuff,(PULONG)&s2440NAND->NFDATA); // Write page/sector data.
}
// Write the SectorInfo data to the media.
//
if(pSectorInfoBuff)
{
// Write the first reserved field (DWORD)
NF_DATA_W4(pSectorInfoBuff->dwReserved1);
// Write OEM reserved flag
NF_WRDATA( (pSectorInfoBuff->bOEMReserved) );
// Write the bad block flag
NF_WRDATA( (pSectorInfoBuff->bBadBlock) );
// Write the second reserved field
NF_WRDATA( (pSectorInfoBuff->wReserved2 >> 8) & 0xff );
NF_WRDATA( (pSectorInfoBuff->wReserved2) & 0xff );
}else
{
int i;
// Make sure we advance the Flash's write pointer (even though we aren't writing the SectorInfo data)
for(i=0; i<sizeof(SectorInfo); i++)
{
NF_WRDATA(0xff);
}
}
#if 0
if(pSectorInfoBuff)
{
WrPageInfo((PBYTE)pSectorInfoBuff,(PULONG)&s2440NAND->NFDATA);
pSectorInfoBuff++;
}
else // Make sure we advance the Flash's write pointer (even though we aren't writing the SectorInfo data)
{
BYTE TempInfo[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
WrPageInfo(TempInfo,(PULONG)&s2440NAND->NFDATA);
}
#endif
pSectorBuff += NAND_PAGE_SIZE;
}
NF_CLEAR_RB();
NF_CMD(CMD_WRITE2); // Send write confirm command.
// Wait for RB
NF_DETECT_RB(); // Wait tR(max 12us)
// Check the status
NF_CMD(CMD_STATUS);
Status = NF_RDDATA();
if (Status & 1)
{
SetKMode (bLastMode);
RETAILMSG(1,(TEXT("ERROR: FMD_WriteSector: failed sector write.\r\n")));
return(FALSE);
}
NF_nFCE_H(); // Deselect the flash chip.
++SectorAddr;
}
// NF_nFCE_H(); // Deselect the flash chip.
SetKMode (bLastMode);
return(TRUE);
}
VOID FMD_PowerUp(VOID)
{
// Enable the clock to NAND controller
s2440CLKPWR->CLKCON |= (1<<4);
// Reinit the NAND controller
s2440NAND->NFCONF = (TACLS << 12) | /* CLE & ALE = HCLK * (TACLS + 1) */
(TWRPH0 << 8) | /* TWRPH0 = HCLK * (TWRPH0 + 1) */
(TWRPH1 << 4); /* TWRPH1 = HCLK * (TWRPH1 + 1) */
s2440NAND->NFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0);
s2440NAND->NFSTAT = 0;
NF_Reset();
}
VOID FMD_PowerDown(VOID)
{
// Disable the clock to NAND controller
s2440CLKPWR->CLKCON &= ~(1<<4);
}
BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
return(TRUE);
}
BOOL FMD_Deinit(PVOID hFMD)
{
return(TRUE);
}
/*
@func BOOL | FMD_GetInfo | Provides information on the NAND flash.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
if (!pFlashInfo)
return(FALSE);
pFlashInfo->flashType = NAND;
pFlashInfo->wDataBytesPerSector = NAND_PAGE_SIZE;
pFlashInfo->dwNumBlocks = NAND_BLOCK_CNT;
pFlashInfo->wSectorsPerBlock = NAND_PAGE_CNT;
pFlashInfo->dwBytesPerBlock = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
return(TRUE);
}
static BOOL IsBlockBad(BLOCK_ID blockID)
{
BYTE Data;
SECTOR_ADDR blockPage = (blockID * NAND_PAGE_CNT);
BOOL bLastMode = SetKMode(TRUE);
NF_nFCE_L(); // Select the flash chip.
// NF_CMD(CMD_RESET); // Send reset command.
// NF_WAITRB(); // Wait for flash to complete command.
NF_CLEAR_RB();
NF_CMD(CMD_READ2); // Send read confirm command.
NF_ADDR(0); // Column = 0.
NF_ADDR(blockPage & 0xff); /* The mark of bad block is in 0 page */
NF_ADDR((blockPage >> 8) & 0xff); /* For block number A[24:17] */
NF_ADDR((blockPage >> 16) & 0xff); /* For block number A[25] */
// Wait for Ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
// TODO
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
if(0xff != Data)
{
SetKMode (bLastMode);
RETAILMSG(1,(TEXT("IsBlockBad: TRUE\r\n")));
return(TRUE);
}
NF_nFCE_H(); // Deassert the flash chip.
SetKMode (bLastMode);
return(FALSE);
}
/*
@func DWORD | FMD_GetBlockStatus | Returns the status of the specified block.
@rdesc Block status (see fmd.h).
@comm
@xref
*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
SECTOR_ADDR Sector = (blockID * NAND_PAGE_CNT);
SectorInfo SI;
DWORD dwResult = 0;
if (IsBlockBad(blockID))
return BLOCK_STATUS_BAD;
if (!FMD_ReadSector(Sector, NULL, &SI, 1))
return BLOCK_STATUS_UNKNOWN;
if (!(SI.bOEMReserved & OEM_BLOCK_READONLY))
dwResult |= BLOCK_STATUS_READONLY;
if (!(SI.bOEMReserved & OEM_BLOCK_RESERVED))
dwResult |= BLOCK_STATUS_RESERVED;
return(dwResult);
}
/*
@func BOOL | MarkBlockBad | Marks the specified block as bad.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
static BOOL MarkBlockBad(BLOCK_ID blockID)
{
BYTE Status;
ULONG blockPage = (blockID * NAND_PAGE_CNT); // Convert block address to page address.
BOOL bLastMode = SetKMode(TRUE);
NF_nFCE_L(); // Select the flash chip.
NF_CLEAR_RB();
// NF_CMD(CMD_RESET); // Send reset command.
// NF_WAITRB(); // Wait for flash to complete command.
NF_CMD(CMD_READ2); // Send read confirm command.
NF_CMD(CMD_WRITE); // Send write command.
NF_ADDR(0); // Column = 0.
NF_ADDR(blockPage & 0xff); /* The mark of bad block is in 0 page */
NF_ADDR((blockPage >> 8) & 0xff); /* For block number A[24:17] */
NF_ADDR((blockPage >> 16) & 0xff); /* For block number A[25] */
// TODO
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0); // Write bad block marker.
NF_CMD(CMD_WRITE2); // Send write confirm command.
// Wait for RB
NF_DETECT_RB(); // Wait tR(max 12us)
// Get the status
NF_CMD(CMD_STATUS);
Status = NF_RDDATA(); // Read command status.
NF_nFCE_H(); // Deassert the flash chip.
SetKMode (bLastMode);
return((Status & 1) ? FALSE : TRUE);
}
/*
@func BOOL | FMD_SetBlockStatus | Marks the block with the specified block status.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
RETAILMSG(1,(TEXT("FMD_SetBlockStatus:block:%d,status:%d \r\n"),blockID,dwStatus));
if (dwStatus & BLOCK_STATUS_BAD)
{
if (!MarkBlockBad(blockID))
return(FALSE);
}
if (dwStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
SECTOR_ADDR Sector = blockID * NAND_PAGE_CNT;
SectorInfo SI;
if (!FMD_ReadSector(Sector, NULL, &SI, 1)) {
return FALSE;
}
if (dwStatus & BLOCK_STATUS_READONLY) {
SI.bOEMReserved &= ~OEM_BLOCK_READONLY;
}
if (dwStatus & BLOCK_STATUS_RESERVED) {
SI.bOEMReserved &= ~OEM_BLOCK_RESERVED;
}
if (!FMD_WriteSector (Sector, NULL, &SI, 1)) {
return FALSE;
}
}
return(TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -