官术网_书友最值得收藏!

  • 存儲技術原理分析
  • 敖青云著
  • 2505字
  • 2018-12-27 02:38:24

3.2 PCI子系統對象

在PCI總線體系結構中,存在兩個核心的概念:PCI總線和PCI設備(橋設備是一種特殊的PCI設備)。基于對這兩個核心概念的抽象,Linux PCI子系統定義了兩個關鍵的數據結構:pci_bus和pci_dev,以分別描述PCI總線和PCI設備。

圖3-9反映了PCI子系統對象之間的關系。接下來會看到,PCI總線的掃描、PCI設備的配置以及在sysfs文件系統中的目錄樹都是基于這種關系展開的。

在圖3-9中,我們看到,總線分為兩類:根總線和非根總線。系統中可能有多條根總線,它們組成一個鏈表。非根總線也鏈接到父總線的子總線鏈表中。每條總線都有一個設備鏈表,其中鏈接有橋設備和非橋設備。非根總線和引出它的橋設備相互關聯起來。

圖3-9 PCI子系統對象之間的關系

3.2.1 pci_bus:PCI總線

pci_bus是描述PCI總線的結構。無論是根PCI總線,還是非根PCI總線,都對應一個pci_bus(其結構中的域如表3-1所示)描述符。這里所述的PCI總線需要稍微解釋一下。它并不是驅動模型中講到的總線類型的概念。在PCI子系統中,和驅動模型相對應的概念是PCI總線類型,亦即前面提到的pci_bus_type。

表3-1 pci_bus結構中的域(來自文件include/linux/pci.h)

每條PCI非根總線的parent域都指向它在層次結構上的父總線,至于PCI根總線,因為沒有更上層的總線,所以parent域為NULL。

對于PCI根總線而言,其pci_bus結構鏈入到根總線鏈表,根總線鏈表的表頭記錄在全局變量pci_root_buses,PCI根總線鏈入此鏈表的連接件為node域。

而對于非根PCI總線,其pci_bus結構通過node成員鏈接到父PCI總線的子總線鏈表children中。

每條PCI總線都維護一個自己的設備鏈表視圖,以便描述所有連接在該PCI總線上的設備,其表頭為devices域。

非根PCI總線的self域指向引出它的橋設備。而對于根PCI總線,雖然它是從主橋引出的,但是主橋的行為與PCI設備和橋設備有很大的不同,在PCI子系統中沒有對應的pci_dev結構,因此這個域為NULL。

接下來介紹結構中描述PCI總線信息的主要域。primary、secondary和subordinate域反映了PCI總線的各種總線號。PCI總線枚舉過程中,這些號碼被確定下來,一方面記錄在對應PCI橋設備的配置空間中(使得PCI配置事務可以正常工作),另一方面保存在pci_bus描述符的內部域中(被PCI核心提供給PCI設備驅動的API使用,或者被PCI設備驅動直接使用)。number域為PCI的總線號,總是等于secondary域的值。

3.2.2 pci_dev:PCI設備

PCI設備可以從兩個方面理解。由于每條PCI總線上可以掛載的物理設備數目是有限的,因此作為擴展,每個物理設備可以包含多個功能,即邏輯設備。從物理硬件的角度,PCI設備實際上指的是包含從一個到八個“功能”的某個PCI硬件,它被集成到系統主板上,或者安裝在插槽中,這是PCI物理硬件的概念。但是,從操作系統的角度,PCI設備的每個功能都是一個設備,或者說PCI邏輯設備,它們會在系統中有自己的數據結構,可以被內核或驅動獨立地操作。

為避免混淆,本書用通常用術語“PCI插槽”來表示一個PCI物理設備,而用“PCI設備”作為PCI邏輯設備的簡稱,表示PCI物理設備中的一個功能。所有種類的PCI設備都可以用數據結構pci_dev(其結構中的域如表3-2所示)來描述。更為準確地說,一個pci_dev描述了PCI設備的一個功能,即PCI邏輯設備。

表3-2 pci_dev結構中的域

續表

續表

這里需要再強調一次,Linux PCI子系統中的pci_dev描述符指的是PCI邏輯設備。因此看到一個PCI主機適配器,就應該想到在系統內存中可能有多個對應的pci_dev。對于SCSI子系統也是這樣的道理,只不過在那里,PCI設備功能的概念被換成了SCSI磁盤的邏輯單元。

pci_dev數據結構中一些域的具體說明如下。

