<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 模擬技術(shù) > 設計應用 > PCI設備WINDOWS驅動(dòng)程序的開(kāi)發(fā)

PCI設備WINDOWS驅動(dòng)程序的開(kāi)發(fā)

作者: 時(shí)間:2012-04-18 來(lái)源:網(wǎng)絡(luò ) 收藏
統BIOS功能調用,通過(guò)供應商識別號(VendorID)和設備識別號 (DeviceID)直接訪(fǎng)問(wèn)設備,也可以利用配置管理器(Configuration Manager)封裝的功能函數,根據供應商識別號(VendorID)和設備識別號 (DeviceID)搜索設備結點(diǎn)樹(shù),查詢(xún)。由于編寫(xiě)PCI系統BIOS功能調用程序更為簡(jiǎn)捷,所以本文采用這種方法。
PCI系統BIOS功能提供了BIOS的訪(fǎng)問(wèn)與控制的具體方法,所有軟件(設備、擴展ROM碼)將通過(guò)標準中斷號1AH調用BIOS功能訪(fǎng)問(wèn)特殊部件。在中調用VtoolsD系統服務(wù)Exec_VxD_Int()來(lái)實(shí)現PCI系統BIOS的1AH中斷。
首先,通過(guò)的供應商識別號(VendorID)、 設備識別號 (DeviceID)和索引號(Index)查找特定設備所在的總線(xiàn)號(Bus Num)、設備號(Device NUM)、功能號(Function Num)和寄存器號(Register Num)??偩€(xiàn)號是從0到255的數值,在一個(gè)系統中,可把多達256條的PCI總線(xiàn)用橋連接在一起。由于編號是從0開(kāi)始的,所以當系統有N條總線(xiàn)時(shí),總線(xiàn)號會(huì )達到N-1;設備號是在0到31之間分配的任意值,并不拘于從0開(kāi)始按順序分配;功能號分配從0到7的值。代碼如下:

ALLREGS* pRegisters; // pRegisters是指向寄存器結構體的指針
pRegisters->REAX =0xb102; // 0xb102是功能號
pRegisters->RECX =0x1001; // 假設Device ID=0x1001
pRegisters->REDX=0x102b; // 假設Vendor ID=0x102b
Exec_VxD_Int(0x1a,pRegisters); // 調用1AH中斷

返回值是pRegisters->REBX。BH寄存器是總線(xiàn)號,BL寄存器的高5位是設備號,低3位是功能號。
然后,向配置空間地址寄存器CF8h寫(xiě)入總線(xiàn)號、設備號、功能號、索引號, 從配置空間數據寄存器CFCh讀出配置空間的內容。
配置空間地址寄存器(CF8h)格式如下:
Bit31 30-24 23-16 15-11 10-8 7-2 10
使能位 保 留 總線(xiàn)號 設備號 功能號 寄存器號 00

使能位為“1”表示允許訪(fǎng)問(wèn)

配置空間數據寄存器(CFCh)存放要讀寫(xiě)的數據。
代碼如下:

DWORD d=0;
d=pRegisters->REBX;
(d=8)|=0x80000000;
for (short i=0;i16;i++) // 讀取64字節配置空間
{
_outpd(0xcf8,d+4*i); // 按DWORD類(lèi)型一次讀取四個(gè)字節
dprintf("%8x",_inpd(0xcfc)); // 打印輸出
}

3、內存的讀寫(xiě)
Winsows工作在32位保護模式下,保護模式與實(shí)模式的根本區別在于CPU尋址方式上的不同,這也是Windows設計中需要著(zhù)重解決的問(wèn)題。Windows采用了分段、分頁(yè)機制,這樣使應用程序產(chǎn)生一種錯覺(jué),好象程序中可以使用非常大的物理存儲空間。這樣做最大的好處就是一個(gè)程序可以很容易地在物理內存容量不一樣的、配置范圍差別很大的計算機上運行,編程人員使用虛擬存儲器可以寫(xiě)出比任何實(shí)際配置的物理存儲器都大得多的程序。每個(gè)虛擬地址由16位的段選擇字和32位段偏移量組成。通過(guò)分段機制,系統由虛擬地址產(chǎn)生線(xiàn)性地址。再通過(guò)分頁(yè)機制,由線(xiàn)性地址產(chǎn)生物理地址(如圖2)。線(xiàn)性地址被分割成頁(yè)目錄(Page Directory)、頁(yè)表(Page Table)和頁(yè)偏移(Offset)三個(gè)部分。當建立一個(gè)新的Win32進(jìn)程時(shí),操作系統會(huì )為它分配一塊內存,并建立它自己的頁(yè)目錄、頁(yè)表,頁(yè)目錄的地址也同時(shí)放入進(jìn)程的現場(chǎng)信息中。當計算一個(gè)地址時(shí),系統首先從CPU控制器CR3中讀出頁(yè)目錄所在的地址,然后根據頁(yè)目錄得到頁(yè)表所在的地址,再根據頁(yè)表得到實(shí)際代碼/數據頁(yè)的頁(yè)幀,最后再根據頁(yè)偏移訪(fǎng)問(wèn)特定的單元。硬件設備讀寫(xiě)的是物理內存,但應用程序讀寫(xiě)的是虛擬地址,所以存在著(zhù)將物理內存地址映射到用戶(hù)程序線(xiàn)性地址的問(wèn)題。

15 0 31 0 31 0 31 0


圖2 虛擬地址轉換為物理地址

從物理地址到線(xiàn)性地址的轉換工作是由驅動(dòng)程序來(lái)完成的。驅動(dòng)程序的內存映射部分主要是調用VxD的系統服務(wù)MapPhysToLinear。在VtoolsD中這個(gè)函數的定義如下:

PVOID MapPhysToLineag(CONST VOID * PhysAddr,DWORD nBytes,DWORD Flags);

其中第一個(gè)參數PhysAddr就是要映射的內存的物理地址的起始位置,這個(gè)物理地址可以從PCI配置空間的基址寄存器中獲得,nBytes是內存區域的長(cháng)度,Flags必須設置為0。這個(gè)函數返回的就是這段物理地址映射的線(xiàn)性?xún)却娴刂?。如果指定的內存不能存取,函數將返回FFFFFFFFH。
如:PDWORD pBase = (PDWORD)MapPhysToLinear((PVOID)PhysAddress,PhysSize,0);
將pBase傳遞給調用驅動(dòng)的用戶(hù)程序,用戶(hù)程序就可以像使用指針一樣利用pBase訪(fǎng)問(wèn)內存。

4、I/O端口的操作
在PC機上,I/O尋址方式與內存尋址方式不同,所以處理方法也不同。I/O空間是一個(gè)64K字節的尋址空間,I/O尋址沒(méi)有實(shí)模式與保護模式之分,在各種模式下尋址方式相同。在Windows9x系統下,運行于第3級的應用程序也可以直接使用I/O指令訪(fǎng)問(wèn)I/O空間。在設備初始化訪(fǎng)問(wèn)配置空間時(shí),已用到了I/O指令,在對硬件進(jìn)行配置時(shí),也可以根據從配置空間基址寄存器PCI Base Address 1中返回的I/O端口基地址使用I/O指令。

5、響應中斷
VTOOLSD提供了VHardwareInt類(lèi),虛擬IRQ,處理硬件中斷。在Windows9x中,VPICD虛擬了物理可編程中斷控制器的端口,從而可以控制物理中斷控制器。虛擬IRQ的編程思路:首先從VHardwareInt類(lèi)中派生出一個(gè)類(lèi),重載OnHardwareInt函數;然后,動(dòng)態(tài)創(chuàng )建一個(gè)派生類(lèi)對象實(shí)例;最后鉤掛處理程序,這就是需要編寫(xiě)的中斷服務(wù)程序。(關(guān)于VHardwareInt類(lèi)可參考VTOOLSD)

四、驅動(dòng)程序的調用和封裝
編寫(xiě)設備驅動(dòng)并不是最終的目的,需要由用戶(hù)程序來(lái)調用驅動(dòng)并實(shí)現一定的功能。一般調用設備驅動(dòng)是使用CreateFile函數打開(kāi)設備文件,得到一個(gè)文件句柄。使用如下的語(yǔ)句就可以打開(kāi)文件。

HANDLE hVxD=CreateFile("\\.\PCIDEVICE.VXD",0,0,0, OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE,
0);
打開(kāi)設備文件后,調用DeviceIoControl函數就可以實(shí)現應用程序與設備驅動(dòng)程序的通信。完成硬件操作之后,可以調用函數CloseHandle(hVxD);關(guān)閉設備驅動(dòng)。(關(guān)于這三個(gè)函數的詳細說(shuō)明請參考MSDN)
至此,我們完成了對驅動(dòng)程序的初步設計,考慮到有的函數(如DeviceIoControl)調用起來(lái)非常復雜,為了提高程序的通用性,要對部分函數進(jìn)行封裝。因為動(dòng)態(tài)鏈接庫(DLL)可以在多數軟件開(kāi)發(fā)平臺中調用,所以常用DLL封裝形式。另外需要注意的是由于驅動(dòng)程序具有與操作系統相同的特權,并且直接操作硬件,如果程序工作不穩定,會(huì )造成死機甚至系統崩潰,所以要對驅動(dòng)程序進(jìn)行全面細致的測試。
參考文獻

c++相關(guān)文章:c++教程




關(guān)鍵詞: PCI設備 WINDOWS 驅動(dòng)程序

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>