先選清單,再把序號讀出來

選擇步驟後,圖中對應的元件與下方解說會加上重點標示。完整圖與所有解說會持續顯示;也可用方向鍵切換步驟。

先讀兩種入口的差別,再沿右側完成 DSN 查詢。左側是對照,並非必須先走完它才能開始右側。

兩個入口,沿正確清單找到序號傳統與延伸清單分別從自己的入口開始;找到DSN後才從目前結構起點加資料位移。Function 03:00.0同一份設定空間傳統清單0x34 → 0x40延伸清單從 0x100 開始Null → PCIe → MSI-X0x50 → 0x70 → 0xD0AER → DSN0x100 → 0x180讀取序號資料起點+0x04/起點+0x08按目標功能選清單Next:從 Function 起點算Next=0x180ID=0003h; Version=1
作者的清單查詢圖;兩條支線表示兩種入口。Next 使用 Function 內的 byte offset;資料欄位則使用目前結構的相對位移。
MSI-X
Message Signaled Interrupts Extension,表格式訊息中斷
AER
Advanced Error Reporting,進階錯誤回報

沿用前章已找到的裝置功能,本章要讀出它提供的裝置序號。查詢先從設定空間選對清單,再沿指標找到能力結構,最後讀取資料欄位並解釋位元組順序。這條路徑也能用來理解其他能力的查詢。

  1. 選定 Function 與正確入口

    普通 Type 0 Endpoint;平台能存取完整設定空間,讀取成功且快照穩定。

    先用 Segment 與 BDF 選定設定對象,再以 byte offset 選擇其中的位置。傳統清單與 Extended Capability(延伸能力)清單各有入口。

    BDF
    Bus/Device/Function,匯流排、裝置與功能識別

    Base 6.0 §7.2/Figure 7-3、§7.6.1/Figure 7-42,文件頁/PDF 頁 905–906、1009。

  2. 用傳統清單看懂 Next 的用途

    此處作為清單格式的對照;本次序號查詢使用右側的延伸清單。

    傳統清單的 Null Capability 是沒有功能資料的節點。其 ID=0 仍須依 Next Pointer(下一項位置)繼續到 0x70;這一路沒有接到延伸清單。

    Base 6.0 §7.9.27/Figure 7-384/Table 7-336,文件頁/PDF 頁 1315。

  3. 從延伸清單找到序號結構

    AER 是進階錯誤回報結構;本例不支援 Flit Mode,因此使用其 Version 2。

    AER
    Advanced Error Reporting,進階錯誤回報

    在 0x100 讀 Header,分出 ID、Version 與 Next。沿 Next=0x180 到下一項,確認 DSN(Device Serial Number,裝置序號)ID=0003h、Version=1。

    Base 6.0 Figures 7-43/7-154/7-242、Tables 7-39/7-134/7-221,文件頁/PDF 頁 1010、1112、1206。

  4. 以目前結構起點取得資料

    DWORD 是四個 bytes。這組序號數值只示範重組,不宣稱已配發,也不用來認證硬體。

    DSN 是提供裝置序號的能力。由目前起點 0x180 加 0x04、0x08,讀取低、高 DWORD,再依 Table 7-222 的位元組對映重組序號。

    Base 6.0 Figures 7-241–7-243/Tables 7-221–7-222,文件頁/PDF 頁 1205–1207。

圖中元件

Function:本次的設定對象

本次固定查詢 0000:03:00.0 的設定空間。

基本責任

每個 Function 各有設定空間;byte offset 只在選定的 Function 內定位。

DSN:裝置序號能力

在 0x180 確認結構後,才讀它的兩個資料 DWORD。

基本責任

DSN 為可選能力;一般多功能 Device 中有實作的各 Function 必須回報相同序號。

先回想兩個步驟:Segment 與 BDF 選定要查的功能,Header Layout 與 Device/Port Type 說明它採用的結構與角色。這裡從相同對象繼續往設定空間內部找。

BDF
Bus/Device/Function,匯流排、裝置與功能識別

1. 同一個 offset,先問它從哪裡算起

選定 Function 之後,它的 PCIe Configuration Space(設定空間)提供 4096 bytes 的位置。前 256 bytes 保留 PCI 相容布局,其後是 Extended Configuration Space(延伸設定空間)。本章的 byte offset 都只描述這份設定空間內的位置;CPU 實際執行存取所需的平台位址另由存取機制提供。

設定空間的三個閱讀區域000至03F為標頭,040至0FF放傳統Capability等內容,100至FFF為Extended Configuration Space。傳統清單入口在標頭034,Extended清單由100開始。圖不按容量比例。Configuration Header0x000–0x03F0x034:傳統清單入口傳統 Capability 等內容0x040–0x0FFPCIe Capability 在此區Extended Configuration0x100–0xFFF0x100:Extended 清單入口同一個已選定的 Function前 256 bytes:PCI 相容區後 3840 bytes:延伸區示意圖不按容量比例繪製;空白位置不代表可自行放入新結構。
自製閱讀地圖,依 Base 6.0 Figure 7-3(p.906)、Figure 7-4(p.916)與 Figure 7-42(p.1009)整理。

例如,0x34 是從 Function 設定空間起點計算的 Capabilities Pointer;某個結構標示的 Offset 04h,則可能是從該結構起點計算。先確認原圖畫的是整份設定空間,還是其中一個結構,再做加法。

設定空間透過記憶體映射存取,就等於裝置的 Memory BAR 嗎?

BAR
Base Address Register,基底位址暫存器

不等於。ECAM(Enhanced Configuration Access Mechanism)把 CPU 對指定記憶體範圍的存取轉成 Configuration Request;BAR 則描述裝置所需的資源。兩者都可能從 CPU 的記憶體位址發起,目的與轉換方式卻不同。

BAR
Base Address Register,基底位址暫存器

查詢介面還必須能存取所需範圍。PCI 相容存取機制只涵蓋前 256 bytes;不能用它沒有提供的能力,推論 0x100 之後的功能不存在。ECAM(將 CPU 記憶體存取轉成設定要求的機制) 的平台基址與可用 Bus 範圍要由平台提供,本章不自行猜一個實體位址。

規格依據與存取限制

Base 6.0 §7.2–§7.2.2.2,pp.905–909;Table 7-1(pp.907–908)列出 ECAM 位址中的 Bus、Device、Function 與 Register 部分。跨 DWORD 邊界或使用鎖定語意的 CPU 存取,不保證能由 Root Complex 轉成 Configuration Request(pp.907、909)。本章使用自然對齊、大小明確的設定讀取。

同一個 offset,為什麼兩個 Function 的欄位不同?

先讀所選 Function 在 0x0E 的 Header Type Register(標頭類型暫存器),以 bits 6:0 的 Header Layout 選圖。Type 0 的配置看 Figure 7-10;代表 Root Port 或 Switch Port 的 Type 1 配置看 Figure 7-14。兩張圖的橫向位置是 bit,最右側是從 Configuration Space 起點算的 byte offset。

同一個 byte offset 在兩種 Header 中的用途
offsetType 0Type 1(Root/Switch Port)
0x10–0x14Base Address Registers(BAR,資源基底暫存器)的一部分此 Port 的 BAR 0、BAR 1
0x18BAR 區域的一部分Primary、Secondary、Subordinate Bus Number 等欄位
0x20BAR 區域的一部分Memory Base 與 Memory Limit

例如,看到 0x18 的 32-bit 讀值後,先取得同一 Function 的 Header Layout;選到 Type 1 才把其中對應的 bytes 解作 Bus Number。Type 0 的同一位置則屬於 BAR 區域。再查具體 BAR 的型態與欄位定義,才能解讀其用途。Type 1 的 Bus Number 用於安排下游搜尋範圍,Memory Base/Limit 描述資源視窗;完整配置與路由分別接到 Chapter 3 和 Chapter 4。

Header Type 的 bit 7 與 bits 6:0 要分開讀。以本章假設值 0x80 為例,Layout 為 Type 0,bit 7 表示 Device 可能有多個 Function,還需進一步查詢。VF 有不同適用規則,本例不納入。Header Layout 與 Configuration Request 的 Type 0/Type 1 封包分類也各有定義。

VF
Virtual Function,虛擬功能

閱讀位置:Base 6.0 §7.5.1.1.9、Figure 7-8/Table 7-7(文件頁/PDF 頁 924–925);Figure 7-10(p.928);Figure 7-14 及其適用說明(p.936)。先從 Header Type 選圖,再讀該圖的 offset 與對應欄位說明。

