📄 nandfmd.cpp
字号:
}
}
else if (pSectorInfoBuff != NULL)
{
#ifndef NAND_LARGE_PAGE
NF_CMD(CMD_READ2); // Send spare read command.
NF_ADDR_COL(ColumnAddr); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
#else
NF_CMD(CMD_READ); // Send read command
NF_ADDR_COL(ColumnAddr + NAND_SECTOR_SIZE); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
NF_CMD(CMD_READ_2CYCLE); // Send 2nd cycle read command
#endif
// Read page data into NFC buffer
NF_RD_SPARE();
NFCReadSpare(pSectorInfoBuff);
pSectorInfoBuff++;
}
++SectorAddr;
bSeqRead = NF_READ_SEQ(SectorAddr);
}
rc = TRUE;
cleanUp:
NFCSetClock(FALSE);
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: FMD_EraseBlock
//
// This function erases the specified flash block.
//
// Parameters:
// blockID
// [in] The block number to erase.
//
// Returns:
// Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
UINT16 Status;
UINT32 RowAddr = blockID * (NAND_SECTOR_CNT / NAND_SECTORS_PERPAGE);
// RETAILMSG(TRUE, (_T("FMD_EraseBlock(block = %d, addr = 0x%x)\r\n"), blockID, addr));
NFCSetClock(TRUE);
#ifndef NAND_LARGE_PAGE
NF_CMD(CMD_READ); // Set address pointer to main area
#endif
NF_CMD(CMD_ERASE); // Send block erase setup command
NF_ADDR_PAGE(RowAddr); // Send page address
NF_CMD(CMD_ERASE2); // Send block erase command
NF_CMD(CMD_STATUS) // Send status command
NF_RD_STATUS(); // Read status into NFC buffer
Status = INREG16(&g_pNFC->MAIN[0][0]); // Read status from NFC buffer
NFCSetClock(FALSE);
if (Status & NAND_STATUS_MASK_ERROR)
{
ERRORMSG(TRUE, (_T("NAND erase failed (blockID = 0x%x)\r\n"), blockID));
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------------
//
// Function: FMD_WriteSector
//
// This function writes the requested sector data and metadata to the
// flash media.
//
// Parameters:
// startSectorAddr
// [in] The starting physical sector address to write to.
//
// pSectorBuff
// [in] Pointer to the buffer that contains the sector data to write.
// Set to NULL if no data is to be written.
//
// pSectorInfoBuff
// [in] Buffer for an array of sector information structures. There
// must be one sector information entry for each sector that is to be
// written. Set to NULL if this data is not written.
//
// dwNumSectors
// [in] Number of sectors to write.
//
// Returns:
// Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff,
PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
UINT16 Status;
SECTOR_ADDR SectorAddr = startSectorAddr;
UINT32 ColumnAddr, RowAddr;
BOOL rc = FALSE;
NFCSetClock(TRUE);
if (!pSectorBuff && !pSectorInfoBuff)
{
ERRORMSG(TRUE, (_T("Sector/Info buffers are NULL\r\n")));
goto cleanUp;
}
while (dwNumSectors--)
{
RowAddr = (UINT32)SectorAddr/NAND_SECTORS_PERPAGE;
ColumnAddr = ((UINT32)SectorAddr%NAND_SECTORS_PERPAGE)
* (NAND_SECTOR_SIZE + NAND_SPARE_SIZE);
if (pSectorBuff)
{
if (pSectorInfoBuff)
{
// Update spare area with sector information provided
NFCWriteSpare(pSectorInfoBuff);
pSectorInfoBuff++;
}
else
{
// Clear out the spare area
NFCClearSpare();
}
// Move page data from sector buffer to NFC buffer
NFCWriteMain(pSectorBuff);
#ifndef NAND_LARGE_PAGE
NF_CMD(CMD_READ); // Set address pointer to main area
#endif
NF_CMD(CMD_WRITE); // Send sequential data input command
NF_ADDR_COL(ColumnAddr); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
NF_WR_PAGE(); // Write out the page data
pSectorBuff += NAND_SECTOR_SIZE; // Next sector
}
else
{
// Update spare area with sector information provided
NFCWriteSpare(pSectorInfoBuff);
#ifndef NAND_LARGE_PAGE
NF_CMD(CMD_READ2); // Set address pointer to spare area
NF_CMD(CMD_WRITE); // Send sequential data input command
NF_ADDR_COL(ColumnAddr); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
#else
NF_CMD(CMD_WRITE); // Send sequential data input command
NF_ADDR_COL(ColumnAddr + NAND_SECTOR_SIZE); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
#endif
NF_WR_SPARE(); // Write out the spare data
pSectorInfoBuff++;
}
NF_CMD(CMD_WRITE2) // Send program command
NF_CMD(CMD_STATUS) // Send status command
NF_RD_STATUS(); // Read status into NFC buffer
Status = INREG16(&g_pNFC->MAIN[0][0]); // Read status from NFC buffer
if (Status & NAND_STATUS_MASK_ERROR)
{
ERRORMSG(TRUE, (_T("NAND program failed (Sectoraddr = 0x%x)\r\n"), SectorAddr));
goto cleanUp;
}
++SectorAddr;
}
rc = TRUE;
cleanUp:
NFCSetClock(FALSE);
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: FMD_PowerUp
//
// This function restores power to the flash memory device, if applicable.
//
// Parameters:
// None
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
VOID FMD_PowerUp(VOID)
{
}
//-----------------------------------------------------------------------------
//
// Function: FMD_PowerDown
//
// This function suspends power to the flash memory device, if applicable.
//
// Parameters:
// None
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
VOID FMD_PowerDown(VOID)
{
}
//-----------------------------------------------------------------------------
//
// Function: FMD_OEMIoControl
//
// This function implements user-defined commands for the flash memory device.
//
// Parameters:
// dwIoControlCode
// [in] The control code specifying the command to execute.
//
// pInBuf
// [in] Long pointer to a buffer that contains the data required to
// perform the operation. Set to NULL if the dwIoControlCode parameter
// specifies an operation that does not require input data.
//
// nInBufSize
// [in] Size, in bytes, of the buffer pointed to by pInBuf.
//
// pOutBuf
// [out] Long pointer to a buffer that receives the output data for
// the operation. Set to NULL if the dwIoControlCode parameter
// specifies an operation that does not produce output data.
//
// nOutBufSize
// [in] Size, in bytes, of the buffer pointed to by pOutBuf.
//
// pBytesReturned
// [out] Long pointer to a variable that receives the size, in bytes,
// of the data stored into the buffer pointed to by pOutBuf. Even
// when an operation produces no output data and pOutBuf is set to
// NULL, the DeviceIoControl function uses the variable pointed to
// by pBytesReturned. After such an operation, the value of the
// variable has no meaning.
//
// Returns:
// Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize,
PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
BOOL rc = FALSE;
return(rc);
}
//-----------------------------------------------------------------------------
//
// Function: FMD_GetInfo
//
// This function determines the size characteristics for the flash memory
// device.
//
// Parameters:
// pFlashInfo
// [out] A pointer to a structure that contains the size
// characteristics for the flash memory device.
//
// Returns:
// Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
if (!pFlashInfo)
return(FALSE);
pFlashInfo->flashType = NAND;
pFlashInfo->wDataBytesPerSector = NAND_SECTOR_SIZE;
pFlashInfo->dwNumBlocks = NAND_BLOCK_CNT;
pFlashInfo->wSectorsPerBlock = NAND_SECTOR_CNT;
pFlashInfo->dwBytesPerBlock = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
return(TRUE);
}
//-----------------------------------------------------------------------------
//
// Function: FMD_GetBlockStatus
//
// This function returns the status of a block.
//
// Parameters:
// blockID
// [in] The block number used to check status.
//
// Returns:
// Flags to describe the status of the block.
//
//-----------------------------------------------------------------------------
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
SECTOR_ADDR Sector = (blockID * NAND_SECTOR_CNT);
SectorInfo SI[2];
DWORD dwResult = 0;
// Samsung makes sure that either the 1st or 2nd page of every initial
// invalid block has non-FFh data at the column address of 517. Read
// first two page spare areas and to determine block status.
if (!FMD_ReadSector(Sector, NULL, SI, 2))
{
ERRORMSG(TRUE, (_T("NAND block %d status is unknown.\r\n"), blockID));
dwResult = BLOCK_STATUS_UNKNOWN;
goto cleanUp;
}
if ((SI[0].bBadBlock != 0xFF) || (SI[1].bBadBlock != 0xFF))
{
DEBUGMSG(TRUE, (_T("NAND block %d is bad.\r\n"), blockID));
dwResult = BLOCK_STATUS_BAD;
goto cleanUp;
}
if (!(SI[0].bOEMReserved & OEM_BLOCK_READONLY))
dwResult |= BLOCK_STATUS_READONLY;
if (!(SI[0].bOEMReserved & OEM_BLOCK_RESERVED))
dwResult |= BLOCK_STATUS_RESERVED;
cleanUp:
return(dwResult);
}
//-----------------------------------------------------------------------------
//
// Function: FMD_SetBlockStatus
//
// This function sets the status of a block.
//
// Parameters:
// blockID
// [in] The block number used to set status.
//
// dwStatus
// [in] The status value to set.
//
// Returns:
// Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
SECTOR_ADDR Sector = (blockID * NAND_SECTOR_CNT);
SectorInfo SI;
if (dwStatus & (BLOCK_STATUS_BAD | BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
if (!FMD_ReadSector(Sector, NULL, &SI, 1)) {
return FALSE;
}
if (dwStatus & BLOCK_STATUS_BAD)
{
SI.bBadBlock = 0x00;
}
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 + -