PCI設備WINDOWS驅動程序的開發
本文主要介紹了在Windows9x操作系統下開發PCI設備驅動程序的方法。
關鍵詞:PCI設備 驅動程序
PCI設備概述
近幾年來,隨著諸如圖形處理、圖像處理、三維動畫技術的發展,計算機與外設通信需要處理的數據量迅速增加,基于ISA總線的通信方式已經不能滿足高速數據傳輸的要求,PCI局部總線的引用就是為了打破高速數據傳輸的瓶頸。PCI總線的英文全稱是:Peripheral Component Interconnect Special Interest Group,簡稱PCISIG,即外部器件互連。PCI是先進的高性能局部總線,可同時支持多組外圍設備,具體表現在:
(1) 以33MHz的時鐘頻率操作,(2) 采用32位數據總線,(3) 數據傳送率可高達132MB/s;
(4) 支持突發傳輸,(5) 即總線主控設備(6) 發出地址之后,(7) 可以連續進行多次數據傳送;
(8) 提供了配置空間,(9) 能夠支持即插即用;
(10) 支持3.3V電壓,(11) 有利于降低系統功耗。
為了減少開發難度,縮短開發周期,我們建議選擇專用芯片。根據硬件要實現的功能,選擇芯片。
以PLX公司的產品為例,PCI9052提供了5個局部地址存儲空間、支持中斷、支持從模式數據傳輸;PCI9054和PCI9080在PCI9052的基礎上又增加了主模式數據傳輸、兩個獨立的DMA通道和八個郵箱寄存器等功能。
驅動程序的模式和開發工具的選擇
以上是對PCI設備硬件方面的介紹,為了實現PCI設備與計算機的通信,還需要開發PCI設備驅動程序。驅動程序是用來管理系統資源的可執行二進制代碼,與操作系統擁有相同的級別,不同的操作系統支持不同類型的驅動程序。目前在市場上比較流行的操作系統是Windows9x和WindowsNT這兩種系列。Windows9x包括Windows95、Windows98、WindowsME;WindowsNT包括WindowsNT4.0、Windows2000。Windows95支持VXD類型的驅動程序,而WindowsNT支持WDM類型的驅動程序,Windows98兼容Windows95的VXD驅動程序,同時它又推出一個新的Win32 Drivers Mode (WDM)驅動類型。這個新的類型實際是在Windows NT的驅動模型的基礎上增加了即插即用等內容。WDM驅動也可以用在Windows 2000(先前叫Windows NT5.0)中。一個完善的驅動程序應至少開發Windows 9X和Windows NT兩個版本。目前,雖然Windows 2000非常流行,但由于Windows98仍占有相當規模的市場,而且它又兼容Windows95的VXD驅動程序,因此VXD驅動程序仍然實用。本文只介紹基于Windows9x系統下VXD驅動程序的開發。
VXD是虛擬設備驅動程序的簡稱,x 代表各種設備的名字,如虛擬鍵盤驅動程序(vkd),虛擬鼠標驅動程序(vmd)等等。開發驅動程序需要對硬件進行操作,由于Intel 80386以上的微處理器有4個優先級別:0級、1級、2級和3級,一般操作系統運行于優先級第0級上,而用戶程序運行在第3級上,Windows9x操作系統對系統硬件采取了屏蔽的策略,限制了運行于第3級的應用程序對系統資源(如中斷控制器、內存等)的操作。但VXD運行在最高級特權級——第0級,擁有操作系統的特權,可以超越這些屏蔽,直接進行系統硬件的操作。
開發設備驅動采用的主要開發工具是微軟為設備開發者提供的軟件包Device Driver Kit (DDK)。這個軟件包包括有關設備開發的文檔、編譯需要的頭文件和庫文件、調試工具和程序范例。在DDK中還定義了一些設備驅動可以調用的系統底層服務,如DMA服務、中斷服務、內存管理服務、可安裝文件系統服務等等。這些都是編寫設備驅動所必須的。但由于Windows 95的DDK主要使用匯編語言描述,代碼可讀性不強,開發起來比較困難。因此,我們在Windows 9x操作系統中采用了Numega公司的產品VtoolsD。VtoolsD是基于C/C++的,支持Borland C++和Visual C++,代碼可讀性強,使用和維護都較Windows DDK容易。
驅動程序的設計
編寫設備驅動程序的目的是使被驅動的硬件可以管理系統資源,與PC機系統兼容,正常工作,通過設備驅動程序,多個進程可以同時使用這些資源(如內存、I/O、中斷源等),實現多進程并行運行。驅動程序是針對具體硬件設計的,不同硬件有不同的驅動程序,下面僅討論開發驅動程序幾個必要的通用的步驟。
1、PCI配置空間簡介
每個PCI設備都有自己的配置空間,用于支持即插即用,使之滿足現行的系統配置結構。下面對PCI配置空間做一下簡要介紹。
配置空間是一容量為256字節并具有特定結構的地址空間。這個空間又分為頭標區和設備有關區兩部分。頭標區的長度是64字節,每個設備都必須配置該區的寄存器。該區中的各個字段用來唯一地識別設備。其余的192字節因設備而異。配置空間的頭標區64個字節的使用情況如圖1示。
為了實現即插即用,系統可根據硬件資源的使用情況,為PCI設備分配新的資源。因此編寫設備驅動程序重點是獲得基址寄存器(Base Address)和中斷干線寄存器的內容。配置空間共有六個基址寄存器和一個中斷干線寄存器,具體用法如下:
PCI Base Address 0寄存器:系統利用此寄存器為PCI接口芯片的配置寄存器分配一段PCI地址空間,通過這段地址我們可以以內存映射的形式訪問PCI接口芯片的配置寄存器。
PCI Base Address 1寄存器:系統利用此寄存器為PCI接口芯片的配置寄存器分配一段PCI地址空間,通過這段地址我們可以以I/O的形式訪問PCI接口芯片的配置寄存器。
PCI Base Address 2、3、4、5寄存器:系統BIOS利用這些寄存器分配PCI地址空間以支持PCI接口芯片的局部配置寄存器0、1、2、3的訪問。
在所有基址寄存器中,第0位均為只讀位,表示這段地址映射到存儲器空間還是I/O空間,如果是“1”表示映射到I/O空間,如果是“0”則表示映射到存儲器空間。
中斷干線寄存器(Interrupt Line):用于說明中斷線的連接情況,這個寄存器的值與標準8259的IRQ編號(0~15)對應。
設備識別號 供應商識別號
狀態寄存器 命令寄存器
分類代碼 修改版本
自測試 頭標類型 延時計數 Cache
基址寄存器
保留
保留
擴展ROM基址寄存器
保留
保留
Max-Lat Min-Gnt中斷引腳 中斷干線
圖1 配置空間頭標區
2、設備初始化
PCI設備驅動程序要完成識別PCI器件、分配PCI硬件資源、響應PCI器件中斷等功能,這就需要訪問PCI配置空間來獲得必需的參數。實現在Windows9x操作系統下訪問PCI配置空間可以利用PCI系統BIOS功能調用,通過供應商識別號(VendorID)和設備識別號 (DeviceID)直接訪問設備,也可以利用配置管理器(Configuration Manager)封裝的功能函數,根據供應商識別號(VendorID)和設備識別號 (DeviceID)搜索設備結點樹,查詢PCI設備。由于編寫PCI系統BIOS功能調用程序更為簡捷,所以本文采用這種方法。
PCI系統BIOS功能提供了BIOS的訪問與控制的具體方法,所有軟件(設備驅動程序、擴展ROM碼)將通過標準中斷號1AH調用BIOS功能訪問特殊部件。在驅動程序中調用VtoolsD系統服務Exec_VxD_Int()來實現PCI系統BIOS的1AH中斷。
首先,通過PCI設備的供應商識別號(VendorID)、 設備識別號 (DeviceID)和索引號(Index)查找特定設備所在的總線號(Bus Num)、設備號(Device NUM)、功能號(Function Num)和寄存器號(Register Num)。總線號是從0到255的數值,在一個系統中,可把多達256條的PCI總線用橋連接在一起。由于編號是從0開始的,所以當系統有N條總線時,總線號會達到N-1;設備號是在0到31之間分配的任意值,并不拘于從0開始按順序分配;功能號分配從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寄存器是總線號,BL寄存器的高5位是設備號,低3位是功能號。
然后,向配置空間地址寄存器CF8h寫入總線號、設備號、功能號、索引號, 從配置空間數據寄存器CFCh讀出配置空間的內容。
配置空間地址寄存器(CF8h)格式如下:
Bit31 30-24 23-16 15-11 10-8 7-2 10
使能位 保 留 總線號 設備號 功能號 寄存器號 00
使能位為“1”表示允許訪問
配置空間數據寄存器(CFCh)存放要讀寫的數據。
代碼如下:
DWORD d=0;
d=pRegisters->REBX;
(d<<=8)|=0x80000000;
for (short i=0;i<16;i++) // 讀取64字節配置空間
{
_outpd(0xcf8,d+4*i); // 按DWORD類型一次讀取四個字節
dprintf("%8x",_inpd(0xcfc)); // 打印輸出
}
3、內存的讀寫
Winsows工作在32位保護模式下,保護模式與實模式的根本區別在于CPU尋址方式上的不同,這也是Windows驅動程序設計中需要著重解決的問題。Windows采用了分段、分頁機制,這樣使應用程序產生一種錯覺,好象程序中可以使用非常大的物理存儲空間。這樣做最大的好處就是一個程序可以很容易地在物理內存容量不一樣的、配置范圍差別很大的計算機上運行,編程人員使用虛擬存儲器可以寫出比任何實際配置的物理存儲器都大得多的程序。每個虛擬地址由16位的段選擇字和32位段偏移量組成。通過分段機制,系統由虛擬地址產生線性地址。再通過分頁機制,由線性地址產生物理地址(如圖2)。線性地址被分割成頁目錄(Page Directory)、頁表(Page Table)和頁偏移(Offset)三個部分。當建立一個新的Win32進程時,操作系統會為它分配一塊內存,并建立它自己的頁目錄、頁表,頁目錄的地址也同時放入進程的現場信息中。當計算一個地址時,系統首先從CPU控制器CR3中讀出頁目錄所在的地址,然后根據頁目錄得到頁表所在的地址,再根據頁表得到實際代碼/數據頁的頁幀,最后再根據頁偏移訪問特定的單元。硬件設備讀寫的是物理內存,但應用程序讀寫的是虛擬地址,所以存在著將物理內存地址映射到用戶程序線性地址的問題。
15 0 31 0 31 0 31 0
圖2 虛擬地址轉換為物理地址
從物理地址到線性地址的轉換工作是由驅動程序來完成的。驅動程序的內存映射部分主要是調用VxD的系統服務MapPhysToLinear。在VtoolsD中這個函數的定義如下:
PVOID MapPhysToLineag(CONST VOID * PhysAddr,DWORD nBytes,DWORD Flags);
其中第一個參數PhysAddr就是要映射的內存的物理地址的起始位置,這個物理地址可以從PCI配置空間的基址寄存器中獲得,nBytes是內存區域的長度,Flags必須設置為0。這個函數返回的就是這段物理地址映射的線性內存地址。如果指定的內存不能存取,函數將返回FFFFFFFFH。
如:PDWORD pBase = (PDWORD)MapPhysToLinear((PVOID)PhysAddress,PhysSize,0);
將pBase傳遞給調用驅動的用戶程序,用戶程序就可以像使用指針一樣利用pBase訪問內存。
4、I/O端口的操作
在PC機上,I/O尋址方式與內存尋址方式不同,所以處理方法也不同。I/O空間是一個64K字節的尋址空間,I/O尋址沒有實模式與保護模式之分,在各種模式下尋址方式相同。在Windows9x系統下,運行于第3級的應用程序也可以直接使用I/O指令訪問I/O空間。在設備初始化訪問配置空間時,已用到了I/O指令,在對硬件進行配置時,也可以根據從配置空間基址寄存器PCI Base Address 1中返回的I/O端口基地址使用I/O指令。
5、響應中斷
VTOOLSD提供了VHardwareInt類,虛擬IRQ,處理硬件中斷。在Windows9x中,VPICD虛擬了物理可編程中斷控制器的端口,從而可以控制物理中斷控制器。虛擬IRQ的編程思路:首先從VHardwareInt類中派生出一個類,重載OnHardwareInt函數;然后,動態創建一個派生類對象實例;最后鉤掛處理程序,這就是需要編寫的中斷服務程序。(關于VHardwareInt類可參考VTOOLSD)
四、驅動程序的調用和封裝
編寫設備驅動并不是最終的目的,需要由用戶程序來調用驅動并實現一定的功能。一般調用設備驅動是使用CreateFile函數打開設備文件,得到一個文件句柄。使用如下的語句就可以打開文件。
HANDLE hVxD=CreateFile("\\\\.\\PCIDEVICE.VXD",0,0,0, OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE,
0);
打開設備文件后,調用DeviceIoControl函數就可以實現應用程序與設備驅動程序的通信。完成硬件操作之后,可以調用函數CloseHandle(hVxD);關閉設備驅動。(關于這三個函數的詳細說明請參考MSDN)
至此,我們完成了對驅動程序的初步設計,考慮到有的函數(如DeviceIoControl)調用起來非常復雜,為了提高程序的通用性,要對部分函數進行封裝。因為動態鏈接庫(DLL)可以在多數軟件開發平臺中調用,所以常用DLL封裝形式。另外需要注意的是由于驅動程序具有與操作系統相同的特權,并且直接操作硬件,如果程序工作不穩定,會造成死機甚至系統崩潰,所以要對驅動程序進行全面細致的測試。
參考文獻
1.李貴山. PCI局部總線開發者指南 西安電子科技大學出版社 1997
2.彭禮孝.虛擬設備驅動程序開發起步與進階 人民郵電出版社 2000
3.PCI BIOS SPECIFICATION Revision 2.1 1994
評論
查看更多