在修改C8051F320單片機(jī)的驅(qū)動(dòng)程序時(shí),一開始真的有點(diǎn)無從下手,幸好看到了這本書-《USB應(yīng)用開發(fā)技術(shù)大全》(人民郵電出版社),使自己對(duì)那一大堆的代碼,終于理出了思路。在這里就把WDM驅(qū)動(dòng)程序的組成的大概內(nèi)容摘抄出來,與大家分享。
在Windows操作系統(tǒng)下,一般不能直接對(duì)硬件接口進(jìn)行操作,而必須采用驅(qū)動(dòng)程序作為橋梁。主要程序和驅(qū)動(dòng)程序直接通信,交換數(shù)據(jù);而驅(qū)動(dòng)程序則和計(jì)算機(jī)的硬件資源進(jìn)行通信。
WDM(Windows Driver Model),即Windows驅(qū)動(dòng)程序模型,是Microsoft力推的全新驅(qū)動(dòng)程序模式,旨在通過一種靈活的方式來簡化驅(qū)動(dòng)程序的開發(fā),實(shí)現(xiàn)對(duì)硬件的支持,并減少和降低所有所須開發(fā)的驅(qū)動(dòng)程序的數(shù)量和復(fù)雜性。
在WDM驅(qū)動(dòng)程序模型中主要包括兩個(gè)驅(qū)動(dòng)程序:功能驅(qū)動(dòng)程序和總線驅(qū)動(dòng)程序。由于總線驅(qū)動(dòng)程序已經(jīng)由操作系統(tǒng)提供,因此,關(guān)心的主要是功能驅(qū)動(dòng)程序。一個(gè)完整的功能驅(qū)動(dòng)程序包括許多例程:
基本驅(qū)動(dòng)程序例程:DriverEntry和AddDevice。
I/O控制例程:StartIO、AdapterControl、OnInterrupt……
派遣函數(shù):DispatchPnP、DispatchPower、DispatchRead、DispatchWrite……
當(dāng)操作系統(tǒng)遇到一個(gè)I/O請(qǐng)求包(IRP)時(shí),系統(tǒng)調(diào)用驅(qū)動(dòng)程序中的例程來執(zhí)行相應(yīng)的操作。在這些例程中,DriverEntry例程和AddDevice例程對(duì)每個(gè)驅(qū)動(dòng)程序都是必須的,當(dāng)然還需要其他一些I/O控制例程和派遣函數(shù)。其中StartIO例程用于對(duì)IRP進(jìn)行排隊(duì),AdapterControl例程用于執(zhí)行DMA操作的驅(qū)動(dòng)程序中,OnInterrupt例程為中斷服務(wù)例程。
I/O請(qǐng)求包(IRP)主要由MajorFunction和MinorFunction字段構(gòu)成,當(dāng)然還可以包括Struct Read和Struct Write等控制參數(shù)。MajorFunction字段是IRP的主要功能代碼,MinorFunction字段是IRP的次要功能代碼,它們指明了驅(qū)動(dòng)程序應(yīng)該執(zhí)行的具體操作。
常用的IRP主功能代碼:
IRP_MJ_CREATE 打開文件句柄
IRP_MJ_CLOSE 關(guān)閉文件句柄
IRP_MJ_READ 讀取數(shù)據(jù)
IRP_MJ_WRITE 寫數(shù)據(jù)
IRP_MJ_CLEANUP 清除掛起的IRP
IRP_MJ_DEVICE_CONTROL 設(shè)備I/O控制
IRP_MJ_INTERNAL_DEVICE_CONTROL 底層的設(shè)備I/O控制
IRP_MJ_SYSTEM_CONTROL 系統(tǒng)管理與測試
IRP_MJ_POWER 電源管理
IRP_MJ_PNP 即插即用管理
WDM驅(qū)動(dòng)程序的功能實(shí)現(xiàn)主要由特定的例程決定。在不同的情況下,操作系統(tǒng)或主機(jī)程序觸發(fā)相應(yīng)的例程,實(shí)現(xiàn)不同的操作。一個(gè)典型的WDM驅(qū)動(dòng)程序由以下部分構(gòu)成:
入口例程DriverEntry:主要用于WDM驅(qū)動(dòng)程序的初始化,是所有驅(qū)動(dòng)程序必須的。
即插即用例程:用戶處理即插即用設(shè)備的添加、停止和刪除等。
分發(fā)例程:用于處理主機(jī)程序的各種I/O請(qǐng)求。
電源管理例程:用于處理系統(tǒng)和設(shè)備的電源管理請(qǐng)求。
卸載例程:處理WDM驅(qū)動(dòng)程序的卸載等操作。
驅(qū)動(dòng)程序入口例程,即DruverEntry例程,是所有驅(qū)動(dòng)程序的入口。DriverEntry例程由操作系統(tǒng)的I/O管理器在設(shè)備驅(qū)動(dòng)功能加載的時(shí)候進(jìn)行調(diào)用,主要負(fù)責(zé)WDM驅(qū)動(dòng)程序的初始化。
即插即用例程,當(dāng)設(shè)備連接到計(jì)算機(jī)上的時(shí)候,操作系統(tǒng)自動(dòng)識(shí)別,自動(dòng)選擇并加載合適的驅(qū)動(dòng)程序。當(dāng)設(shè)備從系統(tǒng)中移除的時(shí)候,自動(dòng)處理相應(yīng)的清除工作。在設(shè)備連接和斷開的時(shí)候,整個(gè)過程不需要用戶的干預(yù)。
其例程主要有兩個(gè):一個(gè)AddDevice例程和一個(gè)IRP_MJ_PNP例程。
AddDevice 例程主要使用IoCreateDevice函數(shù)來創(chuàng)建和初始化一個(gè)設(shè)備對(duì)象,然后初始化設(shè)備擴(kuò)展,并使用IoAttachDeviceToDeviceStack函數(shù)將設(shè)備連接到設(shè)備棧。
IRP_MJ_PNP例程主要負(fù)責(zé)處理系統(tǒng)即插即用管理器發(fā)出的PnP信息,包括啟動(dòng)設(shè)備(IRP_MN_START_DEVICE)、停止設(shè)備(IRP_MN_STOP_DEVICE)、刪除設(shè)備(IRP_MN_REMOVE_DEVICE)等。
分發(fā)例程,用于處理各種I/O請(qǐng)求,這是主機(jī)程序控制硬件的接口。每個(gè)分發(fā)例程對(duì)應(yīng)一個(gè)Win32函數(shù),主機(jī)程序便是通過Win32函數(shù)來和相應(yīng)的分發(fā)例程通信的。常用的分發(fā)例程如下所示。
IRP_MJ_CREATE例程,對(duì)應(yīng)的Win32函數(shù)為CreateFile。
IRP_MJ_CLOSE例程,對(duì)應(yīng)的Win32函數(shù)為CloseHandle。
IRP_MJ_READ例程,對(duì)應(yīng)的Win32函數(shù)為ReadFile。
IRP_MJ_WRITE例程,對(duì)應(yīng)的Win32函數(shù)為WriteFile。
IRP_MJ_DEVICE_CONTROL例程,對(duì)應(yīng)的Win32函數(shù)為DeviceIoControl。
一般來說,并不是所有的分發(fā)例程都是必須的,但是所有的驅(qū)動(dòng)程序都要包含IRP_MJ_CREATE例程和IRP_MJ_CLOSE例程。如果沒有這兩個(gè)例程,主機(jī)程序便不能獲得設(shè)備句柄,也就不能控制設(shè)備。
電源管理例程,用于管理設(shè)備或系統(tǒng)的電源狀態(tài),其有四個(gè)次功能代碼:
IRP_MN_SET_POWER設(shè)置系統(tǒng)或設(shè)備電源狀態(tài)。
IRP_MN_QUERY_POWER查詢是否允許改變系統(tǒng)或設(shè)備的電源狀態(tài)。
IRP_MN_WAIT_WAKE響應(yīng)外部事件以喚醒設(shè)備。
IRP_MN_POWER_SEQUENCE確認(rèn)設(shè)備是否進(jìn)入指定的電源狀態(tài)。
卸載例程,只在需要卸載驅(qū)動(dòng)程序的時(shí)候調(diào)用,一般來說,驅(qū)動(dòng)程序的卸載例程需要完成如下幾個(gè)方面的工作:保存設(shè)備的狀態(tài),以便于設(shè)備恢復(fù)到最近保存的設(shè)備狀態(tài)。釋放該驅(qū)動(dòng)程序所占用的內(nèi)存空間。刪除設(shè)備對(duì)象及其符號(hào)鏈接名或GUID描述符。通常情況下,卸載例程可以什么也不做,因?yàn)槠渲饕墓ぷ鞫荚谔幚砝?/span>IRP_MN_REMOVE_DEVICE中完成。