pci枚举初始化部分(2)
1.2.8判斷pcie設(shè)備是否支持雷電技術(shù)
Intel具有一種基于Thunderbolt技術(shù)的PCIE變體,它結(jié)合了DisplayPort和PCIe協(xié)議,與Mini DisplayPort兼容。
Thunderbolt技術(shù)融合兩種通信方法或者說協(xié)議,其中PCI Express用于數(shù)據(jù)傳輸,可以連接幾乎任何類型的設(shè)備,DisplayPort用于顯示,能同步傳輸1080p乃至超高清視頻和最多八聲道音頻。
因此代碼只在intel生產(chǎn)的設(shè)備中進(jìn)行判別。
set_pcie_thunderbolt()
其中有
#define PCI_VNDR_HEADER_ID(x) ((x) & 0xffff) #define PCI_VSEC_ID_INTEL_TBT 0x1234 //雷電接口1.2.9修復(fù)某些特殊的bug
對于某些bug,只存在于特定體系或設(shè)備,無法在此處進(jìn)行列舉,因此提供一個hook用于修復(fù)特殊設(shè)備的bug。而hook通過內(nèi)核配置情況進(jìn)行掛載。
pci_fixup_device()
其中hook可有由
#define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class, \class_shift, hook) \DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early, \hook, vendor, device, class, class_shift, hook)等宏進(jìn)行掛載。
- 舉個例子
arch\x86\pci
通過DECLARE_PCI_FIXUP_EARLY宏將pci_early_fixup_cyrix_5530回調(diào)函數(shù)注冊到pci_fixup_early段中,在通過hook函數(shù)指針調(diào)用并執(zhí)行函數(shù)解決x86平臺下5530設(shè)備特有的錯誤情況。
1.2.10 設(shè)置command寄存器
1.2.10.1 錯誤情況禁止IO空間和內(nèi)存空間
//沒有識別正確的if (dev->non_compliant_bars) {pci_read_config_word(dev, PCI_COMMAND, &cmd);if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {pci_info(dev, "device has non-compliant BARs; disabling IO/MEM decoding\n");cmd &= ~PCI_COMMAND_IO;cmd &= ~PCI_COMMAND_MEMORY;pci_write_config_word(dev, PCI_COMMAND, cmd);}}COMMAND[0] :IO SPACE位
該位表示PCI設(shè)備是否響應(yīng)I/O請求,為1時響應(yīng),0時不響應(yīng)。
COMMAND[1]: Memory Space位
該位表示PCI設(shè)備是否響應(yīng)存儲器請求,為1時響應(yīng),0時不響應(yīng)。
1.2.10.2 判斷command寄存器中斷禁止位是否可寫
pci_intx_mask_broken()
u16 orig, toggle, new;pci_read_config_word(dev, PCI_COMMAND, &orig);toggle = orig ^ PCI_COMMAND_INTX_DISABLE;pci_write_config_word(dev, PCI_COMMAND, toggle);pci_read_config_word(dev, PCI_COMMAND, &new);pci_write_config_word(dev, PCI_COMMAND, orig);//PCI_COMMAND_INTX_DISABLE是預(yù)留位并在PCIr2.3版本是只讀的,因此嚴(yán)格輸出//如果他是不可寫的,則這個設(shè)備沒有損壞。if (new != toggle)return 1;return 0;COMMAND[10] :interrupt Disable位
復(fù)位值為0,該位為1時,PCI設(shè)備不能通過INTx信號向HOST主橋提交中斷請求,為0時可以使用INTx信號提出請求。當(dāng)PCI設(shè)備使用MSI中斷方式提交中斷請求時,該位將被置為1。
1.2.11 根據(jù)不同頭類型做初始化
1.2.11.1標(biāo)準(zhǔn)頭
1.2.11.1.1獲取設(shè)備信息
獲取設(shè)備中斷信息和BAR空間信息。
switch (dev->hdr_type) { /* header type */case PCI_HEADER_TYPE_NORMAL: /* standard header */ //錯誤情況if (class == PCI_CLASS_BRIDGE_PCI)goto bad; //獲取中斷號和中斷引腳pci_read_irq(dev); //獲取基地址pci_read_bases(dev, 6, PCI_ROM_ADDRESS);//獲取子廠商號設(shè)備號pci_subsystem_ids(dev, &dev->subsystem_vendor, &dev->subsystem_device);(1)中斷信息
包括中斷號,中斷引腳。
pci_read_irq()
(2)BAR空間信息
包括BAR空間大小,空間基地址,空間類型(IO/內(nèi)存),空間位數(shù)(32位,64位)等。
pci_read_bases函數(shù)調(diào)用__pci_read_base函數(shù)來獲取這些信息。
__pci_read_base()
(2.1)默認(rèn)為 32位PCI時,獲取PCI空間大小
- (2.2) 通過decode_bar()函數(shù)判別PCIBAR空間類型*
- 判斷是否IO空間類型。
通過BAR基地址的bit[0]可判別BAR空間類型為IO空間還是內(nèi)存空間,1表示IO空間,0表示內(nèi)存空間。
bit[1,2]則表示了BAR空間為32位還是64位。
bit[3]表示BAR是否支持預(yù)取。
其中bit[1,2]=01在linux4.x代碼中代表1M這種類型。
- 判斷內(nèi)存空間位數(shù)
- 64位的處理
獲取地址和大小后還需判斷其是否超過體系所支持的位數(shù),32位下是不能支持64位PCI設(shè)備的,PCI空間大小也是不能超過4G的。
- 測試BAR空間映射是否正確。
pcibios_bus_to_resource函數(shù)用于總線地址轉(zhuǎn)換到資源地址(用于CPU的物理地址)。
pcibios_resource_to_bus執(zhí)行相反操作,如果,相互轉(zhuǎn)換的值不正確,則不能使用該設(shè)備。
1.2.11.1.2 對于ATA控制器的特殊設(shè)置
傳統(tǒng)模式ATA控制器具有固定地址。且BAR0-3的數(shù)據(jù)在某些情況下是無效的。
classCode寄存器用于判斷設(shè)備類別。
通過base class=01,subclass =01,可以確定為IDE類型存儲器
對于IDE控制器類型的PCI設(shè)備,又通過interface寄存器字段進(jìn)行了細(xì)分:
interface:
bit7:確定是否為主IDE設(shè)備
bit3:可編程指示器(次通道)
bit2:操作模式(次通道)
bit1:可編程指示器(主通道)
bit0:操作模式(主通道)
根據(jù)PCI IDE Controller Specification Revision 1.0文檔可知
對于主通道來說,命令寄存器被固定為1f0h-1f7h,其控制塊地址為3fh,
次通道命令寄存器地址170h-177h,控制寄存器376h.
1.2.11.2橋頭
PCI-PCI橋若要求譯碼(比如透明橋),橋的編程接口代碼必須是0x01
case PCI_HEADER_TYPE_BRIDGE: /* bridge header */if (class != PCI_CLASS_BRIDGE_PCI)goto bad;pci_read_irq(dev);dev->transparent = ((dev->class & 0xff) == 1);pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); //查詢是否支持熱插拔set_pcie_hotplug_bridge(dev); //查找capability中子系統(tǒng)的廠商號和設(shè)備號pos = pci_find_capability(dev, PCI_CAP_ID_SSVID);if (pos) {pci_read_config_word(dev, pos + PCI_SSVID_VENDOR_ID, &dev->subsystem_vendor);pci_read_config_word(dev, pos + PCI_SSVID_DEVICE_ID, &dev->subsystem_device);}break;對于熱插拔
set_pcie_hotplug_bridge()
其中
#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ #define PCI_EXP_SLTCAP_HPC 0x00000040 /* Hot-Plug Capable */通過查詢pcie_3.0總線規(guī)范,可以看到偏移為14h的寄存器中有關(guān)于是否支持熱插拔的狀態(tài)位。
bit6 = 1時,表示設(shè)備支持熱插拔。
1.2.11.2cardBus橋頭
case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */if (class != PCI_CLASS_BRIDGE_CARDBUS)goto bad;pci_read_irq(dev);pci_read_bases(dev, 1, 0);pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);break;結(jié)束
pci_setup_device()函數(shù)完成了對單個設(shè)備的設(shè)備和檢測,并將獲取的信息存取設(shè)備結(jié)構(gòu)體中,用于后期具體設(shè)備的使用。
轉(zhuǎn)載于:https://www.cnblogs.com/weiyoutongxing/p/10045668.html
總結(jié)
以上是生活随笔為你收集整理的pci枚举初始化部分(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 要不要立Flag呢
- 下一篇: Python脚本--微信公众号自定义菜单