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的理解
- pci匯流排驅動及pci裝置驅動註冊
- 【原創】Linux PCI驅動框架分析(二)Linux框架
- 【原創】Linux PCI驅動框架分析(一)Linux框架
- 驅動開發:核心使用IO/DPC定時器定時器
- windows驅動註冊中斷服務程式Windows
- linux nvidia驅動錯誤--NVRM: This PCI I/O region assigned to your NVIDIA device is invalidLinuxVRdev
- Windows核心驅動-程序回撥Windows
- extcon驅動及其在USB驅動中的應用
- 【Java面試】什麼是 ISR,為什麼需要引入 ISRJava面試
- DPC++中的現代C++語言特性C++
- windows中Python Playsound報錯:驅動程式無法識別指定的命令WindowsPython
- Redis 中的事件驅動模型Redis事件模型
- iOS 裝置驅動 for windows 32&64iOSWindows
- windows10驅動未通過怎麼辦_windows10檢測到驅動未通過處理方法Windows
- MM32F0140 UART1 DMA Interrupt RX and TX (UART1 DMA中斷接收和DMA中斷髮送資料)
- Windows驅動分為如下幾種型別Windows型別
- Windows驅動如何用INF檔案安裝Windows
- 如何將WHQL驅動程式釋出到 Windows 更新Windows
- windows10怎麼更新音效卡驅動_win10更新音效卡驅動的方法WindowsWin10
- windows10怎麼安裝藍芽驅動_win10安裝藍芽驅動的方法Windows藍芽Win10
- Windows10系統載入ahci驅動程式的方法Windows
- Windows 無法安裝未簽名的驅動檔案Windows
- Windows 11重新安裝音訊驅動程式的教程Windows音訊
- windows10驅動未透過怎麼辦_windows10檢測到驅動未透過處理方法Windows
- 流式dma和一致性dma的區別
- JavaScript中的領域驅動設計JavaScript
- 事件驅動架構EDA中的元件事件架構元件
- 混合雲中的事件驅動架構事件架構
- WDS+MDT網路啟動自動部署windows(七)新增驅動Windows
- windows10系統如何回退網路卡驅動Windows
- Windows驅動開發入門 -- 理清基本概念Windows
- windows10系統安裝水星網路卡驅動的方法Windows
- windows10系統關閉軟盤驅動器的方法Windows
- MySQL的驅動表與被驅動表MySql
- spring — Spring中的事件驅動機制解析Spring事件
- 按鍵中斷驅動程式
- 事件驅動的微服務-事件驅動設計事件微服務