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),請按以下步驟操作:

  1. 打開命令提示符窗口;
  2. 輸入命令pci_dump > dump.txt並運行pci_dump
  3. 持續按下回車鍵,直至程序執行完成;
  4. 操作完成後,在運行pci_dumpWinDriver/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配置空間讀寫方式:

  1. 在WinDriver驅動INF文件(windrvr<版本號>.inf,例如windrvr1650.inf;早期版本為windrvr6.inf)中,將PciCfgRwCompat註冊表項標誌設置為1:
HKR, Parameters, PciCfgRwCompat, 0x00010001, 1

從WinDriver 11.1.0版本開始,驅動INF文件中已包含類似配置行,默認將PciCfgRwCompat標誌設為0,因此您只需將現有行中的標誌值修改為1即可。

  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卡的內存?

  1. 首先,調用WDC_PciScanDevices()函數定位您的PCI卡所連接的插槽;
  2. 然後,調用WDC_PciGetDeviceInfo()函數獲取該卡的相關信息,其中包括即插即用(Plug and Play)系統為該卡分配的內存範圍;
  3. 調用WDC_PciDeviceOpen()函數安裝該內存範圍,並將其映射到內核模式和用户模式的虛擬地址空間;
  4. 之後,您可通過以下兩種方式訪問內存:
  • 從用户模式應用程序直接訪問內存(效率更高):使用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支持,請查閲主板廠商的相關文檔獲取詳細信息。