本文主要介紹乙個簡單的單一裝置pcie驅動程式和裝置的通訊協議,從上到下大致分為三層:應用層、驅動層和裝置層。其中,應用層和驅動層通過系統匯流排(win32 api呼叫)實現通訊,驅動層和裝置層通過pci匯流排(位址空間對映)進行通訊。
一、driver和device的資料互動方式
driver和device的通訊主要是通過位址空間對映來實現。作業系統將device的物理位址對映為系統虛擬位址,driver可以直接讀寫;driver也可以分配一段記憶體,對映為pci位址,供device讀寫。後面將這種對映的記憶體稱為buffer,driver和device的資料互動就是通過這種讀寫共享buffer的方式實現的。大致可以分為以下幾種型別:
write_cmd方式:driver寫device的buffer
read_cmd方式:driver讀device的buffer
dma_write方式:device讀driver的buffer
dma_read方式:device寫driver的buffer
二、buffer劃分
driver開闢兩塊4mbytes的buffer,用於dma讀寫,讀寫的時候,資料按4mbytes對齊,不足4mbytes的資料塊按填零處理。
device對映3塊bar空間到driver,ba0為標準的pci配置空間,大小為4k位元組。bar1和bar2作為資料互動buffer,大小為4m位元組。其中,bar1用於driver發資訊給device,bar2用於device返回資訊給driver。按byte計算,兩個buffer的offset範圍是:0 ~ 4*1024*1024 – 1。
在實際使用中,我們一般以32bits來表示乙個資訊單元,即轉化為乙個ulong值。因此,實際上,我們是以4bytes為單元,用index來定位。但又乙個例外——frame資料,後續講到了再展開說。以4bytes為單元,按index劃分buffer,它的index範圍是:0 ~ 1024*1024 – 1。
注:後續沒有特殊說明,buffer內部都按index計算。
同樣,bar2的前4個index全部保留。從index4起,作為response的content,其中包括response typeid、the number of returned values和returned values。
四、資料互動過程
各flag初始態都是0。
write_cmd的steps:
1)device迴圈讀major flag,等待1。
2)driver將資料填入bar1的資料域,然後對major flag置1。
3)driver開迴圈讀major flag,等待0。
4)device等到1,取走bar1資料域中的資料。
5)device將返回值填入bar2的資料域,然後對major flag置0。(device側該次互動結束)
6)driver等到0,取走bar2資料域中的資料,返回應用層;
對於driver和device的互動來說,read_cmd的steps與write_cmd的steps相同,這裡區分開來是便於應用層理解。
dma_read的steps:
1)device迴圈讀major flag,等待1。
2)driver將資料填入bar1的資料域,然後對major flag置1。
3)driver開迴圈讀major flag,等待0。
4)device等到1,取走bar1資料域中的資料,然後對major flag置0。
5)device從資料中獲知dma,開啟dma迴圈計數,並在迴圈體中讀minor flag,等待1。
6)driver等到major flag的0,返回應用層;
以上過程完成命令互動,下面開始dma資料互動
應用層開啟乙個for迴圈,執行n次dma資料互動。
7)driver收到應用層的dma read請求,對minor flag置1。
8)driver開迴圈讀minor flag,等待0。
9)device等到minor flag的1,將資料填入read buffer,然後對major flag置0。(device側的一次dma資料傳輸結束,進入下一次小迴圈)
10)driver等到minor flag的0,將資料取回,然後返回應用層;(應用層的一次dma資料read結束,進入下一次小迴圈)
11)……
12)pc側和device側的dma迴圈計數結束,完成整個dma過程。
從以上過程來看,dma_read其實分為兩大步,首先是pc給device發乙個「dma預備」的命令,然後雙方都進入實際的dma迴圈過程。
dma_write與dma_read類似,不再另書。
注:在「dma預備」命令中,包含這一次dma傳輸的總資料量,以位元組為單位, device需要換算成迴圈次數。
字元裝置驅動1 乙個簡單的字元裝置驅動示例
1.註冊主次裝置號 register chrdev region 和 alloc chrdev region 2.註冊字元裝置驅動 cdev init 初始化,cdev add 新增,註冊裝置驅動,cdev alloc 申請空間,cdev del 登出驅動 3.建立驅動的裝置檔案 class cre...
乙個極簡單的 塊裝置驅動 的編寫
目標平台 loongson 1b 目標系統 1b linux 3.0 目標開發板架構 mipsel架構 實現平台 ubuntu 13.04 include include include include include include include include include include ...
簡單的乙個字元裝置驅動
include include include include include include include include include include include include 包含記憶體管理兩個核心函式 include memdev.h static int mem major me...