首页 NDIS_中间层驱动程序(IMD)开发人员指南

NDIS_中间层驱动程序(IMD)开发人员指南

举报
开通vip

NDIS_中间层驱动程序(IMD)开发人员指南NDIS IM Developer Guide 目 录 TOC \o "1-4" \h \z 1 NDIS中间层驱动程序 2 1.1 NDIS中间层驱动程序(NDIS Intermediate Drivers)概述 2 1.2 NDIS中间层驱动程序的用途 4 1.3 NDIS中间层驱动程序的开发环境 4 2 NDIS中间层驱动程序的开发 4 2.1 可分页和可丢弃代码 4 2.2 共享资源的访问同步 5 2.3 中间层驱动程序的DriverEntry函数 5 2.3.1 注册NDIS中间层驱动程序 6 2.3.1...

NDIS_中间层驱动程序(IMD)开发人员指南
NDIS IM Developer Guide 目 录 TOC \o "1-4" \h \z 1 NDIS中间层驱动程序 2 1.1 NDIS中间层驱动程序(NDIS Intermediate Drivers)概述 2 1.2 NDIS中间层驱动程序的用途 4 1.3 NDIS中间层驱动程序的开发环境 4 2 NDIS中间层驱动程序的开发 4 2.1 可分页和可丢弃代码 4 2.2 共享资源的访问同步 5 2.3 中间层驱动程序的DriverEntry函数 5 2.3.1 注册NDIS中间层驱动程序 6 2.3.1.1 注册中间层驱动程序的Miniport 6 2.3.1.2 注册中间层驱动程序的 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 8 2.4 中间层驱动程序的动态绑定 11 2.4.1 打开中间层驱动程序下层的适配器 12 2.4.2 微端口(Miniport)初始化 12 2.4.3 中间层驱动程序查询和设置操作 13 2.4.3.1 发布设置和查询请求 14 2.4.3.2 响应设置和查询请求 15 2.4.4 作为面向连接客户程序注册中间层驱动程序 15 2.5 中间层驱动程序数据包管理 17 2.5.1.1 重用数据包 18 2.6 中间层驱动程序的限制 19 2.7 中间层驱动程序接收数据 19 2.7.1 下边界面向无连接的中间层驱动程序接收数据 19 2.7.1.1 在中间层驱动程序中实现ProtocolReceivePacket处理程序 20 2.7.1.2 在中间层驱动程序中实现ProtocolReceive处理程序 21 2.7.1.3 下边界面向无连接中间层驱动程序接收OOB数据信息 22 2.7.2 下边界面向连接的中间层驱动程序接收数据 22 2.7.2.1 在中间层驱动程序中实现ProtocolCoReceivePacket处理程序 23 2.7.2.2 在下边界面向连接的中间层驱动程序中接收OOB数据信息 23 2.7.3 向高层驱动程序指示接收数据包 23 2.8 通过中间层驱动程序传输数据包 23 2.8.1 传递介质相关信息 25 2.9 处理中间层驱动程序的PnP事件和PM事件 26 2.9.1 处理OID_PNP_XXX查询和设置 26 2.9.2 中间层驱动程序ProtocolPnPEvent处理程序的实现 27 2.9.3 处理规定的电源请求 28 2.9.3.1 睡眠状态的电源设置请求 28 2.9.3.2 工作状态的电源设置请求 29 2.10 中间层驱动程序复位操作 29 2.11 中间层驱动程序拆除绑定操作 30 2.12 中间层驱动程序状态指示 31 3 负载平衡和失效替换 31 3.1 关于LBFO 31 3.2 指定对LBFO的支持 32 3.3 在微端口驱动程序上实现LBFO 32 3.3.1 初始化微端口束 33 3.3.2 平衡微端口驱动程序的工作量 33 3.3.3 在主微端口失效后提升一个次微端口 34 4 安装网络组件 34 4.1 用于安装网络组件的组件和文件 34 4.2 创建网络INF文件 35 4.2.1 网络INFS文件名的约定 35 4.2.2 网络INF文件的版本节 35 4.2.3 网络INF文件的模型节 36 4.2.4 INF文件的DDInstall节 37 4.2.5 删除节 38 4.2.6 ControlFlags节 39 4.2.7 网络INF文件的add-registry-sections 39 表格 1 缩略语表 项目 英文描述 中文描述 NDIS Network Driver Interface Specification 网络驱动程序接口标准 IMD Intermediate Drivers 中间层驱动 TDI Transport driver Interface 传输驱动程序接口 NIC Network Interface Card 网络接口卡 SP Service Pack 服务包 LAN Local Area Network 局域网 LAN-E LAN Emulation 局域网仿真 NAT Network Address Translation 网络地址转换 LBFO Load Balancing And Fail-Over 负载平衡和失效替换 DDK Device Drivers Kit 设备驱动程序开发包 SMP Symmetry Multiprocessing 对称多处理 OS Operating System 操作系统 IDE Integrated Development Environment 集成开发环境 1​ NDIS中间层驱动程序 1.1​ NDIS中间层驱动程序(NDIS Intermediate Drivers)概述 微软Windows网络驱动程序接口标准(NDIS 4.0)和Windows NT 4.0(SP3)引入了一种新的NDIS驱动程序,它可以嵌在NDIS 传输驱动程序TDI(如,TCP/IP)和底层的NDIS网络接口驱动程序的中间。这种新类型的驱动程序被称为NDIS中间层驱动,如图表 1。NDIS(网络驱动器接口标准)中间层驱动程序在其上边界导出MiniportXxx函数,在其下边界导出ProtocalXxx函数。该驱动程序在其上边界仅提供面向无连接通信支持,而在其下边界,则即可支持面向无连接通信,也可支持面向连接通信。 中间层驱动程序的微端口部分(上边界)必须是非串行的,系统将依赖这些非串行驱动程序,而不是NDIS对MiniportXxx函数的操作进行串行化处理和对内部生成的输出包进行排队操作提供良好界导出TDI驱动程序__________________________________________________________________________________________________________________,这样驱动程序只要保持很小的临界区(每次只能有一个线程执行该代码)就能提供性能良好的全双工操作。但是这些非串行Miniport要受到更多也更严格的设计要求的限制,往往要为此付出更多的调试和测试时间。 中间层驱动程序是一种典型的层次结构程序,它基于一个或多个NDIS NIC驱动程序,其上层是一个向上层提供TDI(传输驱动程序接口)支持的传输驱动程序(也可能是多层结构)。从理论上讲,一个中间层驱动程序也可以是基于其他中间层驱动程序或作为其他中间层驱动程序的低层出现的,尽管这种 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 未必能展现更好的性能。 中间层驱动程序的一个示例是LAN仿真中间层驱动程序,其上层是一个早期传输驱动程序,下层是一个非LAN介质的微端口 NIC驱动程序。该驱动程序从上层接收LAN格式的数据包并将其转换为本地网卡的介质格式,然后将其发送到那个NIC的NDIS 微端口。接收数据时,该驱动程序将低层网卡驱动程序送来的数据包转换为LAN兼容格式,最后向上层传输驱动程序提交这些转换过的数据包。 例如,NDISWAN就具有一些上述特征。NDISWAN将数据包从上层的传输LAN格式转换为WAN数据包格式,或者将数据包从低层的网卡驱动WAN格式转换为LAN数据包格式。另外,如果低层NIC硬件不支持这些功能,那么NDISWAN也可提供诸如压缩、加密和端对端协议(PPP)等的数据格式化功能。NDISWAN为在NDIS API和网卡驱动程序之间进行通信提供了一个专用接口,同时,NDISWAN也将协议绑定映射为活动连接请求。 另一个中间层驱动程序的例子是ATM LANE (LAN仿真)驱动程序,它将数据包从上层无连接的传输格式转换为下层面向连接的网卡支持的ATM格式。 图1.1说明了中间层驱动程序结构 图表 1 中间层驱动程序结构 NDIS中间层驱动程序在NDIS中起着转发上层驱动程序送来的数据包,并将其向下层驱动程序发送的接口功能。当中间层驱动程序从下层驱动程序接收到数据包时,它要么调用NdisMXxxIndicateReceive函数,要么调用NdisMindicateReceivePacket函数向上层指示该数据包。 中间层驱动程序通过调用NDIS打开和建立一个对低层NIC驱动程序或者NDIS中间层驱动程序的绑定。中间层驱动程序提供MiniportSetInformation和MiniportQueryInformation函数来处理高层驱动程序的设置和查询请求,某些情况下,可能还要将这些请求向低层NDIS驱动程序进行传递,如果其下边界是面向无连接的可通过调用NidsRequest实现这一功能,如果其下边界是面向连接的则通过调用NidsCoRequest实现该功能。 中间层驱动程序通过调用NDIS提供的函数向网络低层NDIS驱动程序发送数据包。例如,下边界面向无连接的中间层驱动程序必须调用NdisSend或NdisSendPackets来发送数据包或者包数组,而在下边界面向连接的情况下就必须调用NdisCoSendPackets来发送包数组数据包。如果中间层驱动程序是基于非NDIS NIC驱动程序的,那么在调用中间层驱动程序的MiniportSend或Miniport(Co)SendPackets函数之后,发送接口对NDIS将是不透明的。 NDIS提供了一组隐藏低层操作系统细节的NdisXxx函数和宏。例如,中间层驱动程序可以调用NdisMInitializeTimer来创建同步时钟,可以调用NdisInitializeListHead创建链表。中间层驱动程序使用符合NDIS标准的函数,来提高其在支持Win32接口的微软操作系统上的可移植性。 1.2​ NDIS中间层驱动程序的用途 NDIS中间层驱动有几个方面的用途,包括: ​ 局域网仿真(LAN Emulation) – NDIS中间层驱动可以使一个非局域网NIC驱动(如,ATM)犹如一个局域网NIC驱动(如,Ethernet)。 ​ 包过滤(Packet Filtering) - 可以拦截和修改高层TDI(传输驱动程序)和底层NIC驱动程序之间的网络包(Packets): ​ 通过或过滤掉(Pass/Drop Packets) ​ 延迟或重新排序( Delay/Reorder Packets) ​ 加密或解密(Packet Encryption/Decryption) ​ 压缩或解压(Packet Compression/Decompression) ​ 路由包(Route Packets): ​ NAT网络地址转换(Network Address Translation) ​ LBFO负载平衡和失效替换(Adapter Load Balancing And Fail-Over) 1.3​ NDIS中间层驱动程序的开发环境 OS : Microsoft Windows 2000 Server IDE : Microsoft Visual C++ V6.0 DDK : Windows 2000 Device Drivers Kit 2​ NDIS中间层驱动程序的开发 2.1​ 可分页和可丢弃代码 每一个MiniportXxx函数或ProtocolXxx函数都运行在一个特定的IRQL上,在中间层驱动程序中这些函数可使用的IRQL从PASSIVE_LEVEL一直到DISPATCH_LEVEL(包括DISPATCH_LEVEL)。 总是运行在IRQL PASSIVE_LEVEL上的中间层驱动程序函数可通过调用NDIS_PAGEABLE_FUNCTION宏将其标记为可分页代码。驱动程序设计者应尽可能的将程序代码设计为可分页的,为那些必须驻留内存代码释放系统空间。运行在IRQL PASSIVE_LEVEL的驱动程序函数,当其既不调用运行在IRQL >=DISPATCH_LEVEL的任何函数,也不被运行在IRQL >=DISPATCH_LEVEL的任何函数调用时,可将其标注为可分页的。例如,一个获取自旋锁的函数,而获取自旋锁将促使获取线程提升到IRQL DISPATCH_LEVEL上运行。一个运行在IRQL PASSIVE_LEVEL的函数,如ProtocolBindAdapter,如果被标注为可分页的,就不能再调用运行在IRQL >=DISPATCH_LEVEL NDIS的函数。关于运行在IRQL 上的NDIS函数的更多信息,请参阅在线DDK的“Network Drivers Reference”,其中列出了每一个NdisXxx函数的IRQL。 中间层驱动程序的DriverEntry函数以及只在DriverEntry中调用的代码,应该用NDIS_INIT_FUNCTION宏将其设定为仅用作系统初始化功能。假定NDIS_INIT_FUNCTION宏标识的代码仅在系统初始化时运行,这样该部分代码将只有在初始化时才会被映射,在DriverEntry返回后,NDIS_INIT_FUNCTION宏标识的这部分代码将被丢弃。 2.2​ 共享资源的访问同步 如果驱动程序分配的资源能够被两个驱动程序函数同时共享,或者中间层驱动程序能够运行在SMP(对称多处理)机器上,这样相同的驱动程序函数能够从多个处理器同时访问该资源,那么对这些共享资源的访问必须进行同步。例如,驱动程序维持一个共享队列,使用自旋锁来对队列的访问进行同步,自旋锁在队列创建之前调用NdisAllocateSpinLock进行初始化。 当然,也不必过分地保护共享资源,例如,对于队列,一些读操作不进行串行化也是可以成功执行的。但任何针对队列链接的操作都必须进行同步。自旋锁应该尽量少使用,并且每次都要尽可能缩短其使用的时间。关于自旋锁更深入的讨论可参阅“Kernel_Mode Drivers Design Guide”。 2.3​ 中间层驱动程序的DriverEntry函数 为了使加载程序能够准确地识别,必须将中间层驱动程序的初始入口点明确地指定为DriverEntry的形式。所有其他的驱动程序导出函数,像这里所描述的MiniportXxx和ProtocolXxx函数,由于其地址传给了NDIS,因此在设计时可由开发者任意指定名称。任何内核模式驱动程序DriverEntry的定义具有以下形式: NTSTAUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); 如果除了ProtocolXxx之外,驱动程序还导出一组标准的内核模式驱动程序函数,那么必须将这些标准函数的地址写入要传给DriverEntry的驱动程序对象中。 在中间层驱动程序中,DriverEntry至少应该完成以下工作: 1、​ 调用NdisMInitializeWrapper并保存在NdisWrapperHandle中返回的句柄; 2、​ 传递上一步保存的句柄,调用NdisIMRegisterLayeredMiniport注册驱动程序的MiniportXxx函数; 3、​ 如果驱动程序随后要绑定到低层NDIS驱动程序上,则调用NdisRegisterProtocol注册驱动程序的ProtocolXxx函数; 4、​ 如果驱动程序导出了MiniportXxx和ProtocolXxx函数,那么调用NdisIMAssociateMiniport向NDIS通告有关驱动程序的微端口低边界和协议高边界信息; DriverEntry能够为中间层驱动程序分配的所有共享资源初始化自旋锁,例如驱动程序用于跟踪运行中的连接和发送任务的构件和内存区。 当DriverEntry不能为驱动程序分配用于网络I/O操作的所有资源时,它就应该释放先前已经分配的任何资源并返回一个适当的错误状态。例如,如果DriverEntry已经调用了NdisMInitializeWrapper函数,那么当后续操作出错时必须调用NdisTerminateWrapper复位系统状态。 中间层驱动程序的DriverEntry函数能够执行一些全局初始化操作。然而,如果驱动程序提供了在2.4节所描述的,实现对低层设备的打开和绑定功能的ProtocolBindAdapter函数,那么驱动程序就能够让ProtocolBindAdapter来分配绑定相关的系统资源,ProtocolBindAdapter根据要求为DeviceName设备进行资源分配和绑定操作。DriverEntry必须初始化该包裹程序并注册微端口驱动程序。如果中间层驱动程序导出了一组ProtocolXxx函数的话,也要注册协议驱动程序。 如果中间层驱动程序仅向NDIS导出了一组MiniportXxx函数,只要向NDIS库注册这些函数即可,如下所述。 2.3.1​ 注册NDIS中间层驱动程序 NDIS中间层驱动程序必须在DriverEntry函数的环境中向NDIS注册其MiniportXxx函数和ProtocolXxx函数。驱动程序通过调用NdisIMRegisterLayeredMiniport对MiniportXxx函数进行注册,该调用导出中间层驱动程序的MiniportXxx函数。当虚拟NIC被初始化时,以及随后当驱动程序将要基于该NIC接收和发送数据包时,注意驱动程序的控制过程。 对于指定的虚拟NIC,NDIS将在NdisIMInitializeDeviceInstance的环境中调用中间层驱动程序的MiniportInitialize函数对其进行初始化操作。如果中间层驱动程序导出了多个虚拟NIC,那么为使其可用于网络请求,驱动程序必须为每一个NIC调用NdisIMInitializeDeviceInstance函数进行初始化。这样可根据网络业务量,生成相应的数量的虚拟NIC。 如果NDIS中间层驱动程序也导出了一组ProtocolXxx函数,则必须调用相应的NdisRegisterProtocol函数向NDIS库注册这些函数。 2.3.1.1​ 注册中间层驱动程序的Miniport 中间层驱动程序通过调用NdisIMRegisterLayeredMiniport导出MiniportXxx函数。 NdisIMRegisterLayeredMiniport以如下方式进行声明: NDIS_STATUS NdisIMRegisterLayeredMiniport( IN NDIS_HANDLE NdisWrapperHandle, IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics, IN UINT CharacteristicsLength, OUT PNDIS_HANDLE DriverHandle ); 中间层驱动程序必须保存NdisIMRegisterLayeredMiniport返回的DriverHandle句柄,并且在驱动程序中调用NdisIMInitializeDeviceInstance函数,请求中间层驱动程序的MiniportInitialize函数对虚拟NIC进行初始化时,将该句柄输入NDIS。当中间层驱动程序成功的绑定到一个或多个低层NIC驱动程序上或者当其绑定在一个非NIC设备驱动程序上后,将调用NdisIMInitializeDeviceInstance函数,使得中间层驱动程序可以初始化Miniport组件来接受虚拟NIC上的I/O请求。 NdisWrapperHandle句柄是由先前的NdisMInitializeWrapper函数返回的。 中间层驱动程序必须完成以下操作: 1.​ 用NdisZeroMemory函数零初始化一个NDIS_MINIPORT_CHARACTERISTICS类型的构件; 2.​ 保存所有驱动程序导出的强制性的和非强制的MiniportXxx函数的地址,并将所有非强制的MiniportXxx入口指针设为NULL; 当其他类型的NDIS驱动程序的有效主版本是0x03、0x04、0x05时,如果要导出任何新的V4.0或 V5.0的MiniportXxx函数,中间层驱动程序的主版本必须是4.0并提供4.0或5.0版的MiniportCharacteristics构件。 对于MiniportCharacteristics,如果驱动程序不用导出MiniportXxx函数,则必须将其设为NULL,但是如果要导出函数的话,则必须将其设为某个有效的MiniportXxx函数地址值。 HaltHandler 当低层NIC超时并且NDIS已经中止了网卡驱动程序时,或者操作系统正在执行一个可控的系统关闭操作时,NDIS将调用该函数。 InitializeHandler 作为中间层驱动程序调用NdisIMInitializeDeviceInstance初始化微端口的结果,调用该函数对虚拟网卡进行初始化。 QueryInformationHandler 该函数接收OID_XXX请求,这个请求来自于高层驱动程序(用NdisRequestQueryInformation请求类型作参数,调用NdisRequest)。 ResetHandler 在高层协议驱动程序调用NdisReset的指示下,NDIS能够调用中间层驱动程序的MiniportReset函数。然而,协议驱动程序并不启动复位功能,通常,NDIS启动低层网卡驱动程序复位操作并调用中间层驱动程序的ProtocolStatus和ProtocolStatusComplete函数通知中间层驱动程序低层微端口正在复位网卡。 SetInformationHandler 该函数接收OID_XXX请求,这个请求来自于高层驱动程序(用NdisRequestSetInformation请求类型作参数,调用NdisRequest)。 SendHandler NDIS调用该函数向低层网卡(或设备)驱动程序发送单个数据包。如果中间层驱动程序不支持MiniportSendPackets函数,那么MiniportSend函数(或MiniportWanSend函数)是必须提供的。除非中间层驱动程序总是基于那些每次只发送单一数据包或将自身绑定到低层WAN NIC的驱动程序,否则MiniportSendPackets函数应该总是以SendPacketsHander方式提供,而不是以该SendHander处理程序方式提供,关于这方面的更多讨论请参阅2.9节。 SendPacketsHander 该函数接收用于指定网上传输数据包的包描述符指针数组。除非中间层驱动程序绑定到低层WAN NIC驱动程序上并提供了MiniportWanSend函数,否则驱动程序应提供对MiniportSendPackets而不是MiniportSend函数支持。换句话说,不管中间层驱动程序是基于每次只能传送单个数据包的网卡驱动程序;还是基于每次可以传送多个数据包的网卡驱动程序,也不管中间层驱动程序是基于每次只能传送单个数据包的协议驱动程序;还是基于每次可以传送多个数据包的协议驱动程序,MiniportSendPackets函数都能实现最好的性能,关于这方面的更多讨论可参阅2.9节。 TransferDataHandler 该函数用于传输在前视缓冲区中没有指示的接收数据包的剩余部分,该前视缓冲区由中间层驱动程序传递给NdisMXxxIndicateReceive函数。这个被指示的数据包可以是中间层驱动程序的ProtocolReceive函数或者是ProtocolReceivePackets处理程序接收的转换数据包。如果中间层驱动程序通过调用(除NdisMWanIndicateReceive之外)NdisMXxxIndicateReceive函数向上层驱动程序指示接收数据包,那么该处理程序是必须提供的。如果中间层驱动程序总是通过调用NdisMIndicateReceivePacket向上层驱动程序指示接收数据包,则不必要提供MiniportTransferData函数。 ReturnPacketHandler 该函数接收返回包描述符(该包描述符先前通过NdisMIndicateReceivePacket调用向高层指示),从而释放指示给高层驱动程序的资源的控制权。在高层驱动程序处理完所有指示之后,中间层驱动程序分配的描述符及所描述的资源将返回给MiniportReturnPacket函数。当然,如果中间层驱动程序总是通过调用介质相关的NdisMXxxIndicateReceive函数向上层指示数据包,或者在调用NdisMIndicateReceivePacket之前总是将OOB数据块(与每一个描述符相关的)状态设置为NDIS_STATUS_RESOUCES,则不必提供MiniportReturnPacket函数。 CheckForHangHandler 该函数以NDIS规定的时间间隔调用,或者以中间层驱动程序规定的时间间隔运行,二者只居其一。如果提供了该处理程序,那么MiniportCheckForHang函数每两秒钟被调用一次(或者按驱动程序要求的间隔调用)。关于MiniportCheckForHang函数的更多信息可参见在线DDK的“Network Drivers Reference”或者该手册的第二部分。通常情况下,由于驱动程序无法确定低层网卡是否悬挂,NDIS中间层驱动程序并不提供对MiniportCheckForHang函数的支持。如果驱动程序基于状态不能到达NDIS的非NDIS驱动程序,中间层驱动程序可能会提供对该处理程序的支持。 由于驱动程序并不管理中断设备,不为使用中的IRQL分配缓冲区,或者因为NDIS并不调用MiniportReconfigure函数(在ReconfigureHandler情况下),因此中间层驱动程序不会提供以下的几个微端口处理程序函数。 ​ DisableInterruptHandler ​ EnableInterruptHandler ​ HandleInterruptHandler ​ ISRHandler ​ AllocateCompleteHandler ​ ReconfigureHandler 2.3.1.2​ 注册中间层驱动程序的协议 中间层驱动程序通过调用NdisRegisterProtocol向NDIS注册ProtocolXxx函数。 NdisRegisterProtocol以如下方式进行声明: VOID NdisRegisterProtocol( OUT PNDIS_STATUS Status, OUT PNDIS_HANDLE NdisProtocolHandler, IN NDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics, IN UINT CharacteristicsLength ); 在调用NdisRegisterProtocol函数之前,中间层驱动程序必须完成以下操作: 1.​ 零初始化一个NDIS_PROTOCOL_CHARACTERISTICS类型的结构。中间层驱动程序能够使用4.0或者5.0版的ProtocolCharacteristics结构。协议驱动程序必须支持即插即用功能,因此NDIS不再支持3.0版的协议驱动程序。 2.​ 保存所有驱动程序支持的强制性的和非强制的ProtocolXxx函数的地址; 该调用的返回句柄NdisProtocolHandler对中间层驱动程序是不透明的,中间层驱动程序必须保存该句柄,并在将来NDIS中间层驱动程序的协议部分的函数调用中作为输入参数传递,例如,打开低层适配器的函数调用。 2.3.1.2.1​ 注册下边界面向无连接的中间层驱动程序的ProtocolXxx函数 下边界面向无连接中间层驱动程序能够导出的(包括可选的和必须的)协议处理程序函数如下所列: BindAdapterHandler 这是一个必须提供的函数。NDIS调用该函数请求中间层驱动程序绑定到低层NIC或虚拟NIC上,NIC名作为该处理程序的一个参数传递。关于动态绑定的更多的信息参见2.4节. UnbindAdapterHandler 这是一个必须提供的函数。NDIS调用ProtocolUnbindAdapter释放对低层NIC或虚拟NIC的绑定,网卡名作为该处理程序的一个参数传递。当绑定成功关闭时,ProtocolUnbindAdapter将调用NdisCloseAdapter函数并释放相关资源。 OpenAdapterCompleteHandler 这是一个必须提供的函数。如果中间层驱动程序对NdisOpenAdapter的调用返回NDIS_STATUS_PENDING,则接着调用ProtocolOpenAdapterComplete来完成绑定。 CloseAdapterCompleteHandler 这是一个必须提供的函数。如果中间层驱动程序对NdisCloseAdapter的调用返回NDIS_STATUS_PENDING,则接着调用ProtocolCloseAdapterComplete来完成绑定释放。 ReceiveHandler 这是一个必须提供的函数。ProtocolReceive函数以指向包含网络接收数据的前视缓冲区的指针为参数被调用执行。如果该缓冲区包含的不是完整的网络数据包,ProtocolReceive以数据包描述符作为参数,调用NdisTransferData接收该数据包的剩余部分。如果低层驱动程序调用NdisMIndicateReceivePacket指示接收数据包,那么传给ProtocolReceive函数的前视缓冲区将总是完整的网络数据包。 ReceivePacketHandler 这是一个可选函数。如果中间层驱动程序所基于的NIC驱动程序指示的是数据包描述符指针数组,或者调用NdisMIndicateReceivePacket函数指示接收带外数据,那么驱动程序应提供ProtocolReceivePacket函数。如果开发者不能确定中间层驱动程序的执行环境,也应提供函数,因为在能够产生多包指示的低层NIC驱动程序上,中间层驱动程序将获得更好的性能。 ReceiveCompleteHandler 这是一个必须提供的函数。当先前指示给ProtocolReceive 函数的数据包被处理后,将调用ProtocolReceiveComplete函数。 TransferDataCompleteHandler 如果ProtocolReceive要调用NdisTransferData函数,则必须提供该处理程序。如果复制接收数据包剩余部分的NdisTransferData函数调用返回NDIS_STATUS_PENDING,那么当传输操作完成后,将调用ProtocolTransferDataComplete函数。 ResetCompleteHandler 这是一个必须提供的函数。当NdisReset函数(返回NDIS_STATUS_PENDING)调用启动的复位操作完成时,ProtocolResetComplete函数将被调用。通常情况下,中间层驱动程序并不调用NdisReset,但由于上层驱动程序可能会调用该函数,所以中间层驱动程序可能只是向低层NDIS驱动程序转发复位请求而已。 RequestCompleteHandler 这是一个必须提供的函数。当NdisRequest函数(返回NDIS_STATUS_PENDING)调用启动的查询或设置操作完成时,ProtocolRequestComplete函数将被调用。 SendCompleteHandler 这是一个必须提供的函数。对每一个调用NdisSend函数传输的数据包,当其返回NDIS_STATUS_PENDING作为发送状态时,将调用ProtocolSendComplete函数完成发送操作。如果调用NdisSendPackets发送一组数据包,那么对于每一个传送给NdisSendPackets的数据包,ProtocolSendComplete将被调用一次。中间层驱动程序仅仅根据送给ProtocolSendComplete的状态参数就能确定调用NdisSendPackets函数的发送操作的状态。 StatusHandler 这是一个必须提供的函数。NDIS用低层NIC驱动程序发起的状态通知来调用ProtocolStatus函数。 StatusCompleteHandler 这是一个必须提供的函数。NDIS调用ProtocolStatusComplete函数来指示状态改变操作已经完成,该状态先前被指示给ProtocolStatus函数。 PnPEventHandler 这是一个必须提供的函数。NDIS调用ProtocolPnPEvent来指示即插即用事件或电源管理事件。更多信息可参见2.9节。 UnloadHandler 这是一个可选函数。NDIS调用ProtocolUnload函数来响应用户卸载中间层驱动程序的请求。对于每一个绑定的适配器,NDIS在调用ProtocolUnbindAdapter之后,将调用ProtocolUnload函数卸载驱动程序。ProtocolUnload执行驱动程序决定的清除操作。 2.3.1.2.2​ 注册下边界面向连接的中间层驱动程序的ProtocolXxx函数 下边界面向连接的中间层驱动程序必须注册如下的面向无连接的和面向连接的微端口所共有的协议处理程序函数: ​ BindHandler ​ UnbindHandler ​ OpenAdapterCompleteHandler ​ CloseAdapterCompleteHandler ​ ReceiveCompleteHandler ​ ResetCompleteHandler ​ RequestCompleteHandler ​ StatusCompleteHandler ​ PnPEventHandler 这些函数已经在上一小节作了汇总。 下边界面向连接的中间层驱动程序还必须注册如下的面向连接协议函数: CoSendCompleteHandler 这是一个必须提供的函数。对于传给NdisCoSendPackets的每一个数据包都要调用一次ProtocolCoSendComplete函数。中间层驱动程序仅仅根据送给ProtocolCoSendComplete的状态参数就能确定调用NdisCoSendPackets的发送操作的状态。 CoStatusHandler 这是一个必须提供的函数。NDIS用低层NIC驱动程序发起的状态通知来调用ProtocolCoStatus函数。 CoReceivePacketsHandler 这是一个必须提供的函数。当绑定的面向连接NIC驱动程序或者集成微端口呼叫管理器(MCM)通过调用NdisMCoIndicateReceivePackets指示一个指针数组时,NDIS将调用中间层驱动程序的ProtocolCoReceivePacketHandler函数。 CoAfRegisterNotifyHandler 如果中间层驱动程序是一个使用呼叫管理器或MCM驱动程序的呼叫管理服务的面向连接客户,那么就必须注册ProtocolCoAfRegisterNotify函数,该函数用来确定中间层驱动程序能否使用呼叫管理器或MCM(已经通过注册地址族,公布其服务)的服务。 2.4​ 中间层驱动程序的动态绑定 中间层驱动程序必须提供ProtocolBindAdapter和ProtocolUnbindAdapter函数以支持对低层NIC的动态绑定。当NIC可用时,NDIS调用中间层驱动程序(能够绑定到NIC)的ProtocolBindAdapter函数实现动态绑定操作。 VOID ProtocolBindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE BindContext, IN PNDIS_STRING DeviceName, IN PVOID SystemSpecific1, IN PVOID SystemSpecific2 ); BindContext句柄代表绑定请求的NDIS环境,中间层驱动程序必须保存该句柄,并且在中间层驱动程序完成绑定相关操作,并准备接受发送请求时,将该句柄作为NdisCompleteBindAdapter的参数返回NDIS。 绑定时的操作包括为该绑定分配NIC相关的环境区域并进行初始化,接着调用NdisOpenAdapter绑定到DeviceName参数指定的适配器。DeviceName可以是低层NIC驱动程序管理的NIC,也可以是介于被调用的中间层驱动程序和管理适配器的NIC驱动程序之间,由中间层NDIS驱动程序导出的控制传输请求的虚拟NIC。通常情况下,可能仅有一个基于NIC驱动程序的中间层NDIS驱动程序,实现早期的高层协议驱动程序支持的介质格式和低层NIC驱动程序支持的介质格式之间的转换。 注意,中间层驱动程序向NdisOpenAdapter传递的DeviceName必须与先前向ProtocolBindAdapter函数传递的DeviceName(一个Unicode字符串缓冲区指针)相同,驱动程序不能复制该指针并将指针副本传递给NdisOpenAdapter函数。 中间层驱动程序能够在已分配的绑定相关环境区域或者另一个驱动程序可访问位置保存BindContext。如果NdisOpenAdapter返回NDIS_STATUS_PEDDING,则必须保存BindContext值,在这种情况下,中间层驱动程序直到打开适配器的操作完成,并且其ProtocolOpenAdapterComplete函数已调用完成,才能调用NdisCompleteBindAdapter函数完成绑定工作。BindContext必须从某个已知位置获得,并由ProtocolOpenAdapterComplete传递给NdisCompleteBindAdapter函数。 如果中间层驱动程序将适配器相关信息存入注册表,那么SystemSpecific1将指向注册表路径,该值将被传给NdisOpenProtocolConfiguration函数以获取用于读写适配器信息的句柄。 SystemSpecific2预留系统使用。 如果中间层驱动程序要将内入数据包从一种介质格式转化为另一种格式,那么ProtocolBindAdapter能够分配数据包描述符池和每一个绑定所需的缓冲描述符。关于分配和管理数据包的要求可参阅2.5节。另外,如果中间层驱动程序仅仅用Protocol(Co)Receive函数接收内入数据,那么驱动程序应该分配数据包池和缓冲池来复制接收的数据。 2.4.1​ 打开中间层驱动程序下层的适配器 ProtocolBindAdapter函数通过DeviceName参数值打开低层NIC或虚拟网卡,从而建立到低层NIC驱动程序的绑定,它也能够从注册表中读取所要求的附加配置信息。NdisOpenProtocolConfiguration用于获取指向中间层驱动程序存储适配器相关信息的注册表主键句柄。中间层驱动程序通过调用NdisOpenConfigurationKeyByIndex函数或者NdisOpenConfigurationKeyByName函数打开并获取主键(由NdisOpenProtocolConfiguration函数打开)下的子键句柄。然后,中间层驱动程序能够调用NdisRead(Write)Configuration函数读写注册表主键或子键下的相关信息。NdisRead(Write)Configuration函数在在线DDK的“Network Drivers Reference”中有详细的描述。 典型地,ProtocolBindAdapter使用环境区域(代表对DeviceName绑定)存储所有绑定相关信息(与绑定适配器相关联的)。 绑定操作最终由NdisOpenAdapter函数调用来实现,该函数声明如下: VOID NdisOpenAdapter( OUT PNDIS_STATUS Status, OUT PNDIS_STATUS OpenErrorStatus, OUT PNDIS_HANDLE NdisBindingHandle, OUT PUNIT SelectedMediumIndex, IN PNDIS_MEDIUM MediumArray, IN UINT MediumArraySize, IN NDIS_HANDLE NdisProtocolHandle, IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_STRING AdapterName, IN UINT OpenOptions, IN PSTRING AddressingInformation ); 中间层驱动程序在ProtocolBindingContext中传递代表绑定相关环境区域(已经分配并初始化)的句柄。NDIS在未来与绑定相关的调用中,将向中间层驱动程序返回该环境。例如,在对Protocol(Co)Receive或Protocol(Co)Status函数的调用中。相似地,当NdisOpenAdapter 调用返回时,NDIS将向中间层驱动程序传递该NdisProtocolHandle句柄。驱动程序必须保存该句柄,通常保存在绑定相关的环境区域,在以后与该绑定相关的调用中,中间层驱动程序将向NDIS传送该句柄,例如NdisSend或Ndis(Co)SendPackets函数调用。 ProtocolBindAdapter也能够通过MediumArray传递所支持的介质类型。如果NdisOpenAdapter函数调用成功,低层NIC驱动程序将选择一种其所支持的介质类型,并通过SelectedMediumHandle返回其从MediumArray中所选介质的索引。 ProtocolBindAdapter可以通过NdisProtocolHandle传递前面对NdisRegisterProtocol函数成功调用所返回的值。 如果NdisOpenAdapter返回了一个错误,那么中间层驱动程序应该收回为绑定相关环境区域分配的内存空间,并释放为绑定分配的其他所有资源。典型地,ProtocolBindAdapter通过调用NdisWriteErrorLogEntry,用适当的描述信息 记录 混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载 任何失败的绑定操作。 2.4.2​ 微端口(Miniport)初始化 当成功打开低层NIC并准备在虚拟NIC或NIC上接收请求和发送数据之后,ProtocolBindAdapter将对NdisIMIntializeDeviceInstance进行一次或多次调用来请求对一个或多个网卡进行初始化操作。NdisIMIntializeDeviceInstance调用中间层驱动程序的MiniportInitialize函数执行指定网卡的初始化。当MiniportInitialize函数返回后,上层NDIS驱动程序就能够进行对中间层驱动程序的虚拟NIC(s)的绑定操作了。 MiniportInitialize函数必须分配和初始化虚拟NIC相关的环境区域。作为初始化操作的一部分,MiniportInitialize必须用相应的环境句柄调用NdisMSetAttributeEx函数,NDIS将在以后对MiniportXxx函数调用中传递该环境句柄。MiniportInitialize也必须设置AttributeFlags参数(将被传递给NdisMSetAttributeEx函数)中的NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER标记。中间层驱动程序通过设置NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER标记来标识NDIS驱动程序类型。 另外,如果当中间层驱动程序队列中的发送和请求操作超时时,不想让NDIS调用MiniportCheckForHang(或MiniportReset)函数,那么MiniportInitialize必须对AttributeFlags参数(将被传递给NdisMSetAttributeEx函数)中的NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT和NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT标记进行设置。通过设置超时标记来通知NDIS将由中间层驱动程序负责处理虚拟NIC超时操作。因为中间层驱动程序并不操纵低层NIC,因此它无法控制到底花了多长时间完成未决发送和请求操作,驱动程序通常既不提供MiniportCheckForHang函数也不处理虚拟NIC超时。 然而,如果中间层驱动程序已经注册了CheckForHangHandler句柄的入口点,并且没有请求NDIS忽略数据包和请求超时,也没有改变超事间隔,那么,在默认情况下,将每隔两秒对MiniportCheckForHang函数进行一次调用。如果MiniportCheckForHang函数返回TRUE,驱动程序将调用MiniportReset函数。如果驱动程序支持MiniportCheckForHang函数,那么可以通过调用NdisMSetAttributeEx函数来明确指定一个不同的TimeInSeconds值,改变默认的两秒调用间隔设置。 中间层驱动程序必须像一个非串行驱动程序那样进行操作,并且通过设置将要传递给NdisMSetAttributeEx函数的AttributeFlags参数中的NDIS_ATTRIBUTE_DESERIALIZE标记来进行注册。非串行驱动程序对MiniportXxx函数的操作进行串行化,并且对所有引入的发送数据包在内部进行排队,而不是依靠NDIS来保存发送队列。 中间层驱动程序也必须设置AttributeFlags参数(将被传给NdisMSetAttributeEx函数)中的NDIS_ATTRIBUTE_NO_HALT_SUSPEND标记,防止NDIS在低层微端口过渡到低功耗状态之前中断驱动程序。 中间层驱动程序要确保所保持的状态信息是完全初始化过的。如果中间层驱动程序请求发送相关的资源(例如MiniportSend或MiniportSendPackets将要向相邻低层发送的数据包的包描述符),那么如果在调用NdisIMInitializeDeviceInstance之前,ProtocolBindAdapter还没有分配数据包池,则分配数据包池。 2.4.3​ 中间层驱动程序查询和设置操作 当成功绑定到低层NIC并完成虚拟NIC(s)的初始化操作之后,中间层驱动程序就可以查询低层NIC驱动程序的操作特性,设置其内部状态,也可以协商一些参数(如为低层NIC驱动程序预留的缓冲区大小等)。下边界面向无连接的中间层驱动程序通过调用NdisRequest实现该功能,下边界面向连接的中间层驱动程序则通过调用Ndis(Co)Request函数实现该功能。 中间层驱动程序也能够接收来自协议驱动程序的MiniportQueryInformation和MiniportSetInformation函数的查询和设置请求,它要么响应这些请求要么将这些请求传给低层驱动程序。 在在线DDK的“Network Drivers Reference”中包含了中间层驱动程序开发者所关心的全部通用的、面向连接的、非介质相关的OID,以及介质相关的OID的详细信息。接下来将讨论几个标准且常用的通用分类OID、面向连接OID以及一些介质相关OID。 2.4.3.1​ 发布设置和查询请求 典型地,下边界面向无连接的中间层驱动程序通过发布OID_GEN_MAXIMUM_FRAME_SIZE请求,查询低层NIC驱动程序所支持的帧最大长度,该请求返回值不包括帧头部分的长度。 下边界面向无连接的中间层驱动程序能够用OID_GEN_MAXIMUM_TOTAL_SIZE请求,查询绑定从而确定低层NIC驱动程序所管理的NIC所能接纳的最大数据包,中间层驱动程序必须对发送数
本文档为【NDIS_中间层驱动程序(IMD)开发人员指南】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_327340
暂无简介~
格式:doc
大小:521KB
软件:Word
页数:59
分类:互联网
上传时间:2011-10-27
浏览量:49