今天是介紹 PCI(e) 部分的最後一篇,我們將深入探討 MMIO(Memory-Mapped I/O)和 PMIO(Port-Mapped I/O)的建立與管理過程。
昨天我們談到,PCI(e) 設備的 Configuration Space Header 保存了該設備的基本資訊和設置。而其中的 Base Address Registers (BARs),就是今天要討論的重點。
BARs 是一系列 32 bits 的暫存器,用來管理 PCI 設備的記憶體映射。不論是透過 MMIO 或是 PMIO,都是將 PCI 設備的記憶體區塊映射到物理記憶體空間(Physical Address Space)或 I/O 空間(I/O Space)。
在系統初始化時,作業系統會向 Base Address Register 寫入 0xFFFFFFFF
,然後讀取該暫存器,這時 PCI 設備會返回所需的映射空間大小,並告知是使用 I/O Space 還是 Memory Space。
BAR 的 bit 0 會指示該設備是使用 I/O Space 或 Memory Space。如果是使用 Memory Space,因為該空間較大,可以允許映射到 64 位元的定址範圍,因此 bit 2:1 會指示該 BAR 是 32 位元還是 64 位元的暫存器。
接下來,從 BAR 的欄位可以計算出該設備所需的記憶體大小。以下是計算過程:
經過上述計算,就能得到設備所需的地址大小。例如,某個設備需要 1MB 的 MMIO 記憶體,BAR 讀取出來的數值會是 0xFFF00000
。因為使用的是 MMIO,所以 bit 3:0 歸零後不變。邏輯反運算後,~0xFFF00000 = 0x000FFFFF
,加 1 得到 0x00100000
,也就是 1MB。
lspci
查看 BAR 設定透過 lspci
指令,我們可以檢視 PCI 設備的映射區域資訊:
> lspci -s 07:00.0 -vvv
07:00.0 Ethernet controller: Intel Corporation Ethernet Controller I225-V (rev 03)
Subsystem: ASUSTeK Computer Inc. Ethernet Controller I225-V
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 19
IOMMU group: 20
Region 0: Memory at 86500000 (32-bit, non-prefetchable) [size=1M]
Region 3: Memory at 86600000 (32-bit, non-prefetchable) [size=16K]
Capabilities: [40] Power Management version 3
在這裡,我們可以看到該設備有兩個 MMIO 映射區,分別大小為 1MB 和 16KB,並且映射地址分別為 0x86500000
和 0x86600000
。
透過額外的參數,我們可以直接讀取 Configuration Space Header 的數據:
lspci -s 07:00.0 -Qkxxxxnnv
07:00.0 Ethernet controller [0200]: Intel Corporation Ethernet Controller I225-V [8086:15f3] (rev 03)
Subsystem: ASUSTeK Computer Inc. Device [1043:87d2]
Flags: bus master, fast devsel, latency 0, IRQ 19, IOMMU group 20
Memory at 86500000 (32-bit, non-prefetchable) [size=1M]
Memory at 86600000 (32-bit, non-prefetchable) [size=16K]
...
00: 86 80 f3 15 06 04 10 00 03 00 00 02 10 00 00 00
10: 00 00 50 86 00 00 00 00 00 00 00 00 00 00 60 86
....
對照 Configuration Space Header 的欄位,我們可以看到 Bar 0
的數值是 00 00 50 86
,正好對應 Region 0
的映射地址 0x86500000
。同樣地,Bar 3
是 00 00 60 86
,剛好對應 Region 3
的映射地址`0x86600000。
今天我們了解了如何建透過 BARs 管理 PCIe 設備的映射,接著我們將會回到驅動層來探索。