2. 想查某項功能,要先走哪一份清單?

先在指定版本的規格中找到目標功能的正式結構。本章要找 Device Serial Number,它屬於 Extended Capability;先前用過的 PCI Express Capability 則屬於前 256 bytes 的傳統清單。確認分類後,才使用相應入口與 Header 格式。

兩份清單的差異
比較項目傳統 CapabilityExtended Capability
設定空間內的入口先看 Status.Capabilities List,再讀 Header 的 Capabilities Pointer;本章 Type 0/1 在 0x34。從 0x100 的 32-bit Header 開始,不接在傳統清單尾端。
識別與下一項一般開頭的低 byte 是 8-bit ID,高 byte 是 8-bit Next Pointer。bits 15:0 為 ID,19:16 為 Version,31:20 為 Next Offset。
下一項的基準Function 設定空間起點;不是目前結構起點。同樣從 Function 設定空間起點計算。取出後要遮掉低 2 bits。
清單結束Next Pointer 為 0。ID 為 0 的 Null Capability 仍可能有下一項。Next Offset 為 0。若完全沒有 Extended Capability,0x100 的 Header 依規格回報 ID、Version、Next 全為 0。
這張表的來源與例外

Base 6.0 §7.5.1.1.4,Figure 7-6/Table 7-5(pp.921–922);§7.5.1.1.11(p.926);傳統 Header 例見 Figure 7-22/Table 7-18(p.953)。Extended 格式見 §7.6–§7.6.3、Figures 7-42/7-43、Table 7-39(pp.1008–1010)。Null Capability 見 §7.9.27、Figure 7-384/Table 7-336(p.1315)。RCRB 的起點與空清單規則不同,本章沒有把它納入。

3. 清單中出現 ID = 0,就可以停止了嗎?

傳統清單的假設讀值
Function 內 byte offset讀取寬度讀值這次查詢的用途
0x0E8 bits0x80Header Layout 為 Type 0;bit 7 表示 Device 可能有多個 Function。
0x0616 bits0x0010Status bit 4 為 1,有 Capability 清單。
0x348 bits0x40第一項位於 0x40。
0x4016 bits0x5001ID 01h:Power Management;下一項 0x50。
0x5016 bits0x7000ID 00h:Null Capability;下一項 0x70。
0x7016 bits0xD010ID 10h:PCI Express Capability;下一項 0xD0。
0xD016 bits0x0011ID 11h:MSI-X;Next 為 0,清單結束。
MSI-X
Message Signaled Interrupts Extension,表格式訊息中斷

案例推演:入口為 0x40 & 0xFC = 0x40。每次讀取 16 bits 後,以 value & 0xFF 取 ID,以高 8 bits 對應的 (value >> 8) & 0xFC 取得下一項的位置。

0x40 → PM → 0x50 → Null → 0x70 → PCIe → 0xD0 → MSI-X → 結束
在 0x50:ID = 0x7000 & 0xFF = 0
         Next = (0x7000 >> 8) & 0xFC = 0x70

在 0x50,Null Capability 的 ID 表示這個節點沒有功能資料,Next 卻仍指向 0x70,所以繼續走到 PCIe 與 MSI-X。完成這條傳統清單後,序號查詢仍應回到延伸清單的獨立入口;兩份清單各自描述所屬能力。

本例的 MSI-X 結構存在,也不代表中斷已啟用。能力的存在、控制位設定及目前是否能使用,仍是不同問題;MSI-X 的設定流程留到中斷章。

本例 ID 與指標的核對位置

PM:§7.5.2.1,Figure 7-18/Table 7-14,p.945。Null:§7.9.27,p.1315。PCIe:§7.5.3.1,Figure 7-22/Table 7-18,p.953。MSI-X:§7.7.2.1,Figure 7-59/Table 7-48,pp.1021–1022;啟用位另見 Table 7-49,p.1022。起始指標低 2 bits 的遮罩規則見 p.926;配置資料採小端序,見 §7.5.1.1,p.916。

4. 要找 Device Serial Number,依序翻哪幾張圖?

  1. 確認入口
    Figure 7-42/§7.6.1:Extended 清單由設定空間 0x100 開始。
  2. 解開清單 Header
    Figure 7-43/Table 7-39:讀 32 bits,分出 ID、Version 與 Next。
  3. 確認目標與資料位置
    Figure 7-242/Table 7-221:DSN 的 ID 為 0003h;Figure 7-241:序號位於結構起點 +0x04、+0x08。

DSN 是 Device Serial Number 的縮寫。這是可選的 Extended Capability,不是每個 Function 都必須提供,也不是每個 Function 各自擁有不同序號。

Extended 清單與序號的假設讀值
Function 內 byte offset讀取寬度讀值解讀
0x10032 bits0x18020001AER:ID 0001h、Version 2;下一項 0x180。
0x18032 bits0x00010003DSN:ID 0003h、Version 1;Next 為 0。
0x18432 bits0x33221100Serial Number Register 的 Lower DW。
0x18832 bits0x77665544Serial Number Register 的 Upper DW。
DW
Double Word,4 bytes的資料單位
header = 0x18020001
ID      = header & 0xFFFF          = 0x0001
Version = (header >> 16) & 0xF     = 2
Next    = (header >> 20) & 0xFFC   = 0x180

案例推演:從 Header 取出的 Next 已經是 Function 內的 byte offset,因此下一筆直接讀 0x180。DWORD 對齊表示低 2 bits 為 0,無須再乘 4。確認 ID 0003h、Version 1 後,才由目前 DSN 起點加上資料位移,得到 0x180 + 0x04 = 0x184 與 0x180 + 0x08 = 0x188。

兩個 DWORD 拼起來,就是平常書寫的 EUI-64 順序嗎?

先分清楚「Register 整數」與「識別碼的位元組順序」。本例組成的 Register 整數是 (0x77665544 << 32) | 0x33221100 = 0x7766554433221100。Table 7-222 另外規定,Register bits 7:0 對應 EUI bits 63:56,接著依 byte 對映;因此本例按 EUI 的高位元組到低位元組書寫時,是 00-11-22-33-44-55-66-77。

這組數字只示範資料重組,不主張是已配發或可以拿去使用的產品序號。真實 DSN 必須符合 Table 7-222 的 IEEE 公司識別碼與製造商延伸識別碼規則。序號也不能單獨當成身分認證證據。

DSN 的範圍還要讀 §7.9.3:一般多功能 Device 若實作這項能力,Function 0 必須實作;其他有實作的 Function 必須回報相同值。因此,找到相同 DSN 不能用來區分同一個 Device 的 Function 0 與 Function 1;目前的設定對象仍由 Segment 與 BDF(Bus、Device、Function 識別號) 選定。

原文定位與版本條件

清單:§7.6–§7.6.3,Figures 7-42/7-43、Table 7-39,pp.1008–1010。AER Header:§7.8.4.1、Figure 7-154/Table 7-134,p.1112;支援 Flit Mode 時須用 Version 3,本例已排除該情況。DSN:§7.9.3–§7.9.3.2,Figures 7-241–7-243、Tables 7-221/7-222,pp.1205–1207。RCiEP、PF/VF 有另外規則,本例不適用。Table 7-39 允許向前相容的更高 Capability Version,不能把「只接受等於 1」寫成所有版本的通用搜尋規則。

5. 讀到一個欄位,就能把原值寫回去嗎?

讀取欄位定義時,也要看表格的 Attributes(存取屬性)。這一欄說明軟體寫入會觸發什麼行為。能力查詢只需要讀取;若另有修改需求,先按屬性與當前條件組成寫值,避免把查詢所得的狀態直接回寫。

先認識會直接影響判讀的存取屬性
屬性讀值與寫入的意義常見誤判
RO軟體不能改寫;若欄位明確反映硬體狀態,值仍可能隨執行狀態改變。唯讀不等於永遠不變。
RW軟體可設定或清除,仍須遵守該欄位的額外條件。可寫不代表任何時刻、任何值都合法。
RW1C讀取狀態;寫 1 清除對應狀態,寫 0 沒有效果。把讀值原樣寫回,可能清掉原本想保留的事件。
RsvdP保留且保存。此版本讀為 0,寫入時軟體必須保存讀到的值。不能自行借來存資料。
RsvdZ保留且寫零。此版本讀為 0,寫入時軟體必須使用 0。不能對所有 Reserved 都套相同的讀改寫方式。
規格依據

