?? nand.c
字號:
// Merge 16bits UUID data
if (i%2)
{
pDriverGlobals->dwUUID[i/2] |= (((dwRead & 0xff) | ((dwRead & 0xff0000)>>8)) << 16);
}
else
{
pDriverGlobals->dwUUID[i/2] = (dwRead & 0xff) | ((dwRead & 0xff0000)>>8);
}
}
if (i>=g_FlashExtInfo.fi.wDataBytesPerSector/4 && i <=g_FlashExtInfo.fi.wDataBytesPerSector/4+1)
{
if (i%2)
dwSig |= (((dwRead & 0xff) | ((dwRead & 0xff0000)>>8)) << 16);
else
dwSig = (dwRead & 0xff) | ((dwRead & 0xff0000)>>8);
}
}
else
{
if (i<8)
{
pDriverGlobals->dwUUID[i] = dwRead;
#if 0
NandDbgPutString("\r\n &(pDriverGlobals->dwUUID)=");
NandDbgPutHex((int)(pDriverGlobals->dwUUID));
NandDbgPutString("\r\nUUID");
NandDbgPutHex(pDriverGlobals->dwUUID[i]);
NandDbgPutHex(dwRead);
#endif
}
if (i==g_FlashExtInfo.fi.wDataBytesPerSector/4)
dwSig = dwRead;
}
}
if (0xaa55aa55 != dwSig)
{
pDriverGlobals->dwUUID[8]=0x00;
NandDbgPutString("\r\nUUID ERR!");
// NandDbgPutHex(dwSig);
goto ERREXIT;
}
for (i=4;i<8; i++)
{
if(pDriverGlobals->dwUUID[i]+pDriverGlobals->dwUUID[i-4]+1)
{
pDriverGlobals->dwUUID[8]=0x00;
NandDbgPutString("UUID C ERR!\r\n");
goto ERREXIT;
}
}
pDriverGlobals->dwUUID[8]=0xF1;
ERREXIT:
NF_CMD(SMDF_CMD_RESET);
}
#endif
/*-----------------------------------------------------------------------------
* FMD Interface functions
*
*----------------------------------------------------------------------------*/
// FMD_Init
//
// Initialize the flash chip
//
void FMD_Init(void)
{
// Read UUID here
// FMDReadUUID();
// Issue a reset command here
FMDInitHardware();
FMDReadFlashID();
PROTECT_NAND();
g_SI.bBadBlock = BADBLOCKMARK;
g_SI.bOEMReserved = OEM_RESERVED_BLOCK;
g_SI.dwReserved1 = 0;
g_SI.wReserved2 = 0;
}
BOOL FMDReadSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pSectorInfoBuff)
{
NF_STOP_FIFO();
NF_IO_RD_MODE();
NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
NF_LEN(g_FlashExtInfo.wSpareDataLength/2);
NF_FIFO_THRD(g_FlashExtInfo.wSpareDataLength/2);
FMDSetAddress (sectorAddr,
g_FlashExtInfo.fi.wDataBytesPerSector,
0);
//the FIFO threshold interrupt should be cleared
//just before write NandFlash command
NF_CLR_INT(SMDF_FIFO_INT);
NF_CMD(SMDF_CMD_READ2);
NF_START_FIFO();
NF_WAIT_INT(SMDF_FIFO_INT);
FMDReadFifo ((PDWORD)pSectorInfoBuff, g_FlashExtInfo.wSpareDataLength/2);
#if 0
NandDbgPutString ("si.bBadBlock=");
NandDbgPutHex (pSectorInfoBuff->bBadBlock);
NandDbgPutString ("\r\n");
NandDbgPutString ("si.bOEMReserved=");
NandDbgPutHex (pSectorInfoBuff->bOEMReserved);
NandDbgPutString ("\r\n");
NandDbgPutString ("FMDReadSectorInfo: end.\r\n");
#endif
return TRUE;
}
BOOL FMDWriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pSectorInfoBuff)
{
UNPROTECT_NAND();
FMDChangePointer (POINTER_TO_SPARE_AREA);
NF_STOP_FIFO();
NF_IO_WR_MODE();
NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
NF_LEN(g_FlashExtInfo.wSpareDataLength/2);
FMDSetAddress (sectorAddr,
g_FlashExtInfo.fi.wDataBytesPerSector,
0);
NF_CLR_INT (0xFF);
NF_CMD (SMDF_CMD_SEQ_DATA_INPUT);
NF_WAIT_INT (SMDF_ADD_INT);
NF_START_FIFO ();
FMDWriteFifo ((PDWORD) pSectorInfoBuff, g_FlashExtInfo.wSpareDataLength/2);
NF_WAIT_INT (SMDF_DMA_INT);
FMDPageProgram ();
PROTECT_NAND();
if (!FMDVerifyWrite(g_nNandCS)) {
// NandDbgPutHex (SectorAddr);
// NandDbgPutString (" Verify Write Error\r\n");
return FALSE;
}
return TRUE;
}
BOOL FMDWriteEcc(SECTOR_ADDR sectorAddr, PBYTE eccBuf)
{
FMDChangePointer (POINTER_TO_SPARE_AREA);
NF_INIT_FIFO();
NF_IO_WR_MODE();
NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
NF_LEN(g_FlashExtInfo.wSpareDataLength/2);
// v_pSMDFRegs->SmFIFOLevelChk = 0;
FMDSetAddress (sectorAddr,
g_FlashExtInfo.fi.wDataBytesPerSector + g_FlashExtInfo.wSpareDataLength/2,
g_FlashExtInfo.wSpareDataLength/2);
NF_CLR_INT (0xFF);
NF_CMD (SMDF_CMD_SEQ_DATA_INPUT);
NF_WAIT_INT (SMDF_ADD_INT);
NF_START_FIFO ();
FMDWriteFifo ((PDWORD) eccBuf, g_FlashExtInfo.wSpareDataLength/2);
NF_WAIT_INT (SMDF_DMA_INT);
FMDPageProgram ();
return TRUE;
}
/*
@func BOOL | FMD_WriteSector | Writes the specified data to the specified NAND flash sector/page.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
ULONG SectorAddr = (ULONG)startSectorAddr;
BYTE eccBuf[32];
if (!pSectorBuff && !pSectorInfoBuff)
return(FALSE);
UNPROTECT_NAND();
//PreWrite Initialization
while (dwNumSectors--)
{
if (pSectorBuff)
{
// Special case to handle un-aligned buffer pointer.
memcpy(v_pDMAAddr, pSectorBuff, g_FlashExtInfo.fi.wDataBytesPerSector); // Write page/sector data.
CacheRangeFlush ((PVOID)v_pDMAAddr, g_FlashExtInfo.fi.wDataBytesPerSector, CACHE_SYSNC_DISCARD);
NF_CLR_INT(SMDF_DMA_INT);
NF_STOP_FIFO();
NF_RESET_ECC();
//We need to change the write pointer to the correct area by issueing a read cmd in the area
FMDChangePointer (POINTER_TO_DATA_AREA);
NF_DMA_WR_MODE();
NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
FMDSetAddress (SectorAddr, 0, 0);
NF_LEN(g_FlashExtInfo.fi.wDataBytesPerSector);
NF_CLR_INT (0xFF);
NF_CMD (SMDF_CMD_SEQ_DATA_INPUT);
NF_WAIT_INT (SMDF_ADD_INT);
NF_START_FIFO();
NF_WRITE_DMA(g_FlashExtInfo.fi.wDataBytesPerSector);
NF_WAIT_INT(SMDF_DMA_INT);
//Commit what we have just write
FMDPageProgram ();
ECC_ENCODE (pSectorBuff, g_FlashExtInfo.fi.wDataBytesPerSector, (DWORD *)eccBuf);
FMDWriteEcc(SectorAddr, eccBuf);
if (!FMD_ReadSector(SectorAddr, ReadSectBuf, NULL, 1))
{
NandDbgPutString ("FMD: read error!\r\n");
PROTECT_NAND();
return FALSE;
}
if (memcmp (pSectorBuff, ReadSectBuf, g_FlashExtInfo.fi.wDataBytesPerSector))
{
// NandDbgPutString ("FMD: check error!\r\n");
PROTECT_NAND();
return FALSE;
}
pSectorBuff += g_FlashExtInfo.fi.wDataBytesPerSector;
}
if(pSectorInfoBuff)
{
FMDWriteSectorInfo(SectorAddr, pSectorInfoBuff);
pSectorInfoBuff++;
}
SectorAddr++;
}
PROTECT_NAND();
if (!FMDVerifyWrite(g_nNandCS)) {
// NandDbgPutHex (SectorAddr);
// NandDbgPutString (" Verify Write Error\r\n");
return FALSE;
}
return(TRUE);
}
/*
@func BOOL | FMD_EraseBlock | Erases the specified flash block.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_EraseBlock(DWORD blockID)
{
DWORD Sector = BOOT_BLOCK_TO_SECTOR(blockID);
UNPROTECT_NAND();
NF_CMD_MODE();
NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucNumBlockCycles);
NF_SET_ADDR(Sector);
NF_SET_ADDR_HI(0);
NF_CLR_INT (SMDF_ADD_INT);
NF_CMD (SMDF_CMD_BLOCK_ERASE);
NF_WAIT_INT (SMDF_ADD_INT);
PROTECT_NAND();
if (!FMDVerifyWrite(g_nNandCS)) {
// NandDbgPutHex (Sector);
// NandDbgPutString (" Verify Erase Error\r\n");
return FALSE;
}
return TRUE;
}
BOOL WriteImage(DWORD dwStartSearchBlock, DWORD dwTotalBlocks, PBYTE pImageCache/*, DWORD *pdwActualStartBlock, DWORD *pdwNextAvailableBlock*/)
{
int i,j;
DWORD dwBlock, dwSector;
PBYTE pBuf = pImageCache;
dwBlock = dwStartSearchBlock;
pBuf = pImageCache;
i = 0;
while((i < dwTotalBlocks) && (dwBlock < (dwStartSearchBlock + SEARCH_BLOCKS)) )
{
i++;
if(!NandCheckAndReserveBlock(dwBlock))
{
dwBlock ++;
continue;
}
if(!NandIsOEMReservedBlock(dwBlock))
{
dwBlock ++;
continue;
}
dwSector = BOOT_BLOCK_TO_SECTOR(dwBlock);
for(j = 0; j < g_FlashExtInfo.fi.wSectorsPerBlock; j++)
{
if(!FMD_WriteSector(dwSector, pBuf, &g_SI, 1)) {
return FALSE;
}
dwSector ++;
pBuf += g_FlashExtInfo.fi.wDataBytesPerSector;
}
dwBlock ++;
}
if(i != dwTotalBlocks || dwBlock >= (dwStartSearchBlock + SEARCH_BLOCKS))
return FALSE;
return TRUE;
}
BOOL NandIsOEMReservedBlock(DWORD dwBlock)
{
SectorInfo si;
if(FMDReadSectorInfo(BOOT_BLOCK_TO_SECTOR(dwBlock), &si))
{
if( si.bBadBlock == BADBLOCKMARK &&
si.bOEMReserved == OEM_RESERVED_BLOCK &&
si.dwReserved1 == 0 &&
si.wReserved2 == 0)
{
return TRUE;
}
}
// NandDbgPutString ("NandIsOEMReservedBlock: failed.\r\n");
return FALSE;
}
/*
@func BOOL | FMD_ReadSector | Reads the specified sector(s) from NAND flash.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
BYTE eccBuf[32];
ULONG SectorAddr = (ULONG)startSectorAddr;
if (!pSectorBuff && !pSectorInfoBuff)
{
return(FALSE);
}
pSectorBuff = (LPBYTE) ((DWORD)pSectorBuff & ~0xc0000000);
while (dwNumSectors--)
{
CacheRangeFlush ((PVOID)v_pDMAAddr, g_FlashExtInfo.dwPageSize, CACHE_SYSNC_DISCARD);
if (pSectorBuff)
{
NF_RESET_ECC();
//We will totally read out the whole page bytes.
NF_STOP_FIFO();
NF_DMA_RD_MODE();
NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
FMDSetAddress (SectorAddr, 0, 0);
NF_LEN(g_FlashExtInfo.dwPageSize);
NF_CLR_INT(SMDF_DMA_INT);
NF_CMD(SMDF_CMD_READ1);
NF_READ_DMA(g_FlashExtInfo.dwPageSize, dwDmaPhysAddr);
NF_START_FIFO();
NF_WAIT_INT (SMDF_DMA_INT);
while((v_pDMAReg->chnValid.chn4))
{
}
IOBG_FLUSH = 1;
while (IOBG_FLUSH);
memcpy(eccBuf,
(void*)(v_pDMAAddr + g_FlashExtInfo.fi.wDataBytesPerSector + g_FlashExtInfo.wSpareDataLength/2),
g_FlashExtInfo.wSpareDataLength/2);
if (!ECC_DECODE (v_pDMAAddr, g_FlashExtInfo.fi.wDataBytesPerSector, (DWORD *)eccBuf)) {
// NandDbgPutHex (SectorAddr);
// NandDbgPutString (" ecc error\r\n");
return FALSE;
}
memcpy (pSectorBuff, v_pDMAAddr, g_FlashExtInfo.dwPageSize);
pSectorBuff += g_FlashExtInfo.fi.wDataBytesPerSector;
if(pSectorInfoBuff)
{
memcpy(pSectorInfoBuff, pSectorBuff, sizeof (SectorInfo));
pSectorInfoBuff ++;
}
}
else if(pSectorInfoBuff)//Only ask for pSectorInfo
{
FMDReadSectorInfo(SectorAddr, pSectorInfoBuff);
pSectorInfoBuff ++;
}
++SectorAddr;
}
return(TRUE);
}
static BOOL NandCheckAndReserveBlock(DWORD dwBlockIndex)
{
DWORD dwSector;
SectorInfo WriteSectInfo, ReadSectInfo;
int j;
if (!FMD_EraseBlock(dwBlockIndex)) {
goto BadBlockReturn;
}
// Because the bits denoting a bad block can be erased, we take the cautious approach - we'll write an read-verify each sector in this
// block to make sure the block is good. If it's good, we'll re-erase else we'll mark the block bad.
dwSector = BOOT_BLOCK_TO_SECTOR (dwBlockIndex);
for (j = 0 ; j < g_FlashExtInfo.fi.wSectorsPerBlock ; j++)
{
// Make sure erase set all bits high.
memset(WriteSectBuf, 0xFF, g_FlashExtInfo.fi.wDataBytesPerSector);
memset(&WriteSectInfo, 0xFF, g_FlashExtInfo.wSpareDataLength/2);
FMD_ReadSector((dwSector + j), ReadSectBuf, &ReadSectInfo, 1);
if (memcmp(ReadSectBuf, WriteSectBuf, g_FlashExtInfo.fi.wDataBytesPerSector) ||
memcmp(&ReadSectInfo, &WriteSectInfo, g_FlashExtInfo.wSpareDataLength/2))
{
// NandDbgPutString ("Bad block: read after erasing not FF\r\n");
goto BadBlockReturn;
}
// Now, make sure we can store zero - this is meant to check for bad blocks (in the event that the bad block marker was erased).
// Note that we *don't* write sector info data here - this is where bad block data is stored.
memset(WriteSectBuf, 0, g_FlashExtInfo.fi.wDataBytesPerSector);
if (!FMD_WriteSector((dwSector + j), WriteSectBuf, NULL, 1))
{
// NandDbgPutString ("Bad block: write 0 error\r\n");
goto BadBlockReturn;
}
}
// If the block has already been marked bad, skip it and increase the total number of blocks to be erased by a block. Note that bad
// blocks do count against the total number of blocks to be erased since the caller has max constraints on the erase region size.
if (!FMD_EraseBlock(dwBlockIndex)) {
goto BadBlockReturn;
}
for (j = 0 ; j < g_FlashExtInfo.fi.wSectorsPerBlock ; j++)
{
/* WriteSectInfo.dwReserved1 = 0;
WriteSectInfo.bOEMReserved = OEM_RESERVED_BLOCK;
WriteSectInfo.bBadBlock = BADBLOCKMARK;
WriteSectInfo.wReserved2 = 0;
if (!FMD_WriteSector (dwSector + j, NULL, &WriteSectInfo, 1))
*/
if (!FMD_WriteSector (dwSector + j, NULL, &g_SI, 1))
goto BadBlockReturn;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -