Windows CE的SD卡驱动包括总线驱动(bus driver),主控制器驱动(host controller driver)和客户端驱动(client driver).
总线驱动是客户端驱动和主控制器驱动之间的抽象管理层.提供了标准API允许SD卡客户端驱动运行在任何包含Sdbus.dll的Windows CE设备上.总线驱动独立于应用程序和客户端驱动,可以不加修改的移植到不同处理器平台.
主控制器驱动控制主控制器硬件,遵循主控制器驱动接口,能够被客户端驱动使用进行通信和设置参数.主控制器驱动提供了客户端驱动和主控制器实现之间的硬件抽象层.
客户端驱动通过其接口允许与SD卡设备通信.客户端驱动接口被设计抽象了SD总线的物理实现,同时提供了客户端驱动最大的弹性.客户端驱动接口允许客户端驱动实现从简单的,同步访问存储卡驱动到完整线程的异步通信驱动.(翻译自MS帮助,更多内容可参考MS帮助)
下面就结合SMDK2410的SDHC驱动来进行分析.
这个驱动实现了就是主控制器驱动(host controller driver).
主控制器驱动包含了硬件相关的代码,主要包含了controller, slot支持逻辑,包含了实际的硬件实现;实现SD/MMC传送与接收;可以是本地总线上的内存映射设备(如继承控制器),或者是外部总线如PCMCIA,PCI,USB;可以使用IO操作或者DMA.
SMDK2410 BSP下的SDHC是一个流接口驱动.由两部分组成:
SDHCBASE(sdhcmain.cpp,sdiocontrollerbase.cpp,sdiocontrollerbase.h,实现了标准的流接口函数);SDHC(sdiocontroller.cpp,sdiocontroller.h,实际的硬件操作函数)生成最终的dll,同时包含了注册表设置sdhc_sc2410.reg,导出函数定义sdhc_sc2410.def
我们先来看sdhcmain.cpp,里面实现如SDH_Init,,SDH_Deinit,SDH_Open等的流接口函数.
1.DllEntry
DllEntry是最终生成的dll入口函数,在source中定义:DLLENTRY=DllEntry
当加载dll时(DLL_PROCESS_ATTACH)首先调用DisableThreadLibraryCalls来禁止DLL_THREAD_ATTACH和DLL_THREAD_DETACH通知给hLibModule参数定义的dll,在不使用线程级跟踪(thread-level tracking)情况下可以减少工作代码空间.
然后调用SDInitializeCardLib来初始化SD卡库.该函数实现在Sdcardlib.lib(/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/SDCARD/SDCARDLIB).
如果调用SDInitializeCardLib成功,则调用SDHCDInitializeHCLib进一步初始化,如果调用失败则调用SDDeinitializeCardLib(实现在Sdhclib,/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/SDCARD/SDHCLIB)取消初始化SD卡库.设置全局变量g_fRegisteredWithBusDriver表示未使用BusDriver注册.
卸载dll时(DLL_PROCESS_DETACH)调用SDHCDDeinitializeHCLib和SDDeinitializeCardLib来取消SD CardLib和HCLib的初始化.
- BOOL DllEntry(HINSTANCE hInstance, ULONG Reason, LPVOID pReserved)
- {
- BOOL fRet = TRUE;
- if(Reason == DLL_PROCESS_ATTACH)
- {
- DEBUGREGISTER(hInstance);
- DisableThreadLibraryCalls( (HMODULE) hInstance );
- if( !SDInitializeCardLib() )
- {
- fRet = FALSE;
- }
- else if( !SD_API_SUCCESS( SDHCDInitializeHCLib() ) )
- {
- SDDeinitializeCardLib();
- fRet = FALSE;
- }
- g_fRegisteredWithBusDriver = FALSE;
- }
- if(Reason == DLL_PROCESS_DETACH)
- {
- SDHCDDeinitializeHCLib();
- SDDeinitializeCardLib();
- }
- return(TRUE);
- }
2.SDH_Init
首先调用SDHCDAllocateContext来分配一段HC的上下文,如果成功就调用CreateSDIOController创建SD Host Controller对象CSDIOController类对象,CSDIOController是(CSDIOControllerBase的继承类).并将其赋值给pHostContext->pHCSpecificContext.接着调用InterpretCapabilities(CSDIOControllerBase成员函数)从注册表获得SD Host Controller信息.该函数的具体实现稍后在看.
最后调用SDHCDRegisterHostController来Host Controller.设置g_fRegisteredWithBusDriver注册标志为TRUE.返回pController.如果上述操作中任何一项失败,则进入Exit调用诸如SDHCDDeregisterHostController和SDHCDDeleteContext来取消注册和删除HC对象(上下文).
- extern "C"
- DWORD SDH_Init(DWORD dwContext)
- {
- DWORD dwRet = 0; // return value
- PSDCARD_HC_CONTEXT pHostContext = NULL; // new HC context
- SD_API_STATUS status; // SD status
- LPCTSTR pszActiveKey = (LPCTSTR) dwContext;
- CSDIOControllerBase* pController = NULL;
- DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDHC +Init/n")));
- ASSERT( g_fRegisteredWithBusDriver == FALSE );
- // Allocate the context
- status = SDHCDAllocateContext(SDHCD_SLOTS/*, sizeof(SDHCD_HARDWARE_CONTEXT)*/, &pHostContext);
- if(!SD_API_SUCCESS(status))
- {
- DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD: Failed to allocate context : 0x%08X /n"), status));
- goto EXIT;
- }
- // Create the SD Host Controller object
- pController = CreateSDIOController( pHostContext );
- if( pController == NULL ) {
- DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC Failed to allocate SD Host Controller object/n")));
- goto EXIT;
- }
- // Set our extension
- pHostContext->pHCSpecificContext = pController;
- // Read SD Host Controller Info from registry.
- if (!pController->InterpretCapabilities((LPCTSTR)dwContext)) {
- goto EXIT;
- }
- // now register the host controller
- status = SDHCDRegisterHostController(pHostContext);
- if(!SD_API_SUCCESS(status))
- {
- DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD: Failed to register host controller: %0x08X /n"),status));
- goto EXIT;
- }
- g_fRegisteredWithBusDriver = TRUE;
- // return the controller context
- dwRet = (DWORD)pController;
- EXIT:
- if( dwRet == 0 )
- {
- if( pHostContext )
- {
- // deregister the host controller
- if (g_fRegisteredWithBusDriver)
- {
- SDHCDDeregisterHostController(pHostContext);
- g_fRegisteredWithBusDriver = FALSE;
- }
- // delete the SD Host Controller object
- if( pController )
- {
- delete pController;
- }
- // cleanup the host context
- SDHCDDeleteContext(pHostContext);
- }
- }
- DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDHC -Init/n")));
- return dwRet;
- }
3.SDH_PreDeinit
SDH_PreDeinit首先获得HC Context,然后调用CSDIOControllerBase的成员函数PreDeinit,最后调用SDHCDDeregisterHostController解除HC Context的注册.
- extern "C"
- BOOL SDH_PreDeinit(DWORD hDeviceContext)
- {
- CSDIOControllerBase *pController = (CSDIOControllerBase*)hDeviceContext;
- if( g_fRegisteredWithBusDriver )
- {
- PSDCARD_HC_CONTEXT pHostContext = pController->GetHostContext();
- pController->PreDeinit();
- // deregister the host controller
- SDHCDDeregisterHostController(pHostContext);
- g_fRegisteredWithBusDriver = FALSE;
- }
- return TRUE;
- }
4.SDH_Deinit
SDH_Deinit首先根据g_fRegisteredWithBusDriver来判断host controller有没被解除注册,没有就再次调用SDHCDDeregisterHostController
然后删除SD Host Controller对象,清除host context.
- extern "C"
- BOOL SDH_Deinit(DWORD hDeviceContext)
- {
- CSDIOControllerBase *pController = (CSDIOControllerBase*)hDeviceContext;
- PSDCARD_HC_CONTEXT pHostContext = pController->GetHostContext();
- if( g_fRegisteredWithBusDriver )
- {
- // deregister the host controller
- SDHCDDeregisterHostController(pHostContext);
- g_fRegisteredWithBusDriver = FALSE;
- }
- // delete the SD Host Controller object
- delete pController;
- // Cleanup the host context
- SDHCDDeleteContext(pHostContext);
- return TRUE;
- }
5..SDH_Open
SDH_Open返回CSDIOControllerBase类对象pController.
- extern "C"
- DWORD SDH_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
- {
- DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDHCD: +-SDH_Open/n")));
- CSDIOControllerBase *pController = (CSDIOControllerBase*)hDeviceContext;
- return (DWORD) pController;
- }
6.SDH_IOControl,SDH_Close
SDH_IOControl,SDH_Close未做任何工作,直接返回.
7.SDH_PowerDown,SDH_PowerUp
SDH_PowerDown,SDH_PowerUp分别调用CSDIOControllerBase类的成员函数OnPowerDown和OnPowerUp.
接下来就来看看CSDIOControllerBase和其继承类CSDIOController的实现