之前調(diào)試了幾個PCI網(wǎng)卡驅(qū)動,雖然功能沒什么問題,但驅(qū)動中調(diào)用的某些內(nèi)核提供的PCI相關(guān)的接口一直沒搞太清楚,所以最近準(zhǔn)備深入研究一把。
PCI設(shè)備的識別及配置方式
PCI總線使用單端并行數(shù)據(jù)總線,采用地址譯碼方式進(jìn)行數(shù)據(jù)傳遞,而采用ID譯碼方式進(jìn)行配置信息(比如配置某個PCI設(shè)備的物理地址)的傳遞。其中地址譯碼方式使用地址信號,而ID譯碼方式使用PCI設(shè)備的ID號,包括Bus Number、Device Number、Function Number和Register Number。Linux系統(tǒng)中使用了Bus Number、Device Number和Function Number區(qū)分不同的設(shè)備;對于有兩個接口的網(wǎng)卡,Linux會按照兩個設(shè)備處理,因?yàn)檫@兩個接口會呈現(xiàn)出不同的Function Number。
Posted和Non-Posted傳送方式
PCI總線規(guī)定了兩類數(shù)據(jù)傳送方式,分別是Posted和Non-Posted數(shù)據(jù)傳送方式。又分別對應(yīng)了Posted和Non-Posted總線事務(wù)。
Posted總線事務(wù)指PCI主設(shè)備向PCI目標(biāo)設(shè)備進(jìn)行數(shù)據(jù)傳遞時,當(dāng)數(shù)據(jù)到達(dá)PCI橋后,即由PCI橋接管來自上游總線的總線事務(wù),并將其轉(zhuǎn)發(fā)到下游總線。采用這種數(shù)據(jù)傳遞方式,在數(shù)據(jù)還沒有到達(dá)最終的目的地之前,PCI總線就可以結(jié)束當(dāng)前總線事務(wù),從而在一定程度上解決了PCI總線的擁塞問題,所以這種方式的PCI總線利用率較高。只有存儲器寫請求可以采用Posted總線事務(wù),簡稱為PMW(Posted Memory Write)。
Non-Posted總線事務(wù)是指PCI主設(shè)備向PCI目標(biāo)設(shè)備進(jìn)行數(shù)據(jù)傳遞時,數(shù)據(jù)必須到達(dá)最終目的地之后,才能結(jié)束當(dāng)前總線事務(wù)的一種數(shù)據(jù)傳遞方式。存儲器讀請求、I/O讀寫請求、配置讀寫請求只能采用Non-Posted總線事務(wù)。
中斷請求和數(shù)據(jù)傳送的同步問題(MSI中斷機(jī)制不存在這個問題)
在PCI總線中,INTx信號是一個異步信號。所謂異步,是指INTx信號的傳遞并不與PCI總線的數(shù)據(jù)傳送同步。假設(shè)某個PCI設(shè)備在使用DMA方式將一組數(shù)據(jù)寫入存儲器,該設(shè)備在最后一個數(shù)據(jù)離開自己的發(fā)送FIFO時,即認(rèn)為DMA操作已經(jīng)完成。此時這個設(shè)備將通過INTx信號,通知處理器DMA寫操作完成。
但是,當(dāng)處理器收到INTx信號時,并不意味著PCI設(shè)備已經(jīng)將數(shù)據(jù)寫入存儲器中,因?yàn)镻CI設(shè)備的數(shù)據(jù)傳遞需要經(jīng)過PCI橋/HOST主橋,最終才能到達(dá)存儲器。
PCI總線提供了以下兩種方法解決這個同步問題。
(1)PCI設(shè)備保證在數(shù)據(jù)到達(dá)目的地之后,再提交中斷請求。具體來說,PCI設(shè)備在提交中斷請求之前,向DMA寫的數(shù)據(jù)區(qū)域發(fā)出一個讀請求。PCI總線的“序”機(jī)制,保證了在這個存儲器讀請求完成前,會將以前發(fā)出的DMA數(shù)據(jù)寫入存儲器。PCI總線規(guī)范要求HOST主橋和PCI橋必須保證這種讀操作可以刷新寫操作。但問題是,沒有多少芯片設(shè)計者愿意提供這種機(jī)制,因?yàn)檫@將極大地增加他們的設(shè)計難度。除此之外,使用這種方法也將增加中斷請求的延時。
(2)中斷服務(wù)程序在使用“PCI設(shè)備寫入存儲器”的這些數(shù)據(jù)之前,需要對這個PCI設(shè)備進(jìn)行讀操作。這個讀操作也可以強(qiáng)制將數(shù)據(jù)最終寫入存儲器。這種方法也是利用了PCI總線的傳送序規(guī)則,與第1種方法類似。只是這種方法使用軟件方式,而第1種方式使用硬件方式。這是絕大多數(shù)處理器系統(tǒng)采用的方法。在中斷服務(wù)程序中,往往都是先讀取PCI設(shè)備的中斷狀態(tài)寄存器,判斷中斷產(chǎn)生原因之后,才對PCI設(shè)備寫入的數(shù)據(jù)進(jìn)行操作。這個讀取中斷狀態(tài)寄存器的過程,一方面可以獲得設(shè)備的中斷狀態(tài),另一方面可以保證DMA寫的數(shù)據(jù)(在被CPU讀取前)已經(jīng)到達(dá)存儲器。
PCI配置空間中的幾個寄存器的作用
(1)Cache Line Size寄存器:記錄HOST處理器使用的Cache Line長度。在PCI總線中和Cache相關(guān)的總線事務(wù),如存儲器寫并無效和Cache多行讀等總線事務(wù)需要使用這個寄存器。該寄存器由系統(tǒng)軟件設(shè)置,但是在PCI設(shè)備的運(yùn)行過程中,只有其硬件邏輯才會使用該寄存器。對于PCIe設(shè)備,該寄存器的值無意義,因?yàn)镻CIe設(shè)備在進(jìn)行數(shù)據(jù)傳送時,在其報文中含有一次數(shù)據(jù)傳送的大小,PCIe總線控制器可以使用這個“大小”,判斷數(shù)據(jù)區(qū)域與Cache Line的對應(yīng)關(guān)系。
(2)Interrupt Line寄存器:由系統(tǒng)軟件對PCI設(shè)備進(jìn)行配置時寫入,記錄當(dāng)前PCI設(shè)備使用的中斷向量號。設(shè)備驅(qū)動程序可以通過這個寄存器,判斷當(dāng)前PCI設(shè)備使用處理器中的哪個中斷向量號,并將驅(qū)動程序中的中斷服務(wù)例程注冊到操作系統(tǒng)中。但是,目前在絕大多數(shù)處理器系統(tǒng)中,并沒有使用該寄存器存放PCI設(shè)備使用的中斷向量號。
(3)Base Address Register 0~5 寄存器:簡稱為BAR寄存器。保存的是PCI設(shè)備在PCI總線域中的基地址,由操作系統(tǒng)配置。在PCI設(shè)備復(fù)位之后,該寄存器將存放PCI設(shè)備需要使用的基址空間大小、這段空間是I/O空間還是存儲器空間、如果是存儲器空間是否可預(yù)取等。
系統(tǒng)軟件對PCI總線進(jìn)行配置時,先獲取BAR寄存器中的初始化信息,之后根據(jù)處理器系統(tǒng)的配置,將合理的基地址寫入相應(yīng)的BAR寄存器中。系統(tǒng)軟件還可以使用該寄存器獲得PCI設(shè)備使用的BAR空間的長度,方法是向BAR寄存器中寫入0xFFFFFFFF,然后再讀取該寄存器。
(4)Command寄存器:在初始化時,其值為0,此時這個PCI設(shè)備除了能夠接收配置請求總線事務(wù)外,不能接收任何存儲器或者I/O請求。在Linux系統(tǒng)中,設(shè)備驅(qū)動程序調(diào)用pci_enable_device函數(shù)(也可以是pci_enable_device_mem-> pci_enable_device_flags-> do_pci_enable_device-> pcibios_enable_device-> pci_enable_resources-> pci_write_config_word),使能該寄存器的I/O和Memory Space位之后,才能訪問該設(shè)備的存儲器或者I/O地址空間。
另外,該寄存器中還有Bus Master位表示該設(shè)備是否可以作為主設(shè)備(Linux驅(qū)動程序中調(diào)用pci_set_master函數(shù),將此位設(shè)置為1,表示設(shè)備可作為master)。寄存器中的Interrupt Disable位默認(rèn)為0,為1時表示不允許該設(shè)備使用INTx信號提交中斷請求,當(dāng)PCI設(shè)備使用MSI中斷方式時,該位將被設(shè)置為1(Linux驅(qū)動程序中調(diào)用的函數(shù)為pci_alloc_irq_vectors-> pci_alloc_irq_vectors_affinity-> __pci_enable_msi_range-> msi_capability_init-> pci_intx_for_msi-> pci_intx)。
Linux的PCI設(shè)備驅(qū)動程序中調(diào)用的dma_set_mask_and_coherent函數(shù)有什么作用
Linux的PCI設(shè)備驅(qū)動中一般都會調(diào)用諸如dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))之類的接口。這是用來通知內(nèi)核當(dāng)前設(shè)備支持的DMA訪問的尋址能力,作用是限制內(nèi)核為當(dāng)前設(shè)備分配的內(nèi)存地址范圍。比如之前的例子就表示當(dāng)前設(shè)備支持64位尋址,并且在此范圍內(nèi)支持一致性DMA訪問。
Linux的PCI設(shè)備驅(qū)動程序中調(diào)用的pci_disable_link_state函數(shù)有什么作用
有些PCI設(shè)備的驅(qū)動中會調(diào)用諸如pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM)之類的接口。其作用是設(shè)置PCIe設(shè)備的擴(kuò)展配置空間中的Link Control寄存器。具體到前例,是把Link Control寄存器中的“ASPM Control”字段和“Enable clkreq”字段設(shè)置為0,作用分別是禁止PCI設(shè)備進(jìn)入L0s和L1(低功耗)狀態(tài)以及禁止CLKREQ功能(相當(dāng)于禁止設(shè)備的時鐘管理功能,起到性能優(yōu)先的效果,不考慮省電;具體效果還取決于內(nèi)核中CONFIG_PCIEASPM_XXXX相關(guān)的配置)。
-
網(wǎng)卡
+關(guān)注
關(guān)注
4文章
313瀏覽量
27420 -
PCI
+關(guān)注
關(guān)注
4文章
671瀏覽量
130395 -
總線
+關(guān)注
關(guān)注
10文章
2898瀏覽量
88270
發(fā)布評論請先 登錄
相關(guān)推薦
評論