📄 fmd.cpp
字号:
DWORD dwNumSectors)
{
UCHAR addr1, addr2, addr3, status;
DWORD i,count;
// Sanity check
// BUGBUGBUG: I need to come back to support dwNumSectors > 1
//
if((!pSectorBuff && !pSectorInfoBuff) || dwNumSectors == 0) {
RETAILMSG(1, (TEXT("Invalid parameters!\n")));
return FALSE;
}
// We don't really need to reset the chip. Just set the offset to beginning
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)0); // enable chip
CheckStatus((DWORD) -1); // check ready
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_READ);
for (count=0;count<dwNumSectors;count++) {
CheckStatus((DWORD) -1);
if(!pSectorBuff) {
// If we are asked just to write the SectorInfo, we will do that separately
if(!NAND_WriteSectorInfo(startSectorAddr, pSectorInfoBuff)) {
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return FALSE;
}
pSectorInfoBuff ++;
}
else {
addr1 = (UCHAR) ((startSectorAddr) & 0xff);
addr2 = (UCHAR) ((startSectorAddr >> 8) & 0xff);
addr3 = (UCHAR) ((startSectorAddr >> 16) & 0xff);
// Issue write command
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_WRITE);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, 0x0);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr1);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr2);
if(NEED_EXT_ADDR) {
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr3);
}
// Write the data
for(i=0; i<SECTOR_SIZE; i++) {
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR) pSectorBuff[i]);
}
// Write the SectorInfo data to the media
if(pSectorInfoBuff)
{
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR)((pSectorInfoBuff->dwReserved1 & 0x000000FF))); // Reserved field 1
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR)((pSectorInfoBuff->dwReserved1 & 0x0000FF00) >> 8));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR)((pSectorInfoBuff->dwReserved1 & 0x00FF0000) >> 16));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR)((pSectorInfoBuff->dwReserved1 & 0xFF000000) >> 24));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR)(pSectorInfoBuff->bOEMReserved)); // OEM byte
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR)(pSectorInfoBuff->bBadBlock)); // Bad block byte
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR)((pSectorInfoBuff->wReserved2 & 0x000000FF)));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR)((pSectorInfoBuff->wReserved2 & 0x0000FF00) >> 8)); // Reserved field 2
pSectorInfoBuff ++;
}else
{
// 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++)
{
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, (UCHAR)(0xFF));
}
}
// Compute the ECC for this data (only 6 of the available 8 bytes are used)
if(!ECC_ComputeECC(pSectorBuff, SECTOR_SIZE, ECC, ECC_BUFF_LEN))
{
RETAILMSG(1, (TEXT("FMD: Unable to compute ECC(sector 0x%x) !!!\r\n"),startSectorAddr));
}
// Write the sector info and ECC into the spare area
for(i=0; i<ECC_SIZE; i++) {
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, ECC[i]);
}
// Instruct the Flash to commit the data to the media
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_WRITE2);
// Check the status of the write.
status = GetStatus((DWORD) -1);
if(status & STATUS_ERROR) {
RETAILMSG(1, (TEXT("######## Error Programing page %d!\n"), startSectorAddr));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return FALSE;
}
pSectorBuff += SECTOR_SIZE;
}
startSectorAddr ++;
}
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // edisable chip
return TRUE;
}
/*
* FMD_GetBlockStatus
*
* Returns the status of a block. For read-only blocks, checks the sector info data for the first sector of the block.
*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
SECTOR_ADDR Sector = blockID * g_wPagesPerBlock;
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;
}
/*
* FMD_SetBlockStatus
*
* Sets the status of a block.
* Returns TRUE if no errors in setting.
*/
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
if (dwStatus & BLOCK_STATUS_BAD) {
if (!MarkBlockBad (blockID))
return FALSE;
}
if (dwStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
SECTOR_ADDR Sector = blockID * g_wPagesPerBlock;
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;
}
// FMD_PowerUp
//
// Performs any necessary powerup procedures...
//
VOID FMD_PowerUp(VOID)
{
return;
}
// FMD_PowerDown
//
// Performs any necessary powerdown procedures...
//
VOID FMD_PowerDown(VOID)
{
return;
}
// FMD_OEMIoControl
//
// Used for any OEM defined IOCTL operations
//
BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize,
PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
return TRUE;
}
//------------------------------- 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)
{
UCHAR addr1, addr2, addr3, wData;
// Check the parameters
if(pOEMReserved == NULL)
{
return FALSE;
}
addr1 = (UCHAR) ((physicalSectorAddr) & 0xff);
addr2 = (UCHAR) ((physicalSectorAddr >> 8) & 0xff);
addr3 = (UCHAR) ((physicalSectorAddr >> 16) & 0xff);
// For our NAND flash, we don't have to issue two read command. We just need
// to issue one read command and do contiquous read
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)0); // enable chip
CheckStatus((DWORD) -1);
// Seek to the correct byte in the spare area
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, CMD_READ2);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, OEMADDR);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr1);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr2);
if(NEED_EXT_ADDR) {
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr3);
}
CheckStatus((DWORD) -1);
// Read the data from the media
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
*pOEMReserved = wData;
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return TRUE;
}
// FMD_SetOEMReservedByte
//
// Sets the OEM reserved byte (for metadata) for the specified physical sector.
//
BOOL FMD_SetOEMReservedByte(SECTOR_ADDR physicalSectorAddr, BYTE bOEMReserved)
{
UCHAR addr1, addr2, addr3, status;
// We will try to write the OEM data to the 516th byte of the first page
addr1 = (UCHAR) ( (physicalSectorAddr) & 0xff );
addr2 = (UCHAR) ( (physicalSectorAddr >> 8) & 0xff );
addr3 = (UCHAR) ( (physicalSectorAddr >> 16) & 0xff );
// Wait for our term!
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)0); // enable chip
CheckStatus((DWORD) -1);
// First we set the pointer to point to the spare area
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_READ2);
CheckStatus((DWORD) -1); // check ready
// Seek to the correct byte in the spare area
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_WRITE);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, OEMADDR);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr1);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr2);
if(NEED_EXT_ADDR) {
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr3);
}
// Write the OEM data to the media
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_DATA_PORT, bOEMReserved);
// Close out the write.
CheckStatus((DWORD) -1); // check ready
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_WRITE2);
status = CheckStatus((DWORD) -1);
if(status & STATUS_ERROR) {
RETAILMSG(1, (TEXT("######## Failed to set OEM Reserved byte!\n")));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return FALSE;
}
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return TRUE;
}
//---------------------------------------- Helper Functions ----------------------------------------
// Interface function for testing purpose.
//
BOOL FMD_ReadSpare(DWORD dwStartPage, LPBYTE pBuff, DWORD dwNumPages)
{
UCHAR addr1, addr2, addr3, wData;
DWORD i, n;
addr1 = (UCHAR) ( (dwStartPage) & 0xff );
addr2 = (UCHAR) ( (dwStartPage >> 8) & 0xff );
addr3 = (UCHAR) ( (dwStartPage >> 16) & 0xff );
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)0); // enable chip
CheckStatus((DWORD) -1); // check ready
// Issue the READ command
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_READ2);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, 0x0);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr1);
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr2);
if(NEED_EXT_ADDR) {
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr3);
}
CheckStatus((DWORD) -1);
for(n=0; n<dwNumPages; n++) {
// Read the spare area
for(i=0; i<16; i++) {
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
pBuff[i] = wData;
}
}
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -