沿一次讀取追蹤 Request 與 Completion
選擇步驟後,圖中對應的元件與下方解說會加上重點標示。完整圖與所有解說會持續顯示;也可用方向鍵切換步驟。
由上往下看一次正常讀取。本圖省略中間 Port;實際 Request 與 Completion 各依其路由規則穿過拓樸。
作者依 Base 6.0 的 Request/Completion 規則繪製的交換示意;分段回覆在正文另行放大。
一次 MMIO(Memory-Mapped I/O,記憶體映射輸入輸出)讀取,會由主機端提出要求,再由目標端回覆資料。PCIe 用 TLP(Transaction Layer Packet,交易層封包)承載這些交換。
前情提要:Chapter 4 已完成本例的 BAR、Bridge Window 與解碼配置。現在沿同一路徑觀察一筆 4-byte 讀取。
- BAR
- Base Address Register,基底位址暫存器
規格路線:交易類別 Table 2-1 → Request 的 ID/Tag 與 Memory Request 格式 → Completion 格式 → 分段與邊界條件。
先辨認交易類別
本例是已配置、已就緒裝置上的正常 Memory Read;Memory Write 等其他類別另有回覆規則。
本例是 Memory Read,屬於需要 Completion 的 Non-Posted Request。先看交易類別,才知道後面要等待哪種回覆。
Base 6.0 §2.1.1/Table 2-1,pp.116–117;§2.2.7.1,pp.162–165。
把讀取範圍編進要求
本章先以 Non-Flit Mode 解釋既有格式;後文另列 Flit Mode 的格式差異。
由 Request 格式讀位址、Length 與 Byte Enable,再看 Requester ID、Tag 如何識別這筆要求。TLP 的長度欄位使用自己的單位及編碼。
- TLP
- Transaction Layer Packet,交易層封包
Base 6.0 §2.2.5.1、§2.2.6.2/Figures 2-26–2-28,pp.150–155。
讀取目標端的回覆
若發生非成功完成,資料與狀態依該完成規則判讀;一次要求也可能分成多段回覆。
目標以 Completion with Data 回覆正常讀取;讀 Completion Status、Byte Count 與 Lower Address,確認本段資料代表的範圍。
Base 6.0 §2.2.9.1/Figures 2-73–2-74,pp.196–197;§2.3.1.1,pp.214–218。
配對並確認整筆讀取完成
Tag 配對與資料範圍都須吻合;本章的分段案例會列出每筆 Completion 的實際資料量。
以 Requester ID 與 Tag 找回原要求,再累計各段有效資料。最後把 Length、Byte Enable 與 4 KiB 邊界等條件接回原要求。
Base 6.0 §2.2.7.1、§2.2.9.1、§2.3.1.1,pp.163、196–197、214–218。
圖中元件
Requester:提出要求的一端
本例是主機端的交易要求者,保留這筆讀取的識別與範圍。
基本責任
CPU 的軟體讀取由平台轉成 PCIe 交易;圖不表示 CPU 指令本身直接就是 TLP。
Completer:處理要求並回覆的一端
本例由裝置端提供暫存器讀取資料。
基本責任
Requester 與 Completer 是本次交易中的角色,不是每個元件永遠固定的身分。
1. 讀取時,誰提出要求,誰負責回覆?
Transaction Layer Packet(TLP,交易層封包)承載要求與回覆。提出這筆要求的一方稱為 Requester;服務目標位址並回覆的一方稱為 Completer。這兩個名稱隨交易改變:CPU 讀裝置時,平台代表 CPU 發出要求;裝置讀主記憶體時,裝置反而是 Requester。
本例假設平台選用 Requester ID 0x0000,並配置尚未使用的 Tag 0x12。這是平台端的教學假設,不能只看 Root Port 的 BDF 就推定 CPU 存取必定使用那個 ID。Endpoint 的 Completer ID 則為 0x0300,來自已完成設定的 03:00.0。
- BDF
- Bus/Device/Function,匯流排、裝置與功能識別
Requester ID 與 Tag 合起來辨識一筆尚待完成的交易。同一 Requester 不得讓兩筆同時未完成、需要 Completion 的要求共用 Tag。本例只用較小的合法 Tag;Base 6.0 還定義較大的 Tag 能力與啟用條件,因此不能把 Tag 永遠說成 8 bits。
先看哪幾張圖?
先看 §2.1.2 Figure 2-2(p.117),分清 Header 與可能存在的 Payload;再看 §2.2.6.1–§2.2.6.2 Figures 2-27/2-28(pp.152–154),理解 Transaction ID。Completer ID 見 §2.2.9.1 Figures 2-74/2-75(p.197)。圖中的路徑是作者整理,不是規格原圖。
2. 有寫入,就一定會有 Completion 嗎?
要先辨認交易類型。Posted Request 不要求回傳一般 Completion;Non-Posted Request 則需要 Completion 結束該要求。名稱不是在描述「軟體有沒有等待」,也不是在表示工作成功與否。
| 交易 | 要求如何找到目標 | 成功時的交易層回覆 |
|---|---|---|
| Memory Read(MRd) | 依 Memory 位址 | Non-Posted;以一個或多個 CplD 回傳資料。 |
| 一般 Memory Write(MWr) | 依 Memory 位址 | Posted;沒有對應的普通 Completion。 |
| Configuration Read/Write | 依目標 ID;沿 Chapter 3 的 Type 1/Type 0 規則 | Non-Posted;讀取回 CplD,寫入回 Cpl。 |
| I/O Read/Write | 依 I/O 位址,供相容用途 | 兩者都是 Non-Posted;不能套用 Memory Write 的結論。 |
| Message Request | 依該 Message 規定;可能依位址、ID 或隱含目的地 | 交易層屬 Posted;上層協定仍可能另外定義回應。 |
因此,CPU 寫入裝置的通知 Register 後,不能等待一個並不存在的 MWr Completion,也不能因為沒有 Completion 就推定錯誤。裝置何時完成工作,必須依裝置介面的狀態或通知判斷。PCIe 另外有 DMWr、AtomicOp 等交易;它們有自己的 Completion 規則,本章的「一般 MWr」不包括這些類型。
交易分類與編碼來源
§2.1.1 Table 2-1(pp.116–117);§2.2.1.1 Table 2-3(pp.120–122);§2.4.1 Table 2-42 及分類說明(pp.222–223)。Memory/I/O/Configuration 的路由見 §2.2.7.1(pp.162–165),Message 路由另見 §2.2.8 Table 2-20。
3. 如何把「讀 4 bytes」對到 Request 與 Completion?
先用 Table 2-3 找到 MRd,再看 Figure 2-31 的 32-bit 位址格式。不要因為要讀「32-bit 資料」就選 3 DW Header;Header 的選擇與目標位址格式有關。本例的位址可用 32 bits 表示,因此採 3 DW Header。DW 是 Double Word,這裡固定為 4 bytes。
| 欄位 | MRd Request | 成功的 CplD |
|---|---|---|
| Fmt/Type | 000b/00000b | 010b/01010b |
| Requester ID/Tag | 0x0000/0x12 | 0x0000/0x12 |
| 目標位址/Completer ID | Address=0x80004120 | Completer ID=0x0300 |
| Length | 1 DW,要求 4 bytes;Request 本身沒有資料 Payload。 | 1 DW,這個回覆帶 4 bytes。 |
| First/Last DW BE | 1111b/0000b | 沒有這組 Request 欄位。 |
| Completion Status/Byte Count/Lower Address | 不是 Request 欄位。 | SC=000b/4 bytes/0x20 |
這裡有三個必須分開的量。Request 的 Length 表示要存取多少個 DW;CplD 的 Length 表示這個回覆帶多少個 DW;Byte Count 則表示連同這個回覆在內,這筆 Memory Read 還要回傳多少 bytes。因為本例一次回完,後兩者剛好對應相同的 4 bytes。
Byte Enable(BE)決定哪些位元組有效。Length=1 DW 時,First DW BE 控制唯一的 DW,Last DW BE 必須為零。Lower Address 是本次回傳第一個有效位元組位址的低 7 bits,因此 0x80004120 & 0x7F = 0x20。它不是完整目標位址;Completion 回程依 Requester ID 路由,不靠這 7 bits 找 CPU。
假設四個有效資料 bytes 按位址遞增為 78 56 34 12,且這個裝置 Register 定義為 little-endian,軟體便可解讀為 0x12345678。這個 Register 意義和數值是教學假設,不是 PCIe 為所有 MMIO 裝置統一定義的值。
- MMIO
- Memory-Mapped I/O,記憶體映射輸入輸出
從 Figure 到欄位的閱讀路線
Figure 2-31(p.163)定位 Request;Figure 2-26/Table 2-10(pp.150–151)定位 BE;Table 2-4(p.122)確認 Length 單位;Figure 2-73(p.196)定位 Completion;Table 2-37(p.197)解讀 Status;§2.3.1.1 與 Table 2-41(pp.215、218)解讀 Byte Count 和 Lower Address。特別注意:適用 Length 的資料交易中,編碼 0 表示 1024 DW,不是「沒有資料」。
4. 如果只讀中間 6 bytes,Length 要填 6 嗎?
不行,Length 的單位是 DW。另作一個教學假設:裝置在這段範圍提供可合法讀取的連續 bytes,現在要讀 0x80004121–0x80004126。這六個 bytes 橫跨兩個對齊的 DW,因此 Request 使用對齊位址 0x80004120、Length=2。
| 對齊 DW | 位址由低至高的 bytes | 有效範圍與 BE |
|---|---|---|
| 第一個 DW | 0x120、0x121、0x122、0x123(BAR0 內位移) | 只讀後三個 bytes;First BE=1110b。 |
| 最後一個 DW | 0x124、0x125、0x126、0x127(BAR0 內位移) | 只讀前三個 bytes;Last BE=0111b。 |
因為目標是 non-Prefetchable 資源,未啟用的兩個 bytes 不得在 Completer 被讀取。成功且一次回完時,CplD 的 Payload 仍占 2 DW,但有效資料只有 6 bytes;Byte Count=6,Lower Address=0x21。軟體不能把兩端的無效 bytes 當成額外有效 Register 資料。
這個例子也提醒我們:TLP 能表示某種 byte 存取,不代表每個裝置 Register 都接受這種寬度。實際能否讀取,還要看裝置介面規格。BE 的連續性也有條件;本例符合規則,不能據此假設任意長度都可隨意挖空中間 bytes。
部分存取的依據
§2.2.5.1,Figure 2-26/Table 2-10(pp.150–151);§2.3.1.1,Table 2-40(p.217)及 Table 2-41(p.218)。Table 2-40 在 Length=2、First BE=1110b、Last BE=0111b 時給出 6 bytes。
5. 為什麼一次讀取可能收到兩個 Completion?
先把目標換成主記憶體,預習下一章的 DMA。假設 Endpoint 03:00.0 要從 DMA 位址 0x40001000 讀 256 bytes,使用 Tag 0x13。平台已準備好這段映射與讀取權限,Endpoint 及沿途的 BME 也已啟用。
- DMA
- Direct Memory Access,裝置直接存取記憶體
本例的 Requester 最大讀取要求為 512 bytes;Completer 的有效傳送 Payload 上限為 128 bytes,路徑接收能力也相容,Read Completion Boundary(RCB,讀取回覆切分邊界)為 128 bytes。因此 256-byte 要求可以發出,但不能塞進一個 256-byte CplD。我們選擇在 128-byte 邊界切成兩份;並不宣稱所有讀取都固定這樣切。
| 回覆 | 回傳位址範圍 | Length(DW) | Byte Count(bytes) | Lower Address |
|---|---|---|---|---|
| 第一個 CplD | 0x40001000–0x4000107F | 32 | 256 | 0x00 |
| 第二個 CplD | 0x40001080–0x400010FF | 32 | 128 | 0x00 |
Request 的 Length=64 DW;兩個回覆都帶 Requester ID=0x0300、Tag=0x13,且都假設 SC、BCM=0。第一個回覆的 Byte Count 包含尚未回傳的第二份,所以是 256,而非自己的 Payload 大小 128。第二個回覆的 Lower Address 仍為零,因為 0x80 & 0x7F = 0;Requester 要結合原要求與已收到的資料追蹤位置。
同一筆讀取的成功回覆必須依位址遞增;不同 Tag 所屬的兩筆讀取,回覆卻不必按發出順序到達。也不能把兩筆要求的資料合成一個 Completion。這就是配對不能只靠「第幾個收到」的原因。
長度、切分與順序來源
MRRS:§2.2.7.1(p.162);有效 Payload 上限:§2.2.2 與 §2.3.1.1(p.214);RCB、Byte Count、遞增位址:pp.215–218;不同交易的回覆順序:§2.4.1 D5a/D5b(p.224)與 §2.4.2 的例子(p.228)。本例直接給定有效上限,沒有把 Base 6.0 的所有傳送/接收上限簡化成單一 MPS 暫存器值。
兩個裝置用了相同 Tag,回覆要怎麼分?
先把每個 Completion 的 Requester ID(原要求者識別號)和 Tag(要求者分配的交易標籤)一起對回原始 Request,再用 Status、Length、Byte Count 和 Lower Address 檢查資料範圍。完成分組後,才知道哪筆讀取還缺哪些資料。
規格閱讀順序:Figure 2-28 先建立 Transaction ID;Figure 2-73 找到 Completion 的 Requester ID、Tag、Status、Byte Count 和 Lower Address,再讀 §2.3.1.1 的 Byte Count 與遞增位址規則。不同 Transaction ID 的 Completion 允許互相超越,不表示一定會重新排序。核對完整封包時還要確認 Completer ID、TC、Attributes、資料長度與適用條件。(Base 6.0,文件頁/PDF 頁 153、196–198、215、218、224。)
- TC
- Traffic Class,流量類別
Tag 位數變大後,可以任意選數值嗎?
先回到 Figure 2-28:Requester ID 與 Tag 一起識別未完成的交易;在同一個 PCIe Hierarchy(階層)中,同一個 Requester ID 的未完成 Non-Posted Requests,不論 Traffic Class,都必須使用不同的 Tag。現在要擴大可用範圍時,還需要把 Requester 設定、完成端能力與中間路徑一起帶入 Table 2-11。Flit Mode 的跨 Hierarchy Segment 識別另有規則,本例不展開。
表格左邊三欄依序是 14-Bit Tag Requester Enable、10-Bit Tag Requester Enable 和 Extended Tag Field Enable;右邊依完成端及路徑共同支援的最大 Tag 能力分欄。先確認 Requester 本身支援並允許使用該能力,再選正確欄位。Enable=1 不是完成端支援能力的證明,也不是一定會同時送出該數量的要求。
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。下列兩列是互不相依的設定;Requester、目標及中間路徑均已確認支援表中使用的能力,且未使用 VF 或 Phantom Function。第二列中使用 14-bit Tag 的路徑均以 Flit Mode 傳送。
- VF
- Virtual Function,虛擬功能
手機閱讀時,表格可以左右滑動。
| 14-bit/10-bit/Extended Enable | 8-bit 完成端/路徑 | 10-bit 完成端/路徑 | 14-bit 完成端/路徑 |
|---|---|---|---|
| 0/1/1 | 0–255 | 256–1023 | 256–1023 |
| 1/1/0 | 0–31 | 256–1023 | 1024–16383 |
例如第一列如果目的端與路徑共同支援 10-bit Tag,Table 2-11 的可用範圍從 256 開始;不能把它讀成「任何小於 1024 的 Tag 都屬於這個 10-bit 範圍」。同一列若目的端和路徑只支援 8-bit,則使用 0–255。5-bit 完成端/路徑的範圍恆為 0–31。
查設定時,Extended Tag Field Enable 在 PCI Express Capability 的 Device Control;10-Bit Tag Requester Enable 在 Device Control 2;14-Bit Tag Requester Enable 則在 Device 3 Extended Capability 的 Device Control 3。應先走訪對應 Capability,再查各欄位的適用條件;VF 另有 PF 的控制規則。軟體若在 Function 尚有未完成 Non-Posted Requests 時修改 10-bit 或 14-bit Requester Enable,結果為 undefined(未定義)。
- VF
- Virtual Function,虛擬功能
- PF
- Physical Function,實體功能
若同時向較大與較小 Tag 能力的目標發送要求,還須依 Table 2-11 使用各自範圍,並避免較大 Tag 因不支援的完成端截斷而與仍未完成的小 Tag 混淆。發送前確認完整路徑,比等到 Completion 的 Tag 異常後再推測更容易定位問題。
PCI Express Base 6.0 §2.2.6.2、Figure 2-28/Table 2-11,文件頁/PDF 頁 153–156;§7.5.3.4、Table 7-21,p.960;§7.5.3.15–§7.5.3.16、Tables 7-33–7-34,pp.991、997;§7.7.9.2–§7.7.9.3、Tables 7-108–7-109,pp.1073、1075。
同時使用大小 Tag,為什麼還要檢查低位元?
前一節的範圍是發送要求前的選擇。§2.2.6.2 還要求:若 Requester 同時向較大與較小 Tag 能力的目標發送要求,即使某筆較大 Tag 要求意外由不具足夠能力的完成端回覆,也要避免它與仍未完成的小 Tag 交易混淆。
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。同一 Requester ID 有兩筆尚未完成的 Read:送往它認為支援 10-bit 的路徑 A 的 Tag 是 100h,送往 8-bit 路徑 B 的 Tag 是 00h。A 的完整路徑能力尚未核實。兩個原始 Tag 不同,但低 8 bits 都是 00h。
假設 A 的要求途中出錯,某個不具 10-bit Completer 能力的元件代為回覆,且這次回覆遺失了 Tag 高位,因而帶回 00h。若 Requester 只依這個回覆的 Requester ID 與低位 Tag 配對,就可能把 A 的異常回覆誤認成 B 的結果。這是教學假設,不表示每個中間元件都會以相同方式截斷 Tag。
Base 6.0 p.159 的 Using Larger Tags and Smaller Tags Concurrently Implementation Note 提供一種配置方式:假設小 Tag 只使用低 8 bits 中的 00h–0Fh,則較大的 10-bit Tag 不使用低 8 bits 為 00h–0Fh 的值。這 16 個低位值各對應三個合法的 10-bit 高位組合,原本 768 個 10-bit 值因此少了 48 個,剩下 720 個;小 Tag 還有 16 個。
這是規格提供的一種實作方法,不要求所有 Requester 都用同一種切分。規格要求的是避免上述混淆;實際可同時追蹤的交易數還受裝置資源及路徑條件限制。前一節的 Table 2-11 仍要先用來判斷每筆要求允許使用的 Tag 範圍。
PCI Express Base 6.0 §2.2.6.2,文件頁/PDF 頁 154–155;Implementation Note: Using Larger Tags and Smaller Tags Concurrently,p.159;Table 2-11,pp.155–156。
跨 Hierarchy 的讀取,Completion 要回到哪裡?
前面的例子在同一個 PCIe Hierarchy(階層)內用 Requester ID 與 Tag 配對。Flit Mode 跨 Hierarchy 時,還要先看 Segment:它幫助路徑辨認封包屬於哪個階層,再由 Requester ID 找到要求者。Chapter 3 的 Segment 捕捉例子先說明 Function 如何取得自己的 Segment。
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。Endpoint A 在 Segment 02h,Endpoint B 在 Segment 03h;兩端 Segment Captured 均為 1。A 對 B 發出 Non-Posted Memory Read。假設沿途皆為 Flit Mode,位址路由及平台的 Peer-to-Peer 支援已確認,Root Complex(RC)這次不接手交易。A 的 Request 攜帶 OHC-C,Requester Segment 為 02h,Requester Segment Valid(RSV)為 1。
Request 依位址到達 B。B 比較 Requester Segment 02h 與自己捕捉的 Segment 03h:兩者不同,所以該 Request 的每個 Completion 都必須包含 OHC-A5。假設其中一個 Completion 的 Status 為 Successful,Lower Address 低兩位為 00b;依 Figure 2-11,OHC-A5 的四個 bytes 是:
| Byte | 模擬值 | 意義 |
|---|---|---|
| 0 | 02h | Destination Segment:返回 A 所在的階層。 |
| 1 | 03h | Completer Segment:B 捕捉的 Segment。 |
| 2 | 80h | Destination Segment Valid(DSV)為 1,其餘 Reserved 位元為 0。 |
| 3 | 00h | Lower Address 低兩位與 Successful Completion Status 都為 0。 |
也就是 02 03 80 00。回程經過 RC 時,Destination Segment 指向 A 的階層;到達要求者後,仍要用 Requester ID 和 Tag 對回原始交易,再檢查 Completion Status 和資料範圍。Requester 不得以收到的 Completion 的 Destination Segment 作為接收條件。
這個例子有兩個重要前提。第一,對非 IDE Memory Request,Requester 是否帶入 Requester Segment 可以是可選的;若 B 收到的 Non-Posted Memory Request 沒有 Requester Segment,B 在有 OHC-A5 的回覆中須將 DSV 清為 0、Destination Segment 設為 00h。第二,RC 接手交易時有另一套識別與還原規則;不要把本例「不接手」的結果直接套到所有路徑。
- IDE
- Integrity and Data Encryption,完整性與資料加密
閱讀時先看 §2.2.1.2 的 Figure 2-13 找到 Request 的 Requester Segment 與 RSV,再讀同節的 Requester、Completer 及 RC 規則,最後用 Figure 2-11 對照 Completion 的 OHC-A5。§2.2.9.2 補充哪些 Completion 條件需要 OHC-A5。還要分別確認觀察點、路徑模式、Segment Captured 與 RC 是否接手;單看封包內的 Segment 值無法確認整筆交易成功。
PCI Express Base Specification Revision 6.0,§2.2.1.2、Figures 2-11、2-13,文件頁/PDF 頁 133–134、138–141;§2.2.9.2,p.199。
6. 長度沒超過上限,就一定是合法要求嗎?
還要檢查 4 KiB 邊界。假設要從 0x40001FF0 讀 32 bytes,結尾會落在 0x4000200F。即使 MRRS 容許 32 bytes,這個 Address/Length 組合跨過了 4 KiB 邊界,仍不得作為單一 Memory Request 發出。可改成兩筆 16-byte 要求:0x40001FF0–0x40001FFF 與 0x40002000–0x4000200F,各自追蹤 Tag。
回到 §2.2.7.1 的 Memory Request 規則:發送端不得產生跨越邊界的 Address/Length 組合;接收端可以選擇實作這項檢查。若接收端有實作,且檢查發現違規,就將該 TLP 視為 Malformed TLP(格式錯誤的封包)。所以,沒有看到這類錯誤紀錄,還不足以證明原要求沒有跨界。這裡分析的是 Non-Flit Mode 的一般 Memory Read;AtomicOp 的 operand 與對齊另有規則,見 Chapter 15。
這裡談的是 Request 的邊界限制;上一節談的是同一 Request 的 Completion 切分,兩者發生在不同階段。
收到 Completion 也要先看 Status。SC 表示這次要求成功完成;UR、CA 是不同的失敗結果,不能把無資料的 Cpl 解成讀到了零。RRS 只在規定的 Configuration 情境適用,並不是普通 MMIO 讀取的通用「稍後再試」。若分段讀取中收到失敗 Completion,該回覆會終結這筆要求,不應繼續等剩餘成功片段。
邊界與失敗回覆來源
4 KiB 規則:§2.2.7.1,p.163。Status:Table 2-37,p.197;RRS 限制:§2.3.1,p.214 的說明;失敗讀取回覆與終止:§2.3.1.1,pp.214、218。接收端對部分非法封包的檢查是可選的,不代表發送端可以產生那些封包。
7. 沿回覆欄位重新配對交易
第一個回覆帶 128 bytes,Byte Count 卻是 256,是否互相矛盾?
不矛盾。Byte Count 是這筆要求從目前片段起尚待回傳的量,包含目前片段。用 兩段回覆表 可算出下一段應剩 128 bytes;Payload 大小另由 Length 表達。
收到 Requester ID 相同但 Tag 不同的 CplD,可以拿來補這筆讀取缺少的資料嗎?
不能。它屬於另一個 Transaction ID。即使長度、數值或抵達時間恰好相符,也不能取代配對條件。(Figures 2-27/2-28,p.153。)
4-byte MWr 沒收到 Completion,應該重送嗎?
不能以此作為重送依據。普通 MWr 是 Posted Request,本來就沒有對應的一般 Completion;重送反而可能重複觸發 Register 的副作用。應依裝置介面定義的狀態或通知判斷進度。(Table 2-42,p.222。)
在 Base 6.0 查到 Figure 2-31,就能解所有 PCIe 6.0 封包嗎?
不能。這張圖屬於 Non-Flit Mode 的 Request 格式。先確認模式,再選 §2.2.1.1 或 §2.2.1.2 的 Header 定義;不能把版本號與模式當成同一件事。
8. 從封包走到資料可見性
本章已能配對一筆交易並核對資料範圍。Chapter 6 接著追問:裝置用哪種位址進行 DMA?資料先寫、通知後寫,就能讓 CPU 安全使用資料嗎?
版本與來源
主來源為 PCI Express Base Specification Revision 6.0,6.0-1.0-PUB。文件頁碼與 PDF 頁碼相同;查核日期為 2026-10-28。封包值、裝置 Register 與平台條件均為作者設計的教學案例,來源位置已隨各節標示。