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.
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
Select PCI function
Firmware scan theo Bus/Device/Function.
Read Vendor ID
Nếu Vendor ID hợp lệ, function tồn tại.
Read Device ID
Nhận diện chip/vendor cụ thể.
Read Class Code
Phân loại chức năng device.
Choose enumeration behavior
Bridge thì scan downstream, storage/network thì tạo controller handle.
Match driver
Generic hoặc vendor driver dùng class/subclass/prog-if để match.
Base Class, Subclass, Prog IF
| 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
| 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.
| 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.
| 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;}| 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.
| 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.
| 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 | 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ó
| 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ì?
| 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
- PCI/PCIe Architecture Overview
- BDF trong PCIe là gì?
- Vendor ID và Device ID là gì?
- PCI Configuration Space là gì?
- BAR trong PCIe là gì?
- PCI Bus Driver là gì?
- PCI I/O Protocol là gì?
- PCI Root Bridge là gì?
- Bridge Window trong PCIe là gì?
- EFI Unsupported
Nguồn tham khảo public
- PCI-SIG Specifications
- UEFI Specification
- UEFI Platform Initialization Specification
- Tianocore EDK II
- EDK II Driver Writer’s Guide
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ả.
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.
Vendor ID và Device ID trong PCIe là gì?
Giải thích Vendor ID và Device ID trong PCIe: nhận diện thiết bị, config space, driver matching, subsystem ID và debug device/driver sai.
BAR trong PCIe là gì?
Giải thích BAR trong PCIe: Base Address Register, MMIO/I/O BAR, 32-bit/64-bit BAR, prefetchable, sizing, resource allocation và debug MMIO fail.
BDF trong PCIe là gì?
Giải thích BDF trong PCIe: Bus Device Function, địa chỉ thiết bị, enumeration, bridge bus number, multi-function device và debug device mất.
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.