来将自身转入等侯状态。当一个驱动程序线程等待一个事件时,它指定了最大等待时间即等 待事件的时间。当调用 NdisSetevent使时间得到信号量,或最大等待时间段结束时,它们两 个无论是谁先发生时都将结束线程等待状态 典型的,事件是通过相互协调的线程调用 Ndis Setevent来设置的。事件被创建时是没有 信号量的,但为了指示等待线程,它必须要设置信号量,事件将一直处于保持有信号状态, 直到 Ndi Resetevent调用后为止 3.5包结构 通过一个协议驱动程序可以分配NDS包、填充数据,并且将它传递到下层的NDS驱 动程序,以便将数据发送到网络上。一些最底层的NC驱动程序分配包用来保存接收到的 数据,并将包传递到对应的高层驱动程序。有时,一个协议驱动程序分配一个包,并且通过 个请求将它传给NIC驱动程序,以使NC驱动程序将接收到的数据拷贝到提供的包中。 NDS提供函数用来分配和操纵构成包的子结构。 物理内存 缓存 虚拟内存 缓存描述符 虚拟页 物理页 Start virtualAddress 虚拟页 包描述符 ByteOffs 虚拟页 物理页 physicallPage Co Mext p 物理页 ToralLenth First Buffer: P 缓存描述符: 虚拟页 物理页 Start Address 虚拟页 ByteOffs Byte Count 物理页 t P 个包描述符包含一个为微端口NC和协议驱动程序提供的私有区域,一系列与包 有关的、由相互合作的微端口协议驱动程序定义含义的标志量,包含包的物理页的长度,包 的总长,和一个指向第一个缓存描述符的指针,而这个描述符映射了包中的第一个缓存。 组缓存描述符,一个缓存描述符描述了每个缓存虚地址的起始位置,缓存区在页中
- 26- 来将自身转入等侯状态。当一个驱动程序线程等待一个事件时,它指定了最大等待时间即等 待事件的时间。当调用 NdisSetEvent 使时间得到信号量,或最大等待时间段结束时,它们两 个无论是谁先发生时都将结束线程等待状态。 典型的,事件是通过相互协调的线程调用 NdisSetEvent 来设置的。事件被创建时是没有 信号量的,但为了指示等待线程,它必须要设置信号量,事件将一直处于保持有信号状态, 直到 NdiResetEvent 调用后为止。 3.5 包结构 通过一个协议驱动程序可以分配 NDIS 包、填充数据,并且将它传递到下层的 NDIS 驱 动程序,以便将数据发送到网络上。一些最底层的 NIC 驱动程序分配包用来保存接收到的 数据,并将包传递到对应的高层驱动程序。有时,一个协议驱动程序分配一个包,并且通过 一个请求将它传给 NIC 驱动程序,以使 NIC 驱动程序将接收到的数据拷贝到提供的包中。 NDIS 提供函数用来分配和操纵构成包的子结构。 一个包的组成如下: ·一个包描述符包含一个为微端口 NIC 和协议驱动程序提供的私有区域,一系列与包 有关的、由相互合作的微端口协议驱动程序定义含义的标志量,包含包的物理页的长度,包 的总长,和一个指向第一个缓存描述符的指针,而这个描述符映射了包中的第一个缓存。 ·一组缓存描述符,一个缓存描述符描述了每个缓存虚地址的起始位置,缓存区在页中 包描述符 Flags : physicallPageCo unt: ToralLenth : FirstBuffer:P … 缓存描述符: StartVirtualAddress :P ByteOffset ByteCount PhysicalPage [ ] Mext P.... 缓存 缓存描述符: StartVirtualAddress :P ByteOffset ByteCount PhysicalPage [ ] Mext P.... 虚拟内存 虚拟页 虚拟页 虚拟页 虚拟页 虚拟页 物理内存 物理页 物理页 物理页 物理页 物理页
的偏移量(字节,通过虚地址给出),缓存中字节的总数和指向下一个缓存描述符的指针(如 果有的话)。 ·虚拟范围,可以多于一页,它组成了由缓存描述符所描述的缓存。这些虚拟页映射到 物理内存。 个总线管理NC驱动程序为接收包分配共享内存,或协议驱动程序为发送包分配内 存时,必须保证用来存放接收或发出包的缓存与 cache对齐,对于微端口在发送包以前刷新 缓存确保一致性和在指示上层数据到来前刷新接收缓存,这很重要。 3.6使用共享内存 用作总线管理DMA设备的微端口驱动程序必须为NC和NC驱动程序分配共享内存。 当在一个驱动程序和它的NC之间共享 cache时,特别的预防是必须的。在某种结构下,必 须采取特别步骤来保证内存一致,因为NC可以直接访问共享的物理内存,而NC驱动程 序却要通过 cache访问内存。这就引起驱动程序和NC访问内存的不同,即使它们看起来在 同一位置 使用无 cache共享可以避免许多与 cache共享相关的问题。但是不被 cache的内存是 个很稀少的系统资源,并且对这种内存的分配也有很多限制。当必须用写一个小的数据到物 理内存时,没有 cache的数据将不会很快地写到物理内存中,并且不使用 cache不是推荐的 也是不可能的。例如,NC驱动程序反复读数据应当使用 cache来提高效率,或者,另一个 例子,当要求NC驱动程序将接收到的数据包传给许多不同的协议驱动程序时,极力推荐 在这些情况下使用 cache。NC驱动程序也应当使用 cache,来通过协议驱动程序传递任何数 据包。 NdisMAllocate Shared Memory可由总线管理NC驱动程序调用来为网络适配器和NIC 驱动程序分配永久共享内存。这个函数返回了共享内存的虚地址和物理地址,这些地址是有 效的,直到调用了 NdisMFreeSharedMemory来释放内存为止 当使用共享 cache时,NDS提供了一个必须由NC驱动程序调用的函数来确保NC所 见到的和NC驱动程序所见到的是一致的。在为了发送或接收访问共享内存时,NC驱动 程序必须调用 NdisFlushBuffer和 NdisMUPdate SharedMemory来确保 cache一致性 3.7异步I/0和完成函数 因为在一些网络操作中有继承的因素,许多由NIC驱动程序提供的上层函数和协议驱 动程序提供的下层函数被设计成支持异步操作,而不是用CPU消耗一定时间的循环来等待 个任务的完成或硬件事件的指示,网络驱动程序依赖处理许多异步操作的能力。 通过使用完成函数来支持异步网络LO。以下的例子将说明网络的send操作如何使用 个完成函数,同样的机制也存在一个协议或NC驱动程序的其他操作中 当协议驱动程序调用NDS发送一个包时,NDS调用NC驱动程序的 MiniportSend函 数发送请求,NC驱动程序试图立即完成这个请求并且返回一个恰当的状态值。对于异步操 作,可能返回 NDIS STATUS SUCCESS作为发送成功的标志, NDIS STATUS RESOURCES 和 NDIS STATUS FAILURE表明有某些失败 但是一个发送操作要花费一些时间来完成,此时NC驱动程序(或NDIS)可将包排队并 且等侯NC指示发送操作的结果。NC驱动程序的 MiniportSend函数可以通过返回一个 NDIS STATUS PENDING的状态值来异步处理这个操作,当NC驱动程序完成了发送操作 后,包调用完成函数 NdisMSend Complete在调用中传递指向一个已被发送的包的描述符的
- 27- 的偏移量(字节,通过虚地址给出),缓存中字节的总数和指向下一个缓存描述符的指针(如 果有的话)。 ·虚拟范围,可以多于一页,它组成了由缓存描述符所描述的缓存。这些虚拟页映射到 物理内存。 一个总线管理 NIC 驱动程序为接收包分配共享内存,或协议驱动程序为发送包分配内 存时,必须保证用来存放接收或发出包的缓存与 cache 对齐,对于微端口在发送包以前刷新 缓存确保一致性和在指示上层数据到来前刷新接收缓存,这很重要。 3.6 使用共享内存 用作总线管理 DMA 设备的微端口驱动程序必须为 NIC 和 NIC 驱动程序分配共享内存。 当在一个驱动程序和它的 NIC 之间共享 cache 时,特别的预防是必须的。在某种结构下,必 须采取特别步骤来保证内存一致,因为 NIC 可以直接访问共享的物理内存,而 NIC 驱动程 序却要通过 cache 访问内存。这就引起驱动程序和 NIC 访问内存的不同,即使它们看起来在 同一位置。 使用无 cache 共享可以避免许多与 cache 共享相关的问题。但是不被 cache 的内存是一 个很稀少的系统资源,并且对这种内存的分配也有很多限制。当必须用写一个小的数据到物 理内存时,没有 cache 的数据将不会很快地写到物理内存中,并且不使用 cache 不是推荐的 也是不可能的。例如,NIC 驱动程序反复读数据应当使用 cache 来提高效率,或者,另一个 例子,当要求 NIC 驱动程序将接收到的数据包传给许多不同的协议驱动程序时,极力推荐 在这些情况下使用 cache。NIC 驱动程序也应当使用 cache,来通过协议驱动程序传递任何数 据包。 NdisMAllocateSharedMemory 可由总线管理 NIC 驱动程序调用来为网络适配器和 NIC 驱动程序分配永久共享内存。这个函数返回了共享内存的虚地址和物理地址,这些地址是有 效的,直到调用了 NdisMFreeSharedMemory 来释放内存为止。 当使用共享 cache 时,NDIS 提供了一个必须由 NIC 驱动程序调用的函数来确保 NIC 所 见到的和 NIC 驱动程序所见到的是一致的。在为了发送或接收访问共享内存时,NIC 驱动 程序必须调用 NdisFlushBuffer 和 NdisMUPdateSharedMemory 来确保 cache 一致性。 3.7 异步 I/O 和完成函数 因为在一些网络操作中有继承的因素,许多由 NIC 驱动程序提供的上层函数和协议驱 动程序提供的下层函数被设计成支持异步操作,而不是用 CPU 消耗一定时间的循环来等待 一个任务的完成或硬件事件的指示,网络驱动程序依赖处理许多异步操作的能力。 通过使用完成函数来支持异步网络 I/O。以下的例子将说明网络的 send 操作如何使用一 个完成函数,同样的机制也存在一个协议或 NIC 驱动程序的其他操作中。 当协议驱动程序调用 NDIS 发送一个包时,NDIS 调用 NIC 驱动程序的 MiniportSend 函 数发送请求,NIC 驱动程序试图立即完成这个请求并且返回一个恰当的状态值。对于异步操 作,可能返回 NDIS_STATUS_SUCCESS 作为发送成功的标志,NDIS_STATUS_RESOURCES 和 NDIS_STATUS_FAILURE 表明有某些失败。 但是一个发送操作要花费一些时间来完成,此时 NIC 驱动程序(或 NDIS)可将包排队并 且等侯 NIC 指示发送操作的结果。NIC 驱动程序的 MiniportSend 函数可以通过返回一个 NDIS_STATUS_PENDING 的状态值来异步处理这个操作,当 NIC 驱动程序完成了发送操作 后,包调用完成函数 NdisMSendComplete 在调用中传递指向一个已被发送的包的描述符的
指针。这个信息会传给协议驱动程序,指示完成了操作。 许多需要一定时间来完成的驱动程序操作用完成数来完成支持异步的操作。这种函数有 同一形式的名字 Nidis MXXx Complete。不仅可用于发送和接收函数,完成函数也可用于查询、 配置、重新设置硬件、状态指示、指示收到数据和传送收到数据
- 28- 指针。这个信息会传给协议驱动程序,指示完成了操作。 许多需要一定时间来完成的驱动程序操作用完成数来完成支持异步的操作。这种函数有 同一形式的名字 NidisMXxxComplete。不仅可用于发送和接收函数,完成函数也可用于查询、 配置、重新设置硬件、状态指示、指示收到数据和传送收到数据
第二部分微端口NC驱动程序 NDIS NIC微端口驱动程序 二NC微端口操作和函数概要 三NC微端口驱动程序入口点和初始化 四数据传输 五获取和设置WMI的微端口信息及NIS支持 六微端口的电源管理 七重置,停止和关闭 八广域网微端口NC驱动程序 九任务卸载 十负载平衡和失效替换 十一快速转发路径 十二带WDM低级接口的微端口驱动程序 十三IDA微端口NIC驱动程序
- 29- 第二部分 微端口 NIC 驱动程序 一 NDIS NIC 微端口驱动程序 二 NIC 微端口操作和函数概要 三 NIC 微端口驱动程序入口点和初始化 四 数据传输 五 获取和设置 WMI 的微端口信息及 NDIS 支持 六 微端口的电源管理 七 重置,停止和关闭 八 广域网微端口 NIC 驱动程序 九 任务卸载 十 负载平衡和失效替换 十一 快速转发路径 十二 带 WDM 低级接口的微端口驱动程序 十三 IrDA 微端口 NIC 驱动程序
第一章 NDIS NIC微端口驱动程序 这一章介绍了 Windows2000的网络接口卡(N)微端口,以下是将要讨论的主题 ·1.1NC微端口驱动程序类型 12网络接口卡支持 1.3微端口驱动程序代码的重要特征 14驱动程序例子 1.1NIC微端口驱动程序类型 NDIS支持以下几种类型的网络接口卡(NC)驱动程序: 无连接微端口为无连接网络介质控制NC,例如 Ethernet,FD和 Token Ring 无连接微端口进一步又可分为以下几种子类型: 串行化驱动程序依赖NDS来串行调用 MiniportXxx I函数和管理发送队列。 非串行化驱动程序它通常运行在多处理器系统上来获得更高的操作性能,它串行化 自己的 MiniportXxx函数操作,并且在内部对所有发送包进行排队,而不是依赖NDS来完 成这些功能。这种结果显而易见地提高了效率,例如驱动程序的临界区(一个时间内只可 个线程客访问代码区)保持很小,但是,非串行化微端口必须满足额外的并且是极苛刻的设 计要求,同时还要求有额外的调试和测试时间。 面向连接的微端口为面向连接的网络介质(例如ATM)控制NC。 面向连接的微端口通常是非串行化的。这就是说,它们经常自己串行化自己 MiniportXxx函数操作,并且在内部进行发送包的排队 NDS库继续支持早期的NDS30NC驱动程序。但是,只有NDS40和NDS50微 端口可以使用扩充功能和当前NDS库所支持NC驱动程序的特性。也只有NDIS微端口 NIC驱动程序可以使用为NDS库的将来版本所制定的功能 1.2网络接口卡支持 Windows2000支持以下几种类型的网络接口卡: Ethernet(802.3 Token Ring(802.5) FDDI · Localtalk Raw arcnet( ARCNET封装在 Ethernet) ARCNET878.2 WAN(点对点和WAN卡) ·面向连接的WAN 无线 当NDIS调用一个NC驱动程序的 MiniportInitialize函数时,它传递了一组NDS支持 的介质。如果NC驱动程序仅支持一种介质类型,它选择它所支持的介质。或者,如果NC 驱动程序支持多于一种的介质类型,它选择它所喜欢的那一种并且将它的选择返回给NDS
- 30- 第一章 NDIS NIC 微端口驱动程序 这一章介绍了 Windows 2000 的网络接口卡(NIC)微端口,以下是将要讨论的主题: ·1.1 NIC 微端口驱动程序类型 ·1.2 网络接口卡支持 ·1.3 微端口驱动程序代码的重要特征 ·1.4 驱动程序例子 1.1 NIC 微端口驱动程序类型 NDIS 支持以下几种类型的网络接口卡(NIC)驱动程序: ·无连接微端口 为无连接网络介质控制 NIC,例如 Ethernet,FDDI 和 Token Ring。 无连接微端口进一步又可分为以下几种子类型: ·串行化驱动程序 依赖 NDIS 来串行调用 MiniportXxx 函数和管理发送队列。 ·非串行化驱动程序 它通常运行在多处理器系统上来获得更高的操作性能,它串行化 自己的 MiniportXxx 函数操作,并且在内部对所有发送包进行排队,而不是依赖 NDIS 来完 成这些功能。这种结果显而易见地提高了效率,例如驱动程序的临界区(一个时间内只可一 个线程客访问代码区)保持很小,但是,非串行化微端口必须满足额外的并且是极苛刻的设 计要求,同时还要求有额外的调试和测试时间。 ·面向连接的微端口 为面向连接的网络介质(例如 ATM)控制 NIC。 面向连接的微端口通常是非串行化的。这就是说,它们经常自己串行化自己的 MiniportXxx 函数操作,并且在内部进行发送包的排队。 NDIS 库继续支持早期的 NDIS3.0 NIC 驱动程序。但是,只有 NDIS4.0 和 NDIS5.0 微 端口可以使用扩充功能和当前 NDIS 库所支持 NIC 驱动程序的特性。也只有 NDIS 微端口 NIC 驱动程序可以使用为 NDIS 库的将来版本所制定的功能。 1.2 网络接口卡支持 Windows 2000 支持以下几种类型的网络接口卡: ·Ethernet (802.3) ·Token Ring (802.5) ·FDDI ·LocalTalk ·Raw ARCNET (ARCNET 封装在 Ethernet) ·ARCNET878.2 ·WAN(点对点和 WAN 卡) ·面向连接的 WAN ·无线 ·ATM ·IrDA 当 NDIS 调用一个 NIC 驱动程序的 MiniportInitialize 函数时,它传递了一组 NDIS 支持 的介质。如果 NIC 驱动程序仅支持一种介质类型,它选择它所支持的介质。或者,如果 NIC 驱动程序支持多于一种的介质类型,它选择它所喜欢的那一种并且将它的选择返回给 NDIS