WDM(Windows Driver Mode1)是Microsoft公司全新的Windows驅動程序模式,支持即插即用(PNP)、電源管理和WMI技術,它的運行平臺是Windows 98/2000/XP/2003操作系統。這種具有跨平臺性的設備驅動模型可以大大簡化驅動程序的開發工作,為用戶的PNP設備驅動完成了大量的底層工作。這也使得WDM對各種老設備,特別是那些不具有即插即用特性硬件的支持明顯的不足。在科研和工控中,最常用的數據采集卡通常都是基于PC總線的不能為PNP提供硬件支持的ISA設備。為這類硬件編寫非WDM驅動程序只能局部支持PNP特性,而且需要做大量額外的工作如:必須檢測硬件,為硬件創建設備對象(用于代表硬件),配置并初始化硬件使其正常工作,這些工作非常復雜。利用WDM可以大大簡化這些工作。
1 WDM的結構
WDM實際上是一個編寫驅動程序的規范。其驅動程序結構的特點和WINDOWS程序設計的消息驅動機制很相像,采用IRP驅動機制。WINDOWS 98和WINDOWS 2000處理IRP的方式一樣,本質卻完全不同。
Windows2000的內存管理采用了虛擬內存的概念,系統表現為具有一個比物理內存大得多的虛擬內存空間。每個進程都被賦予它自己的虛擬地址空間,這個地址空間劃分成固定大小的頁(x86、32位處理器的頁大小為4KB),一個頁可以駐留在物理內存(非分頁內存),或者被交換到硬盤上(分頁內存)。當進程中的一個線程正在運行時,該線程可以訪問只屬于它的進程的內存,屬于所有其他進程的內存則隱藏著,并且不能被正在運行的線程訪問。每個進程有獨立的內存空間,不會被其他程序訪問,保護了數據的完整性。這樣,有一部分內存實際上不是在物理內存中,而是在硬盤上。當訪問并不存在于實際物理內存的地址時,內存管理器引發DISPATCH_ LEVEL級別的頁故障中斷,調用硬盤驅動程序把故障頁讀入內存。所以,在DISPATCH LEVEL級別上運行代碼時,訪問非分頁內存是一個基本原則,否則進程將被阻塞,因為這個頁故障中斷被屏蔽了。這時,在當前的Windows系統中,就會發生藍屏。虛擬內存方便了應用程序l的開發,卻給ISA設備在分配資源時帶來一些復雜的問題。因為x86處理器的內存頁大小為4KB,所以在為ISA設備進行內存映射時每段就不要超過4KB。否則當訪問超出4KB地內存時就會出現上面所說的藍屏。
WDM驅動程序面對的主要內容是一系列內核驅動對象。這些對象包括驅動對象、設備對象,還有一系列的資源抽象對象如中斷對象、適配器對象(處理DMA操作)、內核模式派發器對象、控制器對象、推遲過程對象、定時器對象、設備隊列對象、回調對象等。其中驅動對象由I/O管理器負責創建和管理。WDM驅動程序利用IRP和這些對象完成硬件設備的抽象化,并對應用程序提供統一操作接口。這就是所謂的WDM規范。
WDM驅動程序的結構很簡單。它的主體是一個入口函數DriverEntry。DriverEntry的第一個參數是指針,指向一個剛被初始化的驅動程序對象,該對象代表驅動程序。WDM驅動程序的DriverEntry例程完成這個對象的初始化并返回。WDM驅動程序的DriverEntry例程的主要工作是把各種函數指針填入驅動程序對象。這些指針對操作系統指明了驅動程序容器中各種子例程的位置。它包括下面這些指針成員:
·DriverUnload指向驅動程序的清除例程。I/O管理器會在卸載驅動程序前調用該例程。通常WDM驅動程序的DriverEntry例程一般不分配任何資源,所以DriverUnload例程也沒有什么清除工作要做。
·DriverStartIo,如果驅動程序使用標準的串行IRP,則必須使用這個函數,使它指向驅動程序的StarIo例程。
·MajorFunction是一個指針數組,它主要處理各種用戶的I/O請求IRP。默認情總況下,用戶的所有I/O請求都會由I/O管理器返回失敗。驅動程序為要處理的IRP指定相應的派遣函數。
2 為ISA設備分配資源
雖然WDM驅動程序可以簡化很多工作,但是給ISA設備編寫WDM驅動程序也有困難。這個困難是ISA設備所需資源的分配問題。根據PNP的規范,支持PNP的設備如PCI總線設備有相應的寄存器標識自己和自己可以接受的資源,如中斷、端口范圍、內存范圍等,并且有相應的邏輯支持配置資源。這使得操作系統啟動過程中可以動態地規劃調整各個設備的資源而不需要用戶的干預。為了兼容非PNP設備,INF文件支持幾個命令為設備分配資源。這些信息初提供給NPN管理器,并且被PNP管理器用來與系統其它部分協商以完成非PNP設備的自動資源分配。LOGCONFIG為設備制定一個可選的資源設定。還有相應的IRQCONFIG、IOCONFIG、DMACONFIG、MEMCONFIG子命令,它們為設備指定具體的可選資源。語法如下:
ConfigPririty=
[DMAConfig=]
[IOConfig=
[IRQConfig=]
[MemConfig=]
其中CONFIGPRIOITY命令指定這個LOGCONFIG項的優先級。其余子命令表示設備選用的硬件資源。下面是一個例子:
[CX2590.Install]
……;其它命令
LogConfig=CX2590_DMA;指定配置項的名稱
[CX2590_DMA];配置項的名稱
ConfigPriority=NORMAL;配置的優先級
IOConfig=4@300-3ff%3ff(3ff::);指定IO范圍
IRQConfig=4,5,9,10,11 ;指定可選的中斷
DMAConfig=0,1,2,3 ;指定可選的DMA
在INF文件中加入LOGCONFIG命令可以解決ISA總線設備資源的自動分配問題,就可以為ISA總線設備編寫WDM驅動程序。
3 一個ISA設備WDM驅動程序的實現
使用Numega公司的開發工具DriverStudio 2.01可以大大地簡化驅動程序的開發過程。DriverStudio開發通用內核模式的開發包是DriverWorks。DriverWorks是一個面向對象的工具包。它封裝了比較底層的繁復操作,提供給開發者一個簡潔的界面。同時,DriverWorks和Visual C++有很多的接口:DriverWorks專門為Visual C++提供了一個專門開發WDM驅動程序的WIZARD。在WIZARD指導下,開發者可以很容易地生成一個驅動程序的框架。開發者要作的工作就是根據特定硬件編寫相應的代碼。
開發的高速旋轉機械監控與故障診斷系統采用的是北京大恒公司的具有FIFO(隊列形式實現的緩存)的8路數據采集卡AC 1810。它的特點是由硬件自動完成采用操作:當FIFO半滿的時候,系統產生中斷通知用戶取走數據;同時,硬件繼續自動采樣FIFO的另一關。驅動程序的主要工作包括設備I/O讀操作和中斷服務操作。下面是WIZARD生成的驅動對換和設備對象的定義(只取主要部分):
// 驅動對象
class AC_1810 : public Kdriver
{
SAFE_DESTRUCTORS
public:
virtual NTSTATUS
DriverEntry(PUNICOE-STRING
RegistryPath);
//驅動程序的入口函數
virtual NTSTATUS
AddDevice(PDEVICE_OBJECT Pdo);
//完成設備對象和驅動對象的連接
……
};
//設備對象
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中斷服務例程
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);
// 開始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);
//完成實際的I/O操作
NTSTATUS IOCTL_SETUP_Handler(KIrp I);
//采樣參數設定
NTSTATUS IOCTL_REW_Handler(KIrp I);
// 開始/停止采樣
……
protected:
KioRange m_IoPotrRange0
// 管理I/O資源
Kinterrupt m_Irq;
// 管理中斷資源
……
};
在實際操作過程中,采用中斷讀數的方法。在驅動程序中設置了兩個緩沖區,一個前臺緩沖區,一個后臺緩沖區(用作后備緩沖區),系統總是先使用前臺緩沖區。這樣可以保證采樣數據序列的時間順序。
具體實現如下:
// ISR例程,完成數據從FIFO中讀出
BOOLEAN AC_1810Device::Isr_Irq(void)
{
//是否觸發不斷?未觸發則返回,判斷兩個緩沖區情況,都滿則返回
……
// 前臺緩沖區未滿,使用前臺緩沖區
if(m_pBuffer->numused < MAX_READ_BUF){
for(int i=0;i
m_pBuffer_>buff[m_pBuffer->numused+i]=READ_FIFO;
}
m_pBuffer->numused +=BLOCK_SIZE;
}
else
//完成其它情況的判斷
……
return TRUE;// 中斷成功返回
}
當應用程序使用標準Win32 API對設備進行讀操作的時候,I/O管理器通知驅動程序并觸發對Read函數的調用。對于通常的串行設備,在Read函數的最后排隊IRP請求,此時系統就可以觸發StartIO例程,并且保證這個過程是串行處理的。
// 讀例程,處理IRP_MJ_READ
NTSTATUS AC_1810 Device::Read(KIrp I)
{
// 檢查輸入的合法性
if (I.ReadSize ()
// 不合法返回錯誤代碼
I.Information()=0;
Return I.PnpComplete(this,STATUS_INVALID_PARAMETER);
}
// 讀0字節,永遠成功
if (I.ReadSize() = =0){
I.Information () = 0;
return
I.PnpComplete(this,STATUS_SUCCESS);
}
// 排隊這個IRP觸發StarIO,完成數據傳輸
return QueueIrp(I,LinkTo(CancelQueuedIrp));
}
// StartIo例程,完成I/O操作
VOID AC_1810 Device::StartIo(KIrp I)
{
// 檢測這個IRP是否被取消
if(!I.TestAndSetCancelRoutine(LinkTo(CancelQueuedIrp),NULL,CurrentIrp()) )
{
return;//取消則返回
}
switch (I.MajorFunction()) {
case IRP_MJ_READ:
//這個函數按邏輯完成讀操作
SerialRead(I);
Breadk
……
// 開始處理下一個IRP
PnpNextIrp(I);
break;
}
}
ISA卡的WDM驅動程序的主體部分就完成了。它具有PNP功能,可以方便地安裝卸載。在中斷到來的時候,系統使用兩個緩沖區完成數據的傳輸,可以避免數據丟失。
以上驅動程序是使用Numega公司的DriverSutdio 2.01版,結合Visual C++ 6.0,Microsoft Windows 2000 sp1 DDk開發調試通過,并且成功地應用到實驗室開發的高速旋轉機械實時狀態監控與故障診斷系統中,該系統界面友好高度可靠。同時由于加入了PNP的支持,使得該系統的硬件安裝卸載非常簡便。這種技術可取代傳統的以DOS為核心的工業用監控與故障診斷系統,具有廣闊的應用前景。
-
內存
+關注
關注
8文章
3019瀏覽量
74003 -
定時器
+關注
關注
23文章
3246瀏覽量
114719 -
驅動程序
+關注
關注
19文章
831瀏覽量
48024
發布評論請先 登錄
相關推薦
評論