ISA數據采集卡的WDM驅動(dòng)程序實(shí)現
摘要:ISA設計在WINOWS新的驅動(dòng)程序模型WDM(WINDOWS DRIVER MODEL)中沒(méi)有獲得很好的支持,使用WDM實(shí)現需要一些特殊處理。主要討論老式ISA設備的WDM驅動(dòng)程序的設計與實(shí)現。
本文引用地址:http://dyxdggzs.com/article/241591.htm關(guān)鍵詞:Windows驅動(dòng)程序模型(WDM) 工業(yè)標準結構(ISA) 數據采集
WDM作為微軟為WINDOWS 2000及以后版本準備的新驅動(dòng)模型,它可以在WINDOWS 98及以后的操作系統上共享。這種具有跨平臺性的設備驅動(dòng)模型可以大大簡(jiǎn)化驅動(dòng)程序的開(kāi)發(fā)工作。WDM支持PNP(即插即用),為用戶(hù)的PNP設備驅動(dòng)完成了大量的底層工作。這也使得WDM對各種老設備,特別是那些不具有即插即用特性硬件的支持明顯的不足。在科研和工控中,最常用的數據采集卡通常都是基于PC總線(xiàn)的不能為PNP提供硬件支持的ISA設備。為這類(lèi)硬件編寫(xiě)非WDM驅動(dòng)程序只能局部支持PNP特性,而且需要做大量額外的工作如:必須檢測硬件,為硬件創(chuàng )建設備對象(用于代表硬件),配置并初始化硬件使其正常工作,這些工作非常復雜。利用WDM可以避免這些麻煩。
1 WDM的結構
WDM實(shí)際上是一個(gè)編寫(xiě)驅動(dòng)程序的規范。其驅動(dòng)程序結構的特點(diǎn)和WINDOWS程序設計的消息驅動(dòng)機制很相像,采用IRP驅動(dòng)機制。WINDOWS 98和WINDOWS 2000處理IRP的方式一樣,本質(zhì)卻完全不同。
WINDOWS 2000主要由I/O管理器來(lái)管理驅動(dòng)程序的行為,管理的方法就是給驅動(dòng)程序發(fā)送各種IRP,同時(shí)I/O管理器還負責傳遞這個(gè)設備的用戶(hù)請求給驅動(dòng)程序。驅動(dòng)程序不能直接操作硬件設備,而是通過(guò)一個(gè)叫做HAL(硬件設備抽象層)的層來(lái)訪(fǎng)問(wèn)底層設備。HAL完成對各種硬件差異的屏蔽。Windows 98內核與Windows 2000內核有很大的差別。Windows 98操作系統的內核稱(chēng)為虛擬機管理器(VMM)。虛擬設備驅動(dòng)程序(VxD)則使設備虛擬化,從而與虛擬機管理器形成虛擬機。Windows 9x的內核不支持IRP,它通過(guò)模擬的方法支持WDM和IRP。Windows 98包含了NTKERN.VXD(VMM32.VXD)系統模塊,該模塊含有大量Windows NT內核支持函數的Windows實(shí)現。NTKERN.VXD使用與Windows 2000相同的方式創(chuàng )建IRP并發(fā)送IRP到WDM驅動(dòng)程序。也就是說(shuō),Windows 98是使用VxD技術(shù)實(shí)現WDM的。盡管Windows 98和Windows 2000的內核完全不同,但是WDM的結構在Windows 98和2000下可以認為是完全相同的。
WDM驅動(dòng)程序面對的主要內容是一系列內核驅動(dòng)對象。這些對象包括驅動(dòng)對象、設備對象,還有一系列的資源抽象對象如中斷對象、適配器對象(處理DMA操作)、內核模式派發(fā)器對象、控制器對象、推遲過(guò)程對象、定時(shí)器對象、設備隊列對象、回調對象等。其中驅動(dòng)對象由I/O管理器負責創(chuàng )建和管理。設備對象代表用戶(hù)需要操作的物理或者是邏輯設備。設備對象負責管理自己設備所需要的各種資源對象。這些資源對象有的代表真正的物理設備如中斷對象、適配器對象、定時(shí)器對象;有的對象則是邏輯對象,它們是操作系統實(shí)現自己的特性所必需的,如推遲過(guò)程調用就是與操作系統的搶占式多任務(wù)的實(shí)現有關(guān)。WDM驅動(dòng)程序利用IRP和這些對象完成硬件設備的抽象化,并對應用程序提供統一操作接口。這就是所謂的WDM規范。
WDM驅動(dòng)程序的結構很簡(jiǎn)單。它的主體是一個(gè)入口函數DriverEntry。DriverEntry的第一個(gè)參數是指針,指向一個(gè)剛被初始化的驅動(dòng)程序對象,該對象代表驅動(dòng)程序。WDM驅動(dòng)程序的DriverEntry例程完成這個(gè)對象的初始化并返回。WDM驅動(dòng)程序的DriverEntry例程的主要工作是把各種函數指針填入驅動(dòng)程序對象。這些指針對操作系統指明了驅動(dòng)程序容器中各種子例程的位置。它包括下面這些指針成員:
·DriverUnload指向驅動(dòng)程序的清除例程。I/O管理器會(huì )在卸載驅動(dòng)程序前調用該例程。通常WDM驅動(dòng)程序的DriverEntry例程一般不分配任何資源,所以DriverUnload例程也沒(méi)有什么清除工作要做。
·DriverExtension->AddDevice指向驅動(dòng)程序的AddDevice函數。AddDevice函數是WDM驅動(dòng)程序的一個(gè)特殊函數,PNP管理器為每個(gè)設備實(shí)例調用該函數。它創(chuàng )建一個(gè)設備對象并把它連接到該驅動(dòng)程序的設備堆棧中。在這個(gè)函數里,設備對象被創(chuàng )建,設備需要的中斷、DMA等資源被掛接到這個(gè)設備對象上,相應地處理函數,如中斷服務(wù)例程等也被指定。
·DriverStartIo,如果驅動(dòng)程序使用標準的串行IRP,則必須使用這個(gè)函數,使它指向驅動(dòng)程序的StarIo例程。
·MajorFunction是一個(gè)指針數組,它主要處理各種用戶(hù)的I/O請求IRP。默認情總況下,用戶(hù)的所有I/O請求都會(huì )由I/O管理器返回失敗。驅動(dòng)程序為要處理的IRP指定相應的派遣函數。
此外,還有一些重要的例程如用于處理中斷操作中斷服務(wù)例程,為了提高系統中斷處理效率的中斷服務(wù)推遲調用例程等。
驅動(dòng)程序的其余部分就是前面所指定的那些例程的實(shí)現。
2 為ISA設備分配資源
雖然WDM驅動(dòng)程序可以簡(jiǎn)化很多工作,但是給ISA設備編寫(xiě)WDM驅動(dòng)程序也有困難。這個(gè)困難是ISA設備所需資源的分配問(wèn)題。根據PNP的規范,支持PNP的設備如PCI總線(xiàn)設備有相應的寄存器標識自己和自己可以接受的資源,如中斷、端口范圍、內存范圍等,并且有相應的邏輯支持配置資源。這使得操作系統啟動(dòng)過(guò)程中可以動(dòng)態(tài)地規劃調整各個(gè)設備的資源而不需要用戶(hù)的干預。為了使ISA設備具有這種PNP的特性, 可以通過(guò)PNP管理器和INF文件完成ISA設備的自動(dòng)資源分配。PNP管理器(PNP AMNAGER)依賴(lài)INF文件完成PNP管理。INF文件為設備、設備驅動(dòng)程序、操作系統的安裝過(guò)程提供信息(包括PNP MANAGER)。為了兼容非PNP設備,INF文件支持幾個(gè)命令為設備分配資源。這些信息初提供給NPN管理器,并且被PNP管理器用來(lái)與系統其它部分協(xié)商以完成非PNP設備的自動(dòng)資源分配。LOGCONFIG為設備制定一個(gè)可選的資源設定。還有相應的IRQCONFIG、IOCONFIG、DMACONFIG、MEMCONFIG子命令,它們?yōu)樵O備指定具體的可選資源。語(yǔ)法如下:
[log-config-section-name>]
ConfigPririty=priority-value>
[DMAConfig=dma-list>]
[IOConfig=io-range-list]
[IRQConfig=irq-list>]
[MemConfig=mem-range-list>]
其中CONFIGPRIOITY命令指定這個(gè)LOGCONFIG項的優(yōu)先級。其余子命令表示設備選用的硬件資源。下面是一個(gè)例子:
[CX2590.Install]
……;其它命令
LogConfig=CX2590_DMA;指定配置項的名稱(chēng)
[CX2590_DMA];配置項的名稱(chēng)
ConfigPriority=NORMAL;配置的優(yōu)先級
IOConfig=4@300-3ff%3ff(3ff::);指定IO范圍
IRQConfig=4,5,9,10,11 ;指定可選的中斷
DMAConfig=0,1,2,3 ;指定可選的DMA
在INF文件中加入LOGCONFIG命令可以解決ISA總線(xiàn)設備資源的自動(dòng)分配問(wèn)題,就可以為ISA總線(xiàn)設備編寫(xiě)WDM驅動(dòng)程序。
3 一個(gè)ISA設備WDM驅動(dòng)程序的實(shí)現
使用Numega公司的開(kāi)發(fā)工具DriverStudio 2.01可以大大地簡(jiǎn)化驅動(dòng)程序的開(kāi)發(fā)過(guò)程。DriverStudio開(kāi)發(fā)通用內核模式的開(kāi)發(fā)包是DriverWorks。DriverWorks是一個(gè)面向對象的工具包。它封裝了比較底層的繁復操作,提供給開(kāi)發(fā)者一個(gè)簡(jiǎn)潔的界面。同時(shí),DriverWorks和Visual C++有很多的接口:DriverWorks專(zhuān)門(mén)為Visual C++提供了一個(gè)專(zhuān)門(mén)開(kāi)發(fā)WDM驅動(dòng)程序的WIZARD。在WIZARD指導下,開(kāi)發(fā)者可以很容易地生成一個(gè)驅動(dòng)程序的框架。開(kāi)發(fā)者要作的工作就是根據特定硬件編寫(xiě)相應的代碼。
WIZARD生成的框架不僅包括設定設備的資源如中斷、IO端口范圍、內存范圍;還包括自動(dòng)生成驅動(dòng)程序與應用程序的接口命令及處理這些命令的處理函數,生成標準驅動(dòng)程序的標準驅動(dòng)程序例程;包括DriverEntry驅動(dòng)程序入口例程、UnLoad卸載例程、Dispach標準派發(fā)器例程、StartIO標準I/O傳輸例程、中斷處理例程等。對于WDM驅動(dòng)程序,包括生成驅動(dòng)程序接口(WDM專(zhuān)有),設備的符號連接,I/O傳輸方式以及WDM電源管理和處理PNP請求的IRP處理子程序。WIZARD完成后的代碼主要包括兩類(lèi),一類(lèi)是驅動(dòng)對象,它構成一個(gè)驅動(dòng)程序的框架;另一類(lèi)是驅動(dòng)程序的設備對象。驅動(dòng)程序對象負責創(chuàng )建并管理驅動(dòng)程序設備對象。設備對象負責管理硬件的各種資源如I/O、IRQ、DMA。它還負責處理各種IRP的例程。設備對象是系統所有I/O操作的基石,一個(gè)驅動(dòng)程序必須有一個(gè)或一個(gè)以上的設備對象才真正有意義。驅動(dòng)對象和設備對象的關(guān)系很象WINDOWS系統中進(jìn)程和線(xiàn)程的關(guān)系:進(jìn)程是可執行代碼(就是線(xiàn)程)的框架。如果說(shuō)驅動(dòng)對象是WINDOWS中的進(jìn)程,那么設備對象就像進(jìn)程中的線(xiàn)程,它們完成實(shí)現的I/O操作。設備對象使用保護成員變量來(lái)管理設備的資源,使用成員函數來(lái)處理各種IRP請求,并由這些函數完成實(shí)現的I/O操作。
筆者開(kāi)發(fā)的高速旋轉機械監控與故障診斷系統采用的是北京大恒公司的具有FIFO(隊列形式實(shí)現的緩存)的8路數據采集卡AC 1810。它的特點(diǎn)是由硬件自動(dòng)完成采用操作:當FIFO半滿(mǎn)的時(shí)候,系統產(chǎn)生中斷通知用戶(hù)取走數據;同時(shí),硬件繼續自動(dòng)采樣FIFO的另一關(guān)。驅動(dòng)程序的主要工作包括設備I/O讀操作和中斷服務(wù)操作。下面是WIZARD生成的驅動(dòng)對換和設備對象的定義(只取主要部分):
// 驅動(dòng)對象
class AC_1810 : public Kdriver
{
SAFE_DESTRUCTORS
public:
virtual NTSTATUS
DriverEntry(PUNICOE-STRING
RegistryPath);
//驅動(dòng)程序的入口函數
virtual NTSTATUS
AddDevice(PDEVICE_OBJECT Pdo);
//完成設備對象和驅動(dòng)對象的連接
……
};
//設備對象
class AC_1810Device : public KpnpDevice
{
// Constructors
public;
AC-1810Device(PDEVICE_OBJECT Pdo,
ULONG Unit);//構造函數完成資源配置
……
public:
AC_1810Device(PDEVICE_OBJECT Pdo,
ULONG Unit);//構造函數完成資源配置
……
public:
BOOLEAN Isr_Irq(void);// IRQ中斷服務(wù)例程
Virtual NTSTATUS Create(KIrp I);
//標準IRP處理函數
virtual NTSTATUS Close(KIrp I);
// COMMENT_ONLY
virtual NTSTATUS Read(KIrp I);
// COMMENT_ONLY
virtual VOID StarIo(KIrp I);
// 開(kāi)始I/O傳輸
VOID CancelQueuedIrp(KIrp I);
// 判斷傳輸IPR是否被取消
VOID Invalidate(void);
// 釋放資源例程
virtual NTSTATUS DefaultPnp(KIrp I);
// 處理默認的PNP操作
virtual NTSTATUS DefaultPower(KIrp I);
// 管理電源
void SerialRead(KIrp I);
//完成實(shí)際的I/O操作
NTSTATUS IOCTL_SETUP_Handler(KIrp I);
//采樣參數設定
NTSTATUS IOCTL_REW_Handler(KIrp I);
// 開(kāi)始/停止采樣
……
protected:
KioRange m_IoPotrRange0
// 管理I/O資源
Kinterrupt m_Irq;
// 管理中斷資源
……
};
在實(shí)際操作過(guò)程中,采用中斷讀數的方法。在驅動(dòng)程序中設置了兩個(gè)緩沖區,一個(gè)前臺緩沖區,一個(gè)后臺緩沖區(用作后備緩沖區),系統總是先使用前臺緩沖區。當前臺緩沖區已滿(mǎn)而仍然未被讀出,系統觸發(fā)中斷時(shí),此時(shí)使用后臺緩沖區。讀數的方法很簡(jiǎn)單,系統先讀前臺緩沖區的數據,只有當前臺緩沖區未滿(mǎn)而后臺緩沖區滿(mǎn)的時(shí)候才讀后臺緩沖區。這樣可以保證采樣數據序列的時(shí)間順序。
具體實(shí)現如下:
// ISR例程,完成數據從FIFO中讀出
BOOLEAN AC_1810Device::Isr_Irq(void)
{
//是否觸發(fā)不斷?未觸發(fā)則返回,判斷兩個(gè)緩沖區情況,都滿(mǎn)則返回
……
// 前臺緩沖區未滿(mǎn),使用前臺緩沖區
if(m_pBuffer->numused MAX_READ_BUF){
for(int i=0;iBLOCK_SIZE;i++){
m_pBuffer_>buff[m_pBuffer->numused+i]=READ_FIFO;
}
m_pBuffer->numused +=BLOCK_SIZE;
}
else
//完成其它情況的判斷
……
return TRUE;// 中斷成功返回
}
當應用程序使用標準Win32 API對設備進(jìn)行讀操作的時(shí)候,I/O管理器通知驅動(dòng)程序并觸發(fā)對Read函數的調用。對于通常的串行設備,在Read函數的最后排隊I(yíng)RP請求,此時(shí)系統就可以觸發(fā)StartIO例程,并且保證這個(gè)過(guò)程是串行處理的。
// 讀例程,處理IRP_MJ_READ
NTSTATUS AC_1810 Device::Read(KIrp I)
{
// 檢查輸入的合法性
if (I.ReadSize ()BLOCK_SIZE){
// 不合法返回錯誤代碼
I.Information()=0;
Return I.PnpComplete(this,STATUS_INVALID_PARAMETER);
}
// 讀0字節,永遠成功
if (I.ReadSize() = =0){
I.Information () = 0;
return
I.PnpComplete(this,STATUS_SUCCESS);
}
// 排隊這個(gè)IRP觸發(fā)StarIO,完成數據傳輸
return QueueIrp(I,LinkTo(CancelQueuedIrp));
}
// StartIo例程,完成I/O操作
VOID AC_1810 Device::StartIo(KIrp I)
{
// 檢測這個(gè)IRP是否被取消
if(!I.TestAndSetCancelRoutine(LinkTo(CancelQueuedIrp),NULL,CurrentIrp()) )
{
return;//取消則返回
}
switch (I.MajorFunction()) {
case IRP_MJ_READ:
//這個(gè)函數按邏輯完成讀操作
SerialRead(I);
Breadk
……
// 開(kāi)始處理下一個(gè)IRP
PnpNextIrp(I);
break;
}
}
ISA卡的WDM驅動(dòng)程序的主體部分就完成了。它具有PNP功能,可以方便地安裝卸載。在中斷到來(lái)的時(shí)候,系統使用兩個(gè)緩沖區完成數據的傳輸,可以避免數據丟失。
以上驅動(dòng)程序是使用Numega公司的DriverSutdio 2.01版,結合Visual C++ 6.0,Microsoft Windows 2000 sp1 DDk開(kāi)發(fā)調試通過(guò),并且成功地應用到實(shí)驗室開(kāi)發(fā)的高速旋轉機械實(shí)時(shí)狀態(tài)監控與故障診斷系統中,該系統界面友好高度可靠。同時(shí)由于加入了PNP的支持,使得該系統的硬件安裝卸載非常簡(jiǎn)便。這種技術(shù)可取代傳統的以DOS為核心的工業(yè)用監控與故障診斷系統,具有廣闊的應用前景。
linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)c++相關(guān)文章:c++教程
評論