📄 fmd.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//------------------------------------------------------------------------------
//
// File: fmd.c
//
//
#include <windows.h>
#include <fmd.h>
#include <oal.h>
#include <omap2420.h>
#include <bsp_nand_cfg.h>
#include <bsp_base_regs.h>
BOOL ECC_ComputeECC(UCHAR *pData, DWORD size, UCHAR *pECC, DWORD eccSize);
BOOL ECC_IsDataValid(UCHAR *pData, DWORD size, UCHAR *pECC, DWORD eccSize);
BOOL ECC_CorrectData(UCHAR *pData, DWORD size, UCHAR *pECC, DWORD eccSize);
// TI's ECC spare area layout
#define ECC_SIZE 3
//------------------------------------------------------------------------------
// Spare area on NAND used for OMAP2420
#pragma pack( push, 1 )
typedef struct {
WORD badBlock1; // Indicates if block is BAD
BYTE ecc[ECC_SIZE]; // ECC values
BYTE badBlock; // Indicates if block is BAD
BYTE unused; // Unused byte
BYTE oemReserved; // For use by OEM
WORD reserved2; // Reserved - used by FAL
WORD badBlock2; // Indicates if block is BAD
DWORD reserved1; // Reserved - used by FAL
} NAND_SPARE_AREA;
#pragma pack( pop )
//------------------------------------------------------------------------------
// Geometry info structure
typedef struct {
UINT8 manufacturerId;
UINT8 deviceId;
UINT32 blocks;
UINT32 sectorsPerBlock;
UINT32 sectorSize;
BOOL extendedAddress;
} NAND_INFO;
//------------------------------------------------------------------------------
// Hardware NAND registers structure
typedef volatile struct {
UINT32 CMD;
UINT32 ADDRESS;
UINT32 DATA;
} NAND_REGS;
//------------------------------------------------------------------------------
// Local Variable
static struct {
CRITICAL_SECTION cs;
OMAP2420_GPMC_REGS *pGPMCRegs;
NAND_REGS *pNANDRegs;
const NAND_INFO *pNANDInfo;
UCHAR *pBuffer;
} g_fmd;
//------------------------------------------------------------------------------
// NAND geometry info
static const NAND_INFO g_nandInfo[] = { BSP_NAND_INFO };
//------------------------------------------------------------------------------
// Local Functions
_inline static BOOL NAND_WaitForReady();
static BOOL NAND_SendFullCommand(UINT8 cmd, SECTOR_ADDR sector, UINT32 offset);
static BOOL NAND_FinishCommand(UINT8 cmd);
static VOID NAND_Read(UINT8 *pBuffer, UINT32 bytes);
static VOID NAND_Write(UINT8 *pBuffer, UINT32 bytes);
//------------------------------------------------------------------------------
//
// Function: FMD_Init
//
// This function is called to initialize flash subsystem.
//
PVOID FMD_Init(LPCTSTR pActive, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
VOID *pHandle = NULL;
PHYSICAL_ADDRESS pa;
UINT8 manufacturer, device;
UINT32 ix;
memset(&g_fmd, 0, sizeof(g_fmd));
InitializeCriticalSection(&g_fmd.cs);
pa.QuadPart = OMAP2420_GPMC_REGS_PA;
g_fmd.pGPMCRegs = MmMapIoSpace(pa, sizeof(OMAP2420_GPMC_REGS), FALSE);
if (g_fmd.pGPMCRegs == NULL) {
goto cleanUp;
}
pa.QuadPart = BSP_NAND_REGS_PA;
g_fmd.pNANDRegs = MmMapIoSpace(pa, sizeof(NAND_REGS), FALSE);
if (g_fmd.pNANDRegs == NULL) {
goto cleanUp;
}
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
// Send Read ID Command
OUTREG16(&g_fmd.pNANDRegs->CMD, BSP_NAND_CMD_READID);
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
// Send Address 00h
OUTREG16(&g_fmd.pNANDRegs->ADDRESS, 0);
if (!NAND_WaitForReady()) goto cleanUp;
// Read the manufacturer ID & device code
manufacturer = (UINT8)INREG16(&g_fmd.pNANDRegs->DATA);
device = (UINT8)INREG16(&g_fmd.pNANDRegs->DATA);
// Find if we support chip
g_fmd.pNANDInfo = NULL;
for (ix = 0; ix < sizeof(g_nandInfo)/sizeof(g_nandInfo[0]); ix++) {
if (
manufacturer == g_nandInfo[ix].manufacturerId &&
device == g_nandInfo[ix].deviceId
) {
g_fmd.pNANDInfo = &g_nandInfo[ix];
break;
}
}
// If we don't support NAND, fail...
if (g_fmd.pNANDInfo == NULL) goto cleanUp;
// Allocate buffer
g_fmd.pBuffer = LocalAlloc(LPTR, g_fmd.pNANDInfo->sectorSize);
if (g_fmd.pBuffer == NULL) goto cleanUp;
// We are done
pHandle = &g_fmd;
cleanUp:
return pHandle;
}
//------------------------------------------------------------------------------
//
// Function: FMD_Deinit
//
BOOL FMD_Deinit(VOID *pContext)
{
BOOL rc = FALSE;
if (pContext != &g_fmd) goto cleanUp;
if (g_fmd.pBuffer != NULL) LocalFree(g_fmd.pBuffer);
if (g_fmd.pGPMCRegs != NULL) MmUnmapIoSpace(
(VOID*)g_fmd.pGPMCRegs, sizeof(OMAP2420_GPMC_REGS)
);
if (g_fmd.pNANDRegs != NULL) MmUnmapIoSpace(
(VOID*)g_fmd.pNANDRegs, sizeof(NAND_REGS)
);
DeleteCriticalSection(&g_fmd.cs);
rc = TRUE;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: FMD_GetInfo
//
// This function is call to get flash information
//
BOOL FMD_GetInfo(FlashInfo *pFlashInfo)
{
BOOL rc = FALSE;
// If we don't support NAND, fail...
if (g_fmd.pNANDInfo == NULL) goto cleanUp;
// Memory type is NAND
pFlashInfo->flashType = NAND;
pFlashInfo->dwNumBlocks = g_fmd.pNANDInfo->blocks;
pFlashInfo->wSectorsPerBlock = g_fmd.pNANDInfo->sectorsPerBlock;
pFlashInfo->wDataBytesPerSector = g_fmd.pNANDInfo->sectorSize;
pFlashInfo->dwBytesPerBlock =
g_fmd.pNANDInfo->sectorSize * g_fmd.pNANDInfo->sectorsPerBlock;
// Done
rc = TRUE;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: FMD_ReadSector
//
// Read the content of the sector.
//
BOOL FMD_ReadSector(
SECTOR_ADDR sector, UCHAR *pBuffer, SectorInfo *pSectorInfo, DWORD sectors
) {
BOOL rc = FALSE;
NAND_SPARE_AREA sa;
UINT32 i;
// There isn't clear semantic how to read more than one sector
if (sectors > 1 || g_fmd.pNANDInfo == NULL) goto cleanUp;
EnterCriticalSection(&g_fmd.cs);
// Read sector from A
if (pBuffer != NULL) {
NAND_SendFullCommand(BSP_NAND_CMD_READ, sector, 0);
NAND_Read(pBuffer, g_fmd.pNANDInfo->sectorSize);
}
// Write the command
NAND_SendFullCommand(BSP_NAND_CMD_READ2, sector, 0);
// Read NAND spare area data
NAND_Read((UINT8*)&sa, sizeof(sa));
LeaveCriticalSection(&g_fmd.cs);
// Copy sector info
if (pSectorInfo != NULL) {
pSectorInfo->bBadBlock = sa.badBlock;
pSectorInfo->bOEMReserved = sa.oemReserved;
pSectorInfo->dwReserved1 = sa.reserved1;
pSectorInfo->wReserved2 = sa.reserved2;
}
// Verify ECC
if (pBuffer != NULL) {
// Check if we get same ECC from data
if (!ECC_IsDataValid(
pBuffer, g_fmd.pNANDInfo->sectorSize, sa.ecc, ECC_SIZE
)) {
// Now try to correct them
if (!ECC_CorrectData(
pBuffer, g_fmd.pNANDInfo->sectorSize, sa.ecc, ECC_SIZE
)) {
// Check if spare and data are all 0xFF - erased sector
for (i = 0; i < sizeof(sa); i++) {
if (((UINT8*)&sa)[i] != 0xFF) goto cleanUp;
}
for (i = 0; i < g_fmd.pNANDInfo->sectorSize; i++) {
if (pBuffer[i] != 0xFF) goto cleanUp;
}
}
}
}
// Done
rc = TRUE;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: FMD_WriteSector
//
BOOL FMD_WriteSector(
SECTOR_ADDR sector, UCHAR *pBuffer, SectorInfo *pSectorInfo, DWORD sectors
) {
BOOL rc = FALSE;
NAND_SPARE_AREA sa;
// There isn't clear semantic how to read more than one sector
if (sectors > 1 || g_fmd.pNANDInfo == NULL) goto cleanUp;
EnterCriticalSection(&g_fmd.cs);
// Remove flash write protection
SETREG32(&g_fmd.pGPMCRegs->ulGPMC_CONFIG,BIT4);
// When there is buffer write data
if (pBuffer != NULL) {
// Select A area
OUTREG16(&g_fmd.pNANDRegs->CMD, BSP_NAND_CMD_READ);
// Issue command
NAND_SendFullCommand(BSP_NAND_CMD_WRITE, sector, 0);
// Write the data
NAND_Write(pBuffer, g_fmd.pNANDInfo->sectorSize);
// Calculate the ECC
ECC_ComputeECC(
pBuffer, g_fmd.pNANDInfo->sectorSize, sa.ecc, ECC_SIZE
);
// Finish up the write operation
if (!NAND_FinishCommand(BSP_NAND_CMD_WRITE2)) goto cleanUp;
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -