Windows驅動中的PCI, DMA, ISR, DPC, ScatterGater, MapRegsiter, CommonBuffer, ConfigSpace
最近有些人問我PCI
裝置驅動的問題, 和他們交流過後, 我建議他們先看一看<<The Windows NT Device Driver Book>>
這本書, 個人感覺, 這本書寫得非常連貫流暢.
PCI
裝置驅動基本包括了PCI
的資源獲取, 配置空間的讀寫, 中斷的處理, 中斷後半部在DPC
中的處理.
同時, 也必須瞭解DMA, ScatterGater, MapRegister, Common Buffer
等基礎.
1.1 PCI
裝置資源獲取
PCI
裝置的資源是系統根據裝置的屬性(配置空間中暫存器的值)來動態分配的.
驅動中只需在PNP START
中獲取這些系統分配的資源:
例如: 筆者開發的PCI
電視卡驅動中, 就使用到了其中了兩類資源, CmResourceTypePort
與CmResourceTypeInterrupt
.
Port
地址作為裝置暫存器首地址, 之後, 可以使用WRITE_PORT_ULONG
與READ_PORT_ULONG
加上相應的OFFSET
來對裝置暫存器進行訪問.
Interrupt
資源中解釋出來的內容, 則主要作為IoConnectInterrupt
系統函式的引數, 將裝置的硬體中斷與ISR
相關聯, KINTERRUPT
的例項則是裝置中斷的軟體形式的載體.
1.2 DMA
DMA
裝置, 在系統中分為MASTER
與SLAVE
, 另外一個很重要的能力就是是否支援Scatter/Gather
.
這些能力最終表現在DEVICE_DESCRIPTION
所定義的資料結構的成員中, 例如:DmaWidth
, ScatterGather
, Master, Dma32BitAddresses, Dma64BitAddresses
.
系統最終將各種不同型別的裝置DMA
抽象為DMA_ADAPTER
的例項, 它是裝置DMA
軟體形式的載體.
驅動程式碼通過IoGetDmaAdapter
系統呼叫, 將物理裝置物件PDO
與DMA
描述結構作為引數, 最終得到這個DMA_ADAPTER
物件, 作為後續一系列DMA
相關操作的實體物件.
1.3 Map Register
使用者空間, 核心空間的虛擬記憶體與實體記憶體的關聯是通過頁表來對映的, 驅動程式設計師常常會使用MDL
, 它也是某一特定區域虛擬記憶體與實體記憶體的對映關係.
而DMA
裝置則需要從匯流排地址(MSDN中又叫邏輯地址)與記憶體物理的對映關係角度去看待系統記憶體.
這個對映的關係就是由Map Register
承擔的.
不過, 這批Map Register
則根據系統而定, 有些是硬體實現, 有些是軟體中劃分出來的特定的一塊記憶體.
IoGetDmaAdapter
的呼叫, 也是向系統申請Map Register
的過程.
1.4 Common Buffer
這也是大家問得最多的問題
簡單地講, Common buffer
是以DMA_ADAPTER
為代表所申請的, 申請成功後, 既能通過虛擬地址訪問, 也可以通過DMA
控制器所屬邏輯地址空間的地址來訪問的連續實體記憶體.
它的好處就是物理上連續, 存在的問題是系統中連續實體記憶體是隨著系統的執行時間的流逝, 越來越稀缺.
AllocateCommonBuffer
系統呼叫是作為DMA_ADAPTER
的DmaOperations
形式存在的, 所以, 具體的一塊Common Buffer
可以說, 是與具體的一個DMA
控制器所關聯的.
AllocateCommonBuffer
成功呼叫後, 會返回虛擬地址與DMA
控制器所屬邏輯空間的邏輯地址.
筆者開發的PCI
電視卡, 就是通過AllocateCommonBuffer
分配一塊較小的連續實體記憶體, 用來存放Scatter/Gather
列表 (某塊記憶體的邏輯地址SCATTER_GATHER_LIST.Elements[i].Address.LowPart
與該記憶體的長度SCATTER_GATHER_LIST.Elements[i].Length
, 相應操作通過common buffer
的虛擬地址 ).
這個Scatter/Gather
List列表最終由具有S/G
能力的DMA
控制器來讀取(相應操作通過common buffer
的邏輯地址), 根據其中的表項, 進行DMA
讀/寫操作.
1.5 S/G
S/G的
能力是DMA
控制器的特性, 如果具有S/G
的能力, 則可以批量地DMA
操作, 否則, 必須一次一次地使用MapTransfer
來完成DMA
操作.
系統空間的中虛擬記憶體與實體記憶體之間的聯絡通過IoAllocateMdl
與MmBuildMdlForNonPagedPool
建立特定的MDL
來表示.
其後,通過DMA_ADAPTER
的DmaOperations
中的GetScatterGatherList
獲取MDL
所描述的虛擬地址記憶體的S/G
列表, 最後, 在GetScatterGatherList
的
ExecutionRoutine
函式中, 將該列表填入Common buffer
的TABLE
(起始邏輯地址 與 長度)中, 以供DMA Controller
所用.
1.6 ISR
與DPC
剛才已經提到, ISR
是通過IoConnectInterrupt
註冊的.ISR
在裝置中斷到來時實呼叫, 但具體的事項則交由(KeInsertQueueDpc
)DPC
來處理.而DPC
則是通過KeInitializeDpc
系統呼叫, 將DPC
物件KDPC
與具體的KDEFERRED_ROUTINE DPC
處理函式相關聯的.
1.7 PCI裝置配置空間的訪問
事實上, 一般情況下, Windows PCI
裝置並不需要訪問PCI
裝置配置空間.但作為一個完整的PCI
裝置驅動, 這裡提及一下.
由於PCI
裝置的配置空間與IO/MEM
空間是分開的, 前面已經提及IO/MEM
的訪問方式, 配置空間的訪問如下:定義變數:BUS_INTERFACE_STANDARD m_BusInterfaceStandard
;建立: IRP
, 主與次分別為IRP_MJ_PNP
, IRP_MN_QUERY_INTERFACE
, 得到BUS_INTERFACE_STANDARD
資料結構.之後, 通過BUS_INTERFACE_STANDARD
中的SetBusData
與GetBusData
來進行PCI
配置空間的暫存器讀寫.
PCI
裝置驅動完全可以用在PCIe
裝置上, 畢竟上層來講, 他們沒有太多的區別.
與USB
驅動不同, PCI
裝置需要考慮驅動設計中的方方面面, 希望這篇文章對大家有所借鑑作用.
相關文章
- DPC和ISR的理解
- 驅動開發:核心使用IO/DPC定時器定時器
- 【原創】Linux PCI驅動框架分析(一)Linux框架
- 【原創】Linux PCI驅動框架分析(二)Linux框架
- Linux下PCI轉串列埠卡驅動安裝方法Linux串列埠
- 蛻變成蝶:Linux裝置驅動之DMALinux
- windows驅動註冊中斷服務程式Windows
- windows8中arduino驅動安裝方法WindowsUI
- Windows XP 中查詢驅動程式資訊(轉)Windows
- Windows的驅動開發模型Windows模型
- Windows驅動程式框架Windows框架
- windows載入驅動Windows
- Windows系統中巧妙隱藏驅動器(轉)Windows
- windows核心原理分析之DPC函式的執行(1)Windows函式
- 【Java面試】什麼是 ISR,為什麼需要引入 ISRJava面試
- Windows裝置和驅動的安裝Windows
- DPC++中的現代C++語言特性C++
- extcon驅動及其在USB驅動中的應用
- 微軟更新 Windows 驅動安全指南微軟Windows
- windows驅動載入順序Windows
- Windows驅動開發入門Windows
- Windows核心驅動-程序回撥Windows
- Redis 中的事件驅動模型Redis事件模型
- 關於windows下安裝mysql的驅動,及安裝完驅動找不到ODBC驅動的解決辦法WindowsMySql
- [Windows驅動開發](一)VS2008搭建windows驅動編譯環境Windows編譯
- windows中Python Playsound報錯:驅動程式無法識別指定的命令WindowsPython
- WHQL認證的Windows 7 RTM顯示驅動Windows
- linux nvidia驅動錯誤--NVRM: This PCI I/O region assigned to your NVIDIA device is invalidLinuxVRdev
- iOS 裝置驅動 for windows 32&64iOSWindows
- windows10驅動未通過怎麼辦_windows10檢測到驅動未通過處理方法Windows
- Windows 11重新安裝音訊驅動程式的教程Windows音訊
- 連線LilyPad之Windows平臺的驅動Windows
- Windows95的裝置驅動程式的編寫 (轉)Windows
- MM32F0140 UART1 DMA Interrupt RX and TX (UART1 DMA中斷接收和DMA中斷髮送資料)
- 事件驅動架構EDA中的元件事件架構元件
- 混合雲中的事件驅動架構事件架構
- JavaScript中的領域驅動設計JavaScript
- Spring中的事件驅動模型(一)Spring事件模型