Upload
fiona-buckley
View
138
Download
12
Embed Size (px)
DESCRIPTION
Windows CE 5.0 总线驱动程序架构. 刘斌 北京数智动力科技有限公司. 概述. 什么是总线驱动程序?为什么需要?能做什么? 架构 新的总线驱动程序命名空间 注册表 资源分配 IOCTLs Application Child 辅助函数. 什么是总线驱动程序 ?. 加载 / 卸载驱动程序 物理总线上的硬件 在总线驱动程序没有直接管理的物理总线上加载驱动程序 管理物理总线 调用 ActivateDeviceEx() 加载设备驱动程序 为从属驱动程序提供服务. 为何需要总线驱动程序 ?. 旧版本的限制 . - PowerPoint PPT Presentation
Citation preview
Windows CE 5.0Windows CE 5.0 总线驱动程序总线驱动程序架构架构
刘斌北京数智动力科技有限公司
概述• 什么是总线驱动程序?为什么需要?能做什么?• 架构
– 新的总线驱动程序命名空间– 注册表– 资源分配
• IOCTLs– Application– Child
• 辅助函数
什么是总线驱动程序 ?
• 加载 / 卸载驱动程序– 物理总线上的硬件– 在总线驱动程序没有直接管理的物理总线上加载驱动程序
• 管理物理总线• 调用 ActivateDeviceEx() 加载设备驱动程序• 为从属驱动程序提供服务
为何需要总线驱动程序 ?
旧版本的限制
• 驱动程序和加载它们的实体间没有任何关联• 根据句柄不能得到流的名称 • 程序不知道谁加载的它们
现在能够做到的 !
• 总线驱动程序加载 / 卸载从属驱动程序并重新列举他们的总线 .• 从属驱动程序可以与总线驱动程序通讯请求服务 ( 比如 . 电源管理 )• 应用程序可以列举设备 , 总线 , 和他们支持的接口
总线驱动程序提供的保护 !• 恢复时 , 总线驱动程序可以防止访问已经移除的设备 :
– Installable ISR– Bus agnostic driver’s power callback
• 恢复时 , 从属驱动程序可以调用总线驱动程序查看硬件是否依然存在 .– IOCTL_BUS_IS_CHILD_REMOVED
新的总线命名空间以前• 加载多个实例 , 如 大于 15 个端口的 COM• 任何应用程序可以发送电源管理 IOCTL ,这将造成驱动程序的电源状态混乱 ? 现在• 命名空间可以创建无限制的实例• 命名空间可以根据总线调用和非总线调用提供保护
Driver Hierarchy<BusEnum>
\
Com1:BuiltIn_1
BCR1:BuiltIn_2
DSK1:BuiltIn_4
<PCI Bus>BuiltIn_3
<Display> (GWES)PCI_0_0_0
WAV1:PCI_0_1_0
UFN1:PCI_0_2_0
DSK2:PCI_0_3_0
<TI1250>PCI_0_4_0
DSK4:TI1250_0_0
NDS1:TI1250_1_0
GPS1:<App loaded>
DSK3:USBFN_0_0
Apps call Apps call Load/unloadLoad/unload
可以借鉴的 Quality 例程可以参考 CE 5.0 中的以下 Production Quality Drivers
(PQD) :• PCCard• PCIBus• USBFn• SDBus• BusEnum (replaces RegEnum)• (new in Mobile 5.0) RootBus driver
新的总线命名空间• 总线驱动程序通过注册表通知设备管理器 驱动之间的从属关系• 总线驱动程序经由 ActivateDeviceEx() 提
供“ BusName”, “BusParent”• 驱动程序在设备标示中提供(可选)
“ BusPrefix”• DeviceManager 通过新的 API 形成层次结构• 总线驱动程序使用总线名称为从属驱动程序提供服务
新旧名称• DM 支持使用不同的命名空间调用
CreateFile() • 旧的命名空间 (e.g., “COM1:”) 以前 CE 中的使用方法• “$bus” 命名空间 (e.g., “$bus\
PCIBUS_0_1_0”) – 用于系统访问 ; driver support required to create
handles with these names• $bus 也可以用于总线驱动程序提供的服务
启用 $bus 命名空间• 在驱动程序的 IClass 注册表项中公布
DMCLASS_PROTECTEDBUSNAMESPACE GUID • 使用 CreateFile(“<$bus name>”) 来打开 Open()• 设置 dwAccess 参数中的 DEVACCESS_BUSNAMESPACE 位• Open 是系统访问• 驱动程序根据该位打开了哪些句柄来决定接受 / 拒绝其它操作• $bus 名称可用来与驱动程序的父总线驱动程序进行通讯,以获得诸如加载、卸载和电源管理之类的服务。
检查总线访问标志DWORD PCI_Open (DWORD dwContext, DWORD dwAccessMode,
DWORD dwShareMode){ OPEN_CONTEXT *pContext = (OPEN_CONTEXT*) LocalAlloc(LPTR, sizeof(OPEN_CONTEXT)); if (pContext == NULL) return 0;
if (dwAccessMode & DEVACCESS_BUSNAMESPACE) { // This is a bus access pContext->fPriviledgedAccess = TRUE; } else { // This is a regular access pContext->fPriviledgedAccess = FALSE; }
... // Initialize the rest of the structure return (DWORD) pContext;}
约束访问BOOL PCI_IOControl(HANDLE pOpenHead, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut){ BOOL fRet = FALSE;
if (pContext->fPriviledgedAccess == TRUE) { // This is a bus access, so allow // system operations. ... } else { // This is a regular access. Fail the call // if it is a system operation. ... }
return fRet;}
注册表• 在 IClass 注册表项中公布
DMCLASS_PROTECTEDBUSNAMESPACE GUID ({B3CC6EBA-5507-4196-8E41-2BF42E4A47C9})
• 在注册表项后增加 “ =%b”• 可以指定驱动程序的“ BusIoctl” 键值来启
用 post-init IOCTL ( IOCTL_BUS_POSTINIT)
注册表示例[HKEY_LOCAL_MACHINE\Drivers\BuiltIn] "Dll"="BusEnum.dll" "BusName"="BuiltIn" "Flags"=dword:8 "BusIoctl"=dword:2a0048 "InterfaceType"=dword:0 "IClass"=multi_sz:"{B3CC6EBA-5507-4196-
8E41-2BF42E4A47C9}=%b","{6F40791D-300E-44E4-BC38-E0E63CA8375C}=%b"
总线驱动程序怎样使用注册表?WCHAR szBusName[ ] = L”BuiltIn_3”;HANDLE hParent = GetDeviceHandleFromContext(pszActiveReg);
REGINI rgRegIni[2] = { { L”BusParent”, REG_DWORD, hParent, sizeof(hParent) },{ L”BusName”, REG_SZ, szBusName, sizeof(szBusName) }};
HANDLE hChildDevice = ActivateDeviceEx(szChildRegPath, 2, rgRegIni, NULL);
I/O 资源管理器• 支持 “ dense” 资源 和 “ sparse” 资源• Dense 资源一般标为可共享资源• Dense 资源的典型代表为 IRQs, 在一些平台中为可共享的• Dense 资源的最大数量可以通过注册表配置 ( 在
4.2 中为 64)• 使用 ResourceRequestEx() 可以得到共享资源的排他访问• 在程序中可以使用 ResourceCreateList 和
ResourceDestroyList 创建和删除资源列表• IORM APIs
与 IORM 交互if (!ResourceRequest(RESMGR_IOSPACE, pInfo->IoBase.Reg[Io], pInfo->IoLen.Reg[Io])) { goto PCIRequestResources_Fail;}
IrqFlag = 0;if ((pInfo->DevFlags & DEVFLAGS_IRQ_EXCLUSIVE) != 0){ IrqFlag = RREXF_REQUEST_EXCLUSIVE;}if (!ResourceRequestEx(RESMGR_IRQ, Irq, 1, IrqFlag)) { goto PCIRequestResources_Fail;}
总线驱动程序 IOCTLs应用程序调用 • 加载 / 卸载子驱动程序调用• Power Operations• Device Removable Media Management• Device Configuration Space Access• Device Bus Address Translation
加载 / 卸载 操作• IOCTL_BUS_DEACTIVATE_CHILD – 卸载
由 Bus Name 指定的从属驱动程序• IOCTL_BUS_ACTIVATE_CHILD – 加载由
Name 指定的从属驱动程序• IOCTL_BUS_NAME_PREFIX – 访问 Bus
Name 使用的前缀( prefix )
现在如何使用 CreateFile1. CreateFile(“COM7:”) 返回对应设备的“传统的” 文件句柄2. CreateFile(“\$device\COM7”) 返回“传统
的” 文件句柄。可用于传统的命名规则不能胜任时的设备访问3. CreateFile(“\$bus\ PCMCIA_0_0_0”) 返回
PCMCIA 总线 0 ,设备 0 ,功能 0 的“系统” 文件句柄
App. 卸载驱动#include <ceddk.h>
...LPWSTR pszParentBusName = L”$bus\\BuiltIn_3”;HANDLE hBusDriver = CreateFile(pszParentBusName,
0, 0, NULL, OPEN_EXISTING, 0, NULL);if (hBusDriver != INVALID_HANDLE_VALUE) {
// Fail!}WCHAR szBusName[] = L”$bus\\PCI_0_2_0”;BOOL fSuccess = DeviceIoControl(hBusDriver,
IOCTL_BUS_DEACTIVATE_CHILD, (PVOID) szBusName, sizeof(szBusName), NULL, 0, NULL, NULL);
电源管理• IOCTL_BUS_SET_POWER_STATE – 改变指定从属驱动程序( By Bus Name )总线电源的级别 . 从属驱动程序向它们的总线驱动程序请求此服务• IOCTL_BUS_GET_POWER_STATE – 获得指定从属驱动程序总线电源的级别
可移动媒体的管理• CE’s “PnP” 结构的一部分• IOCTL_BUS_IS_CHILD_REMOVED – 从属驱动程序可以用此来检测媒体是否移除 . 也可以在从属驱动电源管理的回调中调用
访问设备配置空间• IOCTL_BUS_GET_CONFIGURE_DATA – 读取指定( By Bus Name )子驱动程序的配置空间• IOCTL_BUS_SET_CONFIGURE_DATA – 写入指定( By Bus Name )子驱动程序的配置空间
– 不同总线的配置空间名称不同– 对于 PCI, 支持 PCI_WHICHSPACE_CONFIG– 对于 PCCARD, 对于 32Bit卡支持
PCCARD_PCI_CONFIGURATION_SPACE
设备总线地址转换• IOCTL_BUS_TRANSLATE_SYSTEM_ADDRESS – 转换实际系统地址到逻辑总线地址
– 用于 DMA– 替换 HalTranslateSystemAddress
• IOCTL_BUS_TRANSLATE_BUS_ADDRESS – 转换总线物理地址到系统实际地址– 替换 HalTranslateBusAddress
辅助 APIs为何要用辅助 API?• 加快驱动程序开发速度• 访问上层驱动程序• 使用简单的过程调用 IOCTL
辅助 APIs• CreateBusAccessHandle
– Pass returned bus access handle to other Helper APIs
• GetDeviceConfigurationData• SetDevicePowerState• TranslateBusAddr• BusIoControl
– Pass arbitrary IOCTL to bus parent• CloseBusAccessHandle
Calling Bus ParentIn XXX_Init(), create the bus handle and get a virtual address
to the FIFO Memory Window. pContext->hBusAccess =
CreateBusAccessHandle(pszActiveKey);HANDLE hkDevice = OpenDeviceKey(pszActiveKey);DDKWINDOWINFO wini = { sizeof(wini) };DDKReg_GetWindowInfo(hkDevice, &wini);PHYSICAL_ADDRESS PortAddress = { 0 };PortAddress.LowPart =
wini.memWindows[WINDOW_FIFO_NUM].dwBase;BusTransBusAddrToVirtual(pContext->hBusAccess,
(INTERFACE_TYPE) wini.dwInterfaceType, wini.dwBusNumber, PortAddress, wini.memWindows[WINDOW_FIFO_NUM].dwLen, &dwAddrSpace, &pContext->pFifoAddr);
...
Calling Bus ParentIn XXX_IOControl(IOCTL_POWER_SET), set the power state
for the device. CEDEVICE_POWER_STATE dx =
*(CEDEVICE_POWER_STATE*)pOutBuffer;SetDevicePowerState(pContext->hBusAccess, dx, NULL);
In XXX_Deinit(), free to the FIFO Memory Window and close the bus access handle.
if (pContext->pbFifoAddr) { MmUnmapIoSpace(pContext->pbFifoAddr, 0);}CloseBusAccessHandle(pContext->hBusAccess);
Call To Action• 成为驱动开发者计划的成员
– http://msdn.microsoft.com/embedded/usewinemb/ce/drivers/driverdev/default.aspx
• 发布自己的驱动程序– http://msdn.microsoft.com/embedded/usewine
mb/ce/drivers/supdrivers/default.aspx
Tools & Resources
msdn.microsoft.com/msdn.microsoft.com/ embeddedembedded
microsoft.public.microsoft.public. windowsxp.embeddedwindowsxp.embedded windowsce.platbuilderwindowsce.platbuilder windowsce.embedded.vcwindowsce.embedded.vc
blogs.msdn.com/blogs.msdn.com/ mikehallmikehall
Windows CE 5.0 Eval KitWindows CE 5.0 Eval KitWindows XP Embedded Eval KitWindows XP Embedded Eval Kit
msdn.microsoft.com/msdn.microsoft.com/ mobilitymobility
microsoft.public.microsoft.public. pocketpc.developer pocketpc.developer smartphone.developer smartphone.developer dotnet.framework.compactframeworkdotnet.framework.compactframework
blogs.msdn.com/blogs.msdn.com/ windowsmobilewindowsmobile vsdteamvsdteam netcfteamnetcfteam
Windows Mobile 5.0 Eval KitWindows Mobile 5.0 Eval Kit
WebsitesWebsites
NewsgroupsNewsgroups
BlogsBlogs
ToolsTools
BuildBuild DevelopDevelop
请在课程结束后填写课程培训反馈表,参加抽奖。请填写资料袋内的蓝色大会满意度反馈表,到大会接待台领取《 Windows Mobile手机应用开发》工具书。您还可以:参加 Windows Mobile 动手实验室;参观微软及合作伙伴展区;体验基于 Windows Mobile 平台开发的最新硬件产品及解决方案。
大会注意事项