驱动程序范例6篇

驱动程序

驱动程序范文1

2、下拉菜单中选“属性”,

3、属性中选“硬件”,

4、硬件里选“设备管理器”,

5、设备管理器中点开“端口”,

6、端口里右键点“打印机端口”

7、选“属性”

8、属性里选“驱动程序”

9、驱动程序里选“驱动程序详细信息”

10、此时在驱动文件窗口里显示的就是驱动文件所在位置及名称。

驱动程序范文2

关键词:设备驱动程序;应用模块;探究应用;分析总结

1 设备驱动程序应用环节的分析

为了确保操作系统的整体安全性及其稳定性的提升,我们要进行应用程序可移植性的剖析,这就是进行与之对应的设备驱动程序的应用,这是因为受到 Windows操作系统的程序应用限制,这些硬件资源的调动需要操作者运作设备驱动程序。通过对设备驱动程序的应用,可以实现硬件的有效操作,实现应用程序与设备驱动程序之间的良好通信,确保程序控制底层硬件设备应用效率的优化。这需要我们进行相关具体应用模块的分析。

在该模式应用过程中,需要通过对应用程序的应用,进行设备驱动程序与应用程序的协调应用。同时我们也要确保设备驱动程序与应用程序的协调。在上述环节的应用过程中,为了达到我们的应用需要,需要进行相关函数的设置,从而确保设备驱动程序的正常应用,在该模块中,我们可以利用好Win32函数进行有效应用,实现设备驱动程序与应用程序之间的良好协调,提升其通信的质量效率。在应用过程中,我们也要为其创造一个良好的应用条件,确保其不同应用环节的正常效能的发挥。在设备驱动程序进行相关数据采集工作之后,我们需要进行相关应用程序的应用,保证这些数据的积极处理,以满足当下工作的需要,提升其应用效率。

为了更好的进行设备驱动程序应用程序的优化,我们也要进行相关工作模块的协调,积极做好异步过程调用程序、事件应用程序、消息应用程序等的协调,通过对不同应用模式的协调,实现其现实工作模块的正常开展。在异步过程调用模块中,Win32应用程序需要应用到特殊的函数动态模式,进行设备驱动程序的积极加载,从而实现回调函数的积极定义,这需要我们进行回调函数的具体地址的参考,确保设备驱动程序的综合应用效益的提升。在设备驱动程序获得回调函数的相关地址后,在进行全局变量的保存。

为了更好的进行上述工作环节的优化,我们也要运用函数进行应用程序线程句柄的保存。当具备一定的条件时,我们就可以进行设备驱动程序的调用,确保Win32应用程序的有效应用。该函数带需要满足具体的参数需要。通过对参数的设置进行回调函数地址的应用。在第二个参数应用过程中,要确保回调函数信息的良好应用。

鉴于设备驱动程序通知应用程序的重要性,本人结合一些经验,对它进行了总结,归纳出5种方法摘要:异步过程调用、事件方式、消息方式、异步I/O方式和事件方式(WDM)。下面分别说明这几种方式的原理,并给出实现的部分源代码。

为了满足当下工作的开展,进行事件方式的优化是非常必要的,这需要我们通过Win32应用程序的应用,进行事件的句柄的确立。在通过虚拟设备驱动程序的应用,进行该事件句柄的创建。做好上述应用环节中,在利用一些函数进行未公开的动态链接库的加载,确保其动态链接库的句柄的获得,这需要我们利用好函数的相关特点,进行动态链接库位置的选择,从而实现对该事件的句柄的有效转换,确保Win32应用程序的有效应用。假如加载成功,则调用DeviceIoControl()函数将Ring0事件句柄传给VxD;同时,创建一个辅助线程等待信号变成有信号状态,本身则可去干其它的事情。当条件成熟时,VxD置Ring0事件为有信号状态,调用_VWIN32_SetWin

32Event()函数,这马上触发对应的Ring3事件为有信号状态。一旦Ring3事件句柄为有信号状态,Win32应用程序的辅助线程就对这个消息进行相应的处理。

在消息方式运作模式中,我们要进行Win32应用程序的积极调用,从而确保虚拟设备驱动程序的积极加载,提升其加载的效益。在完成该环节中,我们要进行窗体句柄的积极传送,确保窗体的相关消息的发出,在利用好相关的函数进行Win32应用程序消息的发送,确保该函数的应用成功。在利用一些手段进行消息模块的积极定义,以满足现实工作的需要。要在消息循环中使用ON_MESSAGE()来定义消息对应的消息处理函数,以便消息产生时,能够调用消息处理函数。SHELL_PostMessage()函数的第一个参数为Win32窗体句柄,第二个参数为消息ID号,第三、四个参数为发送给消息处理函数的参数,第五、六个参数为回调函数和传给它的参数。Win32应用程序收到消息后,对消息进行处理。

2 关于异步I/O方式及其事件应用模式的分析

在日常工作过程中,为了保证 Win32加载设备驱动应用程序的正常开展,我们需要做好相关函数的调用工作,确保各个参数之间的良好设置,以满足现实工作的需要。进行文件的重叠I/O操作控制,确保设备驱动程序文件的有效应用。在初始态的创建过程中,要进行手动复位模式的应用,进行相关类型数据结构的积极传送,确保该模块中,参数与函数的不同模块的传送。在该设备驱动应用模块中,其会将其设置为挂起状态,在该模块中,如果IRP队列为空,就可以将IRP放到IRP队列中去,从而确保设备驱动程序的正常工作。在Win32应用程序工作中,其与待IRP处理模块并不能完全实现同步化,这就需要确保gia模块的设备驱动程序结构的优化。

在返回值的判定过程中,我们也要进行IRP处理环节的优化,实现IRP工作程序的优化,为了满足该环节工作,要进行主程序与其他应用程序的协调,确保该模块中各个函数的信号状态的保持,进行设备驱动程序的综合利用效率的提升,从而实现IRP程序的有效开展,确保其处理效益的提升。这需要我们进行函数的应用,保证Overlapped事件中信号状态的保持,从而确保Win32应用程序的正常相应,以满足现实工作的开展,确保事件复位的无信号状态的保持,利用一些函数来满足我们的应用需要。函数获取IRP的处理结果。

在事件应用模块中,我们可以利用Win32应用程序进行事件的创建,将事件句柄进行设备驱动程序的传送,确保辅助线程的积极创建。当然,在该模块应用过程中,要进行等待事件的信号状态的保持。这样方便下序设备驱动程序应用过程中的事件句柄的转换,以方便后续程序应用的开展。

3 结束语

Windows操作系统运作环节中,通过对设备驱动程序的应用,可以实现操纵硬件的最底层软件接口模块的优化。从而进行I/O、硬件中断、DMA和内存访问等操作。通过对上述模块的应用,将应用程序和硬件细节屏蔽开来,使软件不依靠于硬件并且可在多个不同的平台之间移植,以满足现实工作条件的需要。

参考文献

[1]韩海力,郭云峰. 用DDK开发win2000/xp下USB设备驱动程序[J].微型电脑应用,2005.

驱动程序范文3

windows nt是一个功能全面的操作系统,具有完全集成式的连网能力,它的网络模型开始于mac子层,网络接口卡(network interface card以后简称网卡或nic)驱动程序驻留在其中。通过相关的网卡把windows nt与网络连接起来,但一直到80年代后期,许多传输协议的实现受限于mac层接口的独特实现,因为mac层定义了协议与网卡之间的转换机制。

1989年,microsoft和3com两公司提出了一个定义mac层与osi模型高层协议驱动程序之间的网络设备接口规范(network device interface specification : ndis),ndis给数据交换提出了一个灵活的环境,它规范了软件接口──称为ndis接口,传输协议可用它与网卡驱动程序进行通信。因此在windows nt环境下开发核心态网卡驱动程序应遵循ndis规范。

对于高速网络fddi(fiber distributed data interface)网卡驱动程序还需要smt(station management)站管理功能的实现,否则将不能作为一个fddi站连入环结构中,只能实现点到点间的数据通信。故有必要将smt软件移植到网卡驱动程序中,这将又导致对miniport nic驱动程序编程框架的破坏,于是有必要形成fddi网卡驱动程序(包含smt)与windows nt操作系统的良好接口──由逻辑网卡的注册和mac层驱动程序的初始化来完成。

所以,本课题旨在深入研究应用microsoft公司的ddk(device driver kit)将smt移植于windows nt的fddi网卡驱动程序过程中如何注册miniport nic驱动程序。即怎样正确注册逻辑网卡和mac驱动程序的初始化。着重讨论与初始化相关的上边缘函数的使用和调用关系以及初始化过程中遇到的各种问题的具体解决。

第一章windows nt环境下fddi网卡驱动程序

总体结构介绍

第一节windows nt网络结构

§1.1.1 windows nt网络体系结构

windows nt的网络体系结构是基于国际标准化(iso)制定的标准模型──开放式系统互连(open system interconnection:osi)参考模型分层建立的,这种方式有利于随时扩展其它功能和服务。

windows nt网络模型开始于mac子层,网卡驱动程序就驻留在其中。它通过相关的网卡把windows nt与网络连接起来,图中的多个网卡表明在一台运行windows nt的计算机上能使用多种网卡。

这一网络体系结构包括两个重要接口──ndis接口与传输驱动

程序接口(tdi)。这两个接口把两个层隔离开来,办法是相邻的部件只允许按单一的标准来写,不允许多重标准。例如一个网卡驱动程序(在ndis接口的下面)就不需要特地按每个传输协议来写它的代码块,恰恰相反,该驱动程序是写给ndis接口的,它通过符合ndis的相应传输协议来请求服务。这些接口包含在windows nt的网络体系结构中,以容纳可移植、可互换的模块。

在两个接口之间,是传输协议。它在网络中起着组织者的作用。一个传输协议规定了数据以何种方式呈递给下一个接收层,以及如何对数据相应地进行打包。它通过ndis把数据传给网卡驱动程序,并通过tdi把数据传给转发程序(redirector)

tdi之上是转发程序,它把本地的网络资源申请转送给网络。

为了能和其他厂商的网络互连,windows nt允许有多个转发程序。对于每一个转发程序windows nt计算机必须也有一个相应的供应者(provider)(由网络厂商提供)。多供应者路由选择程序决定适当的供应者,然后借助于供应者,对应用请求到相应的转发程序做出选择。

§1.1.2 windows nt网络驱动程序

windows nt支持两种类型的网络驱动程序

传输驱动程序

实现数据链路层中的逻辑链路控制子层协议和传输层协议。向 下与ndis接口,向上与tdi接口。

网卡驱动程序

实现对物理层的管理和数据链路层中介质访问控制子层协议,通过ndis向下管理物理网卡,向上与传输驱动程序通信。

§1.1.3 windows nt网卡驱动程序

windows nt环境下的网卡驱动程序也分为两种:

miniport网卡驱动程序:miniport驱动程序只须实现与网络硬件相关的操作(包括发送和接收)。而所有底层网卡驱动程序的通用操作(如同步),一般由ndis接口程序来实现。

full网卡驱动程序:full网卡驱动程序必须实现所有硬件相关和同步、排队等操作。例如full网卡驱动程序为了响应数据接收,需要保持本身的捆绑信息,而miniport就可以由ndis接口库来实现。

在windows nt的早期版本中,full网卡驱动程序要求开发者实现许多底层操作,来处理多处理器的核心问题以及处理器、线程的同步,这样不同的开发者在大量重复着许多相同的工作。

而miniport网卡驱动程序允许开发者仅仅写一些与网络硬件相关的代码即可,而那些通用的函数由ndis接口库来实现,这样开发出来的驱动程序减少了不必要的工作。

第二节miniport驱动程序的结构

ndis接口规范了网卡驱动程序的实现,同时也对tdi驱动程序的实现提出了一定的要求,在nt中,ndis约束下的网卡驱动程序、tdi驱动程序和系统的关系如下图所示:

图2.0 ndis约束下的网卡驱动程序、tdi驱动程序和系统的关系

miniport驱动程序包括驱动程序对象、驱动程序源代码和ndis接口库代码。windows nt ddk提供ndis.h作为miniport驱动程序的主要头文件,定义了miniport驱动程序的入口点、ndis接口库函数和通用数据结构。

上边缘函数的作用是网卡驱动与ndis接口库进行通信,而下边缘函数是tdi协议驱动程序与ndis通信的手段。

§1.2.1 miniport网卡对象

ndis用一个叫做逻辑网卡的软件对象来描述系统中的每块网卡,而逻辑网卡与windows nt设备对象的通信由i/o子系统来管理,描述网卡的设备对象包括相关的网络信息如名字、网络地址和网卡内存基地址等,它还包含与硬件相关的驱动程序状态数据(捆绑数目,捆绑句柄,包过滤数据库等)。ndis分配一个句柄到miniportinitialize这个上边缘函数的一个结构中,然后miniport网卡驱动程序将在以后提供这个句柄来给ndis调用,这个结构一直被ndis保持,并且对miniport驱动程序不透明。

当miniport网卡驱动程序初始化一块网卡时,它创立自己的内部数据结构来描述网卡,记录需要它管理的与设备相关的状态信息。当miniport网卡驱动程序调用ndismsetatttibutes或ndismsetattributesex两ndis库函数时,它传递一个句柄给这数据结构。这样,当调用miniport驱动程序入口点时,它就传递这个句柄来验证驱动程序所对应的网卡的正确性。这个数据结构为miniport网卡驱动程序所拥有并维护。

§1.2.2网络对象标识符

miniport nic驱动程序还需要维护一组对象,这些对象是系统定义的对象标识符(object idetifier:oid)来标识,以描述驱动程序的性能和当前状态信息。为查询这些信息,上层驱动程序调用ndisrequest向ndis接口库指示oid。oid表示了调用所需的信息类型,如miniport驱动程序所支持的lookahead缓冲区大小等。ndis接到上层驱动程序的查询请求,将oid传递给上边缘函数miniportqueryinformation实现对oid的查询,如果上层驱动程序请求改变状态信息则调用miniportsetinformation实现对oid的设置。

§1.2.3 miniport网卡驱动程序代码

典型的miniport nic驱动程序必须有一些函数来通过ndis接口实现上层驱动程序与硬件的通信。这些函数称为上边缘服务函数。

这些上边缘服务函数由驱动程序的开发者根据驱动程序面向的特定低层网络类型和硬件以及相应环境,可以有选择地实现,但必须保证驱动程序最基本的功能,这些基本功能包括初始化、发送、中断处理、重置、参数查询与设置和报文接收。

miniportinitialize:操作系统根据系统配置信息,检测出网卡已安装时,由ndis接口在初始化时调用,主要完成低层网络类型确定,对应于物理网卡的逻辑网卡初始化,中断信息注册,网卡与主机通讯方式的确认。i/o端口的申请与注册,内存映像,mib的初始化,物理网卡的验证与初始化等。

miniportreconfigure:支持网卡参数动态变化,和miniportinitilize一样由ndis接口以初始化级别调度执行(不能屏蔽中断,必须由驱动程序承认并清除在此期间产生的中断),支持即插即用和软配置的网卡在动态改变参数时,必须提供此函数。

miniportqueryinformation:查询网卡的状态以及网卡驱动程序的操作或统计参数,如是否支持组通讯、网卡的物理速率是否支持回环、是否支持直接拷贝等,这些参数以oid方式统一管理。

miniportsetinformation:ndis接口或协议驱动程序通过调用此接口改变驱动程序维护的oid库,一些操作参数的改变也将同时改变驱动程序状态,例如组地址的设置。

miniportreset:包括网卡硬件重置和驱动程序软件重置,软件重置包括驱动程序状态重置,以及一些相关的参数重置,还需考虑有些参数的恢复,重置时不必完成所有正在活跃的外部请求,但必须释放已占用的外部资源。

miniporthalt:挂起网卡并释放该网卡驱动程序占用的所有资源,在此期间不屏蔽中断。

miniportisr:高优先级的中断处理程序,进行的工作包括初始中断处理类型,决定是否进行中断转交,对卡上中断进行处理 等,该服务类型只在以下情况被调用:

ndis接口调用miniportinitialize和miniporthalt两函数时。

.中断处理类型设为每此中断处理过程都调用时。

为使系统能及时响应所有硬件中断,高优先级的硬件中断处理程序应尽可能的减少运行时间,防止长时间的屏蔽低优先级中断,避免造程中断丢失。

miniporthandleinterrupt:由中断延时处理程序在中断延时处理时进行调用。ndis排队所有的延时处理,该服务主要处理发送完成、报文接收、描述符用尽、溢出、网卡异常等中断。

miniportsend:ndis收到上层发送请求时经过若干协议处理再向下调用此服务过程,发送的packet已含有llc和mac头,该服务过程进行边界对齐、packet约束重整、描述符映射和报文发送、以及发送资源和packet缓冲队列管理。

miniporttransferdata:多个已和网卡捆绑的协议驱动程序在接收到报文到达指示后,向网卡驱动程序发出传送请求以拷贝各自所需的报文数据部分,网卡驱动程序根据各协议驱动程序对单个packet是否进行多次拷贝,以决定是否暂存只允许单次拷贝的packet等。

miniportcheckhandle:ndis每秒调用此服务函数一次,驱动程序发现网卡异常时报告给ndis由ndis调用miniportreset进行硬件重恢复。

miniportenableintrrupt:中断使能。

miniportdisableinterrupt:中断屏蔽。

另外,每个网卡驱动程序必须有一个初始化入口点,由driver entry函数实现,它和系统相关,由操作系统在装入驱动程序时调用,主要完成初始化ndis wrapper,再由wrapper初始生成驱动程序管理块并完成相应各种初始化工作,登录网卡驱动程序所有上边缘服务入口点,同时写入ndis版本信息。

§1.2.4 ndis接口库

ndis接口库包括在ndis.sys中,它是一个核态函数库,有一套抽象的函数,无论协议驱动程序还是nic驱动程序都连接到这个库中,以实现上下层之间的操作。

第二章fddi网卡驱动程序的加载和运行

第一节 网卡驱动程序的安装

windows nt网卡驱动程序安装的目的是实现网卡相应硬件信息和驱动程序在windows nt注册库中的注册,使windows nt能够正确识别网卡,了解所必需的软硬件信息并能在windows nt启动时加载相应驱动程序。

网卡驱动程序安装时,首先在主群组的控制面板中选择“网络”,然后添加网卡,指定相应信息文件──oemsetup.inf的路径,以完成以下两个必要的操作:

复制驱动程序到相应的系统目录(windows nt根目录\system32\drivers\)中;

在windows nt注册库中存入相应软硬件信息。

下面主要以fddi网卡为例介绍安装驱动程序所必需的工作:

§2.1.1网卡一般硬件参数

对于fddi网卡,必须在编写其oemsetup.inf文件时确定以下硬件参数:

总线类型:pci(5)……括号中的数字5表示pci总线在ndis中的总线类型代码;

厂商代号:0x5588……系统加载时确定网卡的标记,也是编程时确定pci槽号的标识;

cfid: 0x01;

介质类型:光纤(3) ……括号中的数字表示光纤在ndis中的介质类型代码;

是否支持全双工:支持。

对于其它的硬件信息在此inf配置信息文件中可有可无,如若配置,则可在驱动程序的编写时利用这些信息,方便编程,同时有利于其它应用对其参数的确定和使用。

§2.1.2 fddi网卡加载时需在注册库登录表里做的网络配置

网卡驱动程序的安装通常将创建登录表中的四个不同子键:

software registrion键,对应于驱动程序,存在于hkey_local_machine\software\company\ productname\version中。我们的fddi网卡驱动程序所对应的是hkey_local_machine\software\net612\yhfddi\yhfddi1.0;

网卡的软件登录键,存在于hkey_local_machine\software\microsoft\ windows nt\nt3.51\networkcards\yhfddi1;

驱动程序的服务登录键,存在于hkey_local_machine\system\currentcontrolset\services

网卡的服务登录键,存在于hkey_local_machine\system\currentcontrolset\services

对于每一个网络部件,一个名为netrules的特殊子键在邻近的驱动程序或网卡登录子键里创建,netrules标识网络部件为网络整体的一部分。

fddi网卡驱动程序对应的标准软件登录表项将出现在以下路径:

hkey_local_machine\software\net612\yhfddi\yhfddi1.0;

驱动程序对应的标准项的值为:

description =yhfddi/pci adapter controller

install date =……

……

refcount =0x01

servicename =yhfddi

softwaretype =driver

title =yhfddi/pci adapter controller

而且在yhfddi驱动程序相关的netrules子键下,这些值项为:

bindable =yhfddi driver yhfddi adapter non exclusiver

bindform =“yhfddisys”yes no container

class = reg_multi_sz “yhfddi driver basic”

infname =oemnad1.inf

type =yhfddisys ndisdriver yhfddidriver

use =driver

yhfddi网卡在如下路径的networkcards子键里介绍:

hkey_local_machine\software\microsoft\

windows nt\nt3.51\networkcards\yhfddi1;

网卡的标准项包括以下这些值:

description =yhfddi/pci adapter controller

install date =……

manufacturer =net612

productname =yhfddi

servicename =yhfddi01

title =[01]yhfddi/pci adapter controller

§2.1.3编写inf信息配置文件

gui inf描述语言被windows nt用以书写系统所有部件的配置文件,当然也可以用以书写网络系统各部件的配置文件,该配置文件描述了网络部件安装、配置、删除的执行过程。当网络部件进行初始安装或二次安装(通常通过ncpa进行)时,安装程序读取部件对应的配置文件,进行解释执行。gui inf描述语言由节、命令、逻辑操作、变量规范、流程控制以及一套调用dll或外部程序的机制组成,其中,节是配置文件的主体,节可分为install节(类似于函数),shell节(也类似于函数,但可调用insall和shell节),detect节(不包含命令),一个配置文件一般由若干不同类型的节组成。驱动程序的开发者根据需要可以在配置文件中编写相应代码,使得用户和系统之间能进行交互,并且由用户决定一些配置参数。

nt网卡配置文件有其一套规范,驱动程序开发者必须按规范编写配置文件,一般来说,一个配置文件至少应该提供下面三个节:

安装入口点:[identify]shell节。该节主要功能是给出安装部件的类型名,系统通过它识别该部件属于哪一大类(display,mouse,scsi,network等)中的哪一类(网络adapter,driver,transport,service,network和netprovidor),同时,还需要给出映像文件和配置文件所在的源介质及标识。

[returnoption]shell节。系统执行安装identify节后,执行该节。它主要功能是检查所需安装的部件是否支持的硬件平台和语言,并给出网卡名(有些配置文件支持多类网卡,此时必须让用户进行选择,并获得选择结果)。

[installoption]shell节。该节是配置文件得主体,也是上次安装完后再次进行配置、删除、更新的入口点。主要功能是拷贝映像文件和配置文件,生成配置的各种选项,创建该部件在注册库中对应的各种登录子树并更新重写。

第二节 驱动程序的加载过程

§2.2.1 windows nt的启动过程

驱动程序范文4

windows nt是一个功能全面的操作系统,具有完全集成式的连网能力,它的网络模型开始于mac子层,网络接口卡(network interface card以后简称网卡或nic)驱动程序驻留在其中。通过相关的网卡把windows nt与网络连接起来,但一直到80年代后期,许多传输协议的实现受限于mac层接口的独特实现,因为mac层定义了协议与网卡之间的转换机制。

1989年,microsoft和3com两公司提出了一个定义mac层与osi模型高层协议驱动程序之间的网络设备接口规范(network device interface specification : ndis),ndis给数据交换提出了一个灵活的环境,它规范了软件接口──称为ndis接口,传输协议可用它与网卡驱动程序进行通信。因此在windows nt环境下开发核心态网卡驱动程序应遵循ndis规范。

对于高速网络fddi(fiber distributed data interface)网卡驱动程序还需要smt(station management)站管理功能的实现,否则将不能作为一个fddi站连入环结构中,只能实现点到点间的数据通信。故有必要将smt软件移植到网卡驱动程序中,这将又导致对miniport nic驱动程序编程框架的破坏,于是有必要形成fddi网卡驱动程序(包含smt)与windows nt操作系统的良好接口──由逻辑网卡的注册和mac层驱动程序的初始化来完成。

所以,本课题旨在深入研究应用microsoft公司的ddk(device driver kit)将smt移植于windows nt的fddi网卡驱动程序过程中如何注册miniport nic驱动程序。即怎样正确注册逻辑网卡和mac驱动程序的初始化。着重讨论与初始化相关的上边缘函数的使用和调用关系以及初始化过程中遇到的各种问题的具体解决。

第一章windows nt环境下fddi网卡驱动程序

总体结构介绍

第一节windows nt网络结构

§1.1.1 windows nt网络体系结构

windows nt的网络体系结构是基于国际标准化(iso)制定的标准模型──开放式系统互连(open system interconnection:osi)参考模型分层建立的,这种方式有利于随时扩展其它功能和服务。

windows nt网络模型开始于mac子层,网卡驱动程序就驻留在其中。它通过相关的网卡把windows nt与网络连接起来,图中的多个网卡表明在一台运行windows nt的计算机上能使用多种网卡。

这一网络体系结构包括两个重要接口──ndis接口与传输驱动

程序接口(tdi)。这两个接口把两个层隔离开来,办法是相邻的部件只允许按单一的标准来写,不允许多重标准。例如一个网卡驱动程序(在ndis接口的下面)就不需要特地按每个传输协议来写它的代码块,恰恰相反,该驱动程序是写给ndis接口的,它通过符合ndis的相应传输协议来请求服务。这些接口包含在windows nt的网络体系结构中,以容纳可移植、可互换的模块。

在两个接口之间,是传输协议。它在网络中起着组织者的作用。一个传输协议规定了数据以何种方式呈递给下一个接收层,以及如何对数据相应地进行打包。它通过ndis把数据传给网卡驱动程序,并通过tdi把数据传给转发程序(redirector)

tdi之上是转发程序,它把本地的网络资源申请转送给网络。

为了能和其他厂商的网络互连,windows nt允许有多个转发程序。对于每一个转发程序windows nt计算机必须也有一个相应的供应者(provider)(由网络厂商提供)。多供应者路由选择程序决定适当的供应者,然后借助于供应者,对应用请求到相应的转发程序做出选择。

§1.1.2 windows nt网络驱动程序

windows nt支持两种类型的网络驱动程序

传输驱动程序

实现数据链路层中的逻辑链路控制子层协议和传输层协议。向 下与ndis接口,向上与tdi接口。

网卡驱动程序

实现对物理层的管理和数据链路层中介质访问控制子层协议,通过ndis向下管理物理网卡,向上与传输驱动程序通信。

§1.1.3 windows nt网卡驱动程序

windows nt环境下的网卡驱动程序也分为两种:

miniport网卡驱动程序:miniport驱动程序只须实现与网络硬件相关的操作(包括发送和接收)。而所有底层网卡驱动程序的通用操作(如同步),一般由ndis接口程序来实现。

full网卡驱动程序:full网卡驱动程序必须实现所有硬件相关和同步、排队等操作。例如full网卡驱动程序为了响应数据接收,需要保持本身的捆绑信息,而miniport就可以由ndis接口库来实现。

在windows nt的早期版本中,full网卡驱动程序要求开发者实现许多底层操作,来处理多处理器的核心问题以及处理器、线程的同步,这样不同的开发者在大量重复着许多相同的工作。

而miniport网卡驱动程序允许开发者仅仅写一些与网络硬件相关的代码即可,而那些通用的函数由ndis接口库来实现,这样开发出来的驱动程序减少了不必要的工作。

第二节miniport驱动程序的结构

ndis接口规范了网卡驱动程序的实现,同时也对tdi驱动程序的实现提出了一定的要求,在nt中,ndis约束下的网卡驱动程序、tdi驱动程序和系统的关系如下图所示:

图2.0 ndis约束下的网卡驱动程序、tdi驱动程序和系统的关系

miniport驱动程序包括驱动程序对象、驱动程序源代码和ndis接口库代码。windows nt ddk提供ndis.h作为miniport驱动程序的主要头文件,定义了miniport驱动程序的入口点、ndis接口库函数和通用数据结构。

上边缘函数的作用是网卡驱动与ndis接口库进行通信,而下边缘函数是tdi协议驱动程序与ndis通信的手段。

§1.2.1 miniport网卡对象

ndis用一个叫做逻辑网卡的软件对象来描述系统中的每块网卡,而逻辑网卡与windows nt设备对象的通信由i/o子系统来管理,描述网卡的设备对象包括相关的网络信息如名字、网络地址和网卡内存基地址等,它还包含与硬件相关的驱动程序状态数据(捆绑数目,捆绑句柄,包过滤数据库等)。ndis分配一个句柄到miniportinitialize这个上边缘函数的一个结构中,然后miniport网卡驱动程序将在以后提供这个句柄来给ndis调用,这个结构一直被ndis保持,并且对miniport驱动程序不透明。

当miniport网卡驱动程序初始化一块网卡时,它创立自己的内部数据结构来描述网卡,记录需要它管理的与设备相关的状态信息。当miniport网卡驱动程序调用ndismsetatttibutes或ndismsetattributesex两ndis库函数时,它传递一个句柄给这数据结构。这样,当调用miniport驱动程序入口点时,它就传递这个句柄来验证驱动程序所对应的网卡的正确性。这个数据结构为miniport网卡驱动程序所拥有并维护。

§1.2.2网络对象标识符

miniport nic驱动程序还需要维护一组对象,这些对象是系统定义的对象标识符(object idetifier:oid)来标识,以描述驱动程序的性能和当前状态信息。为查询这些信息,上层驱动程序调用ndisrequest向ndis接口库指示oid。oid表示了调用所需的信息类型,如miniport驱动程序所支持的lookahead缓冲区大小等。ndis接到上层驱动程序的查询请求,将oid传递给上边缘函数miniportqueryinformation实现对oid的查询,如果上层驱动程序请求改变状态信息则调用miniportsetinformation实现对oid的设置。

§1.2.3 miniport网卡驱动程序代码

典型的miniport nic驱动程序必须有一些函数来通过ndis接口实现上层驱动程序与硬件的通信。这些函数称为上边缘服务函数。

这些上边缘服务函数由驱动程序的开发者根据驱动程序面向的特定低层网络类型和硬件以及相应环境,可以有选择地实现,但必须保证驱动程序最基本的功能,这些基本功能包括初始化、发送、中断处理、重置、参数查询与设置和报文接收。

miniportinitialize:操作系统根据系统配置信息,检测出网卡已安装时,由ndis接口在初始化时调用,主要完成低层网络类型确定,对应于物理网卡的逻辑网卡初始化,中断信息注册,网卡与主机通讯方式的确认。i/o端口的申请与注册,内存映像,mib的初始化,物理网卡的验证与初始化等。

miniportreconfigure:支持网卡参数动态变化,和miniportinitilize一样由ndis接口以初始化级别调度执行(不能屏蔽中断,必须由驱动程序承认并清除在此期间产生的中断),支持即插即用和软配置的网卡在动态改变参数时,必须提供此函数。

miniportqueryinformation:查询网卡的状态以及网卡驱动程序的操作或统计参数,如是否支持组通讯、网卡的物理速率是否支持回环、是否支持直接拷贝等,这些参数以oid方式统一管理。

miniportsetinformation:ndis接口或协议驱动程序通过调用此接口改变驱动程序维护的oid库,一些操作参数的改变也将同时改变驱动程序状态,例如组地址的设置。

miniportreset:包括网卡硬件重置和驱动程序软件重置,软件重置包括驱动程序状态重置,以及一些相关的参数重置,还需考虑有些参数的恢复,重置时不必完成所有正在活跃的外部请求,但必须释放已占用的外部资源。

miniporthalt:挂起网卡并释放该网卡驱动程序占用的所有资源,在此期间不屏蔽中断。

miniportisr:高优先级的中断处理程序,进行的工作包括初始中断处理类型,决定是否进行中断转交,对卡上中断进行处理 等,该服务类型只在以下情况被调用:

ndis接口调用miniportinitialize和miniporthalt两函数时。

.中断处理类型设为每此中断处理过程都调用时。

为使系统能及时响应所有硬件中断,高优先级的硬件中断处理程序应尽可能的减少运行时间,防止长时间的屏蔽低优先级中断,避免造程中断丢失。

miniporthandleinterrupt:由中断延时处理程序在中断延时处理时进行调用。ndis排队所有的延时处理,该服务主要处理发送完成、报文接收、描述符用尽、溢出、网卡异常等中断。

miniportsend:ndis收到上层发送请求时经过若干协议处理再向下调用此服务过程,发送的packet已含有llc和mac头,该服务过程进行边界对齐、packet约束重整、描述符映射和报文发送、以及发送资源和packet缓冲队列管理。

miniporttransferdata:多个已和网卡捆绑的协议驱动程序在接收到报文到达指示后,向网卡驱动程序发出传送请求以拷贝各自所需的报文数据部分,网卡驱动程序根据各协议驱动程序对单个packet是否进行多次拷贝,以决定是否暂存只允许单次拷贝的packet等。

miniportcheckhandle:ndis每秒调用此服务函数一次,驱动程序发现网卡异常时报告给ndis由ndis调用miniportreset进行硬件重恢复。

miniportenableintrrupt:中断使能。

miniportdisableinterrupt:中断屏蔽。

另外,每个网卡驱动程序必须有一个初始化入口点,由driver entry函数实现,它和系统相关,由操作系统在装入驱动程序时调用,主要完成初始化ndis wrapper,再由wrapper初始生成驱动程序管理块并完成相应各种初始化工作,登录网卡驱动程序所有上边缘服务入口点,同时写入ndis版本信息。

§1.2.4 ndis接口库

ndis接口库包括在ndis.sys中,它是一个核态函数库,有一套抽象的函数,无论协议驱动程序还是nic驱动程序都连接到这个库中,以实现上下层之间的操作。

第二章fddi网卡驱动程序的加载和运行

第一节 网卡驱动程序的安装

windows nt网卡驱动程序安装的目的是实现网卡相应硬件信息和驱动程序在windows nt注册库中的注册,使windows nt能够正确识别网卡,了解所必需的软硬件信息并能在windows nt启动时加载相应驱动程序。

网卡驱动程序安装时,首先在主群组的控制面板中选择“网络”,然后添加网卡,指定相应信息文件──oemsetup.inf的路径,以完成以下两个必要的操作:

复制驱动程序到相应的系统目录(windows nt根目录system32drivers)中;

在windows nt注册库中存入相应软硬件信息。

下面主要以fddi网卡为例介绍安装驱动程序所必需的工作:

§2.1.1网卡一般硬件参数

对于fddi网卡,必须在编写其oemsetup.inf文件时确定以下硬件参数:

总线类型:pci(5)……括号中的数字5表示pci总线在ndis中的总线类型代码;

厂商代号:0x5588……系统加载时确定网卡的标记,也是编程时确定pci槽号的标识;

cfid: 0x01;

介质类型:光纤(3) ……括号中的数字表示光纤在ndis中的介质类型代码;

是否支持全双工:支持。

对于其它的硬件信息在此inf配置信息文件中可有可无,如若配置,则可在驱动程序的编写时利用这些信息,方便编程,同时有利于其它应用对其参数的确定和使用。

§2.1.2 fddi网卡加载时需在注册库登录表里做的网络配置

网卡驱动程序的安装通常将创建登录表中的四个不同子键:

software registrion键,对应于驱动程序,存在于hkey_local_machinesoftwarecompany productnameversion中。我们的fddi网卡驱动程序所对应的是hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;

网卡的软件登录键,存在于hkey_local_machinesoftwaremicrosoft windows ntnt3.51networkcardsyhfddi1;

驱动程序的服务登录键,存在于hkey_local_machinesystemcurrentcontrolsetservices

网卡的服务登录键,存在于hkey_local_machinesystemcurrentcontrolsetservices

对于每一个网络部件,一个名为netrules的特殊子键在邻近的驱动程序或网卡登录子键里创建,netrules标识网络部件为网络整体的一部分。

fddi网卡驱动程序对应的标准软件登录表项将出现在以下路径:

hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;

驱动程序对应的标准项的值为:

description =yhfddi/pci adapter controller

install date =……

……

refcount =0x01

servicename =yhfddi

softwaretype =driver

title =yhfddi/pci adapter controller

而且在yhfddi驱动程序相关的netrules子键下,这些值项为:

bindable =yhfddi driver yhfddi adapter non exclusiver

bindform =“yhfddisys”yes no container

class = reg_multi_sz “yhfddi driver basic”

infname =oemnad1.inf

type =yhfddisys ndisdriver yhfddidriver

use =driver

yhfddi网卡在如下路径的networkcards子键里介绍:

hkey_local_machinesoftwaremicrosoft

windows ntnt3.51networkcardsyhfddi1;

网卡的标准项包括以下这些值:

description =yhfddi/pci adapter controller

install date =……

manufacturer =net612

productname =yhfddi

servicename =yhfddi01

title =[01]yhfddi/pci adapter controller

§2.1.3编写inf信息配置文件

gui inf描述语言被windows nt用以书写系统所有部件的配置文件,当然也可以用以书写网络系统各部件的配置文件,该配置文件描述了网络部件安装、配置、删除的执行过程。当网络部件进行初始安装或二次安装(通常通过ncpa进行)时,安装程序读取部件对应的配置文件,进行解释执行。gui inf描述语言由节、命令、逻辑操作、变量规范、流程控制以及一套调用dll或外部程序的机制组成,其中,节是配置文件的主体,节可分为install节(类似于函数),shell节(也类似于函数,但可调用insall和shell节),detect节(不包含命令),一个配置文件一般由若干不同类型的节组成。驱动程序的开发者根据需要可以在配置文件中编写相应代码,使得用户和系统之间能进行交互,并且由用户决定一些配置参数。

nt网卡配置文件有其一套规范,驱动程序开发者必须按规范编写配置文件,一般来说,一个配置文件至少应该提供下面三个节:

安装入口点:[identify]shell节。该节主要功能是给出安装部件的类型名,系统通过它识别该部件属于哪一大类(display,mouse,scsi,network等)中的哪一类(网络adapter,driver,transport,service,network和netprovidor),同时,还需要给出映像文件和配置文件所在的源介质及标识。

[returnoption]shell节。系统执行安装identify节后,执行该节。它主要功能是检查所需安装的部件是否支持的硬件平台和语言,并给出网卡名(有些配置文件支持多类网卡,此时必须让用户进行选择,并获得选择结果)。

[installoption]shell节。该节是配置文件得主体,也是上次安装完后再次进行配置、删除、更新的入口点。主要功能是拷贝映像文件和配置文件,生成配置的各种选项,创建该部件在注册库中对应的各种登录子树并更新重写。

第二节 驱动程序的加载过程

§2.2.1 windows nt的启动过程

第一阶段:调入装入程序。和硬件平台相关,x86机器首先由rom装入根扇区,再由根扇区装入ntldr;

第二阶段:硬件检测。x86机器调ntdetect程序最大限度地获取各种硬件设备信息,引导hal及基本卷设备驱动程序,以便引导nt内核;

第三阶段:获取注册库中各种控制信息,如用户定义的非页内存大小;第四阶段:初始化注册库 registrymachine下system和hardware并创建currentcontrolset,为装入相关硬件设备驱动程序作准备;

第五阶段:装入基本核心驱动程序;

第六阶段:释放一些已经完成使命的装入初始数据块;

第七阶段:进一步初始化注册库,以便有些依赖于基本核心驱动程序的上层驱动程序能顺利装入;

第八阶段:服务控制器装入应该由该服务控制器装入的各种驱动程序。

§2.2.2 fddi网卡驱动程序的加载过程

在windows nt启动的第五个阶段,将加载核心驱动程序。而对于ndis网卡驱动程序是在ndis接口(ndis.sys)加载后调入运行,向ndis wrapper注册、初始化、查询设置参数等。

windows nt启动时,相应的实体如nt的服务控制器根据注册库中yhfddi驱动程序的配置注册信息,初始化ndis wrapper,并装入相应的驱动程序,生成驱动程序管理块结构,申请内存以保存各种信息,向ndis wrapper注册驱动程序。初始化和注册完毕后,再由服务控制器读取注册库中相应的链接信息。

在ndis wrapper和yhfddi驱动程序初始化和注册成功后,ndis wrapper根据系统相应的注册信息,加入和yhfddi驱动程序所对应的fddi网卡,同时读入网卡的注册信息,并进行网卡注册和网卡初始化。

在以上过程成功后,wrapper将查询和设置驱动程序的各种参数,了解驱动程序对哪些操作支持,决定对上层驱动程序的支持范围。

第三节fddi网卡驱动程序的注册

driverentry函数是windows nt ddk规定的核心驱动程序的入口点,wrapper识别到入口点后,调入驱动程序,在driverentry函数内完成两个基本注册任务:

调用ndisminitializewapper函数向ndis接口报告驱动程序将以miniport类网卡驱动程序注册。ndis建立它需要记录的驱动程序状态信息,同时返回ndiswrapperhandle,驱动程序保存这个句柄,以利后来调用ndisxxxconfiguration和initialization等函数。

填写ndisxx_miniport_characteristics属性结构,主要记录ndis版本号和驱动程序支持的miniportxxx函数的入口点,然后调用ndismregisterminiport函数实现驱动程序的整体注册。

以yhfddi为例所要注册的属性结构的内容大致如下:

ndis_miniport_characteristics yhfddichar;

(ndis_miniport_characteristics这个结构将在第三章介绍)

yhfddichar.majorndisversion=yhfddi_ndis_major_version;

yhfddichar.minorndisversion=yhfddi_ndis_minor_version;

这两个属性决定驱动程序是ndis的哪个版本所支持,我们所用的是ndis3.0

yhfddichar.disableinterrupthandler=yhfddidisableinterrupt;

yhfddichar.enableinterrupthandler=yhfddienableinterrupt;

yhfddichar.isrhandle=yhfddiinterruptservice;

yhfddichar.handleinterrupthandler=yhfddihandleinterrupt;

以上四项属性是中断处理所需的上边缘服务函数的入口点(句柄)。fddi网卡驱动程序需要有smt站管理功能,而smt是以中断处理方式进行的,故这四项属性在fddi网卡驱动程序中是很重要的。

yhfddichar.initializehandler=yhfddiinitialize;

此项注册的是驱动程序的初始化函数句柄。

yhfddichar.queryinformationhandler= yhfddiqueryinformation;

yhfddichar.setinformationhandler=yhfddisetinformation;

这两项注册的是参数查询和设置函数的句柄。

yhfddichar.sendhanler= yhfddisend;

yhfddichar.transferdatahandler= yhfdditransferdata;

主要提供数据发送和接收函数句柄。

yhfddichar.resethandler=yhfddireset;

此项注册网卡软硬件重置函数句柄。

yhfddichar.halthandler= yhfddihalt;

此项注册网卡驱动程序挂起函数句柄。

yhfddichar.checkforhandler=null;

yhfddichar.reconfigurehandler=null;

这两个上边缘服务函数是fddi网卡驱动程序所不提供的,故置为null。

填好这些结构以后,调用以下函数实现驱动程序的注册:

ndismregisterminiport(

yhfddiwrapperhandle,

&yhfddichar,

sizeof(yhfddichar));

其中yhfddiwrapperhandle是在此之前初始化wrapper调用ndisminitializewrapper所得的句柄。

如果调用ndismregisterminiport不能返回ndis_status_success,必须在退出driverentry之前释放已经分配的资源(如yhfddiwrapperhandle等),故调用

ndisterminatewrapper(yhfddiwrapperhandle,null)。

这样驱动程序没能正确注册,亦不能正常运行。

第四节 网卡驱动程序对象查询与设置

如果ndis的管理实体要查询或设置一个特定的网络对象,它必须提供一个32位的oid。oid的结构如下: 图2.3.0 oid结构图

由上可以看到,oid可分为三大类:

所有ndis驱动程序都有的一般对象;

特定介质的对象;

特殊的与具体实现相关的对象(如多目地址表的长度)。

一般的和特定介质的oid被记录在windows nt ddk中,对于这些oid ddk文本指明了相关的对象能否通过miniportqueryinformation查询参数和通过miniportsetinformation设置参数。

oid也可被分为操作特性(如多目地址表长度参数)和统计参数(如广播包接收)。最后oid可分为必须的和可选的两种。

oid的前三个字节表明oid的不同类别,而最后一个字节确定这一类别内特定的信息管理对象。

针对于fddi网卡,被查询的oid的第一个字节为0x03。而ndis所查询的介质相关参数为:

0x03010104 oid_fddi_long_max_list_size

0x03010108 oid_fddi_short_max_list_size

0x03010102 oid_fddi_long_current_addr

0x03010106 oid_fddi_short_current_addr

tcp/ip传输驱动程序所要查询的fddi oid为:

0x03010102 oid_fddi_long_current_addr

0x03010103 oid_fddi_long_multicast_list

0x03010107 oid_fddi_short_multicast_list

通过以上两阶段的查询,ndis和tcp/ip驱动程序就分别了解了网卡驱动程序对其的支持,从而进行相应的捆绑,以便数据传输时正确选择网卡驱动程序。

第五节 开发环境与调试方法

开发环境:

fddi网卡驱动程序的开发环境为nt server 3.51,sdk,ddk for workstation 3.51, vc++4.1,硬件平台为586。

调试平台:

主机为nt server 3.51,windbg32

目标机为nt workstation3.51 (check 944)

调试方法:

利用dbgprint把目标机上关键信息通过串口传到主机进行分析,以得出ndis驱动程序的调度机制和运转状况;

利用assert产生异常断点,由主机对异常进行控制

自定义宏,进行分级控制,以根据不同情况产生不同调试信息

第四章 与smt移植相关的问题讨论

在本yhfddi网卡驱动程序中,smt的移植是极其关键的一部分,主要承担了驱动程序中硬件初始化和中断延迟处理。但由于smt是相对独立的软件,这样就有一个ndis wrapper与smt间参数传递的问题。所以本章主要讨论miniport驱动程序与smt的关系和移植smt过程中初始化的要求、中断处理的要求,ndis wrapper与smt如何传递参数。

(一)miniport fddi网卡驱动程序与smt的关系。

在第一章已经谈及网卡驱动程序主要实现osi参考模型中的物理层和mac层。而对于fddi网络的物理层又可分为介质相关子层和介质无关子层。

对于我们的fddi/pci是基于x.3.19、x3.148、x3.166和x3.229而实现的。

smt在整个iso七层模型中属低两层范畴。下图是iso模型与fddi层次的对应关系,从而可知fddi miniport驱动程序在nt网络结构中的位置。

即在windows nt fddi网卡驱动程序应包含smt,实现fddi拓扑环上的站管理。

而在驱动程序内部smt主要是在miniport驱动程序中的中断延迟处理上边缘服务中实现的,也可以说是将smt嵌入中断延迟处理程序中,实现ndis接口对smt的正确调度。

yh-fddi驱动程序的实现可分为硬件无关部分和硬件相关部分。

移植smt过程中初始化的要求.

这里的初始化主要是指硬件初始化,包括寄存器的初始化和数据结构的初始化,由smt共用的硬件相关例程库中硬件初始化部分来完成. 我们在开发过程序是调用fddi_main(bdd_t*bdd)这个函数来调用smt共用的硬件相关例程库的.可见使用fddi_main(bdd_t*bdd)时,需要传递bdd这个参量,而bdd_t这个数据结构的定义如下:

它包含了各类硬件寄存器的基址,所以要对其进行正确赋值就必须首先在nt的内存中映射一块虚存与网卡内存相对应,也就实现了bdd_t结构的赋值,对fddi_main(bdd_t *bdd)的正确调用.

因此,我们在调用fddi_main前首先将网卡上寄存器内存空间映射到nt的虚存空间上,并将bdd结构正确赋值.以映射bsi_phy_base为例,具体过程如下:

pchar destination;

bdd_t *bdd;

ndis_physical_address physicaladdress;

ulong baseaddress;

ndis_status status;

baseadress =0x0d0000+bsi_phy_base;

ndissetphysicaladdresshigh(physicaladdress,0);

ndissetphysicaladdresslow(physicaladdress,baseaddress);

status=ndismmapiospace(

(pvoid *)&destination,

miniportadapterhandle,

physicaladdress,

bsi_phy_len

);

bdd->bsi_vir_base=(pchar) destination;

adapter-> bdd->bsi_vir_base= bsi_vir_base;

/*对adapter结构中的bdd结构赋值,以便在其它上边缘函数中使用这些虚存基地址*/

中断处理要求.

对于中断处理,在smt中主要调用cspintrhandandler()来实现.我们的fddi网卡驱动程序是miniport方式的,若在isr中做此处理将占用大量系统资源,使系统崩溃,所以我们采用只在isr中进行中断的排队,而在dpc中调用cspintrhandler()来完成中断处理.

在中断处理方面还有一个中断屏蔽和中断使能的问题,这两方面smt并不提供,故我们要正确处理.

具体处理方法见第三章.

ndis wrapper与smt间参数如何传递.

miniport方式的网卡驱动程序中,网卡上有中断时,系统反映给ndiswrapper,再由wrapper调度中断处理上边缘服务实现中断处理,在我们的yhfddi网卡驱动程序的中断具体处理是smt完成的所以在调用cspintrhandler时应将adapter结构传进smt以便在以后应用.

如在处理接收中断时,处理的最后应调用ndisindicatefddireceive,向ndiswrapper指示以接收到一个数据包,而ndisindicaterfddireceive的调用需要adapterminiporthandle作为参数,这就必须一级级从中断延迟处理函数(yhfddi handleinterrupt)中将adapter结构传递下来. 当然,其它方面如发送,也会有类似的问题需要考虑.

总之,对于smt的移植,需要详尽的在程序中做好接口,才能实现与

smt的数据交换.

结束语

ndis规范在网络两层间提供了一个统一界面,ndis对网络本身而言,是一个带有协议功能的标准接口,对实现者而言,它应该是一个环境,这种环境不仅带有协议功能,更重要的是带有和软、硬平台无关的核心功能支持,它不会受软、硬平台的变化严重影响,无疑,它是软件的移植和兼容的可靠保证,ndis把网络的一部分共性抽象出来,并根据具体的操作系统实现系统和平台相关的基础库以保证ndis的标准性和对开发者提供最大的功能支持,这也将加速和规范开发过程,但是,在操作系统之上提供ndis基础库获得标准同时也失去直接作用于操作系统带来的灵活性以及更强的功能支持,同时,ndis处于网络中层和低层之间,低层网络的快速发展和ndis对网络部分共性的抽象必然导致ndis对实现者的滞后,例如ddk3.51提供的ndis开发环境只支持10m以太网、fddi、令牌网(802.5)、localtalk、arcnet等,而对新出现的快速以太网及atm不提供支持,这对我们如何在ndis环境下实现诸如atm的lan emulation,ip over atm、快速以太网带来很大问题。

smt是实现fddi网卡驱动程序的关键,然而由于应用ddk开发miniport驱动程序时要遵循其结构框架,所以要想完整地按其结构移植smt,就必须分解smt适应之,即要求对smt有一个很好的理解。但smt是庞大的给开发带来了一定的困难。

参考文献

【1】《device driver kit用户手册》

【2】《device driver kit核心驱动程序设计》

【3】《device driver kit网络驱动程序设计》

驱动程序范文5

第一节windows  nt网络结构

§1.1.1  windows  nt网络体系结构

windows  nt的网络体系结构是基于国际标准化(iso)制定的标准模型──开放式系统互连(open  system  interconnection:osi)参考模型分层建立的,这种方式有利于随时扩展其它功能和服务。

windows  nt网络模型开始于mac子层,网卡驱动程序就驻留在其中。它通过相关的网卡把windows  nt与网络连接起来,图中的多个网卡表明在一台运行windows  nt的计算机上能使用多种网卡。

这一网络体系结构包括两个重要接口──ndis接口与传输驱动

程序接口(tdi)。这两个接口把两个层隔离开来,办法是相邻的部件只允许按单一的标准来写,不允许多重标准。例如一个网卡驱动程序(在ndis接口的下面)就不需要特地按每个传输协议来写它的代码块,恰恰相反,该驱动程序是写给ndis接口的,它通过符合ndis的相应传输协议来请求服务。这些接口包含在windows  nt的网络体系结构中,以容纳可移植、可互换的模块。

在两个接口之间,是传输协议。它在网络中起着组织者的作用。一个传输协议规定了数据以何种方式呈递给下一个接收层,以及如何对数据相应地进行打包。它通过ndis把数据传给网卡驱动程序,并通过tdi把数据传给转发程序(redirector)

tdi之上是转发程序,它把本地的网络资源申请转送给网络。

为了能和其他厂商的网络互连,windows  nt允许有多个转发程序。对于每一个转发程序windows  nt计算机必须也有一个相应的供应者(provider)(由网络厂商提供)。多供应者路由选择程序决定适当的供应者,然后借助于供应者,对应用请求到相应的转发程序做出选择。

§1.1.2  windows  nt网络驱动程序

windows  nt支持两种类型的网络驱动程序

传输驱动程序  

实现数据链路层中的逻辑链路控制子层协议和传输层协议。向  下与ndis接口,向上与tdi接口。

网卡驱动程序  

实现对物理层的管理和数据链路层中介质访问控制子层协议,通过ndis向下管理物理网卡,向上与传输驱动程序通信。

§1.1.3  windows  nt网卡驱动程序

windows  nt环境下的网卡驱动程序也分为两种:  

miniport网卡驱动程序:miniport驱动程序只须实现与网络硬件相关的操作(包括发送和接收)。而所有底层网卡驱动程序的通用操作(如同步),一般由ndis接口程序来实现。  

full网卡驱动程序:full网卡驱动程序必须实现所有硬件相关和同步、排队等操作。例如full网卡驱动程序为了响应数据接收,需要保持本身的捆绑信息,而miniport就可以由ndis接口库来实现。  

在windows  nt的早期版本中,full网卡驱动程序要求开发者实现许多底层操作,来处理多处理器的核心问题以及处理器、线程的同步,这样不同的开发者在大量重复着许多相同的工作。

而miniport网卡驱动程序允许开发者仅仅写一些与网络硬件相关的代码即可,而那些通用的函数由ndis接口库来实现,这样开发出来的驱动程序减少了不必要的工作。

第二节miniport驱动程序的结构

ndis接口规范了网卡驱动程序的实现,同时也对tdi驱动程序的实现提出了一定的要求,在nt中,ndis约束下的网卡驱动程序、tdi驱动程序和系统的关系如下图所示:

图2.0  ndis约束下的网卡驱动程序、tdi驱动程序和系统的关系

miniport驱动程序包括驱动程序对象、驱动程序源代码和ndis接口库代码。windows  nt  ddk提供ndis.h作为miniport驱动程序的主要头文件,定义了miniport驱动程序的入口点、ndis接口库函数和通用数据结构。

上边缘函数的作用是网卡驱动与ndis接口库进行通信,而下边缘函数是tdi协议驱动程序与ndis通信的手段。

§1.2.1  miniport网卡对象

ndis用一个叫做逻辑网卡的软件对象来描述系统中的每块网卡,而逻辑网卡与windows  nt设备对象的通信由i/o子系统来管理,描述网卡的设备对象包括相关的网络信息如名字、网络地址和网卡内存基地址等,它还包含与硬件相关的驱动程序状态数据(捆绑数目,捆绑句柄,包过滤数据库等)。ndis分配一个句柄到miniportinitialize这个上边缘函数的一个结构中,然后miniport网卡驱动程序将在以后提供这个句柄来给ndis调用,这个结构一直被ndis保持,并且对miniport驱动程序不透明。  

当miniport网卡驱动程序初始化一块网卡时,它创立自己的内部数据结构来描述网卡,记录需要它管理的与设备相关的状态信息。当miniport网卡驱动程序调用ndismsetatttibutes或ndismsetattributesex两ndis库函数时,它传递一个句柄给这数据结构。这样,当调用miniport驱动程序入口点时,它就传递这个句柄来验证驱动程序所对应的网卡的正确性。这个数据结构为miniport网卡驱动程序所拥有并维护。

§1.2.2网络对象标识符

miniport  nic驱动程序还需要维护一组对象,这些对象是系统定义的对象标识符(object  idetifier:oid)来标识,以描述驱动程序的性能和当前状态信息。为查询这些信息,上层驱动程序调用ndisrequest向ndis接口库指示oid。oid表示了调用所需的信息类型,如miniport驱动程序所支持的lookahead缓冲区大小等。ndis接到上层驱动程序的查询请求,将oid传递给上边缘函数miniportqueryinformation实现对oid的查询,如果上层驱动程序请求改变状态信息则调用miniportsetinformation实现对oid的设置。

§1.2.3  miniport网卡驱动程序代码

典型的miniport  nic驱动程序必须有一些函数来通过ndis接口实现上层驱动程序与硬件的通信。这些函数称为上边缘服务函数。

这些上边缘服务函数由驱动程序的开发者根据驱动程序面向的特定低层网络类型和硬件以及相应环境,可以有选择地实现,但必须保证驱动程序最基本的功能,这些基本功能包括初始化、发送、中断处理、重置、参数查询与设置和报文接收。

miniportinitialize:操作系统根据系统配置信息,检测出网卡已安装时,由ndis接口在初始化时调用,主要完成低层网络类型确定,对应于物理网卡的逻辑网卡初始化,中断信息注册,网卡与主机通讯方式的确认。i/o端口的申请与注册,内存映像,mib的初始化,物理网卡的验证与初始化等。

miniportreconfigure:支持网卡参数动态变化,和miniportinitilize一样由ndis接口以初始化级别调度执行(不能屏蔽中断,必须由驱动程序承认并清除在此期间产生的中断),支持即插即用和软配置的网卡在动态改变参数时,必须提供此函数。  

miniportqueryinformation:查询网卡的状态以及网卡驱动程序的操作或统计参数,如是否支持组通讯、网卡的物理速率是否支持回环、是否支持直接拷贝等,这些参数以oid方式统一管理。

miniportsetinformation:ndis接口或协议驱动程序通过调用此接口改变驱动程序维护的oid库,一些操作参数的改变也将同时改变驱动程序状态,例如组地址的设置。

miniportreset:包括网卡硬件重置和驱动程序软件重置,软件重置包括驱动程序状态重置,以及一些相关的参数重置,还需考虑有些参数的恢复,重置时不必完成所有正在活跃的外部请求,但必须释放已占用的外部资源。

miniporthalt:挂起网卡并释放该网卡驱动程序占用的所有资源,在此期间不屏蔽中断。

miniportisr:高优先级的中断处理程序,进行的工作包括初始中断处理类型,决定是否进行中断转交,对卡上中断进行处理  等,该服务类型只在以下情况被调用:  

ndis接口调用miniportinitialize和miniporthalt两函数时。  

.中断处理类型设为每此中断处理过程都调用时。

为使系统能及时响应所有硬件中断,高优先级的硬件中断处理程序应尽可能的减少运行时间,防止长时间的屏蔽低优先级中断,避免造程中断丢失。

miniporthandleinterrupt:由中断延时处理程序在中断延时处理时进行调用。ndis排队所有的延时处理,该服务主要处理发送完成、报文接收、描述符用尽、溢出、网卡异常等中断。

miniportsend:ndis收到上层发送请求时经过若干协议处理再向下调用此服务过程,发送的packet已含有llc和mac头,该服务过程进行边界对齐、packet约束重整、描述符映射和报文发送、以及发送资源和packet缓冲队列管理。

miniporttransferdata:多个已和网卡捆绑的协议驱动程序在接收到报文到达指示后,向网卡驱动程序发出传送请求以拷贝各自所需的报文数据部分,网卡驱动程序根据各协议驱动程序对单个packet是否进行多次拷贝,以决定是否暂存只允许单次拷贝的packet等。

miniportcheckhandle:ndis每秒调用此服务函数一次,驱动程序发现网卡异常时报告给ndis由ndis调用miniportreset进行硬件重恢复。

miniportenableintrrupt:中断使能。

miniportdisableinterrupt:中断屏蔽。

另外,每个网卡驱动程序必须有一个初始化入口点,由driver  entry函数实现,它和系统相关,由操作系统在装入驱动程序时调用,主要完成初始化ndis  wrapper,再由wrapper初始生成驱动程序管理块并完成相应各种初始化工作,登录网卡驱动程序所有上边缘服务入口点,同时写入ndis版本信息。

§1.2.4  ndis接口库

ndis接口库包括在ndis.sys中,它是一个核态函数库,有一套抽象的函数,无论协议驱动程序还是nic驱动程序都连接到这个库中,以实现上下层之间的操作。

第二章fddi网卡驱动程序的加载和运行

第一节  网卡驱动程序的安装

windows  nt网卡驱动程序安装的目的是实现网卡相应硬件信息和驱动程序在windows  nt注册库中的注册,使windows  nt能够正确识别网卡,了解所必需的软硬件信息并能在windows  nt启动时加载相应驱动程序。

网卡驱动程序安装时,首先在主群组的控制面板中选择“网络”,然后添加网卡,指定相应信息文件──oemsetup.inf的路径,以完成以下两个必要的操作:  

复制驱动程序到相应的系统目录(windows  nt根目录\system32\drivers\)中;  

在windows  nt注册库中存入相应软硬件信息。  

下面主要以fddi网卡为例介绍安装驱动程序所必需的工作:

§2.1.1网卡一般硬件参数

对于fddi网卡,必须在编写其oemsetup.inf文件时确定以下硬件参数:  

总线类型:pci(5)……括号中的数字5表示pci总线在ndis中的总线类型代码;  

厂商代号:0x5588……系统加载时确定网卡的标记,也是编程时确定pci槽号的标识;  

cfid:  0x01;  

介质类型:光纤(3)  ……括号中的数字表示光纤在ndis中的介质类型代码;  

是否支持全双工:支持。  

对于其它的硬件信息在此inf配置信息文件中可有可无,如若配置,则可在驱动程序的编写时利用这些信息,方便编程,同时有利于其它应用对其参数的确定和使用。

§2.1.2  fddi网卡加载时需在注册库登录表里做的网络配置

网卡驱动程序的安装通常将创建登录表中的四个不同子键:

software  registrion键,对应于驱动程序,存在于hkey_local_machine\software\company\  productname\version中。我们的fddi网卡驱动程序所对应的是hkey_local_machine\software\net612\yhfddi\yhfddi1.0;  

网卡的软件登录键,存在于hkey_local_machine\software\microsoft\  windows  nt\nt3.51\networkcards\yhfddi1;  

驱动程序的服务登录键,存在于hkey_local_machine\system\currentcontrolset\services  

网卡的服务登录键,存在于hkey_local_machine\system\currentcontrolset\services  

对于每一个网络部件,一个名为netrules的特殊子键在邻近的驱动程序或网卡登录子键里创建,netrules标识网络部件为网络整体的一部分。

fddi网卡驱动程序对应的标准软件登录表项将出现在以下路径:

hkey_local_machine\software\net612\yhfddi\yhfddi1.0;

驱动程序对应的标准项的值为:

description  =yhfddi/pci  adapter  controller

install  date  =……

……

refcount  =0x01

servicename  =yhfddi

softwaretype  =driver

title  =yhfddi/pci  adapter  controller

而且在yhfddi驱动程序相关的netrules子键下,这些值项为:

bindable  =yhfddi  driver  yhfddi  adapter  non  exclusiver

bindform  =“yhfddisys”yes  no  container

class  =  reg_multi_sz  “yhfddi  driver  basic”

infname  =oemnad1.inf

type  =yhfddisys  ndisdriver  yhfddidriver

use  =driver

yhfddi网卡在如下路径的networkcards子键里介绍:

hkey_local_machine\software\microsoft\

windows  nt\nt3.51\networkcards\yhfddi1;

网卡的标准项包括以下这些值:

description  =yhfddi/pci  adapter  controller

install  date  =……

manufacturer  =net612

productname  =yhfddi

servicename  =yhfddi01

title  =[01]yhfddi/pci  adapter  controller

§2.1.3编写inf信息配置文件

gui  inf描述语言被windows  nt用以书写系统所有部件的配置文件,当然也可以用以书写网络系统各部件的配置文件,该配置文件描述了网络部件安装、配置、删除的执行过程。当网络部件进行初始安装或二次安装(通常通过ncpa进行)时,安装程序读取部件对应的配置文件,进行解释执行。gui  inf描述语言由节、命令、逻辑操作、变量规范、流程控制以及一套调用dll或外部程序的机制组成,其中,节是配置文件的主体,节可分为install节(类似于函数),shell节(也类似于函数,但可调用insall和shell节),detect节(不包含命令),一个配置文件一般由若干不同类型的节组成。驱动程序的开发者根据需要可以在配置文件中编写相应代码,使得用户和系统之间能进行交互,并且由用户决定一些配置参数。  

nt网卡配置文件有其一套规范,驱动程序开发者必须按规范编写配置文件,一般来说,一个配置文件至少应该提供下面三个节:

安装入口点:[identify]shell节。该节主要功能是给出安装部件的类型名,系统通过它识别该部件属于哪一大类(display,mouse,scsi,network等)中的哪一类(网络adapter,driver,transport,service,network和netprovidor),同时,还需要给出映像文件和配置文件所在的源介质及标识。  

[returnoption]shell节。系统执行安装identify节后,执行该节。它主要功能是检查所需安装的部件是否支持的硬件平台和语言,并给出网卡名(有些配置文件支持多类网卡,此时必须让用户进行选择,并获得选择结果)。  

[installoption]shell节。该节是配置文件得主体,也是上次安装完后再次进行配置、删除、更新的入口点。主要功能是拷贝映像文件和配置文件,生成配置的各种选项,创建该部件在注册库中对应的各种登录子树并更新重写。  

第二节  驱动程序的加载过程

§2.2.1  windows  nt的启动过程

第一阶段:调入装入程序。和硬件平台相关,x86机器首先由rom装入根扇区,再由根扇区装入ntldr;

第二阶段:硬件检测。x86机器调ntdetect程序最大限度地获取各种硬件设备信息,引导hal及基本卷设备驱动程序,以便引导nt内核;

第三阶段:获取注册库中各种控制信息,如用户定义的非页内存大小;第四阶段:初始化注册库  \registry\machine下system和hardware并创建currentcontrolset,为装入相关硬件设备驱动程序作准备;

第五阶段:装入基本核心驱动程序;

第六阶段:释放一些已经完成使命的装入初始数据块;

第七阶段:进一步初始化注册库,以便有些依赖于基本核心驱动程序的上层驱动程序能顺利装入;

第八阶段:服务控制器装入应该由该服务控制器装入的各种驱动程序。

§2.2.2  fddi网卡驱动程序的加载过程

在windows  nt启动的第五个阶段,将加载核心驱动程序。而对于ndis网卡驱动程序是在ndis接口(ndis.sys)加载后调入运行,向ndis  wrapper注册、初始化、查询设置参数等。

windows  nt启动时,相应的实体如nt的服务控制器根据注册库中yhfddi驱动程序的配置注册信息,初始化ndis  wrapper,并装入相应的驱动程序,生成驱动程序管理块结构,申请内存以保存各种信息,向ndis  wrapper注册驱动程序。初始化和注册完毕后,再由服务控制器读取注册库中相应的链接信息。

在ndis  wrapper和yhfddi驱动程序初始化和注册成功后,ndis  wrapper根据系统相应的注册信息,加入和yhfddi驱动程序所对应的fddi网卡,同时读入网卡的注册信息,并进行网卡注册和网卡初始化。

在以上过程成功后,wrapper将查询和设置驱动程序的各种参数,了解驱动程序对哪些操作支持,决定对上层驱动程序的支持范围。

第三节fddi网卡驱动程序的注册

driverentry函数是windows  nt  ddk规定的核心驱动程序的入口点,wrapper识别到入口点后,调入驱动程序,在driverentry函数内完成两个基本注册任务:

调用ndisminitializewapper函数向ndis接口报告驱动程序将以miniport类网卡驱动程序注册。ndis建立它需要记录的驱动程序状态信息,同时返回ndiswrapperhandle,驱动程序保存这个句柄,以利后来调用ndisxxxconfiguration和initialization等函数。  

填写ndisxx_miniport_characteristics属性结构,主要记录ndis版本号和驱动程序支持的miniportxxx函数的入口点,然后调用ndismregisterminiport函数实现驱动程序的整体注册。  

以yhfddi为例所要注册的属性结构的内容大致如下:

ndis_miniport_characteristics  yhfddichar;

(ndis_miniport_characteristics这个结构将在第三章介绍)

yhfddichar.majorndisversion=yhfddi_ndis_major_version;

yhfddichar.minorndisversion=yhfddi_ndis_minor_version;

这两个属性决定驱动程序是ndis的哪个版本所支持,我们所用的是ndis3.0  

yhfddichar.disableinterrupthandler=yhfddidisableinterrupt;

yhfddichar.enableinterrupthandler=yhfddienableinterrupt;

yhfddichar.isrhandle=yhfddiinterruptservice;

yhfddichar.handleinterrupthandler=yhfddihandleinterrupt;

以上四项属性是中断处理所需的上边缘服务函数的入口点(句柄)。fddi网卡驱动程序需要有smt站管理功能,而smt是以中断处理方式进行的,故这四项属性在fddi网卡驱动程序中是很重要的。

yhfddichar.initializehandler=yhfddiinitialize;

此项注册的是驱动程序的初始化函数句柄。

yhfddichar.queryinformationhandler=  yhfddiqueryinformation;

yhfddichar.setinformationhandler=yhfddisetinformation;

这两项注册的是参数查询和设置函数的句柄。

yhfddichar.sendhanler=  yhfddisend;

yhfddichar.transferdatahandler=  yhfdditransferdata;

主要提供数据发送和接收函数句柄。

yhfddichar.resethandler=yhfddireset;

此项注册网卡软硬件重置函数句柄。  

yhfddichar.halthandler=  yhfddihalt;

此项注册网卡驱动程序挂起函数句柄。

yhfddichar.checkforhandler=null;

yhfddichar.reconfigurehandler=null;

这两个上边缘服务函数是fddi网卡驱动程序所不提供的,故置为null。

填好这些结构以后,调用以下函数实现驱动程序的注册:

ndismregisterminiport(

yhfddiwrapperhandle,

&yhfddichar,

sizeof(yhfddichar));

其中yhfddiwrapperhandle是在此之前初始化wrapper调用ndisminitializewrapper所得的句柄。

如果调用ndismregisterminiport不能返回ndis_status_success,必须在退出driverentry之前释放已经分配的资源(如yhfddiwrapperhandle等),故调用

ndisterminatewrapper(yhfddiwrapperhandle,null)。

这样驱动程序没能正确注册,亦不能正常运行。

第四节  网卡驱动程序对象查询与设置

如果ndis的管理实体要查询或设置一个特定的网络对象,它必须提供一个32位的oid。oid的结构如下:  图2.3.0  oid结构图

由上可以看到,oid可分为三大类:

所有ndis驱动程序都有的一般对象;  

特定介质的对象;  

特殊的与具体实现相关的对象(如多目地址表的长度)。  

一般的和特定介质的oid被记录在windows  nt  ddk中,对于这些oid  ddk文本指明了相关的对象能否通过miniportqueryinformation查询参数和通过miniportsetinformation设置参数。

oid也可被分为操作特性(如多目地址表长度参数)和统计参数(如广播包接收)。最后oid可分为必须的和可选的两种。

oid的前三个字节表明oid的不同类别,而最后一个字节确定这一类别内特定的信息管理对象。

针对于fddi网卡,被查询的oid的第一个字节为0x03。而ndis所查询的介质相关参数为:

0x03010104  oid_fddi_long_max_list_size

0x03010108  oid_fddi_short_max_list_size

0x03010102  oid_fddi_long_current_addr  

0x03010106  oid_fddi_short_current_addr

tcp/ip传输驱动程序所要查询的fddi  oid为:

0x03010102  oid_fddi_long_current_addr  

0x03010103  oid_fddi_long_multicast_list

0x03010107  oid_fddi_short_multicast_list

通过以上两阶段的查询,ndis和tcp/ip驱动程序就分别了解了网卡驱动程序对其的支持,从而进行相应的捆绑,以便数据传输时正确选择网卡驱动程序。

第五节  开发环境与调试方法

开发环境:

fddi网卡驱动程序的开发环境为nt  server  3.51,sdk,ddk  for  workstation  3.51,  vc++4.1,硬件平台为586。

调试平台:

主机为nt  server  3.51,windbg32

目标机为nt  workstation3.51  (check  944)

调试方法:

利用dbgprint把目标机上关键信息通过串口传到主机进行分析,以得出ndis驱动程序的调度机制和运转状况;

利用assert产生异常断点,由主机对异常进行控制

自定义宏,进行分级控制,以根据不同情况产生不同调试信息  

第四章  与smt移植相关的问题讨论

在本yhfddi网卡驱动程序中,smt的移植是极其关键的一部分,主要承担了驱动程序中硬件初始化和中断延迟处理。但由于smt是相对独立的软件,这样就有一个ndis  wrapper与smt间参数传递的问题。所以本章主要讨论miniport驱动程序与smt的关系和移植smt过程中初始化的要求、中断处理的要求,ndis  wrapper与smt如何传递参数。

(一)miniport  fddi网卡驱动程序与smt的关系。

在第一章已经谈及网卡驱动程序主要实现osi参考模型中的物理层和mac层。而对于fddi网络的物理层又可分为介质相关子层和介质无关子层。

对于我们的fddi/pci是基于x.3.19、x3.148、x3.166和x3.229而实现的。

smt在整个iso七层模型中属低两层范畴。下图是iso模型与fddi层次的对应关系,从而可知fddi  miniport驱动程序在nt网络结构中的位置。

即在windows  nt  fddi网卡驱动程序应包含smt,实现fddi拓扑环上的站管理。

而在驱动程序内部smt主要是在miniport驱动程序中的中断延迟处理上边缘服务中实现的,也可以说是将smt嵌入中断延迟处理程序中,实现ndis接口对smt的正确调度。

yh-fddi驱动程序的实现可分为硬件无关部分和硬件相关部分。  

移植smt过程中初始化的要求.  

这里的初始化主要是指硬件初始化,包括寄存器的初始化和数据结构的初始化,由smt共用的硬件相关例程库中硬件初始化部分来完成.  我们在开发过程序是调用fddi_main(bdd_t*bdd)这个函数来调用smt共用的硬件相关例程库的.可见使用fddi_main(bdd_t*bdd)时,需要传递bdd这个参量,而bdd_t这个数据结构的定义如下:

它包含了各类硬件寄存器的基址,所以要对其进行正确赋值就必须首先在nt的内存中映射一块虚存与网卡内存相对应,也就实现了bdd_t结构的赋值,对fddi_main(bdd_t  *bdd)的正确调用.  

因此,我们在调用fddi_main前首先将网卡上寄存器内存空间映射到nt的虚存空间上,并将bdd结构正确赋值.以映射bsi_phy_base为例,具体过程如下:

pchar  destination;

bdd_t  *bdd;

ndis_physical_address  physicaladdress;

ulong  baseaddress;

ndis_status  status;

baseadress  =0x0d0000+bsi_phy_base;

ndissetphysicaladdresshigh(physicaladdress,0);

ndissetphysicaladdresslow(physicaladdress,baseaddress);

status=ndismmapiospace(

(pvoid  *)&destination,

miniportadapterhandle,

physicaladdress,

bsi_phy_len

);

bdd->bsi_vir_base=(pchar)  destination;

adapter->  bdd->bsi_vir_base=  bsi_vir_base;  

/*对adapter结构中的bdd结构赋值,以便在其它上边缘函数中使用这些虚存基地址*/

中断处理要求.  

对于中断处理,在smt中主要调用cspintrhandandler()来实现.我们的fddi网卡驱动程序是miniport方式的,若在isr中做此处理将占用大量系统资源,使系统崩溃,所以我们采用只在isr中进行中断的排队,而在dpc中调用cspintrhandler()来完成中断处理.

在中断处理方面还有一个中断屏蔽和中断使能的问题,这两方面smt并不提供,故我们要正确处理.

具体处理方法见第三章.

ndis  wrapper与smt间参数如何传递.  

miniport方式的网卡驱动程序中,网卡上有中断时,系统反映给ndiswrapper,再由wrapper调度中断处理上边缘服务实现中断处理,在我们的yhfddi网卡驱动程序的中断具体处理是smt完成的所以在调用cspintrhandler时应将adapter结构传进smt以便在以后应用.

如在处理接收中断时,处理的最后应调用ndisindicatefddireceive,向ndiswrapper指示以接收到一个数据包,而ndisindicaterfddireceive的调用需要adapterminiporthandle作为参数,这就必须一级级从中断延迟处理函数(yhfddi  handleinterrupt)中将adapter结构传递下来.  当然,其它方面如发送,也会有类似的问题需要考虑.

总之,对于smt的移植,需要详尽的在程序中做好接口,才能实现与

smt的数据交换.

结束语

ndis规范在网络两层间提供了一个统一界面,ndis对网络本身而言,是一个带有协议功能的标准接口,对实现者而言,它应该是一个环境,这种环境不仅带有协议功能,更重要的是带有和软、硬平台无关的核心功能支持,它不会受软、硬平台的变化严重影响,无疑,它是软件的移植和兼容的可靠保证,ndis把网络的一部分共性抽象出来,并根据具体的操作系统实现系统和平台相关的基础库以保证ndis的标准性和对开发者提供最大的功能支持,这也将加速和规范开发过程,但是,在操作系统之上提供ndis基础库获得标准同时也失去直接作用于操作系统带来的灵活性以及更强的功能支持,同时,ndis处于网络中层和低层之间,低层网络的快速发展和ndis对网络部分共性的抽象必然导致ndis对实现者的滞后,例如ddk3.51提供的ndis开发环境只支持10m以太网、fddi、令牌网(802.5)、localtalk、arcnet等,而对新出现的快速以太网及atm不提供支持,这对我们如何在ndis环境下实现诸如atm的lan  emulation,ip  over  atm、快速以太网带来很大问题。

smt是实现fddi网卡驱动程序的关键,然而由于应用ddk开发miniport驱动程序时要遵循其结构框架,所以要想完整地按其结构移植smt,就必须分解smt适应之,即要求对smt有一个很好的理解。但smt是庞大的给开发带来了一定的困难。

参考文献

【1】《device  driver  kit用户手册》

【2】《device  driver  kit核心驱动程序设计》  

【3】《device  driver  kit网络驱动程序设计》

驱动程序范文6

由于工作关系,我经常涉及PC机与设备接口的工作,从PC机这方面要做的工作看来,主要是通过接口处理设备的中断,通过I/O端口或内存地址与外设互相传递数据。从计算机原理的角度看,所要达到的目的很简单,那么如何编写程序完成上述功能呢?

目前国内流行的PC操作系统有三种:DOS,Win95/98系列,WindowsNT。DOS是单用户、单任务操作系统,由于PC机硬件处理速度不断提高,基于单用户、单任务的操作系统越来越不能充分发挥硬件的功能,现在只应用于一些老式PC及其它个别场合,有逐渐被淘汰的趋势;Win95/98系列和WindowsNT属于多任务操作系统,不论从其原理还是界面上看,这两种操作系统都比DOS有着无可比拟的优越性,这两种操作系统虽然在界面和操作上及其相似,但其内部实现的诸多方面有许多区别,有些区别是本质上的。Win95/98设计目标是针对一般家庭用户,安全性及可靠性存在许多薄弱环节,就可靠性而言,Win95/98系列不能很好的防止多任务环境中某个进程的非法操作导致系统中其它程序甚至整个系统的崩溃,而WindowsNT在这方面及其它诸多方面设计的相当严谨。这两种操作系统是Microsoft公司同一时期的产品,但针对不同的使用群,所以在一些重要场合及生产实践中应该选择WindowsNT作为计算机的操作系统,此外,从发展趋势来看,WindowsNT已经成为定型产品,具有相对稳定性。

