Class Code trong PCI là gì?

Giải thích PCI Class Code: Base Class, Subclass, Prog IF, generic driver matching, storage/network/bridge class và debug driver bind sai.

Cập nhật 14 phút đọc
PCI cover

Bạn đọc PCI config space và thấy Vendor ID/Device ID đúng. Nhưng driver của bạn không nên match theo một chip cụ thể, mà nên support cả một loại thiết bị. Ví dụ: driver storage generic, driver network generic, PCI bus driver xử lý bridge, hoặc UEFI driver muốn biết device đó là NVMe, AHCI, USB controller, network controller hay PCI-to-PCI bridge. Khi đó Vendor ID/Device ID chưa đủ. Bạn cần đọc Class Code.

Class Code trả lời câu hỏi: PCI function này thuộc loại chức năng nào?

Nói ngắn gọn: PCI Class Code là bộ 3 byte trong PCI Configuration Space, gồm Base Class, Subclass và Programming Interface. Firmware và OS dùng Class Code để phân loại thiết bị, chọn generic driver, nhận diện bridge, storage, network, display, serial bus controller và debug driver matching.

Class Code nằm ở đâu?

Class Code trong PCI Configuration Space

PCI Configuration Space
├─ Offset 0x00: Vendor ID
├─ Offset 0x02: Device ID
├─ Offset 0x08: Revision ID
├─ Offset 0x09: Programming Interface
├─ Offset 0x0A: Subclass
├─ Offset 0x0B: Base Class
├─ Offset 0x0E: Header Type
├─ Offset 0x10: BAR0
└─ Capability List...

Class Code thường được đọc như 3 byte: Base Class, Subclass, Prog IF.

Class Code trong enumeration flow

01 BDF

Select PCI function

Firmware scan theo Bus/Device/Function.

02 VID

Read Vendor ID

Nếu Vendor ID hợp lệ, function tồn tại.

03 DID

Read Device ID

Nhận diện chip/vendor cụ thể.

04 Class

Read Class Code

Phân loại chức năng device.

05 Policy

Choose enumeration behavior

Bridge thì scan downstream, storage/network thì tạo controller handle.

06 Driver

Match driver

Generic hoặc vendor driver dùng class/subclass/prog-if để match.

Firmware đọc Class Code để biết function là bridge, storage, network hay loại khác.

Base Class, Subclass, Prog IF

Ba phần của PCI Class Code
Field Ý nghĩa Ví dụ
Base Class Nhóm chức năng lớn Mass Storage Controller, Network Controller, Bridge Device
Subclass Loại cụ thể trong nhóm NVM Express, SATA, Ethernet, PCI-to-PCI Bridge
Programming Interface Interface/programming model chi tiết AHCI, XHCI, UHCI/OHCI/EHCI, NVMe
Revision ID Không thuộc class code nhưng nằm gần đó Dùng cho workaround theo stepping
Class tuple Base:Sub:ProgIF 01:08:02 cho NVMe thông dụng
Generic matching Dựa vào class/subclass/prog-if Storage/network/USB generic driver
Vendor-specific Class có thể vendor-specific Cần vendor driver
Debug Biết driver nên match kiểu nào Driver bind sai class

Ví dụ Class Code thường gặp

Ví dụ PCI Class Code hay gặp
Thiết bị Base Class Subclass
NVMe controller Mass Storage Controller NVM Express
AHCI SATA controller Mass Storage Controller SATA Controller
Ethernet controller Network Controller Ethernet Controller
VGA controller Display Controller VGA Compatible Controller
XHCI USB controller Serial Bus Controller USB Controller
PCI-to-PCI bridge Bridge Device PCI-to-PCI Bridge
ISA bridge/LPC Bridge Device ISA Bridge
SMBus controller Serial Bus Controller SMBus

Class Code và Header Type

Class Code cho biết loại chức năng. Header Type cho biết layout config header. Với bridge, hai thứ này liên quan chặt.

Class Code vs Header Type
Khía cạnh Class Code Header Type
Mục tiêu Phân loại chức năng Xác định layout config header
Offset 0x09-0x0B 0x0E
Bridge detect Base Class Bridge + Subclass PCI-to-PCI Header Type 1
Endpoint Class storage/network/display... Header Type 0
CardBus bridge Bridge class Header Type 2
Multi-function Không nằm trong class Bit 7 Header Type
Debug Biết device là gì Biết parse BAR/bridge registers thế nào
Bug nếu sai Driver match sai Parser config header sai

Class Code và generic driver

Class Code cho phép driver generic support nhiều vendor khác nhau.

Generic driver matching theo Class Code
Driver kiểu Match theo gì Ví dụ
NVMe driver Base Mass Storage + Subclass NVMe Support nhiều vendor NVMe
AHCI driver Mass Storage + SATA + Prog IF AHCI SATA AHCI controller
USB XHCI driver Serial Bus + USB + XHCI Prog IF XHCI controller
Network generic Network + Ethernet Có thể cần vendor-specific init
PCI bus driver Bridge class Enumerate bus phía sau bridge
VGA/Graphics Display class Console/graphics init tùy platform
SMBus Serial Bus + SMBus Chipset/platform controller
Vendor-specific driver Vendor/Device ID + capability Class code có thể chưa đủ

Class Code và UEFI DriverBinding

Trong UEFI driver, Supported() có thể match theo Class Code thay vì Vendor ID cụ thể.

if (Pci.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE &&    Pci.Hdr.ClassCode[1] == PCI_CLASS_MASS_STORAGE_NVM) {  return EFI_SUCCESS;}
Supported() match theo Class Code
Match Khi nào dùng Rủi ro
Base Class only Driver rất generic Quá rộng, dễ bind nhầm
Base + Subclass Generic theo loại thiết bị Có thể thiếu Prog IF quan trọng
Base + Subclass + Prog IF Cần đúng programming model Tốt cho AHCI/XHCI/NVMe
Class + Capability Cần feature thật Phức tạp hơn nhưng robust
Class + Vendor quirk Generic nhưng có vendor workaround Cần quirk table rõ
Vendor + Class Tránh match nhầm device cùng vendor Vẫn chưa đủ nếu subsystem khác
Class + BAR layout Đảm bảo resource đúng kỳ vọng Start ít fail hơn
Class + Subsystem Board/SKU-specific Có thể quá chặt

Class Code sai thì sao?

Nếu device expose Class Code sai, firmware/OS/driver có thể chọn sai path.

Hậu quả khi Class Code sai
Sai gì Biểu hiện Debug
Bridge không có bridge class PCI bus driver không scan downstream Endpoint sau bridge mất
Storage class sai Generic storage driver không bind OS không thấy disk
Prog IF AHCI sai AHCI driver không bind SATA controller không hoạt động
USB Prog IF sai XHCI/EHCI driver mismatch USB không hoạt động
Network class sai Network driver không bind PXE/network mất
Class quá generic Generic driver bind nhưng Start fail Check capability/BAR
Vendor-specific class Cần vendor driver Generic driver reject
Firmware policy sai BDS/connect chọn sai Check class code log

Prog IF quan trọng thế nào?

Programming Interface phân biệt các controller cùng subclass nhưng interface khác.

Prog IF debug
Case Prog IF nói gì Bug nếu bỏ qua
SATA controller AHCI hay legacy IDE-like mode Driver AHCI bind sai mode
USB controller UHCI/OHCI/EHCI/XHCI Sai host controller driver
PCI bridge Normal/Subtractive decode Resource/legacy decode issue
NVMe NVM Express programming model Generic NVMe driver cần đúng
VGA VGA compatible behavior Console/video init sai
RAID/storage Vendor-specific Prog IF Generic driver không đủ
Serial controller Interface mode khác nhau Driver chọn sai register model
Debug Base/subclass đúng nhưng driver vẫn reject Check Prog IF

Class Code và PCI-to-PCI Bridge

Firmware PCI bus driver cần nhận ra bridge để scan bus phía sau. Class Code bridge là tín hiệu quan trọng.

Bridge detection bằng Class Code

BDF 00:1C.0
├─ Vendor ID / Device ID valid
├─ Base Class = Bridge Device
├─ Subclass = PCI-to-PCI Bridge
├─ Header Type = Type 1
├─ Secondary Bus = 02
└─ Scan downstream bus 02

Nếu bridge không được nhận diện đúng, endpoint phía sau có thể không bao giờ được scan.

Debug Diary: Driver không bind vì Class Code không khớp

Triệu chứng:

Vendor/Device ID có vẻ đúng
Supported() return EFI_UNSUPPORTED
Class Code không giống expected

Checklist Class Code không khớp

Debug Diary: Generic driver bind nhầm device

Triệu chứng:

Supported() match theo Base Class
Start() fail khi đọc BAR/capability

Checklist generic driver bind quá rộng

Debug Diary: OS không thấy disk vì storage class sai

Triệu chứng:

PCI device tồn tại
OS không load storage driver
Không thấy disk

Checklist storage class sai

Debug Diary: Endpoint sau bridge mất vì bridge class/header sai

Triệu chứng:

Root port/bridge BDF tồn tại
Nhưng downstream bus không được scan

Checklist bridge class/header sai

Debug Diary: Class Code khác giữa UEFI và OS

Triệu chứng:

UEFI log class code khác OS log

Checklist Class Code khác UEFI/OS

Anti-pattern khi dùng Class Code

Anti-pattern Class Code
Anti-pattern Vì sao sai Cách sửa
Match chỉ Base Class Quá rộng Check Subclass và Prog IF
Bỏ qua Prog IF Interface model khác Check đúng programming interface
Coi Class Code là chip identity Không phân biệt vendor/device Log thêm Vendor/Device/SubSystem
Không check capability Class đúng nhưng feature thiếu Read capability list
Hardcode class workaround Có thể sai SKU Dùng quirk table có document
Không log class hex Tên friendly mơ hồ Log Base/Subclass/ProgIF dạng hex
Driver bind dù Start biết sẽ fail Chiếm controller sai Supported nên reject sớm nếu có thể
Sửa match quá rộng để chạy nhanh Bind nhầm device Root-cause class/mode/policy

Instrumentation nên có

Instrumentation cho Class Code debug
Vị trí Nên log Mục tiêu
PCI scan BDF + Base/Subclass/ProgIF Phân loại device
Driver Supported Expected vs actual class Debug reject/match
Driver Start Class + BAR/capability Debug start fail
Bridge enumeration Class + Header Type Debug downstream scan
Storage init Storage class/prog-if Debug disk missing
USB init USB prog-if Debug host controller driver
OS compare UEFI class vs OS class Debug handoff/mode change
Setup policy Controller mode option Debug AHCI/RAID/VMD
Capability scan Capability IDs Verify feature
Good/bad diff Class tuple diff Regression

Class Code debug playbook

Class Code debug playbook

Security checklist

Security checklist khi dùng Class Code

Khi đọc log Class Code nên tìm gì?

Class Code log reading checklist
Cần hiểu Tìm trong log Câu hỏi
BDF Segment:Bus:Device.Function Đọc đúng function không?
Vendor/Device ID Offset 0x00/0x02 Device identity là gì?
Base Class Offset 0x0B Nhóm chức năng đúng không?
Subclass Offset 0x0A Loại cụ thể đúng không?
Prog IF Offset 0x09 Programming model đúng không?
Header Type Offset 0x0E Endpoint/bridge parse đúng không?
Driver expected Supported() expected values Reject vì field nào?
Capability list MSI/MSI-X/PCIe/etc Feature thật có đủ không?
Setup mode AHCI/RAID/VMD/USB mode Class có bị mode đổi không?
OS compare OS class output UEFI và OS có thấy giống nhau không?

Câu hỏi tự kiểm tra

Tự kiểm tra sau khi đọc note này

Blog seeds

  • Class Code trong PCI là gì?
  • Base Class, Subclass, Prog IF giải thích dễ hiểu
  • UEFI driver match thiết bị bằng Class Code thế nào?
  • Vì sao storage controller không bind AHCI/NVMe driver?
  • Bridge class sai làm endpoint phía sau biến mất

Bài liên quan

Nguồn tham khảo public

Bài viết này hữu ích với bạn?

Bạn có thể chia sẻ cho người đang học firmware, BIOS/UEFI, embedded systems hoặc ủng hộ tác giả.

Góp ý

Nội dung liên quan

Một số bài viết, ghi chú hoặc project có liên quan đến nội dung bạn vừa đọc.

Biến note thành bài viết hoàn chỉnh

Notes là nơi ghi nhanh khái niệm.