<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ù) > 設計應用 > Windows設備驅動(dòng)程序編寫(xiě)時(shí)的主要問(wèn)題及解決方案

Windows設備驅動(dòng)程序編寫(xiě)時(shí)的主要問(wèn)題及解決方案

作者: 時(shí)間:2012-04-18 來(lái)源:網(wǎng)絡(luò ) 收藏
(設備驅動(dòng)程序、擴展ROM碼)將通過(guò)標準中斷號1AH調用BIOS功能訪(fǎng)問(wèn)特殊部件。PCI BIOS規范有完整的有關(guān)PCI BIOS功能的描述[3]。
在PCI設備驅動(dòng)程序的初始化過(guò)程中,利用指定器件識別號(device_id)商識別號(vendor_id)、檢索號(index)搜索PCI器件,通過(guò)調用PC IBIOS確認其存在,并確定其物理位置:總線(xiàn)號、器件號和功能號,這是該器件/功能在系統中的唯一尋址標志。利用總線(xiàn)號、器件號和功能號可以尋址該器件/功能的PCI配置空間(configuration space)。 接下來(lái),設備驅動(dòng)就需要從配置空間獲得硬件的參數。PCI設備的許多參數,包括所用的中斷號,端口地址的范圍I/O方式、存儲器的地址?存儲器映射方式?等,都可以從PCI配置空間的各基址所對應的尋址空間中得到。讀寫(xiě)配置空間可以調用BIOS中斷1AH,也可以先向配置空間地址寄存器?(0CF8H)寫(xiě)入總線(xiàn)和設備號?在前面搜索PCI器件時(shí)得到的和寄存器號,再對配置空間數據寄存器?(0CFCH)進(jìn)行讀寫(xiě)。對設備驅動(dòng)來(lái)說(shuō),最重要的是獲得基址寄存器(BADR),不能認為PCI器件資源總是設計設備時(shí)設置的初值,系統可能會(huì )根據硬件情況為PCI設備分配新的資源。我們所設計的PCI設備使用的基址1-3都是按I/O空間映射的,而基址4是按內存方式映射的。確定一個(gè)端口是按什么方式映射的,可以讀對應端口的配置寄存器(Configuration Register)。讀出后,判斷其0位,如果0位為數值0,表示其是按內存方式設置的,否則為I/O方式設置的。內存方式和I/O方式的配置寄存器的含義參見(jiàn)文獻[3]。如果要獲得基址的大小,可以向基址寄存器寫(xiě)入FFFFH,然后讀基址寄存器,如果是內存方式,從第4位開(kāi)始的0的數目表示基址的大小,如果是I/O方式,則從第2位開(kāi)始的0的數目表示基址的大小。
? (2)?端口操作 在PC機上,I/O端口尋址空間和內存尋址空間是不同的,所以處理方法也不同。I/O空間是一個(gè)64K字節的尋址空間,它不象內存有實(shí)模式和保護模式之分,在各種模式下尋址方式相同。在Windows 9X下,用戶(hù)程序可以直接使用I/O指令,而不一定非通過(guò)專(zhuān)門(mén)的驅動(dòng)程序來(lái)完成,所以如果軟件對硬件的操作完全是通過(guò)I/O端口操作來(lái)完成的,甚至可以不用專(zhuān)門(mén)設計驅動(dòng)程序,直接由應用程序來(lái)完成對硬件的控制。由于PCI總線(xiàn)是32位的總線(xiàn)標準,在進(jìn)行I/O操作時(shí)通常要進(jìn)行雙字(DWORD)操作,而且以前大多數C/C++編譯軟件都沒(méi)有提供雙字的函數,所以需要構造雙字操作讀寫(xiě)函數inpd/outpd。
在Windows NT下,系統不允許處于優(yōu)先級3級的用戶(hù)程序和用戶(hù)模式驅動(dòng)程序直接使用I/O指令,如果使用了I/O指令將會(huì )導致特權指令意外(privileged instruction exception)。所以任何對I/O的操作都需要借助內核模式驅動(dòng)來(lái)完成。具體的做法有兩種:一是在驅動(dòng)程序中使用IoReportResourceUsage報告資源占用,然后使用READ_PORT_XXX、WRITE_PORT_XXX函數讀寫(xiě),最后使用IoReportResourceUsage取消資源占用;另一種是驅動(dòng)程序修改NT的I/OPermissions Map(IOPM),以使系統允許用戶(hù)程序對指定的I/O端口進(jìn)行操作,這時(shí)用戶(hù)程序采用通常的I/O指令進(jìn)行操作。后者的優(yōu)點(diǎn)是速度快、用戶(hù)程序設計簡(jiǎn)單,但犧牲了移植性,程序不能移植到非Intel的系統中,而且如果多個(gè)程序同時(shí)讀寫(xiě)同一端口容易導致沖突。 ?


3?內存的讀寫(xiě) Winsows工作在32位保護模式下,保護模式與實(shí)模式的根本區別在于CPU尋址方式上的不同,這也是Windows驅動(dòng)程序設計中需要著(zhù)重解決的問(wèn)題。Windows采用了分段、分頁(yè)機制如圖1?,這樣使應用程序產(chǎn)生一種錯覺(jué),好象程序中可以使用非常大的物理存儲空間。這樣做最大的好處就是一個(gè)程序可以很容易地在物理內存容量不一樣的、配置范圍差別很大的計算機上運行,編程人員使用虛擬存儲器可以寫(xiě)出比任何實(shí)際配置的物理存儲器都大得多的程序。每個(gè)虛擬地址由16位的段選擇子和32位段偏移量組成。通過(guò)分段機制,系統由虛擬地址產(chǎn)生線(xiàn)性地址。再通過(guò)分頁(yè)機制,由線(xiàn)性地址產(chǎn)生物理地址。線(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)題。

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

PVOID MapPhysToLineag(CONST VOID * PhysAddr,DWORD nBytes,DWORD Flags); 其中第一個(gè)參數PhysAddr就是要映射的內存的物理地址的起始位置,而nBytes是內存區域的長(cháng)度,Flags必須設置為0。這個(gè)函數返回的就是這段物理地址映射的線(xiàn)性?xún)却娴刂?。如果指定的內存不能存取,函數將返回FFFFFFFFH。 比如要映射物理內存ED000000H開(kāi)始的4096個(gè)字節,可以這樣做: PCHAR *PointerToPage=(PCHAR)MapPhysToLinear((PVOID)OxED000000,4096,0); 而將PointerToPage傳遞給調用驅動(dòng)的用戶(hù)程序,在用戶(hù)程序中使用 DWORD *pFIFOBodyBase=(DWORD*)PointerToPage; 而這個(gè)PFIFOBodyBase指針就可以象普通的指針一樣進(jìn)行讀寫(xiě)操作,而通過(guò)對這個(gè)指針的操作就可以實(shí)現對物理內存ED000000H進(jìn)行讀寫(xiě)。
在Windows NT下,首先調用IoReportResourceUsage請求使用設備的內存。然后調用HalTranslateBusAddress轉換與總線(xiàn)相關(guān)的內存為系統的物理內存地址。再使用MmMapIoSpace把設備的內存映射到虛擬空間。在設備驅動(dòng)卸出時(shí),調用MmUnmapIoSpace斷開(kāi)設備的內存和虛擬空間的連接。 ?

(4)?中斷的設置、響應與調用 對中斷的設置、響應與調用應該在驅動(dòng)程序中完成。
對中斷的調用?象前面調用BIOS的1AH中斷讀取配置寄存空間?可以由DDK的Exec_Int完成。
PCI設備驅動(dòng)程序應當從PCI配置寄存器的中斷寄存器(INTLN)和中斷引腳寄存器(INTPIN)?中獲得有關(guān)中斷的信息。DDK還提供了響應中斷事件的服務(wù)。如在Windows 95中,VPICD服務(wù)用來(lái)管理所有硬件中斷事件。PC機的硬件中斷需要確定硬件中斷的IRQ,對一個(gè)特定的IRQ中斷源,VPICD或者提供缺省的中斷處理函數,或者允許其它VxD重載中斷處理函數。在VtoolsD中,要處理硬件中斷應該從VHardwareInt繼承一個(gè)類(lèi)。在這個(gè)類(lèi)中,VtoolsD提供了編寫(xiě)中斷響應程序所需的功能。
在Windows NT中,同VPICD對應的中斷服務(wù)為中斷請求層(IRQL)。設備驅動(dòng)首先使用HalGetInterrupuVector將與總線(xiàn)有關(guān)的中斷向量轉換為系統的中斷向量,然后利用IoConnectInterrupu指定中斷服務(wù)。

3 設備驅動(dòng)的調用
編寫(xiě)設備驅動(dòng)并不是最終的目的,總是需要由用戶(hù)程序來(lái)調用驅動(dòng)并實(shí)現一定的功能。一般調用設備驅動(dòng)是使用CreateFile函數打開(kāi)設備文件,得到一個(gè)文件句柄。具體到我們的設備

模擬電路文章專(zhuān)題:模擬電路基礎

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




評論


相關(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>