版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第十一章Windows輸入/輸出程序設(shè)計(jì)11.1Windows9x和虛擬設(shè)備驅(qū)動(dòng)程序11.2設(shè)備驅(qū)動(dòng)程序的編寫
11.3Win32應(yīng)用程序和VxD之間的通信
11.4Windows9x的輸入/輸出
11.5Windows9x的中斷處理
11.6VxD實(shí)例
11.7WDM設(shè)備驅(qū)動(dòng)程序
11.1Windows9x和虛擬設(shè)備驅(qū)動(dòng)程序
11.1.1
Windows9x的分層結(jié)構(gòu) Windows9x是一個(gè)分層結(jié)構(gòu)的操作系統(tǒng),由兩個(gè)不同的層構(gòu)成。頂層(ring3層):給應(yīng)用程序的運(yùn)行提供Win32API服務(wù),包括所有的由USER、GDI、和KERNEL提供的服務(wù)。Windows9x應(yīng)用程序和Win32API服務(wù)一起構(gòu)成操作系統(tǒng)的頂層,運(yùn)行在一個(gè)單一的虛擬機(jī)中,統(tǒng)稱為系統(tǒng)VM。每一個(gè)DOS應(yīng)用程序都在一個(gè)獨(dú)立的虛擬機(jī)中運(yùn)行。操作系統(tǒng)允許多個(gè)虛擬機(jī)同時(shí)處于運(yùn)行狀態(tài)。底層(ring0層):Windows9x操作系統(tǒng)的底層就是虛擬機(jī)管理器。對(duì)于應(yīng)用程序而言,虛擬機(jī)管理器是透明的,應(yīng)用程序感覺(jué)不到管理器的存在。Windows9x虛擬機(jī)管理器由一個(gè)內(nèi)核服務(wù)集和許多虛擬設(shè)備驅(qū)動(dòng)程序(VxDs)組成。許多VxDs是由Microsoft公司隨操作系統(tǒng)提供的,如鍵盤和顯示器等。其他VxDs由第三方提供或者由用戶自行編寫,它們用來(lái)支持特殊的硬件或軟件,完成特定的功能。VxDs中的程序運(yùn)行在ring0層,可以執(zhí)行所有的指令,可以完成任何的軟硬件的操作。11.1.2虛擬設(shè)備虛擬設(shè)備(VxD)是一些程序,它們通過(guò)對(duì)計(jì)算機(jī)的各種硬件設(shè)備和支撐軟件進(jìn)行虛擬化,實(shí)現(xiàn)對(duì)設(shè)備無(wú)關(guān)的虛擬機(jī)管理器(VMM)的支持。VxDs可以虛擬一臺(tái)計(jì)算機(jī)上的所有硬件設(shè)備,如時(shí)鐘、串行通信口、并行通信口等。VxDs也能對(duì)軟件提供支持,它們并不一定有相應(yīng)的硬設(shè)備。Windows9x中,用戶自己也可以安裝新的設(shè)備驅(qū)動(dòng)程序來(lái)對(duì)新增硬件提供支持,或者在系統(tǒng)范圍內(nèi)提供某種軟件服務(wù)。VxDs通過(guò)VMM或其他虛擬設(shè)備向上層提供任何類型的服務(wù)。對(duì)Windows9x應(yīng)用程序來(lái)講,虛擬設(shè)備就是真實(shí)設(shè)備,換句話講,應(yīng)用程序是分不清哪個(gè)設(shè)備是由真實(shí)硬件支持的真實(shí)設(shè)備,哪個(gè)設(shè)備是由虛擬設(shè)備驅(qū)動(dòng)程序模擬的虛擬設(shè)備。11.1.3設(shè)備驅(qū)動(dòng)程序Windows設(shè)備驅(qū)動(dòng)程序是Windows用來(lái)同各種硬件設(shè)備進(jìn)行交互的一些程序。Windows并不直接對(duì)硬件設(shè)備進(jìn)行訪問(wèn),而是通過(guò)加載該設(shè)備的驅(qū)動(dòng)程序,調(diào)用其中的某些接口函數(shù)來(lái)完成對(duì)硬件設(shè)備的操作。每個(gè)設(shè)備驅(qū)動(dòng)程序都有一組完成各種功能的函數(shù)輸出,Windows通過(guò)調(diào)用這些函數(shù)來(lái)對(duì)某一設(shè)備完成特定的操作。在Windows9x操作系統(tǒng)中,各種硬件設(shè)備,如通信端口、鼠標(biāo)、鍵盤和顯示器等,都有相應(yīng)的設(shè)備驅(qū)動(dòng)程序。用戶往系統(tǒng)中安裝其他可選設(shè)備時(shí),需要提供和安裝其相應(yīng)的設(shè)備驅(qū)動(dòng)程序。11.2設(shè)備驅(qū)動(dòng)程序的編寫11.2.1VxD程序結(jié)構(gòu)
VToolsD提供了三個(gè)基本框架類:VDevice類提供了眾多的成員函數(shù)來(lái)處理從虛擬機(jī)(VMM)或其他VxDs發(fā)來(lái)的控制消息;VVirtualMachine類及其派生類用來(lái)處理一些針對(duì)虛擬機(jī)的特殊的控制消息;VThread類處理與線程有關(guān)的控制消息。若所建的VxD對(duì)特定的控制消息感興趣,則要重載其相應(yīng)的成員函數(shù)。1.VxD的控制消息VToolsD提供的三個(gè)基本框架類可以處理50多條控制消息,大多數(shù)的VxD則僅僅處理其中的一部分消息。動(dòng)態(tài)安裝的VxD在安裝時(shí)會(huì)收到Sys_Dynamic_Device_Init消息,卸載時(shí)會(huì)收到Sys_Dynamic_Device_Exit消息。靜態(tài)安裝的VxD安裝時(shí)第一個(gè)消息是Windows初始化時(shí)發(fā)出Sys_Critical_Init消息,然后是Device_Init消息,最后是plete消息。Windows關(guān)閉時(shí)首先發(fā)出Sys_VM_Terminate消息,而后是System_Exit消息,最后為Sys_Critical_Exit消息。2.VDevice類用VtoolsD開發(fā)VxD首先要從派生VDevice類開始。加載VxD時(shí)系統(tǒng)會(huì)自動(dòng)生成一個(gè)VDevice類的實(shí)例。在開發(fā)VxD時(shí)一般只用到VDevice類,只有處理VDevice類不能響應(yīng)的消息時(shí)才用到VVirtualMachine類和VThread類。派生VDevice類的方法:#defineDEVICE_CLASS MyDeviceclassMyDevice:publicVDevice{virtualBOOLOnDeviceInit(VMHANDLEhSysVM,PCHARpszCmdTail); //其他感興趣的成員函數(shù)。};BOOLOnDeviceInit(VMHANDLEhSysVM,PCHARpszCmdTail){ //具體初始化程序。
if初始化成功return(TRUE)elsereturn(FALSE);}11.2.2開發(fā)工具的使用
安裝VtoolsD之前,首先必須安裝VC++6.0。1.VxD設(shè)備參數(shù)(DeviceParameters)
圖11-1為QuickVxD設(shè)備參數(shù)定義欄,主要設(shè)備參數(shù)有:DeviceName:所建VxD的設(shè)備名。每一個(gè)VxD都應(yīng)有它的設(shè)備名字,設(shè)備名不多于8個(gè)字符。DeviceID:所建VxD的設(shè)備標(biāo)識(shí)。如果將要建立的VxD提供了對(duì)其他VxD的調(diào)用入口,或提供了對(duì)其他虛擬8086模式程序的API調(diào)用入口,或保護(hù)模式程序API調(diào)用入口,則DeviceID是必須要具備的。DeviceID是一個(gè)16位的無(wú)符號(hào)整型數(shù),不能任意取值,以免與其他VxD相沖突。圖11-1DeviceInitializationOrder:確定Windows系統(tǒng)啟動(dòng)時(shí)對(duì)該VxD的裝載順序。如果將要建立的VxD不依賴于其他VxD是否裝載,則此項(xiàng)可以使用VtoolsD提供的缺省值:UNDEFINED_INIT_ORDER。否則該參數(shù)必須設(shè)置為在某個(gè)已知VxD之前裝載。DeviceInitializationOrder常數(shù)的形式為:xxxx_INIT_ORDER,其中xxxx表示某個(gè)已知VxD的設(shè)備名。C/C++Framework:決定生成的VxD源程序的代碼類別是基于C語(yǔ)言的還是C++語(yǔ)言的。DynamicallyLoadable:決定將建立的VxD是否可以被操作系統(tǒng)動(dòng)態(tài)加載。Version:建立的VxD的版本號(hào),包括MajorVersion和MinorVersion兩項(xiàng)。2.應(yīng)用程序調(diào)用入口(ApplicationInterfaces)
QuickVxD采用下面幾種方式為應(yīng)用程序提供調(diào)用接口:V86EntryPoint為虛擬8086模式程序調(diào)用VxD服務(wù)提供了調(diào)用入口點(diǎn)。PMEntryPoint為保護(hù)模式程序調(diào)用VxD服務(wù)提供調(diào)用入口點(diǎn)。DOS保護(hù)模式程序調(diào)用入口(Vendorv86API)3.VxD服務(wù)(VxDServices)
VxDServices是提供給其他VxD的服務(wù)函數(shù)。4.VxD的控制消息(ControlMessages)
QuickVxD提供兩類控制消息:ControlMessage:支持Win3.1和Windows9xWindows95ControlMessage:只支持Windows9x5.產(chǎn)生C/C++源文件,工程文件按下GenerateNow按鈕,QuickVxD將在校驗(yàn)所有選擇項(xiàng)和填寫項(xiàng)無(wú)誤的情況下自動(dòng)生成輸出文件若檢驗(yàn)有誤,QuickVxD會(huì)提供出錯(cuò)信息圖11-2圖11-36.編譯生成VxD文件 有兩種方式編譯生成VxD文件采用命令行的方式編譯: MICROSOFTC++: nmake/fVXDNAME.MAK BORLANDC++: make/fVXDNAME.MAK采用MSVC++6.0的集成環(huán)境生成VxD:(1)啟動(dòng)MSVC++6.0。(2)從File菜單選擇OpenWorkspace,打開相應(yīng)的
.mak文件。(3)在接下的兩個(gè)對(duì)話框中按“是(Y)”或“OK"按鈕。(4)保存相應(yīng)的.dsp文件。(5)在當(dāng)前工程中添加所有的.cpp和.h文件。11.3Win32應(yīng)用程序和VxD之間的通信11.3.1Win32應(yīng)用程序?qū)xD的通信1.Win32應(yīng)用程序的編程 Win32應(yīng)用程序調(diào)用VxD,首先必須獲取VxD的設(shè)備句柄,可以用CreateFile來(lái)獲取VxD的設(shè)備句柄:HANDLEhDevice=CreateFile("\\\\.\\VxDName.vxd",0,0,0,CREATE_NEW,FILE_FLAG_DELETE_ON_CLOSE,0);假設(shè)VxD的文件名為VxDName.vxd\\\\.\\VxDName.vxd為VxD的路徑和文件名格式加載VxD時(shí)先搜索當(dāng)前目錄,然后搜索C:\Windows\System目錄。CreateFile函數(shù)實(shí)際是動(dòng)態(tài)加載了VxD。 成功獲取VxD的設(shè)備句柄后,可以在Win32應(yīng)用程序中調(diào)用DeviceIoControl來(lái)傳遞參數(shù)或使用VxD:DeviceIoControl( HANDLE hDevice, //VxD句柄 DWORD dwIoControlCode, //VxD控制代碼 LPVOID lpInBuf, //輸入數(shù)據(jù)塊指針 DWORD cbInBuf, //輸入數(shù)據(jù)塊大小 LPVOID lpOutBuf, //輸出的數(shù)據(jù)塊指針 DWORD cbOutBuf, //輸出數(shù)據(jù)塊大小 LPDWORDlpBytesReturned,//返回的字節(jié)數(shù)長(zhǎng)度指針 NULL )hDevice是CreateFile獲取的VxD設(shè)備句柄dwIoControlCode是應(yīng)用程序向VxD發(fā)出的命令碼lpInBuf和cbInBuf是Win32應(yīng)用程序向VxD傳送的數(shù)據(jù)塊的地址及大小LpOutBuf、cbOutBuf和lpBytesReturned是VxD返回給Win32應(yīng)用程序的數(shù)據(jù)塊的地址、大小以及實(shí)際返回的字節(jié)數(shù)完成通信后,Win32應(yīng)用程序應(yīng)調(diào)用CloseHandle(hDevice)關(guān)閉VxD,即動(dòng)態(tài)卸載VxD。2.VxD的編程Win32應(yīng)用程序調(diào)用DeviceIoControl函數(shù)向VxD發(fā)出命令后,系統(tǒng)即向VxD發(fā)出W32_DEVICEIoCONTROL控制消息。VxD的VDevice類的成員函數(shù)OnW32DeviceIoControl函數(shù)被觸發(fā)來(lái)響應(yīng)此控制消息OnW32DeviceIoControl函數(shù)定義為: VDevice::OnW32DeviceIoControl(PIOCTLPARAMSpParams)參數(shù)pParams為指向PIOCTLPARAMS結(jié)構(gòu)的指針。PIOCTLPARAMS結(jié)構(gòu)定義如下(部分):typedefstructtagIOCTLParams( ...DWORD dioc_IOCtlCode; //應(yīng)用程序發(fā)出的VxD控制代碼PVOID dioc_InBuf, //輸入數(shù)據(jù)塊指針DWORD dioc_cbInBuf, //輸入數(shù)據(jù)塊大小PVOID dioc_OutBuf, //輸出的數(shù)據(jù)塊指針DWORD dioc_cbOutBuf, //輸出數(shù)據(jù)塊大小PDWORD dioc_bytesret, //返回的字節(jié)數(shù)長(zhǎng)度指針...)IOCTLPARAMS,*PIOCTLPARAMS;這些參數(shù)分別與DeviceIOControl函數(shù)的參數(shù)相對(duì)應(yīng)。OnW32DeviceIoControl函數(shù)定義如下:DWORDXYZDevice::OnW32DeviceIoControl(PIOCTLPARAMSp){switch(p->dioc_IOCtlCode){ caseDIOC_OPEN://Win32應(yīng)用程序調(diào)用CreateFile時(shí)產(chǎn)生。
return(0); caseDIOC_CLOSEHANDLE://Win32應(yīng)用程序調(diào)用CloseHandle時(shí)或退出時(shí)產(chǎn)生。 return(0); caseCMD1://CMD1命令對(duì)應(yīng)的處理程序,由DeviceIOControl發(fā)出。
return(0); //其他命令的相應(yīng)程序。
default://非法命令。
returnERROR_INVALID_PARAMETER; } }11.3.2VxD對(duì)Win32應(yīng)用程序的通信一般情況下都是Win32應(yīng)用程序調(diào)用VxD提供的服務(wù)。發(fā)生中斷時(shí),有一些特定的事件發(fā)生時(shí),需要由VxD通知Win32應(yīng)用程序,也就是VxD要首先發(fā)起對(duì)Win32應(yīng)用程序的通信。VxD對(duì)Win32應(yīng)用程序的通信有如下三種方法:(1)異步過(guò)程調(diào)用(APC,asynchronousprocedurecall)(2)Win32事件(3)向Win32應(yīng)用程序發(fā)送消息異步過(guò)程調(diào)用要用到的函數(shù):1.Win32應(yīng)用程序回調(diào)函數(shù)DWORDWINAPICallBackAPC(PVOIDparam) { //具體處理程序
return(0); }參數(shù)param為VxD傳遞給應(yīng)用程序的參數(shù)指針,函數(shù)名可任取。2.向處于警覺(jué)等待狀態(tài)的Win32線程發(fā)送消息的函數(shù)VWIN32_QueueUserApc(PVOIDpR3Proc,DWORDParam,THREADHANDLEhThread)pR3Proc為Win32應(yīng)用程序回調(diào)函數(shù)的入口地址Param為VxD傳遞給Win32應(yīng)用程序回調(diào)函數(shù)的參數(shù)指針hThread為當(dāng)前線程的句柄3.使線程處于警覺(jué)等待狀態(tài)的函數(shù)SleepEx(DWORDdwMilliseconds,BOOLbAlertable)
dwMilliseconds為等待時(shí)間(毫秒),使用INFINITE則為無(wú)限等待。Balertable在此可設(shè)為TRUE。//以下是VxD中的程序片斷PVOIDCallBackApc=0;THREADHANDLETheThread=0;intparams=0; //某一消息處理函數(shù)BOOLXYZDevice::XXX(VMHANDLEhVM){ //具體處理程序//下面的函數(shù)調(diào)用向處于警覺(jué)等待狀態(tài)的Win32線程發(fā)送消息,//即異步過(guò)程調(diào)用Win32應(yīng)用程序回調(diào)函數(shù)CallBAckApc。 VWIN32_QueueUserApc(CallBAckApc,(DWORD)¶m,TheThread) }DWORDXYZDevice::OnW32DeviceIoControl(PIOCTLPARAMSp){switch(p->dioc_IOCtlCode){ //其他命令的相應(yīng)程序。
caseCMD1: //CMD1命令是向VxD傳送Win32回調(diào)函數(shù)入口地址。
CallBackApc=p->dioc_InBuf;TheThread=Get_Cur_Thread_Handle(); return(0); //其他命令的相應(yīng)程序。
}}//以下是Win32應(yīng)用程序的片斷DWORDWINAPICallBackAPC(PVOIDparam){//具體處理程序
return(0);}voidmain(){HANDLEhDevice;hDevice=CreateFile("\\\\.\\XYZDevice.VxD",0,0,0,CREATE_NEW,FILE_FLAG_DELETE_ON_CLOSE,0); if(hDevice==INVALID_HANDLE_VALUE) {printf("無(wú)法打開XYZDevice.VxD!"); exit(1); } printf("按Ctrl-C鍵退出程序\n"); while(TRUE)SleepEx(INFINITE,TRUE); CloseHandle(hDevice);}11.4Windows9x的輸入/輸出11.4.1訪問(wèn)I/O端口硬件設(shè)備對(duì)I/O地址空間的訪問(wèn)采用inp和outp命令:int_inp(unsignedshortport);unsignedshort_inpw(unsignedshortport);unsignedlong_inpd(unsignedshortport);int_outp(unsignedshortport,intdatabyte);unsignedshort_outpw(unsignedshortport,unsignedshortdataword);unsignedlong_outpd(unsignedshortport,unsignedlongdataword);11.4.2訪問(wèn)內(nèi)存映射硬件設(shè)備Windows9x采用虛擬內(nèi)存的工作方式,內(nèi)存中的某些頁(yè)完全有可能被交換到磁盤上,因此程序在訪問(wèn)硬件端口映射的線性內(nèi)存時(shí),要采取相應(yīng)的措施來(lái)阻止這種交換的發(fā)生。有3個(gè)函數(shù)來(lái)完成內(nèi)存映射過(guò)程:1.PvoidPageResever(DWORDipage,DWORDnpages,DWORDflags)
功能:分配指定頁(yè)數(shù)的線性空間。 參數(shù):ipage:線性頁(yè)開始的范圍??梢匀∠铝兄担? PR_PRIVATE在ring3層私有區(qū)域的任意位置。 PR_SHARED在ring3層共享區(qū)域的任意位置。 PR_SYSTEM在系統(tǒng)的任意位置。 npages:保留的線性頁(yè)數(shù)(一頁(yè)為4K) flags:0或下列值: PR_FIXED:固定的 PR_STATIC:拒絕委托,直到靜態(tài)標(biāo)志被指定
才釋放操作。 PR_4MEG:強(qiáng)迫地址在4M邊界。返回值:如果成功返回線性地址,返回0,否則返回-1。2.BOOLmitPhys(DWORDipage,Dwordnpages,DWORDphyspage,DWORDflags); 功能:將指定的物理空間聯(lián)系到線性空間。 參數(shù):ipage:被聯(lián)系的第一個(gè)物理頁(yè)的線性頁(yè)號(hào) npage:被聯(lián)系的頁(yè)數(shù)。 physpage:第一個(gè)物理頁(yè)的物理頁(yè)號(hào)。 flags:取下列值: PC_INCR:線性頁(yè)被映射到物理上鄰接的
物理頁(yè)上。 PC_USER:這些頁(yè)可在ring3層被訪問(wèn)。 PC_0USER:此些頁(yè)可被讀寫。 返回值:如果成功返回TRUE,否則返回FALSE。3.DWORDLinPageLock(DWORDHlinPgNum,DWORDnPages,DWORDflags); 功能:線性頁(yè)面鎖定。 參數(shù):HlinPgNum:要鎖定的線性頁(yè)面的第一頁(yè)。 npages:被鎖定的頁(yè)數(shù)。 flags:可以是0或取下列值之一: PAGELOCKEDIFDP:僅當(dāng)該虛擬頁(yè)交換設(shè)備使用
MS-DOS或BIOS函數(shù)去寫硬件頁(yè)時(shí)被鎖定。 PAGEMAPGLOBAL:映射的一個(gè)全局線性地址被
鎖定。 PAGEMARKDIRTY:如果此些頁(yè)被寫,標(biāo)上標(biāo)志。返回值:當(dāng)PAGEMAPGLOBAL被指定時(shí),如果成功,返回
的是線性基地址,否為返回0。 PAGEMAPGLOBAL未指定時(shí),成功則返回TRUE,
否則返回FALSE。映射處理的最后還需進(jìn)行線性地址+物理地址偏移的處理。這是因?yàn)橐幚淼奈锢砜臻g首地址不一定正好是物理頁(yè)(一頁(yè)是4KB)的首地址。釋放映射空間只要調(diào)用LinPageUnLock、mit和PageFree即可。11.5Windows9x的中斷處理11.5.1VPICD(虛擬可編程中斷控制器)在多任務(wù)環(huán)境里,硬件中斷管理程序是重要的系統(tǒng)級(jí)功能。它不僅要把硬件發(fā)生的中斷事件傳遞給相應(yīng)的驅(qū)動(dòng)程序和應(yīng)用程序,還要允許某些設(shè)備驅(qū)動(dòng)程序提供它們特殊的中斷服務(wù)處理。在Windows9X平臺(tái)下,VPICD就是這樣的硬件設(shè)備管理程序,它負(fù)責(zé)管理所有的硬件中斷事件VPICD通過(guò)一個(gè)缺省機(jī)制觸發(fā)駐留在虛擬機(jī)內(nèi)的中斷處理函數(shù)。并且它可以允許其他VxD重載中斷處理函數(shù)。11.5.2VHardwareInt類
VHardwareInt類可以實(shí)現(xiàn)對(duì)某個(gè)中斷請(qǐng)求(IRQ)號(hào)的虛擬化,重載其成員函數(shù)OnHardwareInt便可響應(yīng)該中斷的請(qǐng)求。VHardwareInt類的主要成員函數(shù)有:(1)VHardwareInt::VHardwareInt(intirq,DWORD
flags,DWORDtimeout,PVOIDrefdata) 構(gòu)造函數(shù),irq是要虛擬化的中斷號(hào),其值為0到15,其余參數(shù)一般設(shè)為0。(2)VOIDVHardwareInt::OnHardwareInt(VMHANDLE
hVM) 中斷發(fā)生時(shí),本成員函數(shù)被調(diào)用。一定要重載此函數(shù)才能響應(yīng)中斷。(3)BOOLVHardwareInt::hook()此成員函數(shù)將虛擬irq和VHardwareInt類中的五個(gè)成員函數(shù)相連,它們是OnHardwareInt,OnVirtualInt,OnVirtualRET,OnVirtualEOI和OnVirtualMask。只有調(diào)用hook后,這五個(gè)成員函數(shù)才會(huì)在中斷響應(yīng)時(shí)被調(diào)用。hook返回TRUE表示成功,返回FALSE表示失敗。(4)BOOLVHardwareInt::unhook() 此成員函數(shù)將取消本irq的虛擬化。11.5.3VSharedHardwareInt類VSharedHardwareInt是VHardwareInt的派生類。與VHardwareInt類的不同之處是,VSharedHardwareInt類允許一個(gè)IRQ被多個(gè)VxD虛擬化。如果需要響應(yīng)PCI卡的中斷時(shí),一般使用VSharedHardwareInt類。VSharedHardwareInt類的成員函數(shù)有:(1)VHardwareInt::VhardwareInt (intirq,DWORDflags,DWORDtimeout,PVOIDrefdata) 構(gòu)造函數(shù),irq是要虛擬化的中斷號(hào),其值為0到15,其余參數(shù)一般設(shè)為0。(2)BOOLVSharedHardwareInt::
OnSharedHardwareInt(VMHANDLEhVM)中斷發(fā)生時(shí),本成員函數(shù)被調(diào)用。返回值通知VPICD是否處理了本次中斷。VSharedHardwareInt類允許一個(gè)IRQ被多個(gè)VxD虛擬化。因此,當(dāng)中斷發(fā)生時(shí),VPICD將依次調(diào)用虛擬化了這個(gè)中斷的VxD的OnSharedHardwareInt函數(shù)。如果某個(gè)OnSharedHardwareInt函數(shù)處理了這次中斷,則返回TRUE告知VPICD中斷已被處理,VPICD不再調(diào)用余下的VxD的OnSharedHardwareInt函數(shù)。函數(shù)認(rèn)為不應(yīng)該處理該次中斷,它就要返回FALSE,VPICD將調(diào)用下一個(gè)VxD的OnSharedHardwareInt函數(shù)。一直到中斷被處理或所有VxD的OnSharedHardwareInt函數(shù)被調(diào)用為止。下面是VxD中虛擬化IRQ的一個(gè)例子:classXMyIRQ:publicVSharedHardwareInt{public: XMyIRQ(intnIRQ); //構(gòu)造函數(shù)。 virtualBOOLOnSharedHardwareInt(VMHANDLE); //必須有的函數(shù) virtualVOIDOnVirtualInt(VMHANDLE); virtualVOIDOnVirtualEOI(VMHANDLE); virtualVOIDOnVirtualIRET(VMHANDLE);}; //在構(gòu)造函數(shù)中調(diào)用類VSharedHardwareInt的構(gòu)造函數(shù),//nIRQ指定要虛擬(處理)的中斷號(hào)XMyIRQ::XMyIRQ(intnIRQ):VSharedHardwareInt(nIRQ,0,0,0) {}//OnSharedHardwareInt成員函數(shù)就是中斷處理程序,當(dāng)相應(yīng)中斷發(fā)生時(shí),該函數(shù)被調(diào)用BOOLXMyIRQ::OnSharedHardwareInt(VMHANDLEhVM) {assert(hVM);//向hVM標(biāo)識(shí)的VM申請(qǐng)?zhí)摂M中斷。 //下面是處理中斷的具體代碼 ... }VOIDXMyIRQ::OnVirtualEOI(VMHANDLEhVM) {deassert(hVM);//VM中斷返回,撤消虛擬中斷申請(qǐng)。 SendPhysicalEOI();//請(qǐng)求VPICD向PPIC發(fā)送中斷結(jié)束指令 } //以下代碼放在VxD初始化代碼區(qū)內(nèi)。 //生成XMyIRQ類實(shí)例對(duì)象,該對(duì)象虛擬(處理)硬件中斷05HXMyIRQmIRQ(5); //調(diào)用成員函數(shù)hook,完成虛擬化(中斷處理程序的掛接)if(mIR.hook()){ //IRQ虛擬化成功。 }
else{ //IRQ虛擬化失敗。 }11.5.4VGlobalEvent類硬件中斷處理通常要利用異步事件類。VMM被中斷轉(zhuǎn)而執(zhí)行中斷處理,在中斷處理中不能調(diào)用同步VMM服務(wù),否則VMM會(huì)因重入而崩潰。所以,在中斷處理中只能安排一個(gè)異步事件函數(shù),以允許系統(tǒng)在中斷處理結(jié)束后返回到正常狀態(tài)時(shí)調(diào)用這個(gè)異步事件函數(shù)。異步事件類的類別較多,它們都是從類VEvent派生而來(lái),共有五個(gè):VEvent,VGlobalEvent,VThreadEvent,VPriorityVMEvent,VVMEvent。其中,VEvent是其他異步事件類的基類。除了VGlobalEvent類外,其他類與中斷無(wú)關(guān)。全局異步事件類VGlobalEvent是受限制最少的異步事件類。一旦所有的中斷處理執(zhí)行完畢,VMM就將回調(diào)全局異步事件類的handler成員函數(shù)。VGlobalEvent類的主要成員函數(shù)(1)VGlobalEvent::VglobalEvent(PVOIDrefData)refData:傳遞給handler成員函數(shù)的參考數(shù)據(jù)。VGlobalEvent函數(shù)創(chuàng)建一個(gè)VGlobalEvent類實(shí)例。在該函數(shù)之后應(yīng)該調(diào)用call或者schedule成員函數(shù)以安排異步函數(shù)的回調(diào)。當(dāng)VMM調(diào)用handler函數(shù)時(shí),refData也傳遞給handler函數(shù).(2)BOOLVGlobalEvent::call()call函數(shù)視具體情況或者立即調(diào)用handler函數(shù)或者只是調(diào)度(schedule)一個(gè)全局事件。當(dāng)VMM處在非中斷狀態(tài)時(shí),call函數(shù)立即調(diào)用handler函數(shù);否則call函數(shù)將調(diào)度一個(gè)異步事件,即當(dāng)中斷結(jié)束返回時(shí)再調(diào)用handler函數(shù)。call函數(shù)返回TRUE表示調(diào)度異步事件,返回FALSE表示handler函數(shù)立即被調(diào)用。(3)VOIDVGlobaleEvent::schedule()schedule函數(shù)調(diào)度一個(gè)異步事件。一旦中斷處理完畢,系統(tǒng)就調(diào)用handler成員函數(shù)。(4)VOIDVGlobalEvent::cancel()cancel成員函數(shù)取消對(duì)一個(gè)異步事件的調(diào)度,該函數(shù)與schedule函數(shù)相對(duì)。handler函數(shù)被調(diào)用時(shí),不能使用cancel函數(shù)。(5)VOIDVGlobalEvent::handler(VMHANDLEhVM,
CLIENT_STRUCT*pRegs,PVOIDrefData)hVM當(dāng)前活動(dòng)VM的句柄;pRegs指向VM寄存器組的指針;refData由構(gòu)造函數(shù)傳來(lái)的參數(shù)。Handler成員函數(shù)在中斷處理完畢后被系統(tǒng)觸發(fā)。在該函數(shù)里可安全的調(diào)用同步VMM服務(wù)。在中斷中使用VGlobalEvent類的例子://中斷處理類classMyINT:publicVSharedHardwareInt {public: MyINT(); virtualBOOLOnSharedHardwareInt(VMHANDLEhVM); };//全局異步事件類classGEvent:publicVGlobalEvent {public: GEvent(); virtualVOIDhandler(VMHANDLEhVM,
CLIENT_STRUCT*pRegs,PVOIDrefData); };//中斷處理程序,其中安排了一全局異步事件BOOLMyINT::OnSharedHardwareInt(VMHANDLEhVM) {pEvent=newGEvent(); if(pEvent){ //具體中斷處理,但不能調(diào)用同步VMM服務(wù) //在中斷處理完成后調(diào)用GEvent::handler. pEvent->schedule(); p_Int->sendPhysicalEOI(); returnTRUE; }//發(fā)中斷結(jié)束消息 p_Int->sendPhysicalEOI(); returnFALSE; }//能調(diào)用同步VMM服務(wù)的中斷處理VOIDGEvent::handler(VMHANDLEhVM,
CLIENT_STRUCT*pRegs,PVOIDrefData) { //中斷處理,能調(diào)用同步VMM服務(wù) }11.6VxD實(shí)例11.6.1PCI設(shè)備配置的獲取獲取配置資源用到的兩個(gè)函數(shù)。(1)CONFIGRETCONFIGMG_Register_Device_Driver(DEVNODEnode,CMCONFIGHANDLERhandler,DWORDrefData,DWORDflags)功能:注冊(cè)一個(gè)設(shè)備節(jié)點(diǎn)配置處理程序。參數(shù):node:設(shè)備節(jié)點(diǎn)句柄
handler:設(shè)備配置處理程序入口 refData:發(fā)送給配置處理程序的數(shù)據(jù)(handler)flags:必須是CM_REGISTER_DEVICE_DRIVER_STATIC、CM_REGISTER_DEVICE_DRIVER_DISABLABLE、CM_REGISTER_DEVICE_DRIVER_REMOVABLE之一或組合。注意:該函數(shù)僅能在PnP的設(shè)備驅(qū)動(dòng)程序的初始化期間被調(diào)用(2)CONFIGMG_Get_Alloc_Log_Conf(PCMCONFIG
pccBuffer,DEVNODEnode,DWORDflags);功能:從-個(gè)nice表格中取得硬件資源數(shù)據(jù)參數(shù):pccBuffer:一個(gè)CMCONFIG結(jié)構(gòu)指針
node:設(shè)備節(jié)點(diǎn)
flags:必須是 CM_GET_ALLOC_LOG_CONF_ALLOC或 CM_GET_ALLOC_CONF_BOOT_ALLOC。返回:如果成功,返回CR_SUCCESS;否則返回值可能是
CR_INVALID_POINTER,CR_INVALID_DEVNODE
或CR_INVALID_FLAG。以上兩個(gè)函數(shù)調(diào)用方式是:CONFIGRETCONFIGMG_Register_Device_Driver函數(shù)在消息PnP_NEW_DEVNODE的處理函數(shù)中在響應(yīng)DLVXD_LOAD_DEVLOADER的裝載類型時(shí)被調(diào)用。這個(gè)函數(shù)在被調(diào)用時(shí)還要觸發(fā)一個(gè)設(shè)備配置處理程序,該程序是一個(gè)自定義函數(shù),其格式如下:CONFIGRETCM_HANDLEROnConfigure(CONFIGUNCcf,SUBCONFIGFUNCsef,DEVNODEdevnode,DWORDrefdata,ULONGflags)為了觸發(fā)該函數(shù),只要將其函數(shù)名作為CONFIGMG_Register_Device_Driver函數(shù)的第二個(gè)參數(shù)即可。CMCONFIG結(jié)構(gòu)定義如下:structCMCONFIG{WORDwNumMemWindows; //存儲(chǔ)器空間數(shù)量DWORDdMemBase[MAX_MEM_REGISTERS]; //存儲(chǔ)器基地址DWORDdMemLength[MAX_MEM_REGISTERS];//存儲(chǔ)空間長(zhǎng)度WORDwMemAttrib[MAX_MEM_REGISTERS];//存儲(chǔ)空間屬性WORDwNumIoports; //I/O端口數(shù)量WORDwIoportBase[MAX_IO_PORTS]; //IO端口基地址WORDwIoportLength[MAX_IO_PORTS]; //IO端口長(zhǎng)度WORDwNumIRQS; //IRQ數(shù)BYTEbIRQRegisters[MAX_IRQS]; //IRQ號(hào)BYTEbIRQAttrib[MAX_IRQS]; //IRQ屬性WORDwNumDMAS; //DMA通道數(shù)BYTEbDMALst[MAX_DMA_CHANNELS]; //DMA號(hào)BYTEwDMAAttrib[MAX_DMA_CHANNELS];//DMA屬性BYTEbReservedl[3]; //保留};
在函數(shù)OnConfigure中調(diào)用CONFIGMG_Get_Alloc_Log_Conf獲取PCI設(shè)備的配置。 下面的VxD程序在Windows9x發(fā)現(xiàn)相應(yīng)的PCI設(shè)備時(shí)被加載,VxD讀取PCI設(shè)備的配置并保存,供Ring3層應(yīng)用程序使用。假設(shè)該P(yáng)CI設(shè)備所需的資源為:一個(gè)存儲(chǔ)器空間,兩個(gè)I/O空間,一個(gè)中斷號(hào)。 //PCI_CON.VXD的頭文件 //PCI_CON.h-includefileforVxDPCI_CON #include<vtoolscp.h> #defineDEVICE_CLASS Pci_conDevice #definePCI_CON_DeviceID UNDEFINED_DEVICE_ID #definePCI_CON_Init_Order UNDEFINED_INIT_ORDER #definePCI_CON_Major 1 #definePCI_CON_Minor 0 #defineDIOC_FAILURE 1//VxD'smessageIDinOnW32DeviceIoControlhandle#defineDIOC_PCICFGCTL_CODE(FILE_DEVICE_UNKNOWN,0x802,\
METHOD_IN_DIRECT,FILE_ANY_ACCESS)classPci_conDevice:publicVDevice{public:virtualBOOLOnDeviceInit(VMHANDLEhSysVM,PCHARpszCmdTail);virtualCONFIGRETOnPnpNewDevnode(DEVNODEdevNode,DWORDloadType);virtualDWORDOnW32DeviceIoControl(PIOCTLPARAMSpDIOCParams);};structpci_cfg{DWORDMemBase; //存儲(chǔ)空間基地址DWORDMemLength; //存儲(chǔ)空間長(zhǎng)度WORDIOBase[2];
//IOBase[0]:S5933狀態(tài)寄存器專用的I/O空間 //IOBase[1]:映射的I/O空間WORDIOPortLength[2];
//IOPortlength[0]:S5933狀態(tài)寄存器空間長(zhǎng)度 //IOPortlength[1]:映射的I/O空間長(zhǎng)度BYTEIRQ; //中斷號(hào)}*pci;//PCI_CON.VXD的源代碼PCI_CON.CPP#defineDEVICE_MAIN#include"pci_con.h"Declare_Virtual_Device(PCI_CON)#undefDEVICE_MAIN BOOL card=FALSE; CMCONFIGconfig; CONFIGRETCM_HANDLEROnConfigure(CONFIGFUNC
cf,SUBCONFIGFUNCscf,DEVNODEdevnode,
DWORDrefdata,ULONGflags); BOOLPci_conDevice::OnDeviceInit(VMHANDLE
hSysVM,PCHARpszCmdTail) {returnOnSysDynamicDeviceInit(); }//響應(yīng)新結(jié)點(diǎn)消息函數(shù)CONFIGRETPci_conDevice::OnPnpNewDevnode(DEVNODEdevNode,DWORDloadType){dprintf("DATAACQ:PnP-newdevnode:");switch(loadType){ caseDLVXD_LOAD_ENUMERATOR: //加載枚舉設(shè)備 returnCR_DEFAULT; caseDLVXD_LOAD_DEVLOADER: //加載設(shè)備加載器 card=TRUE; //表示PCI卡存在//注冊(cè)一個(gè)設(shè)備節(jié)點(diǎn) returnCONFIGMG_Register_Device_Driver(devNode, OnConfigure,0, CM_REGISTER_DEVICE_DRIVER_REMOVABLE| CM_REGISTER_DEVICE_DRIVER_DISABLEABLE); caseDLVXD_LOAD_DRIVER: //加載設(shè)備驅(qū)動(dòng)程序 returnCR_DEFAULT; default: returnCR_DLVXD_NOT_FOUND;}}//設(shè)備配置處理程序CONFIGRETCM_HANDLEROnConfigure(CONFIGFUNCcf, SUBCONFIGFUNCscf,DEVNODEdevnode,
DWORDrefdata,ULONGflags){DWORDtemp; CONFIGRETcr; dprintf("DATAACQ:configuration-handler:");switch(cf){ caseCONFIG_START: //取得配置信息 cr=CONFIGMG_Get_Alloc_Log_Conf(&config, devnode,CM_GET_ALLOC_LOG_CONF_ALLOC); returncr; caseCONFIG_STOP: caseCONFIG_REMOVE: returnCR_SUCCESS; default: returnCR_DEFAULT;}}//VXD響應(yīng)Ring3層應(yīng)用程序調(diào)用消息處理函數(shù)DWORDPci_conDevice::OnW32DeviceIoControl(PIOCTLPARAMSp){switch(p->dioc_IOCtlCode){ caseDIOC_OPEN://應(yīng)用程序調(diào)用CreateFile時(shí)產(chǎn)生。
if(!card) returnDIOC_FAILURE;//表示PCI卡不存在。
returnDEVIOCTL_NOERROR; caseDIOC_CLOSEHANDLE:
//應(yīng)用程序調(diào)用CloseHandle時(shí)或退出時(shí)產(chǎn)生。
returnDEVIOCTL_NOERROR; caseDIOC_PCICFG;
//填具體配置參數(shù)到Ring3層使用的配置結(jié)構(gòu)中
pci=(pci_cfg*)p->dioc_InBuf pci->IRQ=config.bIRQRegisters[0]; pci->IOBase[0]=config.wIOPortBase[0]; pci->IOBase[1]=config.wIOPortBase[1]; pci->IOPortLength[0]=config.wIOPortLength[0]; pci->IOPortLength[0]=config.dMemLength[0]; pci->MemBase=config.dMemBase[0]; pci->MemLength=config.dMemLength[0]; return DEVIOCTL_NOERROR; default: returnERROR_INVALID_PARAMETER; }}下面是應(yīng)用程序,程序在屏幕上顯示PCI設(shè)備的配置信息。#include<stdio.h>#include<conio.h>#include<windows.h>#include<winioctl.h>#defineDIOC_PCICFGCTL_CODE(FILE_DEVICE_UNKNOWN,\
0x802,METHOD_IN_DIRECT,FILE_ANY_ACCESS)//PCI配置信息structPCI_CONFIG{DWORD MemBase; //內(nèi)存范圍起始地址
DWORD MemLength; //內(nèi)存范圍長(zhǎng)度
WORD IOBase[2]; //輸入輸出范圍起始地址
WORD IOPortLength[2]; //輸入輸出范圍長(zhǎng)度
BYTE IRQ; //中斷向量}; HANDLEhDevice=NULL;//設(shè)備(文件)句柄voidmain(){BOOLstatus; PCI_CONFIGpci; //從PCI_CON.VxD獲取PCI設(shè)備的配置。 hDevice=CreateFile("\\\\.\\PCI_CON.VxD",0,0,0,CREATE_NEW,FILE_FLAG_DELETE_ON_CLOSE,0); if(hDevice==INVALID_HANDLE_VALUE) {printf("無(wú)法打開PCI_CON.VxD!"); exit(1); } status=DeviceIoControl(hDevice,DIOC_PCICFG,&pci,
0,NULL,0,&nRet,NULL); if(!status){ printf("無(wú)法獲取PCI配置信息!"); exit(1); } CloseHandle(hDevice);printf(“PCI設(shè)備內(nèi)存基地址:%X長(zhǎng)度:%X\n",pci.MemBase,
pci.MemLength);printf(“PCI設(shè)備I/O基地址1:%X長(zhǎng)度:%X\n",pci.IOBase[0],
pci.IOPortLength[0]); printf(“PCI設(shè)備I/O基地址2:%X長(zhǎng)度:%X\n",pci.IOBase[1],
pci.IOPortLength[1]); printf("PCIS設(shè)備中斷號(hào):%d\n",pci.IRQ);}11.6.2輸入輸出 假設(shè)相對(duì)于PCI設(shè)備I/O空間基地址偏移為1的端口是輸入端口,偏移量為2的端口是輸出端口。 本例先從輸入端口輸入數(shù)據(jù),然后寫入輸出端口。 對(duì)I/O設(shè)備的實(shí)際訪問(wèn),如使用_outp寫端口和使用_inp讀端口,是在虛擬驅(qū)動(dòng)程序IOPORT.VxD中進(jìn)行的。本例中,盡管讀寫I/O端口端口的操作也可在ring3層應(yīng)用程序中進(jìn)行,但在其他設(shè)備中相應(yīng)的I/O操作不一定能在ring3層應(yīng)用程序中進(jìn)行,而必須放在VxD中進(jìn)行。
Ring3層的應(yīng)用程序先打開PCI_CON.VXD取得PCI的配置,然后打開IOPORT.VXD進(jìn)行相應(yīng)的輸入輸出。//C++頭文件IOPORT.h#include<vtoolscp.h>#defineDEVICE_CLASS IODevice#defineIOPORT_DeviceID UNDEFINED_DEVICE_ID#defineIOPORT_Init_Order UNDEFINED_INIT_ORDER#defineIOPORT_Major 1#defineIOPORT_Minor 0//自定義控制代碼#defineDIOC_FAILURE 1#defineDIOC_INPUTCTL_CODE(FILE_DEVICE_UNKNOWN,0x813,\
METHOD_IN_DIRECT,FILE_ANY_ACCESS)#defineDIOC_OUTPUTCTL_CODE(FILE_DEVICE_UNKNOWN,\
0x814,METHOD_IN_DIRECT,FILE_ANY_ACCESS)//I/O數(shù)據(jù)結(jié)構(gòu),用于ring3層應(yīng)用程序和IOPORT.VxD交換數(shù)據(jù)structIOData{WORDwPort;//I/O端口
BYTEbData; //輸入/輸出數(shù)據(jù) };classIODevice:publicVDevice{public: virtualDWORDOnW32DeviceIoControl(PIOCTLPARAMSpDIOCParams);};//C++源文件IOPORT.CPP#defineDEVICE_MAIN#include"ioport.h"Declare_Virtual_Device(IOPORT)#undefDEVICE_MAINDWORDIODevice::OnW32DeviceIoControl(PIOCTLPARAMSpDIOCParams){IOData*pd;switch(pDIOCParams->dioc_IOCtlCode){ caseDIOC_OPEN: returnDEVIOCTL_NOERROR; caseDIOC_CLOSEHANDLE: returnDEVIOCTL_NOERROR;caseDIOC_INPUT; //Ring3層應(yīng)用程序使用控制代碼DIOC_INPUT執(zhí)行DeviceIoControl函數(shù) pd=(IOData*)pDIOCParams->dioc_InBuf;
//使用庫(kù)函數(shù)_inp從端口pd->wPort輸入數(shù)據(jù)到d->bData中 pd->bData=_inp(pd->wPort); returnDEVIOCTL_NOERROR;caseDIOC_OUTPUT://Ring3層應(yīng)用程序使用控制代碼DIOC_OUTPUT執(zhí)行DeviceIoControl函數(shù)
pd=(IOData*)pDIOCParams->dioc_InBuf;
//使用庫(kù)函數(shù)_outp向端口pd->wPort輸出數(shù)據(jù)pd->bData _outp(pd->wPort,pd->bData); returnDEVIOCTL_NOERROR;default: returnERROR_INVALID_PARAMETER; } return0;}下面是應(yīng)用程序。#include<stdio.h>#include<conio.h>#include<windows.h>#include<winioctl.h>#define DIOC_FAILURE1#define DIOC_PCICFGCTL_CODE(FILE_DEVICE_UNKNOWN,0x802,\
METHOD_IN_DIRECT,FILE_ANY_ACCESS)#define DIOC_INPUTCTL_CODE(FILE_DEVICE_UNKNOWN,0x813,\
METHOD_IN_DIRECT,FILE_ANY_ACCESS)#define DIOC_OUTPUTCTL_CODE(FILE_DEVICE_UNKNOWN,0x814,\
METHOD_IN_DIRECT,FILE_ANY_ACCESS)//PCI設(shè)備配置信息structPCI_CONFIG{DWORD MemBase; DWORD MemLength; WORD IOBase[2]; WORD IOPortLength[2]; BYTE IRQ;}; //I/O數(shù)據(jù)結(jié)構(gòu),用于ring3層應(yīng)用程序和IOPORT.VxD交換數(shù)據(jù)structIOData{WORDwPort; BYTEbData;}HANDLEhDevice=NULL;voidmain(){BOOLstatus; PCI_CONFIGpci; //從PCI_CON.VxD獲取PCI設(shè)備的配置。 hDevice=CreateFile("\\\\.\\PCI_CON.VxD",0,0,0,
CREATE_NEW,FILE_FLAG_DELETE_ON_CLOSE,0); if(hDevice==INVALID_HANDLE_VALUE) { printf("無(wú)法打開PCI_CON.VxD!"); exit(1);} status=DeviceIoControl(hDevice,DIOC_PCICFG,&pci,
0,NULL,0,&nRet,NULL); if(!status){printf("無(wú)法獲取PCI配置信息!"); exit(1);}
CloseHandle(hDevice); //打開IOPORT.VxD,準(zhǔn)備進(jìn)行輸入/輸出hDevice=CreateFile("\\\\.\\IOPORT.VxD",0,0,0, CREATE_NEW,FILE_FLAG_DELETE_ON_CLOSE,0);if(hDevice==INVALID_HANDLE_VALUE) {printf("無(wú)法打開IOPORT.VxD!"); exit(1);} //讀取I/O端口
id.wPort=pci.IOBase[1]+0x1; DeviceIoControl(hDevice,DIOC_INPUT,&id,0,NULL,0,
&nRet,NULL);//寫I/O端口
id.wPort=pci.IOBase[1]+0x2; DeviceIoControl(hDevice,DIOC_OUTPUT,&id,0,NULL,0,
&nRet,NULL); CloseHandle(hDevice);//關(guān)閉IOPORT.VxD}11.6.3中斷處理PCI卡采用共享中斷的方式,而且中斷號(hào)是由系統(tǒng)動(dòng)態(tài)分配的,因此中斷處理類MyINT只能是VSharedHardwareInt的派生類。在VxD的初始化階段先要取得所分配的中斷號(hào),然后初始化中斷處理類MyINT,隨后設(shè)置AMCC5933的INTCSRC中斷控制/狀態(tài)寄存器的中斷為輸入郵箱4,這里假設(shè)中斷請(qǐng)求是通過(guò)輸入郵箱4發(fā)出的。通過(guò)IOCTL命令DIOC_INTERR將Win32應(yīng)用程序回調(diào)函數(shù)的入口地址轉(zhuǎn)送給PCI_CON.VxD,并允許硬件中斷,等待中斷發(fā)生。由于采用共享中斷的方式,因此當(dāng)中斷發(fā)生時(shí),中斷服務(wù)程序首先要判斷是否是本PCI卡引起的,若是則進(jìn)行處理,否則通知系統(tǒng)將控制權(quán)交給下一個(gè)設(shè)備。由于VWIN32_QueueUserApc()函數(shù)不能在中斷服務(wù)時(shí)調(diào)用,所以在中斷服務(wù)中安排了一個(gè)全局異步事件。這樣,當(dāng)相應(yīng)中斷發(fā)生時(shí),PCI_CON.VxD將先判斷是否是本PCI卡引起的,若是則引發(fā)一個(gè)全局異步事件。在全局異步事件處理時(shí)調(diào)用VWIN32_QueueUserApc()函數(shù)對(duì)Win32應(yīng)用程序回調(diào)函數(shù)進(jìn)行異步過(guò)程調(diào)用。最后,應(yīng)用程序回調(diào)函數(shù)被調(diào)用時(shí)才對(duì)中斷進(jìn)行相應(yīng)的處理。//PCI_CON.hforPCI_CON.CPP#include<vtoolscp.h>#defineDEVICE_CLASS Pci_conDevice#definePCI_CON_DeviceID UNDEFINED_DEVICE_ID#definePCI_CON_Init_Order UNDEFINED_INIT_ORDER#definePCI_CON_Major 1#definePCI_CON_Minor 0#defineDIOC_FAILURE 1//IOCTL控制碼定義#defineDIOC_PCICFGCTL_CODE(FILE_DEVICE_UNKNOWN,
0x802,METHOD_IN_DIRECT,FILE_ANY_ACCESS)#define DIOC_INTERRCTL_CODE(FILE_DEVICE_UNKNOWN,0x803,
METHOD_IN_DIRECT,FILE_ANY_ACCESS)classPci_conDevice:publicVDevice{public:virtualBOOLOnDeviceInit(VMHANDLEhSysVM,PCHARpszCmdTail); virtualCONFIGRETOnPnpNewDevnode(DEVNODEdevNode,DWORDloadType); virtualDWORDOnW32DeviceIoControl(PIOCTLPARAMSpDIOCParams);};//中斷處理類classMyINT:publicVSharedHardwareInt{ public: MyINT(); virtualBOOLOnSharedHardwareInt(VMHANDLEhVM); }//全局異步事件類classGEvent:publicVGlobalEvent{public: GEvent(); virtualVOIDhandler(VMHANDLEhVM,CLIENT_STRUCT*
pRegs,PVOIDrefData); };//PCI_CON.CPP#defineDEVICE_MAIN#include"pci_con.h"Declare_Virtual_Device(PCI_CON)#undefDEVICE_MAIN#defineIMB4 0x1c //AMCC5933's輸入郵箱地址#defineINTCSR0x38//AMCC5933's中斷控制/狀態(tài)寄存器地址#defineMBEF0x34 //AMCC5933's郵箱空/滿狀態(tài)寄存器地址HANDLE Ring3; //應(yīng)用程序的句柄,由應(yīng)用程序提供MyINT *p_Int=NULL;//中斷程序的實(shí)例指針GEvent *pEvent=NULL;//全局事件實(shí)例指針WORD MsgID; //Ring3層消息ID值DWORD address,IOBase0;BOOL card=FALSE;CMCONFIGconfig; //PCI配置結(jié)構(gòu)實(shí)例BYTE IRQ=255;PVOIDCallBackApc=0;THREADHANDLETheThread=0;CONFIGRETCM_HANDLEROnConfigure(CONFIGFUNCcf,
SUBCONFIGFUNCscf,DEVNODEdevnode,DWORD
refdata,ULONGflags);MyINT::MyINT():VSharedHardwareInt(IRQ,0,0,0){}BOOLPci_conDevice::OnDeviceInit(VMHANDLEhSysVM,
PCHARpszCmdTail) {returnOnSysDynamicDeviceInit(); }CONFIGRETPci_conDevice::OnPnpNewDevnode(DEVNODE
devNode,DWORDloadType){switch(loadType) { caseDLVXD_LOAD_ENUMERATOR: returnCR_DEFAULT; caseDLVXD_LOAD_DEVLOADER: card=TRUE; returnCONFIGMG_Register_Device_Driver (devNode,OnConfigure,0,
CM_REGISTER_DEVICE_DRIVER_REMOVABLE|
CM_REGISTER_DEVICE_DRIVER_DISABLEABLE); caseDLVXD_LOAD_DRIVER: returnCR_DEFAULT; default: returnCR_DLVXD_NOT_FOUND; }returnCR_DEFAULT;}CONFIGRETCM_HANDLEROnConfigure(CONFIGFUNCcf, SUBCONFIGFUNCscf,DEVNODEdevnode,
DWORDrefdata,ULONGflags){DWORDtemp;CONFIGRETcr; switch(cf){ caseCONFIG_START: cr=CONFIGMG_Get_Alloc_Log_Conf(&config,
devnode,CM_GET_ALLOC_LOG_CONF_ALLOC); switch(cr){ caseCR_SUCCESS: caseCR_DEFAULT: IRQ=config.bIRQRegisters[0]; p_Int=newMyINT(); //掛接中斷處理程序
if(!p_Int->hook()||(p_Int==NULL)) returnDIOC_
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年家長(zhǎng)與學(xué)校共同打造學(xué)生成長(zhǎng)檔案合同3篇
- 醫(yī)療設(shè)備售后服務(wù)與客戶關(guān)系維護(hù)
- 在線辦公時(shí)代下的農(nóng)產(chǎn)品直銷新模式-以網(wǎng)絡(luò)直播為例
- 醫(yī)療倫理與患者溝通的藝術(shù)
- 2025中國(guó)鐵塔貴州分公司招聘32人高頻重點(diǎn)提升(共500題)附帶答案詳解
- 2025中國(guó)石化貴州貴陽(yáng)石油分公司加油站營(yíng)業(yè)員招聘45人高頻重點(diǎn)提升(共500題)附帶答案詳解
- 2025中國(guó)電信集團(tuán)限公司春季校園招聘高頻重點(diǎn)提升(共500題)附帶答案詳解
- 2025中國(guó)大唐集團(tuán)限公司福建分公司校招高頻重點(diǎn)提升(共500題)附帶答案詳解
- 2025中國(guó)農(nóng)業(yè)科學(xué)院農(nóng)產(chǎn)品加工研究所谷物加工與品質(zhì)調(diào)控創(chuàng)新團(tuán)隊(duì)博士后公開招聘3人高頻重點(diǎn)提升(共500題)附帶答案詳解
- 2025東方電氣招聘452人歷年高頻重點(diǎn)提升(共500題)附帶答案詳解
- DL∕T 802.7-2023 電力電纜導(dǎo)管技術(shù)條件 第7部分:非開挖用塑料電纜導(dǎo)管
- 品味化學(xué)電源發(fā)展史
- 《植物營(yíng)養(yǎng)學(xué)》課件
- 代收個(gè)人款項(xiàng)聲明書
- 貨源保障協(xié)議書
- JBT 14685-2023 無(wú)油渦旋空氣壓縮機(jī) (正式版)
- 2024會(huì)計(jì)事務(wù)所保密協(xié)議范本
- 2024年遼寧生態(tài)工程職業(yè)學(xué)院?jiǎn)握新殬I(yè)技能測(cè)試題庫(kù)各版本
- 中秋國(guó)慶慰問(wèn)品采購(gòu)?fù)稑?biāo)方案
- 20K607 防排煙及暖通防火設(shè)計(jì)審查與安裝
- 《統(tǒng)計(jì)建模與R軟件》書本課后習(xí)題答案
評(píng)論
0/150
提交評(píng)論