4.1 概述
PCI Express(PCIe)總線架構(前身為3GIO,即第三代輸入/輸出技術)由英特爾聯合IBM、戴爾、康柏、惠普和微軟等領先企業共同推出,旨在未來成為個人計算機輸入/輸出(PC I/O)的主流標準。
相較於標準PCI 2.2總線,PCI Express具備更大帶寬和更高可擴展性。
標準PCI 2.2總線採用單條並行數據總線設計,所有數據均以固定速率傳輸。該總線的帶寬由所有連接設備共享,且無法對設備進行優先級區分,其最大帶寬為132MB/s,需由所有連接設備共同分配使用。
PCI Express由串行、點對點連接、獨立時鐘控制的“通道”(lane)組成,每條通道包含兩對數據線,可同時進行上行和下行數據傳輸(全雙工模式)。總線插槽與一個控制總線數據流的交換機相連,PCI Express設備與交換機之間的連接稱為“鏈路”(link)。每條鏈路由一條或多條通道構成:單通道鏈路稱為x1鏈路,雙通道鏈路稱為x2鏈路,以此類推。PCI Express支持x1、x2、x4、x8、x12、x16和x32等多種鏈路寬度(通道數)。該架構下,每條通道的最大帶寬約為500MB/s,因此不同鏈路寬度對應的最大潛在帶寬分別為:x1鏈路500MB/s、x2鏈路1000MB/s、x4鏈路2000MB/s、x8鏈路4000MB/s、x12鏈路6000MB/s、x16鏈路8000MB/s。這些數值相較於標準32位PCI總線132MB/s的最大帶寬有了顯著提升。增強的帶寬支持使PCI Express成為日益增多的高帶寬需求設備的理想選擇,例如硬盤控制器、視頻流設備和網卡等。
如前所述,PCI Express總線採用交換機控制數據流,相較於共享式PCI總線有了明顯改進:每個設備實質上可直接訪問總線,而非多個組件競爭共享同一條總線資源。這使得每個設備能夠充分發揮其帶寬性能,無需爭奪單一共享總線提供的最大帶寬。加之每個設備在PCI Express總線中可使用獨立通道,PCI Express的帶寬控制能力遠超以往的PCI技術。此外,該架構還支持設備之間直接通信(對等通信)。
同時,與共享總線拓撲結構不同,PCI Express總線拓撲支持集中式流量路由和資源管理,這使其能夠實現服務質量(QoS)保障。PCI Express交換機可對數據包進行優先級排序,確保實時流數據包(如視頻流、音頻流)優先於非時間敏感型數據包傳輸。
PCI Express的另一大核心優勢是,相較於PCI、AGP插槽或PCI-X等其他新型I/O總線解決方案,其製造成本更具經濟性。
儘管PCI Express與現有PCI總線的架構存在差異,但它在設計時充分考慮了與現有PCI總線及PCI設備的完全軟硬件兼容性。
為實現與PCI 2.2總線的向下兼容,傳統PCI 2.2設備可通過PCI Express-to-PCI橋接器接入PCI Express系統,該橋接器能將PCI Express數據包轉換為標準PCI 2.2總線信號。這種橋接功能可集成在主板上,也可通過外置擴展卡實現。
4.2 適用於PCI Express的WinDriver
WinDriver完全支持PCI Express板卡上的標準PCI功能向下兼容。WinDriver對標準PCI總線提供的廣泛支持——包括豐富的API接口、代碼示例以及用於硬件調試和驅動代碼生成的圖形化工具DriverWizard——同樣適用於PCI Express設備(其設計本身就具備與傳統PCI總線的向下兼容性)。
您還可以通過WinDriver的PCI API,輕鬆與通過PCI Express-to-PCI橋接器和交換機連接至計算機的PCI設備進行通信。
此外,對於支持PCI Express擴展配置空間訪問的目標平台(如Windows、Linux、MacOS),WinDriver提供了一套專用API,方便用户訪問該配置空間。
4.2.1 適用於PCI Express的WinDriver API
WinDriver提供兩套API接口——底層API(WD_xxx())和高層API(WDC_xxx()/WDS_xxx())。底層API僅為保留向下兼容性而存在,不建議用於編寫新代碼。使用高層API編寫的代碼通常可縮短約50%,且出錯率更低,因為開發者無需處理WinDriver的內部結構、算法和機制。Jungo始終建議將舊的底層代碼升級至高層API,可參考以下對照表,或聯繫技術支持中心獲取進一步協助。
|
底層API
|
高層API
|
|
原有函數
|
新函數
|
|
WD_Open()、WD_Version()、WD_License()、WD_AgentStart()
|
WDC_DriverOpen()
|
|
WD_Close()、WD_AgentClose()
|
WDC_DriverClose()
|
|
WD_Version()
|
WDC_Version()
|
|
WD_Sleep()
|
WDC_Sleep()
|
|
WD_DebugAdd()
|
WDC_Err()、WDC_Trace()
|
|
PCI相關函數 |
|
|
WD_PciScanCards()
|
WDC_PciScanDevices()
|
|
WD_PciGetCardInfo()
|
WDC_PciGetDeviceInfo()
|
|
WD_PciScanCaps()
|
WDC_PciScanCaps()
|
|
WD_CardCleanupSetup()
|
WDC_CardCleanupSetup()
|
|
WD_CardRegister()
|
WDC_PciDeviceOpen() / WDC_IsaDeviceOpen()
|
|
WD_CardUnregister()、WD_EventUnregister()、WD_IntDisable()、WD_KernelPlugInClose()
|
WDC_PciDeviceClose() / WDC_IsaDeviceClose()
|
|
WD_PciConfigDump()
|
WDC_PciReadCfgBySlot()、WDC_PciWriteCfgBySlot()、WDC_PciReadCfg()、WDC_PciWriteCfg()
|
|
WD_Transfer()
|
WDC_ReadAddrByAddrDescXXX()、WDC_WriteAddrByAddrDescXXX()、WDC_ReadAddrXXX()、WDC_WriteAddrXXX()、WDC_ReadAddrBlock()、WDC_WriteAddrBlock()
|
|
WD_MultiTransfer()
|
WDC_MultiTransfer()
|
|
內核插件相關函數 |
|
|
WD_KernelPlugInOpen()
|
WDC_KernelPlugInOpen()
|
|
WD_KernelPlugInCall()
|
WDC_CallKerPlug()
|
|
中斷/事件相關函數 |
|
|
WD_IntEnable()、ThreadStart()、WD_IntWait()
|
WDC_IntEnable()
|
|
WD_IntDisable()、ThreadWait()
|
WDC_IntDisable()
|
|
WD_EventRegister()
|
WDC_EventRegister()
|
|
WD_EventUnregister()
|
WDC_EventUnregister()
|
|
DMA相關函數 |
|
|
WD_DMALock()
|
WDC_DMAContigBufLock() / WDC_DMATransactionInit()
|
|
WD_DMAUnlock()
|
WDC_DMABufUnlock() / WDC_DMATransactionInit()
|
|
WD_DMASyncCpu()
|
WDC_DMASyncCpu()
|
|
WD_DMASyncIo()
|
WDC_DMASyncIo()
|
|
WD_DMATransactionExecute()
|
WDC_DMATransactionExecute()
|
|
WD_DMATransferCompletedAndCheck()
|
WDC_DMATransferCompletedAndCheck()
|
|
WD_DMATransactionRelease()
|
WDC_DMATransactionRelease()
|
|
WD_DMATransactionUninit()
|
WDC_DMATransactionUninit()
|
|
服務器API相關函數 |
|
|
WD_PciSriovEnable()
|
WDC_PciSriovEnable()
|
|
WD_PciSriovDisable()
|
WDC_PciSriovDisable()
|
|
WD_PciSriovGetNumVFs()
|
WDC_PciSriovGetNumVFs()
|
|
WD_IpcRegister()
|
WDS_IpcRegister()
|
|
WD_IpcUnRegister()
|
WDS_IpcUnRegister()
|
|
WD_IpcScanProcs()
|
WDS_IpcScanProcs()
|
|
WD_IpcSend()
|
WDS_IpcUidUnicast()、WDS_IpcSubGroupMulticast()、WDS_IpcMulticast()
|
|
WD_SharedIntEnable()
|
WDS_SharedIntEnable()
|
|
WD_SharedIntDisable()
|
WDS_SharedIntDisableGlobal()
|
|
WD_KernelBufLock()
|
WDS_SharedBufferAlloc()、WDS_SharedBufferGet()
|
|
WD_KernelBufUnlock()
|
WDS_SharedBufferFree()
|
4.3 pci_dump和pci_scan工具
pci_dump是WinDriver工具包中提供的一款控制枱模式示例工具,可將PCI配置寄存器的內容以可讀格式導出。該工具位於WinDriver/util目錄下。
工具的源代碼同樣隨工具包提供,路徑為:WinDriver/samples/c/pci_dump/pci_dump.c。
pci_scan是WinDriver工具包中的另一款控制枱模式示例工具,能夠以可讀格式掃描連接至計算機的PCI設備。該工具同樣位於WinDriver/util目錄下。
其源代碼路徑為:WinDriver/samples/c/pci_scan/pci_scan.c。
4.3.1 將PCI配置空間導出至文件
如需將pci_dump的輸出內容記錄到文件(dump.txt),請按以下步驟操作:
- 打開命令提示符窗口;
- 輸入命令
pci_dump > dump.txt並運行pci_dump; - 持續按下回車鍵,直至程序執行完成;
- 操作完成後,在運行
pci_dump的WinDriver/util目錄下將生成dump.txt文件。
pci_scan的輸出內容也可通過相同步驟導出至文件。
💡 建議
如遇到任何技術問題,建議您首先查閲本手冊。若未找到解決方案,請發送電子郵件至windriver@jungo.com;若您已與我們的團隊成員取得聯繫,可直接向該聯繫人發送郵件。請注意,為確保獲得快速有效的支持,我們的工程師可能會要求您提供詳細的操作步驟描述、説明失敗的具體環節以及遇到的故障或異常行為的詳細信息(包括完整的錯誤信息、截圖和日誌)。
4.4 常見問題(FAQ)
4.4.1 在Windows系統中啓用傳統PCI配置空間讀寫功能以識別PCI設備
在WinDriver 6.2.0版本中,Windows系統下的PCI配置空間讀寫方式已升級為更先進的版本。但在極少數情況下,該方式可能無法識別部分PCI設備。為解決此問題,從WinDriver 10.3.1版本開始,您可通過以下步驟恢復為傳統PCI配置空間讀寫方式:
- 在WinDriver驅動INF文件(
windrvr<版本號>.inf,例如windrvr1650.inf;早期版本為windrvr6.inf)中,將PciCfgRwCompat註冊表項標誌設置為1:
HKR, Parameters, PciCfgRwCompat, 0x00010001, 1
從WinDriver 11.1.0版本開始,驅動INF文件中已包含類似配置行,默認將PciCfgRwCompat標誌設為0,因此您只需將現有行中的標誌值修改為1即可。
- 打開命令提示符,導航至
WinDriver\util\wdreg目錄(其中“WinDriver”為您的WinDriver安裝路徑),運行以下命令重新安裝驅動:
$ wdreg -inf <設備INF文件路徑> uninstall
$ wdreg -inf <驅動INF文件路徑> uninstall
$ wdreg -inf <驅動INF文件路徑> install
$ wdreg -inf <設備INF文件路徑> install
4.3.2 如何通過WinDriver訪問PCI卡的內存?
- 首先,調用WDC_PciScanDevices()函數定位您的PCI卡所連接的插槽;
- 然後,調用WDC_PciGetDeviceInfo()函數獲取該卡的相關信息,其中包括即插即用(Plug and Play)系統為該卡分配的內存範圍;
- 調用WDC_PciDeviceOpen()函數安裝該內存範圍,並將其映射到內核模式和用户模式的虛擬地址空間;
- 之後,您可通過以下兩種方式訪問內存:
- 從用户模式應用程序直接訪問內存(效率更高):使用WDC_PciDeviceOpen()函數返回的物理地址的用户模式映射,對應參數為
((PWDC_DEVICE)hDev)->cardReg.Card.Item[i].I.Mem.pUserDirectAddr(其中i為內存範圍在Item數組中的索引值); - 在內核中訪問內存:將內存的內核模式映射(
((PWDC_DEVICE)hDev)->cardReg.Card.Item[i].I.Mem.pTransAddr)傳遞給WD_Transfer()/WD_MultiTransfer()函數。
有關WDC_DEVICE的更多信息,請參考相關文檔。
該操作流程的示例代碼可在WinDriver/samples/c/pci_diag目錄中找到,您也可以通過DriverWizard為您的PCI卡生成診斷代碼,其中同樣包含相關實現。
⚠ 注意
若需在Kernel PlugIn項目中直接訪問內核內存,必須使用物理內存地址的內核模式映射(由WDC_PciDeviceOpen()函數返回,對應參數為
(PWDC_DEVICE)hDev)->cardReg.Card.Item[i].I.Mem.pTransAddr),而非用於從用户模式應用程序直接訪問內存的用户模式映射。
4.3.3 如何通過Thunderbolt使用適用於PCI Express的WinDriver?
若您計算機的Thunderbolt適配器配置正確,且操作系統已識別該設備,則通過Thunderbolt連接的PCI Express設備應能被WinDriver識別為普通PCI Express設備,無需在WinDriver端進行特殊配置。部分主板芯片組需要修改BIOS設置以啓用Thunderbolt支持,請查閲主板廠商的相關文檔獲取詳細信息。