Base 6.0 §7.4,Table 7-2,pp.913–915;本表取 RO、RW、RW1C(寫入一才清除對應狀態)、RsvdP(寫入時須保存讀值的保留欄位)、RsvdZ(寫入時須為零的保留欄位) 的語義。HwInit 與 Sticky 類型另有初始化和 Reset 條件,留到相關章節使用,不把未列在此表的類型視為等同 RW。

6. 找不到時,怎麼分清「不存在」與「還不知道」?

把查詢結果寫成可核對的結論
實際取得的證據可以怎麼記錄?仍不能推論什麼?
在正確清單中找到目標 ID,且已核對版本與類型。此 Function 暴露該 Capability;可繼續讀其定義欄位。不能直接宣告功能已啟用、工作已完成。
成功走完適用的清單,Next 為 0,沒有找到可選的目標。這份有效清單沒有暴露目標 Capability。不能因此宣告整張卡、其他 Function 都不支援。
有效讀取 0x100 得 0x00000000。依 §7.6.1,這個 Function 沒有 Extended Capability。不能把同樣規則套到傳統清單的 Null ID。
存取介面不支援延伸區,或這次讀取失敗。尚未取得可用的查詢結果。不能拿失敗後的 buffer 當成「支援位元全為 0」。
指標循環、超出範圍,或資料與必要結構矛盾。清單無法可靠解析,保留異常位置與讀值。不能假裝正常走到結尾。

最後一列整理教材採用的解析檢查:記下走過的 offset,檢查位置範圍與對齊,並辨認是否重訪同一節點。清單位置可以往前或往後;重訪才是循環檢查的依據。遇到無法可靠解析的資料時,保留異常位置與讀值,再釐清原因。

同樣地,成功讀到 0 不保證那裡是一個有意義的欄位。Base 6.0 §7.3.3(p.913)規定,在沒有其他需回報錯誤的情況下,對未實作 Register 的設定讀取成功回傳 0。位置與格式必須先由標頭、Capability 或明確的 Register 定義建立,不能靠讀值看起來合理來猜。

7. 串接一次完整的序號查詢

回到完整序號查詢:先選定 0000:03:00.0,從 0x100 進入延伸清單,沿 Next 找到 0x180 的 DSN,再讀 0x184 與 0x188。最後按序號定義重組位元組,並保留它在多功能 Device 中的共用範圍。以下延伸說明分別改動指標、資料位置與屬性。

讀到 0x50 的值是 0x7000,下一步是停止、讀 0x70,還是讀 0xC0?

讀 0x70。ID 0 是傳統 Null Capability,Next 0x70 從設定空間起點計算。0xC0 是把目前位置錯加上 Next 的結果。(Figure 7-384/Table 7-336,p.1315;各 Next Pointer 的定義見清單來源。)

Extended Header 改成 0x24010003,DSN 資料要到 0x244 讀嗎?

先問這個 Header 是在哪裡讀到的。若仍在 0x180,ID 0003h 代表目前這一項就是 DSN,資料仍在 0x184 與 0x188;0x240 是下一項的位置。只有目前結構真的位於 0x240,Lower DW 才在 0x244。(Figures 7-241/7-243,pp.1205–1206;Table 7-39,p.1010。)

同一個 Device 的兩個 Function 回報相同 DSN,是規格違反嗎?

不是。本章的一般多功能 Device,其他有實作 DSN 的 Function 必須回報與 Function 0 相同的值。DSN 不能拿來代替 BDF 的 Function 部分。(§7.9.3,p.1205。)

某個狀態是 RO,兩次讀值不同,就代表裝置壞了嗎?

不能這樣判定。先查欄位是否明確反映會變動的硬體狀態。RO 限制的是軟體改寫,並不禁止硬體依定義更新狀態。(Table 7-2,p.914。)

8. 查詢入口本身是怎麼找到的?

本章從一個已知存在的 Function 開始。接著的 Chapter 3 會往前追問:系統還不知道有哪些 Bus 和 Function 時,如何安排搜尋路徑?原本尚未配置的 Bridge,又如何逐步成為可查詢的下游入口?

版本與來源

本章以使用者提供的 PCI Express Base Specification Revision 6.0(6.0-1.0-PUB)為依據。各節附精確圖表與頁碼;所有讀值、拓樸位置與解析檢查均已區分為教學假設或作者的檢查方法。查核日期:2026-10-28。原始 PDF 不隨教材散布。