天天看點

PCIE協定解析 synopsys IP Configuration Space Header 讀書筆記(9)

5.1.7.1 PF PCI-Compatible Configuration Space Header – Type 0

Byte

Offset

Byte 3 Byte 2 Byte 1 Byte 0
0x00 Device ID(ROS) Vendor ID(ROS)
0x04 Status Register(ROS) Command Register(RW)
x08 Class Code(ROS) Revision ID
0x0C BIST(0x00)(RO) Header Type(ROS) Latency Timer(RO) Cache Line Size(RW)
0x10 Base Address Register 0
0x14 Base Address Register 1
0x18 Base Address Register 2
0x1C Base Address Register 3
0x20 Base Address Register 4
0x24 Base Address Register 5
0x28 CardBus CIS Pointer RO(cs)
0x2C Subsystem ID RO(cs) Subsystem Vendor ID RO(cs)
0x30 Expansion ROM Base Address (RW)
0x34 Reserved CapPtr
0x38 Reserved
0x3C Max_Latency1 RO(cs) Min_Grant1 RO(cs) Interrupt Pin RO(cs) Interrupt Line

其中,使用者需要配置的寄存器主要包括為以下兩個:

1、  Command Register(RW)

2、  Base Address Register

以下來自王齊老師的書:

(1) Device ID和Vendor ID寄存器

這兩個寄存器的值由PCISIG配置設定,隻讀。其中Vendor ID代表PCI裝置的生産廠商,而Device ID代表這個廠商所生産的具體裝置。如Intel公司的基于82571EB晶片的系列網卡,其Vendor ID為0x8086[1],而Device ID為0x105E[2]。

(2) Revision ID和Class Code寄存器

這兩個寄存器隻讀。其中Revision ID寄存器記載PCI裝置的版本号。該寄存器可以被認為是Device ID寄存器的擴充。

(3) Header Type寄存器

該寄存器隻讀,由8位組成。

第7位為1表示目前PCI裝置是多功能裝置,為0表示為單功能裝置。

第6~0位表示目前配置空間的類型,為0表示該裝置使用PCI Agent裝置的配置空間,普通PCI裝置都使用這種配置頭;為1表示使用PCI橋的配置空間,PCI橋使用這種配置頭;為2表示使用Cardbus橋片的配置空間,Card Bus橋片使用這種配置頭,本篇對這類配置頭不感興趣。

系統軟體需要使用該寄存器區分不同類型的PCI配置空間,該寄存器的初始化必須與PCI裝置的實際情況對應,而且必須為一個合法值。

(4) Cache Line Size寄存器

該寄存器記錄HOST處理器使用的Cache行長度。在PCI總線中和Cache相關的總線事務,如存儲器寫并無效和Cache多行讀等總線事務需要使用這個寄存器。值得注意的是,該寄存器由系統軟體設定,但是在PCI裝置的運作過程中,隻有其硬體邏輯才會使用該寄存器,比如PCI裝置的硬體邏輯需要得知處理器系統Cache行的大小,才能進行存儲器寫并無效總線事務,單行讀和多行讀總線事務。

如果PCI裝置不支援與Cache相關的總線事務,系統軟體可以不設定該寄存器,此時該寄存器為初始值0x00。對于PCIe裝置,該寄存器的值無意義,因為PCIe裝置在進行資料傳送時,在其封包中含有一次資料傳送的大小,PCIe總線控制器可以使用這個“大小”,判斷資料區域與Cache行的對應關系。

(5) Subsystem ID和Subsystem Vendor ID寄存器

這兩個寄存器和DeviceID和Vendor ID類似,也是記錄PCI裝置的生産廠商和裝置名稱。但是這兩個寄存器和Device ID與Vendor ID寄存器略有不同。下文以一個執行個體說明Subsystem ID和Subsystem Vendor ID的用途。

Xilinx公司在FGPA中內建了一個PCIe總線接口的IP核,即LogiCORE。使用者可以使用LogiCORE設計各種各樣基于PCIe總線的裝置,但是這些裝置的Device ID都是0x10EE,而Vendor ID為0x0007[3]。

(6) Expansion ROM base address寄存器

有些PCI裝置在處理器還沒有運作作業系統之前,就需要完成基本的初始化設定,比如顯示卡、鍵錯誤!超連結引用無效。盤和硬碟等裝置。為了實作這個“預先執行”功能,PCI裝置需要提供一段ROM程式,而處理器在初始化過程中将運作這段ROM程式,初始化這些PCI裝置。Expansion ROM base address記載這段ROM程式的基位址。

(7) Capabilities Pointer寄存器

在PCI裝置中,該寄存器是可選的,但是在PCI-X和PCIe裝置中必須支援這個寄存器,Capabilities Pointer寄存器存放Capabilities寄存器組的基位址,PCI裝置使用Capabilities寄存器組存放一些與PCI裝置相關的擴充配置資訊。該組寄存器的詳細說明見第4.3節。

(8) Interrupt Line寄存器

這個寄存器是系統軟體對PCI裝置進行配置時寫入的,該寄存器記錄目前PCI裝置使用的中斷向量号,裝置驅動程式可以通過這個寄存器,判斷目前PCI裝置使用處理器系統中的哪個中斷向量号,并将驅動程式的中斷服務例程注冊到作業系統中[4]。

