📄 fmd.cpp
字号:
// Check the status
status = GetStatus((DWORD) -1);
if(status & STATUS_ERROR) {
RETAILMSG(1, (TEXT("######## Error Programing page %d!\n"), sectorAddr));
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;
}
/*-----------------------------------------------------------------------------
* FMD Interface functions
*
*----------------------------------------------------------------------------*/
// FMD_Init
//
// Initialize the flash chip
//
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
// Issue a reset command here
RETAILMSG(1,(TEXT("FMD_Init\r\n")));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)0); // enable chip
if (IoAddr==0) {
#ifdef READFROMREG
if (lpActiveReg!=NULL) {
DDKWINDOWINFO dwi;
HKEY hConfig;
hConfig=OpenDeviceKey((LPCTSTR)lpActiveReg);
if (hConfig==NULL) {
RETAILMSG(1, (TEXT("FMD: OpenDeviceKey Fails\r\n")));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return 0;
}
dwi.cbSize = sizeof(dwi);
if (DDKReg_GetWindowInfo(hConfig, &dwi)!=ERROR_SUCCESS) {
RETAILMSG(1, (_T("FMD: DDKReg_GetWindowInfo() failed \r\n")));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return 0;
}
if (dwi.dwNumIoWindows>=2) { // second IO address.
IoAddr=dwi.ioWindows[1].dwBase;
}
}
else
#endif
if (!ScanPCI((PPCI_REG_INFO)pRegIn,(PPCI_REG_INFO)pRegOut)) {
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return 0;
}
RETAILMSG(1,(TEXT("Found PCI NAND IO=%x .\r\n"),IoAddr));
if (IoAddr!=NULL) {
DWORD inIoSpace=1;
PHYSICAL_ADDRESS ioPhysicalBase;
ioPhysicalBase.LowPart=IoAddr;
ioPhysicalBase.HighPart=0;
if (HalTranslateBusAddress(PCIBus, 0, ioPhysicalBase, &inIoSpace, &ioPhysicalBase)) {
if (!inIoSpace) { // If it is memory mappes IO.
bIoMemMapped=TRUE;
if ((IoAddr = (DWORD)MmMapIoSpace(ioPhysicalBase, 0x40, FALSE)) == NULL) {
// We may as well not continue
RETAILMSG(1,(TEXT("FMD: Error mapping I/O Ports.\r\n")));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return 0;
}
}
else {
bIoMemMapped=FALSE;
IoAddr=ioPhysicalBase.LowPart;
}
}
else {
RETAILMSG(1,(TEXT("FMD:HalTranslateBusAddress FAILS.\r\n")));
IoAddr=0;
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return 0;
}
}
else
ASSERT(FALSE);
}
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_RESET);
CheckStatus((DWORD) -1); // check ready
dwDeviceId=ReadFlashID();
NEED_EXT_ADDR=TRUE;
switch (dwDeviceId) {
case 0x9875:
g_wPagesPerBlock = 0x20; // 32 pages per block
NEED_EXT_ADDR=FALSE;
break;
case 0x9876: // SanDisk 512.NAND_1.5.pdf
if (ReadFlashID2() == 0) {
g_wPagesPerBlock = 0x20; // 32 pages per block for Binary
} else {
g_wPagesPerBlock = 0x40; // 64 pages per block for MLC
}
break;
case 0x9879: // SanDisk 1024_MLC_1.0.pdf
if (ReadFlashID2() == 0) {
g_wPagesPerBlock = 0x20; // 32 pages per block for Binary
} else {
g_wPagesPerBlock = 0x40; // 64 pages per block for MLC
}
break;
default:
g_wPagesPerBlock = 0;
break;
}
RETAILMSG(1,(TEXT("NAND pages Per Block=%x .\r\n"),g_wPagesPerBlock));
return (PVOID)IoAddr;
}
// FMD_Deinit
//
// De-initialize the flash chip
//
BOOL FMD_Deinit(PVOID hFMD)
{
ASSERT((DWORD)hFMD==IoAddr);
if (bIoMemMapped && hFMD!=NULL && (DWORD)hFMD==IoAddr) {
MmUnmapIoSpace ((PVOID)IoAddr,0);
IoAddr=0;
}
return TRUE;
}
// FMD_GetInfo
//
// Return the Flash information
//
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
pFlashInfo->flashType = NAND;
// OK, instead of reading it from the chip, we use the hardcoded
// numbers here.
pFlashInfo->wDataBytesPerSector = SECTOR_SIZE;
switch (dwDeviceId) {
case 0x9876: // SanDisk 512.NAND_1.5.pdf
pFlashInfo->dwNumBlocks = 0x1000; //4K per page
break;
case 0x9879: // SanDisk 1024_MLC_1.0.pdf
pFlashInfo->dwNumBlocks = 0x1000; //4K per page.
break;
case 0x9875:
pFlashInfo->dwNumBlocks = 0x800; // 2K per page.
break;
default:
pFlashInfo->dwNumBlocks = 0;
pFlashInfo->wSectorsPerBlock = 0;
pFlashInfo->dwBytesPerBlock = 0;
return FALSE;
}
pFlashInfo->wSectorsPerBlock = g_wPagesPerBlock;
pFlashInfo->dwBytesPerBlock = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
return TRUE;
}
// FMD_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
//
BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff,
PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
UCHAR addr1, addr2, addr3, wData;
DWORD i,count;
// BUGBUGBUG: I need to come back to support dwNumSectors > 1
//
// Sanity check
if (!pSectorBuff && !pSectorInfoBuff || dwNumSectors > 1) {
RETAILMSG(1, (TEXT("Invalid parameters!\n")));
return FALSE;
}
// Now reset the chip to a known state
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) {
// We are reading spare only
NAND_ReadSectorInfo(startSectorAddr, pSectorInfoBuff);
pSectorInfoBuff ++;
}
else {
// Reading data from the flash
addr1 = (UCHAR) ((startSectorAddr) & 0xff);
addr2 = (UCHAR) ((startSectorAddr >> 8) & 0xff);
addr3 = (UCHAR) ((startSectorAddr >> 16) & 0xff);
// Issue Read command
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_READ);
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);
// Read only data portion of the sector.
for(i=0; i<SECTOR_SIZE; i++)
{
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
// Copy the bytes directly into pSectorBuff
pSectorBuff[i] = wData;
}
// Read the SectorInfo data (we only need to read first 8 bytes)
// Read the SectorInfo data
if(pSectorInfoBuff)
{
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT); // First reserved field (DWORD)
pSectorInfoBuff->dwReserved1 = (wData);
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
pSectorInfoBuff->dwReserved1 |= (wData << 8);
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
pSectorInfoBuff->dwReserved1 |= (wData << 16);
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
pSectorInfoBuff->dwReserved1 |= (wData << 24);
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT); // OEM byte
pSectorInfoBuff->bOEMReserved = (wData);
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT); // Bad block byte
pSectorInfoBuff->bBadBlock = (wData);
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT); // Second reserved field (WORD)
pSectorInfoBuff->wReserved2 = (wData);
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
pSectorInfoBuff->wReserved2 |= (wData << 8);
pSectorInfoBuff ++;
}else
{
// Make sure we advance the Flash's read pointer (even though we don't need the SectorInfo data).
for(i=0; i<sizeof(SectorInfo); i++)
{
FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
}
}
// Read the ECC info
for(i=0; i<ECC_SIZE; i++)
{
wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
// Read out the ECC bits saved
ECC[i] = wData;
}
// Test the data integrity; if the data is invalid, attempt to fix it using ECC
if(!ECC_IsDataValid(pSectorBuff, SECTOR_SIZE, ECC, ECC_BUFF_LEN))
{
//RETAILMSG(1, (TEXT("FMD: Sector data (sector 0x%x) is invalid. Attempting ECC to fix it.\n"), startSectorAddr));
if(!ECC_CorrectData(pSectorBuff, SECTOR_SIZE, ECC, ECC_BUFF_LEN))
{
// NOTE: this is specifically a debug message because sometimes it's valid to try to read from a sector in a good
// block which might contain bogus data (ECC fails) - example: loader code that needs to save/restore non-block-aligned
// data and we don't want a bunch of warnings in a retail build.
DEBUGMSG(1, (TEXT("FMD: ERROR - Sector data (sector 0x%x) Unable to correct invalid data!\r\n"),startSectorAddr));
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return FALSE;
}else{
DEBUGMSG(1, (TEXT("FMD: Invalid data was corrected using ECC!\r\n")));
}
}
pSectorBuff += SECTOR_SIZE;
}
startSectorAddr ++;
}
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return TRUE;
}
// FMD_EraseBlock
//
// Erase the given block
//
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
UCHAR addr1, addr2, addr3;
UCHAR status;
DWORD dwPageID = blockID*g_wPagesPerBlock; // Get the first page of the blcok
addr1 = (UCHAR) ((dwPageID) & 0xff);
addr2 = (UCHAR) ((dwPageID >> 8) & 0xff);
addr3 = (UCHAR) ((dwPageID >> 16) & 0xff);
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_ERASE);
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); // check ready
FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_ERASE2);
status = GetStatus((DWORD) -1);
if(status & STATUS_ERROR) {
RETAILMSG(1, (TEXT("######## Error Erasing block %d!\n"), blockID));
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;
}
// FMD_WriteSector
//
// Write dwNumPages pages to the startSectorAddr
//
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -