AddDevice是WDM驱动程序另一个入口函数,当DriverEntry初始化成功后,PnP管理器会调用AddDevice创建一个FDO,然后把总线驱动程序创建的PDO连接到FDO上,同时还会创建一个设备扩展对象。本文在设备扩展对象中保存了DMA缓存地址、设备寄存器地址和一些标志位。AddDevice还寄存了一个设备接口,以便应用程序打开设备。
接着,PnP管理器向驱动程序堆栈发送一个PnP启动消息,它是一个主功能代码为IRP_MN_START_DEVICE的IRP。驱动程序并不处理该IRP,只是将它传递给总线驱动程序处理并等待该IRP的处理结果,总线驱动程序将获得的设备资源(中断、DMA通道、内存和I/O资源等)保存在IRP中并通知驱动程序取出这些信息保存在设备扩展对象中。于是,驱动程序就可以根据这些信息对PEX8311进行操作了。
4.2 数据传输初始化
数据传输初始化是在DispatchIoControl派遣例程中实现的。功能驱动程序正常装入后,应用程序就可以发出DeviceIoControl请求初始化数据传输。初始化包括接收用户程序传来的事件句柄、分配DMA缓存、设置中断寄存器。
驱动程序采用事件方式与应用程序进行通信。应用程序中用CreateEvent创建事件hEvent,再调用DeviceIoControl函数将它传给驱动程序,驱动程序响应该请求,从输入缓冲区中取出这个事件句柄存在设备扩展对象中。当驱动程序将该事件设置为信号状态时,应用程序就可以得到通知。
驱动程序通过函数AllocateCommonBuffer分配的一段非分页、连续的DMA缓存,用于缓存从PEX8311传来的雷达数据。为了使应用程序能够直接访问DMA缓存,本文通过函数MmMapLockedPages把这段内存映射到应用程序。每次DMA读取512KB数据,本文分配了60段512KB的连续DMA缓存,驱动程序依次将每次读取的数据存在这些连续的缓存中,而应用程序按相同的顺序取出数据存在SCSI硬盘上。即使应用程序在下次LINT#中断到来时还没及时将缓存中数据写到SCSI硬盘上,驱动程序也会启动DMA将新数据存在下一段缓存中,不会丢失数据。
驱动程序设置PEX8311的中断寄存器,允许LINT#中断和PCI中断。允许LINT#中断可以使LINT#信号处于可用状态,而允许PCI中断可以将LINT#中断和DMA中断路由到计算机系统,操作系统就能调用中断服务程序响应中断。
4.3 数据传输模块
数据传输模块主要包括中断服务例程(ISR)和DPC例程(DpcForIrq)。前者响应LINT#中断和DMA中断,后者启动DMA传输并在数据传完后通知应用程序读取DMA缓存中的数据。因为ISR运行于较高的硬件中断级别[5](DISPATCH_LEVEL),它会阻塞所有的进程,而DpcForIrq运行在软件中断级别,不会阻塞所有进程,所以应该尽量减少ISR的运行时间,而在DpcForIrq中完成耗时的操作。本文在ISR中只判断中断类型,ISR的流程如图3所示:
图3 ISR流程图
在调试中发现:当PEX8311的LINT#中断信号有效时间超过8us时,会造成死机。但系统繁忙时,计算机会因为中断有效时间太短而响应不了中断。为解决这一问题,使LINT#的有效时间加长到32us,驱动程序在刚进入ISR时,先禁止PCI中断,LINT#中断便不能传到计算机系统,也就不会造成死机,ISR也有足够的时间读中断寄存器的值进行判断。
数据传输初始化工作完成后,当有LINT#中断时,系统调用ISR。ISR中先判断是LINT#中断,于是将标志m_LINT设置为true,接着调用IoRequestDpc ()将一个DPC对象放入DPC队列中,最后,中断服务程序退出。
然后,系统取出DPC对象,在DISPATCH_LEVEL的级别下执行DpcForIrq。因为m_LINT为true,说明是FIFO存满数据,DpcForIrq设置DMA参数并启动DMA读数据。然后DpcForIrq退出。当PEX8311完成DMA传输后会产生DMA中断,中断服务程序按相同的方式执行,此时m_LINT被设置为false,说明是PEX8311完成DMA传输而产生的DMA中断,驱动程序在DpcFor_Irq中用事件通知应用程序读取DMA缓存中的数据写到SCSI硬盘上。如果应用程序不退出,驱动程序会一直按上述方式循环运行。当应用程序退出时,驱动程序关闭中断并释放DMA缓存。
4.4 驱动程序调试
本文采用Microsoft随DDK一起发布的调试工具WinDbg调试驱动程序。WinDbg是一种内核模式和用户模式调试器,可以用来分析故障转储文件和执行驱动程序代码。调试需要两台计算机:目标机(雷达数据记录器)和主机(运行Windbg的机器),它们用串口线连接,主机控制和监视目标机上的活动。设置好主机和目标机后,通过WinDbg的命令窗口可以设置断点、观察调试输出信息或分析目标机蓝屏后产生的故障转储文件。
测试时:外部中断频率可以提高到200Hz以上,每次中断读取512KB数据。通过分析,测试数据完全正确。经反复测试,记录器稳定记录速度可达100MB/S以上。
由于只采用了两个SCSI硬盘以及系统运行效率的限制,数据记录速度没有达到PEX8311的理论传输速度。若增加SCSI硬盘数量和升级硬件,记录速度还有很大提升空间。
5 总结
本文详细的介绍了基于PCI Express总线的雷达数据记录器驱动程序的开发。本文创新点为:针对雷达数据记录器和PEX8311的特点设计了高效的驱动程序,它具有易操作、移植性强的优点。该驱动程序已成功地应用于某雷达原始数据记录器中。