在不同操作系统下编写驱动程序是有很大区别的,在DOS平台上,应用程序和设备驱动程序之间没有标准的接口,它们在外部表现为一个扩展名为EXE的文件,驱动程序的作用被柔和在应用程序中,这样,应用程序为了使用不同厂商的同一类设备,必须了解这些设备在接口上具体的硬件实现,同时,对于一个特定型号的硬件产品,所有支持它的应用软件中对于控制整个设备动作的这部分代码,可能被多次重写。这种情况不适应硬件及应用软件的飞速发展。Windows系统在这方面,进行了根本性改进,把控制设备动作的这部分代码独立出来,提出了设备驱动程序的概念,驱动程序是应用程序和硬件设备之间的一个桥梁,应用程序与驱动程序之间有明确的接口,应用程序通过与驱动程序交换信息,达到控制外设的目的。接口定义的操作是面向设备的,这就是说,在应用程序的设计中,并不用关心对外设操作的具体硬件实现,只是对驱动程序发出一系列指令既可;驱动程序接受来自上层应用程序的指示,具体操纵实际硬件,完成用户功能。具体实现上,Win95/98系列与WindowsNT又有所区别,WindowsNT是严格按照上述思路设计的;而Win95/98系列不那么严格,其支持上述思路,但同时应用程序也可以绕过驱动程序直接访问实际物理I/O,这样做,增加程序设计的灵活性,但同时,对系统可靠性造成一定隐患。这也正是Win95/98系列可靠性低于WinNT的原因之一。

表1-1 三种操作系统下访问接口比较

操作系统 应用程序访问接口方式 访问权限 DOS 直接访问 所有[注] Windows95/98 通过设备驱动程序*.VXD 所有[注] 直接访问 仅I/O端口 WindowsNT 通过设备驱动程序*.SYS 所有[注] [注]‘所有’指I/O端口,RAM总线,中断,DMA。

WindowsNT设备驱动程序的组成原理

WindowsNT操作系统结构分为用户模式和内核模式,用户模式下的编程为应用程序的设计,而开发设备驱动程序,则属于内核模式下的编程,内核模式组件包括NT Executive(ExXxx),内核(KeXxx),硬件抽象层(HalXxx)。其层次如图2-1所示,其中NT Executive 包括几个独立的软件组件,它们是系统服务接口(ZwXxx),对象管理器(ObXxx),配置管理器,进程管理器(PsXxx),安全监视器(SeXxx),虚拟空间管理器(MemXxx),本地进程调用,I/O管理器(IoXxx)。内核模式的系统服务并不是全部公开的,而是提供了一系列开发设备驱动程序需要的函数(上文括号内为函数形式,函数手册参见[2]Kernel-Mode Drivers-Reference章节),换言之,这些函数功能是所有内核模式的系统服务功能的子集。

驱动程序由一系列相对独立的函数组成,由I/O管理器根据需要调用这些函数,对于一个需要处理中断的最简单的驱动程序也需要由以下几个函数构成:

1.DriverEntry() 运行于PASSIVE_LEVEL

驱动程序入口点,当驱动程序被手动或自动装入系统后,驱动程序从这点开始执行,主要用于定位硬件资源,建立指向其它驱动程序函数的指针等其它初始化工作。

2.XxUnload() 运行于PASSIVE_LEVEL

用于驱动程序从系统卸出之前,释放由驱动程序占用的所有系统资源。

3.XxIsr() 运行于DIRQL

中断服务程序。

4.XxDpcForIsr() 运行于DISPATCH_LEVEL

中断服务程序后处理程序,以排队方执行不太关键代码的执行,由于排队机制及优先级,不会造成代码拥塞从而提高中断服务程序的响应并且提高系统总体I/O吞吐率。

5.XxOpen() 运行于PASSIVE_LEVEL

处理应用程序Win32函数CreateFile()请求。

6.XxClose() 运行于PASSIVE_LEVEL

处理应用程序Win32函数CloseHandle()请求。

7.XxDispatch() 运行于PASSIVE_LEVEL

处理应用程序Win32函数DeviceIoControl()请求,通过一系列自定义命令,驱动程序与应用程序交换特定的信息。

WindowsNT使用一个抽象化的CPU优先级方案, IRQL代表中断请求级,任一时刻CPU总处在某一级上,这个数越大,表示当前的任务重要性越大,如表2-1所示,从上至下IRQL越来越小。所有上述驱动程序的函数及内核模式函数都必须运行于各自的IRQL级上,如果违反这一调用规定,会造成系统崩溃。例如,中断服务程序(XxIsr)运行于DIRQL及上,那幺在编写中断服务程序时,只能调用允许在这一级运行的内核模式函数(并不是所有内核模式函数都能运行于DIRQL级)。至于每个内核模式函数运行级别的说明,详见[2]Kernel-Mode Drivers-Reference章节。

WindowsNT是一多任务系统,许多设备的驱动程序同时存在系统中,这样各个设备所占用的资源(中断,I/O及RAM地址空间)很有可能冲突,如果设备驱动程序在运行之前不进行‘探测’而使用自己硬件设备的资源,有可能和系统内其它设备占用的资源冲突,后果不堪设想。WindowsNT通过注册表管理硬件资源的占用信息,作为内核模式信任的组件,驱动程序使用硬件资源之前必须遵循‘查询-申请-使用-释放’的原则(如图2-2所示)。

表2-1

来源 IRQL 硬件 HIGHEST_LEVEL POWER_LEVEL IPI_LEVEL CLOCK2_LEVEL CLOCK1_LEVEL PROFILE_LEVEL DIRQLs(I/O设备中断平台相关的级数) 软件 DISPATCH_LEVEL APC_LEVEL PASSIVE_LEVEL WindowsNT设备驱动程序的编写步骤与实例

现以一实际例子简要说明设备驱动程序的开发步骤,本例以CINRAD天气雷达测试卡实际应用为原型,加以简化、抽象。

第一步,了解被控设备的接口情况。

本例为一ISA卡,占用PC机9号中断,I/O地址360H及RAM地址D0228H分别一个字空间。

第二步,确定驱动程序的功能。

驱动程序每当9号中断达到时,检查运行标志变量RunFlag(为一BOOL变量),如果等于TRUE,中断累积计数器counter(为一unsigned short变量)增一,把这个值写入RAM地址D0228H,再从这个地址读出,如果读出值等于写入值,把这个值写入I/O地址360H,这个地址的内容会驱动板卡上的LED显示,把写入值显示出来;如果读出值不等于写入值,设置运行标志变量FALSE。如果运行标志变量等于FALSE,什幺也不做,返回。

第三步,定义驱动程序与应用程序的软件接口。

本例定义两个接口命令:

IOCTL_IOCardA_START:应用程序设置驱动程序内部的运行标志变量等于TRUE。

IOCTL_IOCardA_READ:应用程序查询驱动程序内部的中断累积计数器的值。

第四步,画流程图。这里列举本例实现的几个主要流程图,(图略)。

系统传给驱动程序入口函数系统定义的‘设备驱动对象’DrObj,通过初始化这个对象的一些成员变量,把驱动程序其它函数与这个对象联系起来。

ISA卡为非即插即用设备,事先把资源占用信息手工添加注册表如下:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\IOCardA\parameters]

"IRQ"=dword:00000009

"IOSPAN"=dword:00000004

"IOAdd"=dword:00000360

"RAMAdd"=dword:000d0228

"RAMSPAN"=dword:00000002

其中IOCardA以下各子键及其值为自定义,设备驱动程序利用相应函数检索出这些值。

(3)每个设备驱动程序可以创建若干系统定义的‘设备对象’,本例根据需要只创建了一个‘设备对象’Dev。‘设备对象’其中一个成员变量为指向一非分页的物理内存块DeviceExtension,这块内存大小及内容为用户自定义,由于Dev或DeviceExtension对象会被系统传给驱动程序的其它函数,这样驱动程序各函数通过访问这块内存区,实际上达到互相传递信息的功能。本例在这里存储设备硬件资源信息及RunFlag和中断计数器counter,这些数值在DriverEntry()初始化后,供驱动程序的其它函数使用。

图3-2为中断服务程序IOCardAIsr()流程图。操作系统接受中断,连同DeviceExtension等参数传给中断服务程序,中断服务程序利用这些参数,实现要求功能。

图3-3为IOCardADispatch()流程图,这个函数用于处理来自上层应用程序的命令。上层应用程序通过以下程序段设置驱动程序中RunFlag值为TRUE,从而启动中断服务程序开始计数。

BOOL cmd=TRUE;

hTest = CreateFile(...); //打开设备

DeviceIoControl(hTest, //设备句柄

IOCTL_IOCardA_START,//命令

&cmd,sizeof(BOOL), //输入缓冲区地址及大小

NULL,0,&c,NULL);

CloseHandle(hTest); //关闭设备

上层应用程序通过以下程序段查询当前的中断计数器的值并存于变量w中。

unsigned short w;

hTest = CreateFile(...);

DeviceIoControl(hTest,

IOCTL_IOCardA_READ, //命令

NULL,0,

&w,sizeof(unsigned short),//输出缓冲区地址及大小

&c,NULL);

CloseHandle(hTest);

其中DeviceIoControl()执行后,操作系统调用IOCardADispatch()函数,如流程图所示,这个函数内部通过一个开关语句,根据命令执行相应的分支。驱动程序与应用程序通过此函数接口交换数据时,操作系统提供4种可选数据缓冲方式,本例由于数据I/O量比较小,故选用‘缓冲I/O’ (METHOD_BUFFERED)。过程是,I/O管理器首先分配一个非分页池,它的大小为调用者输入缓冲区和输出缓冲区的较大者,第一段程序为sizeof(BOOL),第二段程序为sizeof(unsigned short),它的地址存到IRP(I/O请求包)的AssociatedIrp.SystemBuffer域中,然后把输入数据拷贝到这个池中,在第一段程序中cmd的值TRUE被拷贝到池中,这样驱动程序通过RtlCopyBytes()函数再把池中的值拷贝到驱动程序的RunFlag中。IOCardADispatch()函数执行完,I/O管理器把池中的内容拷贝到调用者的输出缓冲区,在第二段程序中,驱动程序通过RtlCopyBytes()函数把counter的值拷贝到池中,从而最终传递到应用程序变量w中。

第五步,编程。在编写设备驱动程序的同时,要编写一个简单的应用程序用于测试设备驱动程序的一些功能。

第六步,驱动程序的载入。

驱动程序C语言源程序经过编译、连接生成扩展名为SYS的文件,本例为IOCardA.sys,把这个文件拷贝到\WINNT\system32\drivers\系统目录下,同时手工添加如下信息到注册表:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\IOCardA]

"ErrorControl"=dword:00000001

"Start"=dword:00000003

"Type"=dword:00000001

要保证IOCardA子键名与驱动程序文件名一致,其中Type=1表示此驱动程序为内核模式驱动程序,Start=3表示此驱动程序手动载入,ErrorControl=1表示当驱动程序发生错误时,日志记录错误并显示一个消息框。这样当Windows重新启动后,通过使用控制面板中的Device小应用程序,从列表中找到IOCardA设备名,按Start按钮,于是,设备驱动程序就驻留内存并在底层开始工作了。

第七,调试。设备驱动程序没有界面,完全在系统底层运行,为了观察驱动程序的运行状态,WindowsNT DDK提供windbj.exe程序用于设备驱动程序的调试,调试设备驱动程序需要两台CPU体系结构完全相同的计算机,一台为‘宿主机’,运行windbj.exe程序,另一台为‘目标机’,运行设备驱动程序,两台计算机用串口线连好,进行一系列软件设置(参见[1]第17章),就可以开始调试了,从‘宿主机’可以控制及观察‘目标机’上驱动程序的运行情况。最常用的调试手段是在驱动程序中必要的位置加入DbgPrint()函数,这个函数可以把指定信息输出到‘宿主机’windbg.exe窗口中,通过分析这些信息,可以了解驱动程序当前的运行情况。

结束语 WindowsNT是一个复杂而严密的系统,驱动程序的开发不可避免的涉及现代操作系统理论及其它许多计算机理论,内涵相当广泛,本文围绕着开发实践从一定深度探讨了WindowsNT设备驱动程序开发最基本的知识及一般方法,希望对读者有所帮助,对于复杂,特殊应用的实现及编程技巧,有待于读者在各自实际应用中不断探索。

参考文献