每一個PCI設備也通過其pci_dev結構中的bus_list域鏈入其所在PCI總線的局部設備鏈表中,而對應的表頭就在前面提到的pci_bus結構中的devices域。

指針bus指向這個PCI設備所橋接的主總線,而指針subordinate指向這個PCI設備所橋接的次總線。后者僅對橋設備才有意義,對于一般的非橋PCI設備而言,subordinate指針域總是為NULL。

PCI設備的devfn域是PCI設備在PCI總線上的編號,是將高5位為插槽號、低3位為功能號放在一起編碼的結果,它們是在PCI總線掃描過程中配置的。

pci_dev結構中有很多域是PCI設備的配置空間內容在內存中的“副本”,它們在PCI子系統初始化過程中被讀出,保存在內存中。內核和驅動對PCI的操作大體上直接在這些域上進行,除非發生修改,需要將修改后的數據更新到PCI設備的配置空間。

hdr_type域對應從PCI設備配置寄存器中讀取的頭類型的低7位,第8位多功能標志已經被屏蔽。值00h表示描述符描述的是一個標準的PCI設備,值01h描述的是PCI-PCI橋設備。multifunction域則記錄了PCI設備配置寄存器中的頭類型域的高1位,即上面被被屏蔽掉的多功能位,表示這個PCI邏輯設備是否是多功能設備的一部分。

雖然標準PCI設備和PCI-PCI橋設備的配置空間中都含有ROM基地址寄存器,但是ROM基地址寄存器在這兩種不同類型的PCI配置空間頭部的位置是不一樣的,對于類型0的配置空間布局,ROM基地址寄存器的起始位置是30h,而對于PCI-to-PCI橋所用的類型1配置空間布局,ROM基地址寄存器的起始位置是38h。rom_base_reg域記錄下ROM基地址寄存器在PCI配置空間中的位置。

無論是配置,還是掃描,都是基于PCI邏輯設備的。PCI物理設備的概念在PCI子系統中并不那么突出,也不是本書的重點。不過它也不可或缺,一個典型的例子就是熱插拔,這必然要針對PCI物理設備。描述PCI物理設備(或稱物理插槽)的數據結構是pci_slot(其結構中的域如表3-3所示),pci_dev描述符的slot域就指向它。

表3-3 pci_slot結構中的域(來自文件include/linux/pci.h)

一條PCI總線包含多個PCI插槽,每個PCI插槽屬于一條PCI總線。PCI插槽通過bus域指向所屬的PCI總線,并以list域為連接件鏈接到它的PCI插槽鏈表,PCI總線描述符的slots域為該鏈表的表頭。當然,判斷PCI設備和PCI插槽是否有關聯,需要看它們的插槽/功能號的高5位是否一樣。

在討論了與業務邏輯有關的域之后,在回過頭看與Linux驅動模型有關的域。PCI總線和PCI設備都分別有一個內嵌的驅動模型設備描述符,不過它們的作用不同。PCI總線內嵌的是一個類設備對象,通過它鏈接到PCI總線類(pcibus_class)的設備鏈表;而PCI設備內嵌的是一個通用設備對象,通過它鏈接到PCI總線類型(pci_bus_type)的設備鏈表。

此外,在PCI總線描述符中,還有一個指針域bridge,對于非根PCI總線,它指向引出這條總線的橋設備內嵌的驅動模型設備,這樣就在sysfs文件系統中建立了PCI總線和PCI設備之間的聯系,也即確定了它們所對應目錄的相對位置,PCI子系統的驅動模型對象關系如圖3-10所示。對于根PCI總線,這個域指向一個新建的“虛擬”驅動模型設備,我們可以將它看作是主橋在sysfs文件系統中的代表——它是這條總線及所有下游總線和設備所對應目錄樹在sysfs文件系統中的根。

圖3-10 PCI子系統的驅動模型對象關系

主站蜘蛛池模板: 湄潭县| 和平县| 阿克陶县| 宁都县| 余姚市| 上虞市| 酉阳| 扶沟县| 永年县| 日土县| 沁水县| 江油市| 黑龙江省| 北川| 凤阳县| 吉木萨尔县| 广西| 韶关市| 穆棱市| 灌阳县| 通辽市| 遂宁市| 玉溪市| 皋兰县| 明光市| 九龙县| 民和| 万荣县| 长泰县| 华容县| 民乐县| 平泉县| 扶余县| 天祝| 美姑县| 秭归县| 博乐市| 新平| 庆阳市| 西藏| 玉树县|