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函数。
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函数。
相关文章推荐
- WINCE FAL+FMD nand flash驱动
- 块设备驱动指的是文件系统驱动(FAL+FMD)吗
- Qt for windows消息循环、libqxt分析和wince快捷键处理
- WINCE 6.0 RDP相关的Terminal server Client License界面修改
- CSS selector (jquery的源码分析,修改)
- Android Launcher分析和修改4——初始化加载数据
- WinCE Storage Manager 分析
- 物联网平台机智云Android开源框架入门之旅(二)详细分析在设备列表的代码块,如何修改设备默认图片。
- owncloud源码分析1--部分修改Demo
- 微信任意用户密码修改漏洞分析
- WinCE修改系统时间
- WinCE NAND flash - FAL
- 转载——wince源码分析中断之map.c
- wince注册表编程(新建,读取,修改)
- Telechips 8902 & WinCE6.0 平台下 overlay 使用冲突现象的分析
- 一段程序代码的修改,将原来按分钟活动的方式改为秒级滑动,可以提供数据分析的精度
- .NET / Rotor源码分析4 - 修改Rotor使其发送CLR Notification
- uboot启动阶段修改启动参数方法及分析
- .NET / Rotor源码分析4 - 修改Rotor使其发送CLR Notification
- .NET / Rotor源码分析4 - 修改Rotor使其发送CLR Notification