wince FAL+FMD 分析(修改)

本文介绍了Wince系统中FAL+FMD模块的工作原理。重点解析了设备驱动的数据结构DEVICE及其初始化过程,FMDInterface接口的获取及功能,包括设备初始化、信息获取等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

wince FAL+FMD的简单分析
creator
sz111@126.com
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函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值