linux內(nèi)核中pcie驅(qū)動架構(gòu)
一、PCIe驅(qū)動架構(gòu)層次
Linux PCIe驅(qū)動分為四個核心層次:
-
PCI/PCIe核心層(PCI Core)
-
位于
drivers/pci目錄,負責總線枚舉、資源配置、設(shè)備發(fā)現(xiàn)和通用驅(qū)動框架。 -
關(guān)鍵功能:掃描PCIe拓撲結(jié)構(gòu)、分配內(nèi)存和中斷資源、管理設(shè)備配置空間(如BAR、Capability結(jié)構(gòu))。
-
核心數(shù)據(jù)結(jié)構(gòu):
struct pci_dev(表示一個PCI設(shè)備)、struct pci_bus(表示一條PCI總線)。
-
-
主機控制器驅(qū)動(Host Controller Driver)
-
位于
drivers/pci/controller或drivers/pci/host目錄,負責與硬件SoC/芯片組的PCIe Root Complex交互。 -
示例驅(qū)動:Intel的
pcie-intel、ARM的pcie-rcar、國產(chǎn)芯片的定制控制器驅(qū)動。 -
功能:初始化Root Complex、處理總線掃描觸發(fā)(如通過ACPI或設(shè)備樹)。
-
-
PCIe設(shè)備驅(qū)動(Device Driver)
-
用戶編寫的具體設(shè)備驅(qū)動(如網(wǎng)卡、GPU、量子密碼卡驅(qū)動)。
-
通過
struct pci_driver注冊驅(qū)動,實現(xiàn)probe()、remove()等回調(diào)。 -
關(guān)鍵操作:映射BAR空間、配置DMA、注冊中斷處理函數(shù)。
-
-
用戶空間接口
-
提供
/sys/bus/pci下的sysfs節(jié)點,或通過字符設(shè)備(如/dev/mycrypto)暴露功能。 -
工具鏈:
lspci、setpci等命令直接訪問配置空間。
-
二、總線枚舉與設(shè)備發(fā)現(xiàn)
-
枚舉流程
-
硬件初始化:BIOS/UEFI或Bootloader配置PCIe鏈路,內(nèi)核啟動后重新掃描。
-
拓撲構(gòu)建:從Root Complex開始,遞歸掃描下游設(shè)備(Switch和Endpoint)。
-
資源配置:為每個設(shè)備分配內(nèi)存地址(通過BAR)、中斷號(MSI/MSI-X或INTx)。
-
-
配置空間訪問
-
通過
pci_read_config_byte()、pci_write_config_dword()等API讀寫設(shè)備的配置空間。 -
關(guān)鍵字段:Vendor ID、Device ID、Class Code、BAR0-5、Capability列表(如PCIe Capability)。
-
三、驅(qū)動模型與設(shè)備匹配
-
驅(qū)動注冊
-
設(shè)備驅(qū)動通過
pci_register_driver()注冊,示例代碼:static struct pci_driver my_driver = { .name = "my_pcie_device", .id_table = my_pci_ids, // 設(shè)備ID列表 .probe = my_probe, .remove = my_remove, }; pci_register_driver(&my_driver);
-
-
設(shè)備匹配
-
基于
id_table中的設(shè)備ID(Vendor ID + Device ID)或Class Code匹配設(shè)備。 -
匹配成功后,內(nèi)核調(diào)用
probe()函數(shù)初始化設(shè)備。
-
四、關(guān)鍵驅(qū)動開發(fā)步驟
-
資源映射
-
啟用設(shè)備:
pci_enable_device()。 -
申請BAR資源:
pci_request_regions()。 -
映射BAR到內(nèi)核地址空間:
pci_iomap()。
-
-
中斷處理
-
申請中斷號:
pci_alloc_irq_vectors()(支持MSI/MSI-X)。 -
注冊中斷處理函數(shù):
request_irq()。
-
-
DMA配置
-
設(shè)置DMA掩碼:
dma_set_mask_and_coherent()。 -
分配DMA緩沖區(qū):
dma_alloc_coherent()或使用流式DMA API。
-
五、代碼結(jié)構(gòu)與關(guān)鍵API
-
核心代碼路徑
-
總線管理:
drivers/pci/probe.c、access.c。 -
主機控制器驅(qū)動:
drivers/pci/controller/。 -
設(shè)備驅(qū)動示例:
drivers/net/ethernet/(如Intel網(wǎng)卡驅(qū)動)。
-
-
常用API
-
設(shè)備操作:
pci_read_config_*()、pci_write_config_*()。 -
資源管理:
pci_resource_start()、pci_resource_len()。 -
電源管理:
pci_set_power_state()。
-
六、高級功能
-
SR-IOV虛擬化支持
-
通過
sysfs或驅(qū)動代碼創(chuàng)建Virtual Function(VF)。 -
示例:GPU或網(wǎng)卡的硬件虛擬化。
-
-
熱插拔(Hotplug)
-
支持PCIe設(shè)備的熱插拔,需實現(xiàn)
struct hotplug_slot_ops。
-
-
ACPI/設(shè)備樹集成
-
ACPI:解析
_DSM方法配置設(shè)備。 -
設(shè)備樹:在ARM架構(gòu)中通過
pcie-controller節(jié)點描述拓撲。
-
七、調(diào)試與工具
-
調(diào)試手段
-
dmesg查看內(nèi)核日志,定位probe()失敗或資源沖突。 -
通過
/sys/kernel/debug/pci/查看設(shè)備詳細信息。
-
-
用戶工具
-
lspci -vv:顯示設(shè)備配置空間和Capability。 -
pcimem:直接讀寫設(shè)備內(nèi)存空間。
-
八、典型驅(qū)動示例(偽代碼)
static int my_probe(struct pci_dev *pdev, const struct pci_device_id *id) {
// 啟用設(shè)備
pci_enable_device(pdev);
// 申請BAR資源
pci_request_regions(pdev, "my_driver");
// 映射BAR0到內(nèi)核虛擬地址
void __iomem *regs = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
// 配置DMA
dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
// 注冊中斷
int irq = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
request_irq(irq, my_isr, 0, "my_irq", dev);
// 創(chuàng)建設(shè)備節(jié)點
misc_register(&my_miscdev);
return 0;
}
static void my_remove(struct pci_dev *pdev) {
// 釋放資源
pci_release_regions(pdev);
pci_disable_device(pdev);
}
九、架構(gòu)總結(jié)
Linux PCIe驅(qū)動架構(gòu)通過分層設(shè)計實現(xiàn)了硬件抽象與跨平臺兼容性:
-
核心層統(tǒng)一管理總線與設(shè)備發(fā)現(xiàn)。
-
主機控制器驅(qū)動適配不同硬件平臺。
-
設(shè)備驅(qū)動專注于功能實現(xiàn),通過標準API與內(nèi)核交互。
開發(fā)PCIe設(shè)備驅(qū)動時,需重點關(guān)注資源管理、中斷處理、DMA配置及用戶空間接口設(shè)計。

浙公網(wǎng)安備 33010602011771號