您的位置:首页 > 其它

wince FAL+FMD 分析(修改)

2010-04-11 23:40 330 查看
wince FAL+FMD的简单分析
creator
sz111@126.com

http://hi.baidu.com/guly699 小改

1.首先弄清楚FAL中的设备驱动,物理设备数据类型如下:
typedef struct _DEVICE
{
DWORD dwID;
PVOID hFMD;
PVOID hFMDHook;

} DEVICE , *PDEVICE;

有一个公共变量g_pDevice来保存这个。pDevice指向g_pDevice(如在函数 DWORD DSK_Init(DWORD dwContext) ; 中 PDEVICE pDevice = g_pDevice;)

2.在DSK_Init初始化化中,会通过GetFMDInterface(pDevice)函数获得设备的FMD。

VOID GetFMDInterface(PDEVICE pDevice)
{
FMD.cbSize = sizeof(FMDInterface);

// query FMD intrface from the FMD
FMD.pOEMIoControl = FMD_OEMIoControl;
if (!FMD_OEMIoControl (IOCTL_FMD_GET_INTERFACE, NULL, 0, (PBYTE)&FMD, sizeof(FMDInterface), NULL))
{
// FMD does not support IOCTL_FMD_GET_INTERFACE, so build the FMDInterface
// structure using the legacy FMD functions
FMD.pInit = FMD_Init;
FMD.pDeInit = FMD_Deinit;
FMD.pGetInfo = FMD_GetInfo;
FMD.pGetBlockStatus = FMD_GetBlockStatus;
FMD.pSetBlockStatus = FMD_SetBlockStatus;
FMD.pReadSector = FMD_ReadSector;
FMD.pWriteSector = FMD_WriteSector;
FMD.pEraseBlock = FMD_EraseBlock;
FMD.pPowerUp = FMD_PowerUp;
FMD.pPowerDown = FMD_PowerDown;
}

// query hook library in case any FMD functions need to be shimmed
pDevice->hFMDHook = FMDHOOK_HookInterface(&FMD);

}

typedef struct _FMDInterface
{
DWORD cbSize;
PFN_INIT pInit;
PFN_DEINIT pDeInit;
PFN_GETINFO pGetInfo;
PFN_GETBLOCKSTATUS pGetBlockStatus;
PFN_SETBLOCKSTATUS pSetBlockStatus;
PFN_READSECTOR pReadSector;
PFN_WRITESECTOR pWriteSector;
PFN_ERASEBLOCK pEraseBlock;
PFN_POWERUP pPowerUp;
PFN_POWERDOWN pPowerDown;
PFN_GETPHYSSECTORADDR pGetPhysSectorAddr;
PFN_GETINFOEX pGetInfoEx;
PFN_OEMIOCONTROL pOEMIoControl;

} FMDInterface, *PFMDInterface;

其中FMD_OEMIoControl是在Fmd.cpp中定义的(我的BSP中在文件Fmd_readonly.cpp 和Fmd_writable.cpp中也有定义,不知为什么?希望高人解答下)。通过这个函数把msflash.dll和nandflash.dll联系起来。
通过它获得FMD,是一个函数指针接口,以后就通过FMD来执行FMD中的实际函数了。

BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
switch(dwIoControlCode)
{
case IOCTL_FMD_GET_INTERFACE:
{
RETAILMSG(1, (TEXT("[FMD] FMD_OEMIoControl() : IOCTL_FMD_GET_INTERFACE/r/n")));

if (!pOutBuf || nOutBufSize < sizeof(FMDInterface))
{
DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_INTERFACE bad parameter(s)./r/n")));
return(FALSE);
}

PFMDInterface pInterface = (PFMDInterface)pOutBuf;

pInterface->cbSize = sizeof(FMDInterface);
pInterface->pInit = FMD_Init;
pInterface->pDeInit = FMD_Deinit;
pInterface->pGetInfo = FMD_GetInfo;
pInterface->pGetInfoEx = NULL; //FMD_GetInfoEx;
pInterface->pGetBlockStatus = FMD_GetBlockStatus;
pInterface->pSetBlockStatus = FMD_SetBlockStatus;
pInterface->pReadSector = FMD_ReadSector;
pInterface->pWriteSector = FMD_WriteSector;
pInterface->pEraseBlock = FMD_EraseBlock;
pInterface->pPowerUp = FMD_PowerUp;
pInterface->pPowerDown = FMD_PowerDown;
pInterface->pGetPhysSectorAddr = NULL;

break;
}
.....
}

3.获得FMD之后,首先调用FMD.pInit, 对FMD设备进行初始化。主要是控制器的配置,读ID得到nandflash的容量,
等信息。

4.调用FMD.pGetInfo(&oldFlashInfo)获得nandflash的信息。最终也是调用BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
pFlashInfo->dwNumBlocks = NUM_OF_BLOCKS;
pFlashInfo->wSectorsPerBlock = PAGES_PER_BLOCK;
pFlashInfo->wDataBytesPerSector = NAND_SECTOR_SIZE;
pFlashInfo->dwBytesPerBlock = (PAGES_PER_BLOCK * NAND_SECTOR_SIZE);
把相关信息读到oldFlashInfo中。然后把相关数据写入公共变量g_pFlashMediaInfo
5.然后通过调用CalculateLogicalRange来统计nandflash的区域大小和可以用的block
BOOL CalculateLogicalRange(PFlashRegion pRegion)
{
DWORD dwBlockID;
DWORD dwNumLogicalBlocks = 0;

for (dwBlockID = pRegion->dwStartPhysBlock; dwBlockID < pRegion->dwStartPhysBlock + pRegion->dwNumPhysBlocks; dwBlockID++)
{
DWORD dwStatus = FMD.pGetBlockStatus (dwBlockID);

if (!(dwStatus & (BLOCK_STATUS_RESERVED | BLOCK_STATUS_BAD)))
{
dwNumLogicalBlocks++;
}
}
//pRegion->dwCompactBlocks=MINIMUM_FLASH_BLOCKS_TO_RESERVE最少的block为2,如果wince发现少于2个block的可用块,就会返回error。
if (dwNumLogicalBlocks <= pRegion->dwCompactBlocks)
{
ReportError((TEXT("FLASHDRV.DLL:CalculateLogicalRange() - Invalid number of logical blocks %d/r/n"), dwNumLogicalBlocks));
return FALSE;
}

// Account for compaction blocks
dwNumLogicalBlocks -= pRegion->dwCompactBlocks;
pRegion->dwNumLogicalBlocks = dwNumLogicalBlocks;
return TRUE;
}
最终也是调用FMD_GetBlockStatus函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: