📄 fmd_sb.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// Copyright (c) Samsung Electronics. Co. LTD. All rights reserved.
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
fmd_sb.cpp
Abstract:
This module implements main functions of FMD PDD for Small Block(512Kbyte Block size)
Functions:
FMD_Init,
Notes:
--*/
#include "precomp.h"
extern volatile S3C6410_NAND_REG *g_pNFConReg;
BOOL FMD_SB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
ULONG SectorAddr = (ULONG)startSectorAddr;
ULONG MECC;
UINT32 nRet = TRUE;
UINT32 nRetEcc = 0;
if (!pSectorBuff && !pSectorInfoBuff)
{
RETAILMSG(FMD_ZONE_ERROR,(TEXT("[FMD:ERR] FMD_SB_ReadSector(0x%08x, 0x%08x) : Invalid Parameter\n\r"), pSectorBuff, pSectorInfoBuff));
return(FALSE);
}
while (dwNumSectors--)
{
NF_RSTECC();
NF_MECC_UnLock();
NF_nFCE_L();
if (!pSectorBuff)
{
NF_CLEAR_RB();
NF_CMD(CMD_READ2); // Send read confirm command.
NF_ADDR(0); // Ignored.
NF_ADDR(SectorAddr & 0xff); // Page address.
NF_ADDR((SectorAddr >> 8) & 0xff);
if(g_bNeedExtAddr)
{
NF_ADDR((SectorAddr >> 16) & 0xff);
}
NF_DETECT_RB();
RdPageInfo((PBYTE)pSectorInfoBuff); // Read page/sector information.
pSectorInfoBuff++;
}
else
{
NF_CLEAR_RB();
NF_CMD(CMD_READ); // Send read command.
NF_ADDR(0); // Column = 0.
NF_ADDR(SectorAddr & 0xff); // Page address.
NF_ADDR((SectorAddr >> 8) & 0xff);
if(g_bNeedExtAddr)
{
NF_ADDR((SectorAddr >> 16) & 0xff);
}
NF_DETECT_RB(); // Wait for command to complete.
if( ((DWORD) pSectorBuff) & 0x3)
{
RdPage512Unalign (pSectorBuff);
}
else
{
RdPage512(pSectorBuff); // Read page/sector data.
}
NF_MECC_Lock();
if (pSectorInfoBuff)
{
RdPageInfo((PBYTE)pSectorInfoBuff); // Read page/sector information.
pSectorInfoBuff ++;
}
else
{
BYTE TempInfo[8];
RdPageInfo(TempInfo); // Read page/sector information.
}
MECC = NF_RDDATA_BYTE() << 0;
MECC |= NF_RDDATA_BYTE() << 8;
MECC |= NF_RDDATA_BYTE() << 16;
MECC |= NF_RDDATA_BYTE() << 24;
NF_WRMECCD0( ((MECC&0xff00)<<8)|(MECC&0xff) );
NF_WRMECCD1( ((MECC&0xff000000)>>8)|((MECC&0xff0000)>>16) );
nRetEcc = NF_ECC_ERR0;
if (!ECC_CorrectData(SectorAddr, pSectorBuff, nRetEcc, ECC_CORRECT_MAIN)) // Use specific byte
{
RETAILMSG(FMD_ZONE_ERROR, (TEXT("#### SECC1 ECC correction failed\n")));
NF_nFCE_H();
return FALSE;
}
pSectorBuff += NAND_PAGE_SIZE;
}
NF_nFCE_H();
++SectorAddr;
}
return(nRet);
}
BOOL FMD_SB_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
BYTE Status;
ULONG SectorAddr = (ULONG)startSectorAddr;
ULONG MECC;
if (!pSectorBuff && !pSectorInfoBuff)
return(FALSE);
if (dwNumSectors <= 0)
{
RETAILMSG(FMD_ZONE_ERROR,(TEXT("[FMD:ERR] FMD_SB_ReadSector(0x%08x, 0x%08x) : Invalid Parameter dwNumSectors:%d\n\r"), pSectorBuff, pSectorInfoBuff, dwNumSectors));
return(FALSE);
}
RETAILMSG(FMD_ZONE_FUNCTION,(TEXT("#### FMD_DRIVER:::FMD_sbwrite \r\n")));
NF_nFCE_L(); // Select the flash chip.
while (dwNumSectors--)
{
if (!pSectorBuff) // Only spare area
{
// If we are asked just to write the SectorInfo, we will do that separately
NF_CMD(CMD_READ2); // Send read command.
NF_CMD(CMD_WRITE); // Send write command.
NF_ADDR(0); // Column = 0.
NF_ADDR(SectorAddr & 0xff); // Page address.
NF_ADDR((SectorAddr >> 8) & 0xff);
if(g_bNeedExtAddr)
{
NF_ADDR((SectorAddr >> 16) & 0xff);
}
// Write the SectorInfo data to the media.
// Spare area[7:0]
WrPageInfo((PBYTE)pSectorInfoBuff);
NF_CLEAR_RB();
NF_CMD(CMD_WRITE2); // Send write confirm command.
NF_DETECT_RB();
NF_CMD(CMD_STATUS);
Status = NF_RDDATA_BYTE(); // Read command status.
if (Status & STATUS_ERROR)
{
NF_nFCE_H(); // Deselect the flash chip.
return(FALSE);
}
pSectorInfoBuff++;
}
else // Main area+Spare area.
{
NF_CMD(CMD_READ); // Send read command.
NF_CMD(CMD_WRITE); // Send write command.
NF_ADDR(0); // Column = 0.
NF_ADDR(SectorAddr & 0xff); // Page address.
NF_ADDR((SectorAddr >> 8) & 0xff);
if(g_bNeedExtAddr)
{
NF_ADDR((SectorAddr >> 16) & 0xff);
}
// Special case to handle un-aligned buffer pointer.
NF_RSTECC();
NF_MECC_UnLock();
if( ((DWORD) pSectorBuff) & 0x3)
{
WrPage512Unalign (pSectorBuff);
}
else
{
WrPage512(pSectorBuff); // Write page/sector data.
}
NF_MECC_Lock();
// Write the SectorInfo data to the media.
// Spare area[7:0]
if(pSectorInfoBuff)
{
WrPageInfo((PBYTE)pSectorInfoBuff);
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);
}
// Write the SectorInfo data to the media.
// Spare area[11:8]
// Get the ECC data from status register.
MECC = NF_RDMECC0();
// Now, Write the ECC data to Spare area[11:8]
NF_WRDATA_BYTE((UCHAR)((MECC ) & 0xff)); // Spare area offset 8
NF_WRDATA_BYTE((UCHAR)((MECC >> 8) & 0xff)); // Spare area offset 9
NF_WRDATA_BYTE((UCHAR)((MECC >> 16) & 0xff)); // Spare area offset 10
NF_WRDATA_BYTE((UCHAR)((MECC >> 24) & 0xff)); // Spare area offset 11
NF_CLEAR_RB();
NF_CMD(CMD_WRITE2); // Send write confirm command.
NF_DETECT_RB();
do
{
NF_CMD(CMD_STATUS);
Status = NF_RDDATA_BYTE(); // Read command status.
}while(!(Status & STATUS_READY));
if (Status & STATUS_ERROR)
{
NF_nFCE_H(); // Deselect the flash chip.
return(FALSE);
}
pSectorBuff += NAND_PAGE_SIZE;
}
++SectorAddr;
}
NF_nFCE_H(); // Deselect the flash chip.
return(TRUE);
}
BOOL FMD_SB_EraseBlock(BLOCK_ID blockID)
{
BOOL bRet = TRUE;
DWORD dwPageID = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK;
// Enable the chip
NF_nFCE_L(); // Select the flash chip.
// Issue command
NF_CMD(CMD_ERASE);
// Set up address
NF_ADDR((dwPageID) & 0xff);
NF_ADDR((dwPageID >> 8) & 0xff);
if(g_bNeedExtAddr)
{
NF_ADDR((dwPageID >> 16) & 0xff);
}
NF_CLEAR_RB();
// Complete erase operation
NF_CMD(CMD_ERASE2);
// Wait for ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
if ( NF_RDSTAT & STATUS_ILLACC )
{
RETAILMSG(FMD_ZONE_ERROR, (TEXT("SB######## Error Erasing block (Illigar Access) %d!\n"), blockID));
g_pNFConReg->NFSTAT = STATUS_ILLACC; // Write 1 to clear.
bRet = FALSE;
}
else
{
// Check the status
NF_CMD(CMD_STATUS);
if( NF_RDDATA_BYTE() & STATUS_ERROR)
{
RETAILMSG(FMD_ZONE_ERROR, (TEXT("SB######## Error Erasing block %d!\n"), blockID));
bRet = FALSE;
}
}
NF_nFCE_H(); // Select the flash chip.
return bRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -