利用WinDriver實(shí)現鏈式DMA
使用鏈式DMA傳輸數據時(shí),主機首先通過(guò)設置DMA控制寄存器,告訴設備要傳輸數據的描述符表的起始地址和描述符的個(gè)數,然后啟動(dòng)DMA傳輸。設備收到啟動(dòng)DMA傳輸的命令后,首先根據主機提供的描述符表信息,檢索相應的描述符,并存儲到設備的FIFO中,然后根據每一個(gè)描述符中的地址和長(cháng)度信息,進(jìn)行相應的DMA數據傳輸。所有的DMA描述符處理完成后,設備更新描述符頭的EPLAST域。主機便可通過(guò)查詢(xún)EPLA ST域獲得鏈式DMA傳輸完成的信息,從而可以啟動(dòng)下一次鏈式DMA傳輸。
2 WinDrivet中的DMA功能
WinDriver是Jungo公司提供的一種通用的驅動(dòng)開(kāi)發(fā)支持軟件,它簡(jiǎn)化了用戶(hù)的上層驅動(dòng)開(kāi)發(fā)和應用接口開(kāi)發(fā),而且易于再封裝,實(shí)現商業(yè)化應用。該軟件提供了對PCIExpress接口設備的驅動(dòng)支持,而且也提供了對DMA實(shí)現功能的支持。
WinDriver提供了兩種DMA緩沖區的分配方式,即連續緩沖區和分散/聚合緩沖區。前者當用戶(hù)申請緩沖區時(shí),分配的是一個(gè)物理地址連續的內存塊;而后者分配的緩沖區在物理位置上可以是分段的,這些物理上不連續的內存段通過(guò)虛擬地址空間映射給用戶(hù)的是一個(gè)在應用層連續的緩沖區。
由于采用DMA傳輸數據時(shí),設備需要的主機地址是物理地址;而在主機端,申請大塊的物理地址連續的內存區域往往是非常困難的。因此在使用DMA進(jìn)行大量數據傳輸時(shí),主機端使用分散/聚合緩沖區分配方式更方便和易于實(shí)現。此時(shí),主機可以將緩沖區的每個(gè)內存段對應一個(gè)描述符,這樣采用鏈式DMA方式可以解決大的內存區域物理地址不連續的問(wèn)題,方便了大存儲區域數據的傳輸。
3 具體實(shí)現
在具體實(shí)現時(shí),主機是通過(guò)訪(fǎng)問(wèn)的設備的BAR2地址空間來(lái)設置DMA控制寄存器的。DMA控制寄存器分為DMA讀控制寄存器和DMA寫(xiě)控制寄存器,它們均是由4個(gè)32位的雙字組成,依次表示的含義是:控制域和描述表中描述符的個(gè)數、描述符表的高32位地址、描述符表的低32位地址、最后一個(gè)描述符的索引,其中第一個(gè)雙字的控制域部分用來(lái)控制在每個(gè)描述符傳輸完成時(shí)設備是否更新主機描述符頭的EPLAST域。DMA寫(xiě)(即數據由設備向主機傳送)控制寄存器的開(kāi)始地址位于BAR2地址空間的0字節偏移地址處,DMA讀(即數據由主機向設備傳送)控制寄存器的開(kāi)始地址位于BAR2地址空間的16字節偏移地址處。主機可以通過(guò)調用WinDriver提供的API函數WDC_WriteAddr32每次設置DMA讀/寫(xiě)控制寄存器的一個(gè)雙字。
在每次DMA傳輸開(kāi)始時(shí),根據設備DMA的設計要求,必須先調用WDC_WriteAddr32函數向DMA讀/寫(xiě)控制寄存器的第一個(gè)雙字寫(xiě)入0xFFFF的內容,以使設備DMA進(jìn)入到可以工作的狀態(tài)。這是因為設備每次執行完DMA操作后,處于停止工作狀態(tài),只有通過(guò)對控制寄存器的第一個(gè)雙字寫(xiě)0xFFFF才能使設備DMA模塊退出停止狀態(tài),重新準備檢索DMA描述符。詳見(jiàn)樣本工程的ahpcierd_dma_descriptor模塊的狀態(tài)機部分。
需要注意的是,描述表的描述符中的主機低32位地址必須是16的倍數,設備地址也必須是16的倍數。這是因為設備的端點(diǎn)存儲器是一個(gè)帶有字節寫(xiě)使能控制的RAM,且其每個(gè)周期讀寫(xiě)16個(gè)字節的數據。對于DMA讀操作來(lái)說(shuō),設備收到主機的帶數據的完成包后,是根據主機端的地址設置端點(diǎn)存儲器的字節寫(xiě)使能控制信號的。如果主機端地址的低4位與設備端地址的低4位不一致,將導致數據起始存儲位置不正確。例如:如果主機端地址的低4位是8,設備端地址的低4位是0,端點(diǎn)存儲器寫(xiě)的數據總線(xiàn)接收數據的第一有效時(shí)鐘周期內接收的16字節數據,低8字節對應的字節使能位是0,高8個(gè)字節才是有效的數據。這些有效數據被寫(xiě)入端點(diǎn)存儲器規定存儲位置向后偏移8個(gè)字節的地方,這顯然與設備要求的存儲位置不符。
對于DMA寫(xiě)操作來(lái)說(shuō),設備從端點(diǎn)存儲器中讀取數據時(shí),直接將設備地址的低4位丟棄了,所以設備地址也應為16的倍數。如果主機端地址低32位不是16的倍數,根據設備的Descriptor/Data Interface處理規則和PCI Express規范中存儲器寫(xiě)事務(wù)包的處理規則,將導致主機收到的數據包的有效數據位置向后偏移,部分有效數據丟失,例如:如果主機端低32位地址的低4位是8,那么將使得從端點(diǎn)存儲器讀取的數據的前8個(gè)字節丟失,主機端收到的數據的開(kāi)始位置比預期位置向后移了8個(gè)字節。
在設置主機的描述表時(shí),先調用WinDriver提供的API函數WDC_DMASGBufLock對申請的進(jìn)行DMA數據傳輸的內存塊進(jìn)行鎖定,然后根據鎖定的頁(yè)數,確定描述表中描述符的個(gè)數,每個(gè)描述符對應其中的1頁(yè)存儲區域。根據上面對主機低32位地址的要求,在申請進(jìn)行DMA傳輸的內存區域時(shí),申請的空間大小可以比實(shí)際需要存儲區域多16個(gè)字節。這樣,在調用WDC_DMASGBufLock函數對申請的內存塊進(jìn)行鎖定后,如果第一頁(yè)的物理地址不是16的倍數(在多頁(yè)的情況下,后面的頁(yè)的物理地址均為16的倍數),可以DMA傳輸的實(shí)際區域向后移動(dòng)相應的位置,以使數據存儲的開(kāi)始位置的物理地址為16的倍數。例如,如果第1頁(yè)物理地址的低4位是4,那么可以向后移動(dòng)12個(gè)字節作為DMA傳輸的開(kāi)始位置。如果申請的空間由多頁(yè)組成,應注意第1頁(yè)對應的描述符傳輸數據的長(cháng)度將減少,及對后面頁(yè)對應描述符的設備地址的影響。
設置完成DMA傳輸的描述符表后,需要通過(guò)設置DMA控制寄存器,告訴設備主機描述表的起始物理地址和描述符的個(gè)數。這里,也有上面類(lèi)似的要求。即要求描述表的低32位地址為16的倍數,否則將導致設備FIFO每個(gè)周期接收的描述符不是一個(gè)完整的描述符,即可能是由前一個(gè)描述符的后8字節和后一個(gè)描述符的前8字節組成。這將導致以后DMA數據傳輸的混亂和錯誤。為此,在調用WDC_DMASGBufLock函數對描述符表存儲區域進(jìn)行鎖定時(shí),可以進(jìn)行上面類(lèi)似的地址對齊處理。
因為在調用WDC_DMASGBufLock函數對一塊存儲區域進(jìn)行鎖定時(shí),中間頁(yè)的大小均是4 KB的倍數。這樣就可以估算出一塊內存區域大概可以分成幾頁(yè),從而估計出描述符表由幾個(gè)描述符組成。比如文中的設備存儲器是一個(gè)32 KB的端點(diǎn)存儲器,因此進(jìn)行一次DMA傳輸的描述符個(gè)數不超過(guò)9個(gè),描述符表占用的存儲空間為:16+9*16=160字節。對于這種描述表所需空間少于2 KB的情況下,可以采用如下策略使得描述表的數據集中到一個(gè)物理頁(yè)中,以便于對DMA控制寄存器的設置,即如果所需空間為x(x≤2032)字節,那么申請2(x+16)字節(≤4 KB)的空間,這樣在調用WDC_DMASGBufLock函數進(jìn)行存儲區域鎖定時(shí),得到的頁(yè)數最多為2頁(yè),且至少有一頁(yè)的大小不小于x+16字節。于是,便可用此頁(yè)作為描述符表的存儲區域,并使描述符表的起始地址滿(mǎn)足16的倍數的要求。
存儲器相關(guān)文章:存儲器原理
評論