該寄存器由系統軟體初始化,其儲存的值與8259A中斷控制器相關,該寄存器的值也是由PCI裝置與8259A中斷控制器的連接配接關系決定的。如果在一個處理器系統中,沒有使用8259A中斷控制器管理PCI裝置的中斷,則該寄存器中的資料并沒有意義。

在多數PowerPC處理器系統中,并不使用8259A中斷控制器管理PCI裝置的中斷請求,是以該寄存器沒有意義。即使在x86處理器系統中,如果使用I/O APIC中斷控制器,該寄存器儲存的内容仍然無效。目前在絕大多數處理器系統中,并沒有使用該寄存器存放PCI裝置使用的中斷向量号。

(9) Interrupt Pin寄存器

這個寄存器儲存PCI裝置使用的中斷引腳,PCI總線提供了四個中斷引腳INTA#、INTB#、INTC#和INTD#。Interrupt Pin寄存器為1時表示使用INTA#引腳向中斷控制器送出中斷請求,為2表示使用INTB#,為3表示使用INTC#,為4表示使用INTD#。

如果PCI裝置隻有一個子裝置時,該裝置隻能使用INTA#;如果有多個子裝置時,可以使用INTB~D#信号。如果PCI裝置不使用這些中斷引腳,向處理器送出中斷請求時,該寄存器的值必須為0。值得注意的是,雖然在PCIe裝置中并不含有INTA~D#信号,但是依然可以使用該寄存器,因為PCIe裝置可以使用INTx中斷消息,模拟PCI裝置的INTA~D#信号,詳見第6.3.4節。

(10) Base Address Register 0~5寄存器

該組寄存器簡稱為BAR寄存器,BAR寄存器儲存PCI裝置使用的位址空間的基位址,該基位址儲存的是該裝置在PCI總線域中的位址。其中每一個裝置最多可以有6個基址空間,但多數裝置不會使用這麼多組位址空間。

在PCI裝置複位之後,該寄存器将存放PCI裝置需要使用的基址空間大小,這段空間是I/O空間還是存儲器空間[5],如果是存儲器空間該空間是否可預取,有關PCI總線預讀機制的詳細說明見第3.4.5節。

系統軟體對PCI總線進行配置時,首先獲得BAR寄存器中的初始化資訊,之後根據處理器系統的配置,将合理的基位址寫入相應的BAR寄存器中。系統軟體還可以使用該寄存器,獲得PCI裝置使用的BAR空間的長度,其方法是向BAR寄存器寫入0xFFFF-FFFF,之後再讀取該寄存器。

處理器通路PCI裝置的BAR空間時,需要使用BAR寄存器提供的基位址。值得注意的是,處理器使用存儲器域的位址,而BAR寄存器存放PCI總線域的位址。是以處理器系統并不能直接使用“BAR寄存器+偏移”的方式通路PCI裝置的寄存器空間,而需要将PCI總線域的位址轉換為存儲器域的位址。

如果x86處理器系統使能了IOMMU後,這兩個位址也并不一定相等,是以處理器系統直接使用這個PCI總線域的實體位址,并不能確定通路PCI裝置的BAR空間的正确性。除此之外在Linux系統中,ioremap函數的輸入參數為存儲器域的實體位址,而不能使用PCI總線域的實體位址。

而在pci_devàresource[bar].start參數中儲存的位址已經經過PCI總線域到存儲器域的位址轉換,是以在編寫Linux系統的裝置驅動程式時,需要使用pci_devàresource[bar].start參數中的實體位址,然後再經過ioremap函數将實體位址轉換為“存儲器域”的虛拟位址。

(11) Command寄存器(bring up的時候需要注意????)

該寄存器為PCI裝置的指令寄存器,該寄存器在初始化時,其值為0,此時這個PCI裝置除了能夠接收配置請求總線事務之外,不能接收任何存儲器或者I/O請求。系統軟體需要合理設定該寄存器之後,才能通路該裝置的存儲器或者I/O空間。在Linux系統中,裝置驅動程式調用pci_enable_device函數,使能該寄存器的I/O和Memory Space位之後,才能通路該裝置的存儲器或者I/O位址空間。

(12) Status寄存器

該寄存器的絕大多數位都是隻讀位,儲存PCI裝置的狀态。

(13) Latency Timer寄存器

在PCI總線中,多個裝置共享同一條總線帶寬。該寄存器用來控制PCI裝置占用PCI總線的時間,當PCI裝置獲得總線使用權,并使能Frame#信号後,Latency Timer寄存器将遞減,當該寄存器歸零後,該裝置将使用逾時機制停止[6]對目前總線的使用。

如果目前總線事務為MemeoryWrite and Invalidate時,需要保證對一個完整Cache行的操作結束後才能停止目前總線事務。對于多數PCI裝置而言,該寄存器的值為32或者64,以保證一次突發傳送的基本機關為一個Cache行。

PCIe裝置不需要使用該寄存器,該寄存器的值必須為0。因為PCIe總線的仲裁方法與PCI總線不同,使用的連接配接方法也與PCI總線不同。

繼續閱讀