Add basic PCI support.
Currently can only enumerate the PCI bus with a basic process, and retrieve basic details on every valid device.
This commit is contained in:
parent
493ef776e2
commit
73b51c851d
173
chroma/inc/kernel/system/pci.h
Normal file
173
chroma/inc/kernel/system/pci.h
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2020 ***
|
||||||
|
*** Chroma ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
/* This file contains all of the structures and definitions
|
||||||
|
* required to compatibly access the PCI bus,
|
||||||
|
* as well as set up new PCI devices, PCI bridges, and manipulate
|
||||||
|
* the connections of PCI lanes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PCI_CONFIG_ADDRESS 0xCF8
|
||||||
|
#define PCI_CONFIG_DATA 0xCFC
|
||||||
|
|
||||||
|
extern pci_dev_t** pci_root_devices;
|
||||||
|
extern pci_entry_t* pci_map;
|
||||||
|
|
||||||
|
int pci_init_early();
|
||||||
|
|
||||||
|
const char* pci_get_name(uint8_t devclass, uint8_t subclass, uint8_t progif);
|
||||||
|
|
||||||
|
int pci_enumerate_devices(pci_dev_t* root);
|
||||||
|
|
||||||
|
int pci_get_config(uint16_t seg, uint8_t bus, uint8_t slot, uint8_t function, void** config);
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
uint8_t io_space : 1; // Device can respond to I/O access
|
||||||
|
uint8_t memory_space : 1; // Device can respond to memory access (device is MMIO mapped)
|
||||||
|
uint8_t bus_master : 1; // Device is Bus Master; can generate PCI addresses
|
||||||
|
uint8_t special_cycle : 1; // Device can monitor Special Cycle
|
||||||
|
uint8_t memory_write_and_invalidate : 1; // Device can generate Memory Write And Invalidate commands; else Memory Write must be used
|
||||||
|
uint8_t vga_palette : 1; // Device snoops the VGA palette on write; else is treated like a normal access
|
||||||
|
uint8_t parity_error_response : 1; // Device responds to Parity Errors by setting PERR#; else will set pci_status#parity_error and continue.
|
||||||
|
uint8_t _reserved : 1; // Hardwired to 0
|
||||||
|
uint8_t serr : 1; // Enable SERR# driver; System ERRor
|
||||||
|
uint8_t fast_back_back : 1; // Device is allowed to generate fast back-to-back transactions to other agents.
|
||||||
|
uint8_t disable_interrupt : 1; // Disable assertion of INTx# signal; else enable.
|
||||||
|
} pci_command_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
uint8_t _reserved : 3; // 3 bits hardwired to 0
|
||||||
|
uint8_t interrupt : 1; // State of device's INTx# signal. If pci_command#disable_interrupt is 0 and this is 1, the signal will be asserted.
|
||||||
|
uint8_t capability_list : 1; // If set, device will implement New Capabilities list at 0x34 offset.
|
||||||
|
uint8_t freq_66_capable : 1; // Device can run at 66MHz. Else, device will run at 33MHz.
|
||||||
|
uint8_t _reserved1 : 1; // Reserved as of 3.0, Used in 2.1 as "Supports User Definable Features"
|
||||||
|
uint8_t fast_back_back : 1; // Device is allowed to accept fast back-to-back transactions from other agents.
|
||||||
|
uint8_t master_parity_error : 1; // Only set when PERR# is asserted by the Bus Master while pci_command#parity_error_response is set.
|
||||||
|
uint8_t devsel_timing : 2; // Read-Only; represents the slowest time a device will assert DEVSEL#. 00 = fast, 01 = medium, 11 = slow.
|
||||||
|
uint8_t target_signalled_abort : 1; // Target device terminated transaction via Target-Abort
|
||||||
|
uint8_t received_target_abort : 1; // Master's connection was terminated by Target-Abort
|
||||||
|
uint8_t received_master_abort : 1; // Master's connection was terminated by Master-Abort
|
||||||
|
uint8_t system_error_asserted : 1; // Device asserted SERR#
|
||||||
|
uint8_t parity_error : 1; // Device detected parity error. Parity error may not be handled.
|
||||||
|
} pci_status_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
uint16_t vendor_id; // 16 bit Vendor ID allocated by PCI-SIG. 0xFFFF is invalid.
|
||||||
|
uint16_t device_id; // 16 bit Device ID allocated by the vendor.
|
||||||
|
pci_command_t command; // 16 bit PCI_COMMAND register.
|
||||||
|
pci_status_t status; // 16 bit PCI_STATUS register.
|
||||||
|
uint8_t revision_id; // 8 bit register, revision identifier specified by vendor.
|
||||||
|
uint8_t progIF; // 8 bit register, identifies any programming interface the device may have.
|
||||||
|
uint8_t subclass; // 8 bit Subclass code; identifies the specific function of the device
|
||||||
|
uint8_t class_code; // 8 bit Class Code; identifies the function of the device
|
||||||
|
uint8_t cache_line_size; // 8 bit; specifies system cache line size in 32-bit blocks. Devices can limit this. Unsupported values are treated as 0.
|
||||||
|
uint8_t latency_timer; // 8 bit; specifies latency timer in (bus clock) units.
|
||||||
|
uint8_t header_type; // 8 bit; identifies the layout of the header and the type of device; 00 = device, 01 = pci-pci bridge, 11 = CardBus bridge. Multi-function defined by bit 7.
|
||||||
|
uint8_t bist; // 8 bit; status and control of a device's built-in self-test (BIST)
|
||||||
|
} pci_header_common_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
// pci_header_common_t first, then..
|
||||||
|
uint32_t bar[6]; // 6 x 32 bit Base Address Registers (BARs)
|
||||||
|
uint32_t cis_pointer; // Points to Card Information Structure for PCI devices that share silicon with CardBus
|
||||||
|
uint16_t subsystem_vendor_id;
|
||||||
|
uint16_t subsystem_id;
|
||||||
|
uint32_t expansion_bar; // Points to the base of an Expansion ROM.
|
||||||
|
uint8_t capabilities; // The pointer generated by pci_status#capabilities_list
|
||||||
|
uint8_t _reserved[3]; // 24 bit reserved at top end of register.
|
||||||
|
uint32_t _reserved2;
|
||||||
|
uint8_t interrupt_line; // Specifies the PIC pin that INTx# is connected to. Can be 0-15 because x86 PICs have 16 IRQs. 0xFF is no connection.
|
||||||
|
uint8_t interrupt; // Specifies the interrupt pin the device uses. 0x1 is INTA#, 0x2 is INTB#, 0x3 is INTC#, 0x4 is INTD#, 0x0 is no interrupt.
|
||||||
|
uint8_t min_grant; // Specifies the length of the burst period, in quarter-microsecond units
|
||||||
|
uint8_t max_latency; // Specifies how often the device accesses the PCI bus - in quarter-microseconds
|
||||||
|
} pci_header_device_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
// pci_header_common_t first
|
||||||
|
uint32_t bar[2];
|
||||||
|
uint8_t pri_bus; // Primary Bus Number.
|
||||||
|
uint8_t sec_bus; // Secondary Bus Number.
|
||||||
|
uint8_t sub_bus; // Subordinate Bus Number.
|
||||||
|
uint8_t sec_latency_timer; // Secondary Latency Timer.
|
||||||
|
uint8_t io_base; // IO Base is 24 bits. This is lower 8.
|
||||||
|
uint8_t io_limit; // IO Limit is 24 bits. This is lower 8.
|
||||||
|
pci_status_t sec_status; // Secondary Status.
|
||||||
|
uint16_t mem_base;
|
||||||
|
uint16_t mem_limit;
|
||||||
|
uint16_t mem_base_prefetch; // Prefetchable Memory Base is 48 bits. This is lower 16.
|
||||||
|
uint16_t mem_limit_prefetch; // Prefetchable Memory Limit is 48 bits. This is lower 16.
|
||||||
|
uint32_t mem_base_prefetch_upper; // Prefetchable Memory Base is 48 bits. This is upper 32.
|
||||||
|
uint32_t mem_limit_prefetch_upper; // Prefetchable Memory Limit is 48 bits. This is upper 32.
|
||||||
|
uint16_t io_base_upper; // IO Base is 24 bits. This is upper 16.
|
||||||
|
uint16_t io_limit_upper; // IO Limit is 24 bits. This is upper 16.
|
||||||
|
uint8_t capabilities; // Pointer generated by pci_status#capabilities_list
|
||||||
|
uint8_t _reserved[3]; // 24 reserved bits.
|
||||||
|
uint32_t expansion_bar; // Base of Expansion ROM.
|
||||||
|
uint8_t interrupt_line; // Specifies the PIC pin that INTx# is connected to. Can be 0-15 because x86 PICs have 16 IRQs. 0xFF is no connection.
|
||||||
|
uint8_t interrupt; // Specifies the interrupt pin the device uses. 0x1 is INTA#, 0x2 is INTB#, 0x3 is INTC#, 0x4 is INTD#, 0x0 is no interrupt.
|
||||||
|
uint16_t bridge_control;
|
||||||
|
} pci_header_bridge_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t segment;
|
||||||
|
uint8_t bus;
|
||||||
|
uint8_t slot;
|
||||||
|
uint8_t function;
|
||||||
|
} pci_address_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t present : 1;
|
||||||
|
uint8_t mmio : 1;
|
||||||
|
|
||||||
|
union {
|
||||||
|
size_t addr;
|
||||||
|
uint16_t port;
|
||||||
|
};
|
||||||
|
size_t length;
|
||||||
|
} pci_bar_t;
|
||||||
|
|
||||||
|
typedef struct pci_dev{
|
||||||
|
|
||||||
|
struct pci_dev* parent; // Parent of the device (for PCI hubs / splitters)
|
||||||
|
|
||||||
|
uint16_t device_id;
|
||||||
|
uint16_t vendor_id;
|
||||||
|
|
||||||
|
uint8_t devclass;
|
||||||
|
uint8_t subclass;
|
||||||
|
|
||||||
|
uint8_t progif;
|
||||||
|
|
||||||
|
pci_address_t address;
|
||||||
|
|
||||||
|
pci_bar_t bars[6];
|
||||||
|
|
||||||
|
int irq; // The IRQ of the device if already handled
|
||||||
|
|
||||||
|
// The headers!
|
||||||
|
volatile pci_header_common_t* header;
|
||||||
|
|
||||||
|
union { // The device can only be one of these at a time, but they both form part of the config space.
|
||||||
|
volatile pci_header_bridge_t* bridge;
|
||||||
|
volatile pci_header_device_t* device;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pci_dev** children; // If this device is a hub, it has children...
|
||||||
|
|
||||||
|
// acpi_node_t acpi;
|
||||||
|
} pci_dev_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
pci_address_t key;
|
||||||
|
pci_dev_t* value;
|
||||||
|
} pci_entry_t;
|
||||||
|
|
||||||
|
|
513
chroma/system/pci.c
Normal file
513
chroma/system/pci.c
Normal file
|
@ -0,0 +1,513 @@
|
||||||
|
#include <chroma.h>
|
||||||
|
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2020 ***
|
||||||
|
*** Chroma ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
/* This file contains functions for accessing the PCI bus,
|
||||||
|
* and devices contained wherein.
|
||||||
|
*
|
||||||
|
* It allows you to query the bus, as well as communicate with individual devices.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
pci_dev_t** pci_root_devices = NULL;
|
||||||
|
pci_entry_t* pci_map = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void PCIEnumerate() {
|
||||||
|
|
||||||
|
uint8_t bus = 0, device = 0, function = 0;
|
||||||
|
|
||||||
|
uint32_t register;
|
||||||
|
|
||||||
|
uint16_t device_id, vendor_id;
|
||||||
|
|
||||||
|
uint8_t class_code, subclass_code;
|
||||||
|
|
||||||
|
SerialPrintf("Started PCI Enumeration.");
|
||||||
|
|
||||||
|
SerialPrintf("\nPCI Scan result:");
|
||||||
|
for (bus = 0; bus <= 255; bus++) {
|
||||||
|
for (device = 0; device <= 31; device++) {
|
||||||
|
for(function = 0; function <= 7; function++) {
|
||||||
|
uint32_t temp = PCIReadConfig(bus, device, 0, 0xC); // Read BIST/Header/Latency/Cache Line register
|
||||||
|
uint8_t header = (uint8_t) ((temp & 0x00FF0000) >> 24); // Header is lower byte of upper word, so mask it off and shift it down
|
||||||
|
uint8_t multifunction_bit = header & 0x80; // The multifunction bit is the highest bit of the header
|
||||||
|
|
||||||
|
temp = PCIReadConfig(bus, device, function, 0); // Read the Vendor/Device ID register
|
||||||
|
uint16_t vendor_id = (uint16_t) temp & 0x0000FFFF; // Vendor ID is bottom word
|
||||||
|
uint16_t device_id = (uint16_t) temp >> 16; // Device ID is top word
|
||||||
|
|
||||||
|
temp = PCIReadConfig(bus, device, function, 8); // Read the Device Info register
|
||||||
|
uint8_t device_class = (uint16_t) temp >> 24; // Device class is top byte, so shift them down
|
||||||
|
uint8_t device_subclass = (uint16_t) (temp >> 16) & 0x00FF; // Device subclass is same as header - lower byte of higher word. Shift down and mask just like before.
|
||||||
|
uint8_t device_progif = (uint16_t) temp & 0x0000FF00 >> 8; // Device Programming Interface is higher byte of lower word, so mask and shift
|
||||||
|
uint8_t device_revision = (uint16_t) temp & 0x000000FF; // Device revision is lower byte of whole double word. Just mask it.
|
||||||
|
|
||||||
|
|
||||||
|
/* 0xFFFF is not a valid Vendor ID. This serves as a sanity check.
|
||||||
|
* If this check is true, then nothing is logged and we continue for the next loop.
|
||||||
|
*/
|
||||||
|
if(vendor_id != 0xFFFF) {
|
||||||
|
SerialPrintf("\n\t%x:%x:\n\t\tVendor: %x\n\t\tDevice: %x", bus, device, vendor_id, device_id);
|
||||||
|
SerialPrintf("\n\t\tClass: %s\n\t\tDevice Type: %s\n\t\tRevision: %s", PCIGetClassName(device_class), PCIGetDeviceName_Subclass(device_class, device_subclass, device_progif), device_revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the PCI Device header tells us that this is not a multifunction device,
|
||||||
|
* and we've already scanned function 0, then there is nothing else to see.
|
||||||
|
* Therefore, stop this loop and move onto device++
|
||||||
|
*/
|
||||||
|
if (multifunction_bit == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t PCIReadConfig(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset) {
|
||||||
|
uint32_t address;
|
||||||
|
uint32_t busLong = (uint32_t) bus;
|
||||||
|
uint32_t slotLong = (uint32_t) slot;
|
||||||
|
uint32_t functionLong = (uint32_t) function;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------
|
||||||
|
* | 31 | 30 ... 24 | 23 ... 16 | 15 ... 11 | 10 ... 8 | 7 ... 0 |
|
||||||
|
* ---------------------------------------------------------------
|
||||||
|
* | EN | RESERVED | BUS NUM | DEVICE NO | FUNC NO | REG OFF |
|
||||||
|
* ---------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* NOTE: REG OFF *must* have 0 last two bits (ie. & 0xFC)
|
||||||
|
*/
|
||||||
|
|
||||||
|
address = (uint32_t) (( busLong << 16 ) | ( slotLong << 11 ) |
|
||||||
|
( functionLong << 8 ) | ( offset & 0xFC) | ((uint32_t)0x80000000));
|
||||||
|
|
||||||
|
WritePort(0xCF8, address, 4);
|
||||||
|
|
||||||
|
|
||||||
|
return ReadPort(0xCFC, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_t progif) {
|
||||||
|
switch(devclass) {
|
||||||
|
|
||||||
|
case 0x00: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "Non-VGA-Compatible device";
|
||||||
|
case 0x01: return "VGA-Compatible device";
|
||||||
|
default: return "Unknown Unclassified";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x01: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "SCSI Bus Controller";
|
||||||
|
case 0x01: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "ISA Compatibility Mode-only IDE Controller";
|
||||||
|
case 0x05: return "PCI Native Mode-only IDE Controller";
|
||||||
|
case 0x0A: return "ISA Compatibility Mode IDE Controller (supports PCI Native Mode)";
|
||||||
|
case 0x0F: return "PCI Native Mode IDE Controller (supports ISA Compatibility Mode)";
|
||||||
|
case 0x80: return "ISA Compatibilty Mode-only IDE Controller (supports Bus Mastering)";
|
||||||
|
case 0x85: return "PCI Native Mode-only IDE Controller (supports Bus Mastering)";
|
||||||
|
case 0x8A: return "ISA Compatibility Mode IDE Controller (supports PCI Native Mode & Bus Mastering)";
|
||||||
|
case 0x8F: return "PCI Native Mode IDE Controller (supports ISA Compatibiliy Mode & Bus Mastering)";
|
||||||
|
default: return "IDE Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 0x02: return "Floppy Disk Controller";
|
||||||
|
case 0x03: return "IPI Bus Controller";
|
||||||
|
case 0x04: return "RAID Controller";
|
||||||
|
case 0x05: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x20: return "Single-DMA ATA Controller";
|
||||||
|
case 0x30: return "Chained-DMA ATA Controller";
|
||||||
|
default: return "ATA Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case 0x06: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Vendor-Specific Interface SATA Controller";
|
||||||
|
case 0x01: return "AHCI 1.0 SATA Controller";
|
||||||
|
case 0x02: return "Serial Storage Bus SATA Controller";
|
||||||
|
default: return "Serial ATA Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 0x07: return "Serial Attached SCSI (SAS)";
|
||||||
|
|
||||||
|
case 0x08:{
|
||||||
|
switch(progif) {
|
||||||
|
case 0x01: return "NVMHCI Memory Controller";
|
||||||
|
case 0x02: return "NVMe Memory Controller";
|
||||||
|
default: return "Non-Volatile Memory Controller";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: "Unknown Mass Storage Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x02: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "Ethernet Controller";
|
||||||
|
case 0x01: return "Token Ring Controller";
|
||||||
|
case 0x02: return "FDDI Controller";
|
||||||
|
case 0x03: return "ATM Controller";
|
||||||
|
case 0x04: return "ISDN Controller";
|
||||||
|
case 0x05: return "WorldFip Controller";
|
||||||
|
case 0x06: return "PICMG 2.14 Multi Computing";
|
||||||
|
case 0x07: return "Infiniband Controller";
|
||||||
|
case 0x08: return "Fabric Controller";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: "Unknown Network Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x03: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "VGA Controller";
|
||||||
|
case 0x01: return "8514 VGA Controller";
|
||||||
|
default: return "VGA Compatible Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x01: return "XGA Controller";
|
||||||
|
case 0x02: return "3D Controller (Not VGA-Compatible)";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: "Unknown Display Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x04: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "Multimedia Video Controller";
|
||||||
|
case 0x01: return "Multimedia Audio Controller";
|
||||||
|
case 0x02: return "Computer Telephony Device";
|
||||||
|
case 0x03: return "Audio Device";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: return "Unknown Multimedia Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x05: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "RAM Controller";
|
||||||
|
case 0x01: return "Flash Controller";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: return "Unknown Memory Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x06: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "Host Bridge";
|
||||||
|
case 0x01: return "ISA Bridge";
|
||||||
|
case 0x02: return "EISA Bridge";
|
||||||
|
case 0x03: return "MCA Bridge";
|
||||||
|
case 0x04:
|
||||||
|
case 0x09:
|
||||||
|
return "PCI-to-PCI Bridge";
|
||||||
|
case 0x05: return "PCMCIA Bridge";
|
||||||
|
case 0x06: return "NuBus Bridge";
|
||||||
|
case 0x07: return "CardBus Bridge";
|
||||||
|
case 0x08: return "RACEway Bridge";
|
||||||
|
case 0x0A: return "InfiniBand-to-PCI Host Bridge";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: return "Unknown Bridge Device";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x07: {
|
||||||
|
switch(subclass) {
|
||||||
|
|
||||||
|
case 0x00: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Serial Controller <8250>";
|
||||||
|
case 0x01: return "Serial controller <16450>";
|
||||||
|
case 0x02: return "Serial controller <16550>";
|
||||||
|
case 0x03: return "Serial controller <16650>";
|
||||||
|
case 0x04: return "Serial controller <16750>";
|
||||||
|
case 0x05: return "Serial controller <16850>";
|
||||||
|
case 0x06: return "Serial controller <16950>";
|
||||||
|
default: return "Serial Controller";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x01: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Standard Parallel Port";
|
||||||
|
case 0x01: return "Bi-Directional Parallel Port";
|
||||||
|
case 0x02: return "ECP 1.X Compliant Parallel Port";
|
||||||
|
case 0x03: return "IEEE 1284 Parallel Controller";
|
||||||
|
case 0x04: return "IEE 1284 Parallel Target";
|
||||||
|
default: return "Parallel Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 0x02: return "Multiport Serial Controller";
|
||||||
|
|
||||||
|
case 0x03: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Generic Modem";
|
||||||
|
case 0x01: return "Hayes 16450 Compatible Modem";
|
||||||
|
case 0x02: return "Hayes 16550 Compatible Modem";
|
||||||
|
case 0x03: return "Hayes 16650 Compatible Modem";
|
||||||
|
case 0x04: return "Hayes 16750 Compatible Modem";
|
||||||
|
default: return "Modem";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x04: return "IEEE 488.1/2 (GPIB) Controller";
|
||||||
|
case 0x05: return "Smart Card";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: return "Unknown Simple Comms Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x08: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Generic 8259-Compatible PIC";
|
||||||
|
case 0x01: return "ISA-Compatible PIC";
|
||||||
|
case 0x02: return "EISA-Compatible PIC";
|
||||||
|
case 0x03: return "I/O APIC Interrupt Controller";
|
||||||
|
case 0x04: return "I/O(x) APIC Interrupt Controller";
|
||||||
|
default: "PIC";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x01: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Generic 8237-Compatible DMA Controller";
|
||||||
|
case 0x01: return "ISA-Compatible DMA Controller";
|
||||||
|
case 0x02: return "EISA-Compatible DMA Controller";
|
||||||
|
default: "DMA Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x02: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Generic 8254-Compatible Timer";
|
||||||
|
case 0x01: return "ISA-Compatible Timer";
|
||||||
|
case 0x02: return "EISA-Compatible Timer";
|
||||||
|
case 0x03: return "HPET Timer";
|
||||||
|
default: "Timer";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x03: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Generic RTC Controller";
|
||||||
|
case 0x01: return "ISA-Compatible RTC Controller";
|
||||||
|
default: "RTC Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x04: return "PCI Hot-Plug Controller";
|
||||||
|
case 0x05: return "SD Host Controller";
|
||||||
|
case 0x06: return "IOMMU";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
|
||||||
|
default: return "Unknown Base System Peripheral";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x09: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "Keyboard Controller";
|
||||||
|
case 0x01: return "Digitiser Pen";
|
||||||
|
case 0x02: return "Mouse Controller";
|
||||||
|
case 0x03: return "Scanner Controller";
|
||||||
|
|
||||||
|
case 0x04: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Generic Gameport Controller";
|
||||||
|
case 0x10: return "Extended Gameport Controller";
|
||||||
|
default: return "Gameport Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x80: return "Other";
|
||||||
|
|
||||||
|
default: return "Unknown Input Device Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x0A: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "Generic Docking Station";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: return "Unknown Docking Station";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x0B: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "386 Processor";
|
||||||
|
case 0x01: return "486 Processor";
|
||||||
|
case 0x02: return "Pentium Processor";
|
||||||
|
case 0x03: return "Pentium Pro Processor";
|
||||||
|
case 0x10: return "Alpha Processor";
|
||||||
|
case 0x20: return "PowerPC Processor";
|
||||||
|
case 0x30: return "MIPS Processor";
|
||||||
|
case 0x40: return "Co-Processor";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: return "Unknown Processor";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x0C: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "Generic Firewire Controller";
|
||||||
|
case 0x10: return "OHCI Firewire Controller";
|
||||||
|
default: return "FireWire (IEEE 1394) Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x01: return "ACCESS Bus";
|
||||||
|
case 0x02: return "SSA";
|
||||||
|
|
||||||
|
case 0x03: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "UHCI USB Controller";
|
||||||
|
case 0x10: return "OHCI USB Controller";
|
||||||
|
case 0x20: return "EHCI USB (2.0) Controller";
|
||||||
|
case 0x30: return "XHCI USB (3.0) Controller";
|
||||||
|
case 0x80: return "Unspecified USB Controller";
|
||||||
|
case 0xFE: return "USB Device (NOT a Controller)";
|
||||||
|
default: return "USB Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x04: return "Fibre Channel";
|
||||||
|
case 0x05: return "SMBus";
|
||||||
|
case 0x06: return "InfiniBand";
|
||||||
|
|
||||||
|
case 0x07: {
|
||||||
|
switch(progif) {
|
||||||
|
case 0x00: return "SMIC IPMI Interface";
|
||||||
|
case 0x01: return "Keyboard Controller-Style IPMI Interface";
|
||||||
|
case 0x02: return "Block Transfer IPMI Interface";
|
||||||
|
default: return "IPMI Interface";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x08: return "SERCOS Interface (IEC 61491)";
|
||||||
|
case 0x09: return "CANbus";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: return "Unknown Serial Bus Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x0D: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "IRDA Compatible Controller";
|
||||||
|
case 0x01: return "Consumer IR Controller";
|
||||||
|
case 0x10: return "RF Controller";
|
||||||
|
case 0x11: return "Bluetooth Controller";
|
||||||
|
case 0x12: return "Broadband Controller";
|
||||||
|
case 0x20: return "Ethernet Controller (802.1a)";
|
||||||
|
case 0x21: return "Ethernet Controller (802.1b)";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: return "Unknown Wireless Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x0E: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "I20";
|
||||||
|
default: return "Unknown Intelligent Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x0F: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x01: return "Satellite TV Controller";
|
||||||
|
case 0x02: return "Satellite Audio Controller";
|
||||||
|
case 0x03: return "Satellite Voice Controller";
|
||||||
|
case 0x04: return "Satellite Data Controller";
|
||||||
|
default: return "Unknown Satelllite Comms Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x10: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "Network & Computing Codec";
|
||||||
|
case 0x10: return "Entertainment Codec";
|
||||||
|
case 0x80: return "Other Codec";
|
||||||
|
default: return "Unknown Encryption Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x11: {
|
||||||
|
switch(subclass) {
|
||||||
|
case 0x00: return "DPIO Modules";
|
||||||
|
case 0x01: return "Performance Counters";
|
||||||
|
case 0x10: return "Communication Synchronizer";
|
||||||
|
case 0x20: return "Signal Processing Management";
|
||||||
|
case 0x80: return "Other";
|
||||||
|
default: return "Unknown Signal Processing Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x12: return "Processing Accelerator";
|
||||||
|
|
||||||
|
case 0x13: return "Non-Essential Instrumentation";
|
||||||
|
|
||||||
|
case 0x14:
|
||||||
|
case 0x41: return "Reserved";
|
||||||
|
|
||||||
|
case 0x40: return "Co-Processor";
|
||||||
|
|
||||||
|
case 0xFF: return "Unassigned Class";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* PCIGetClassName(uint8_t devclass) {
|
||||||
|
|
||||||
|
switch(devclass) {
|
||||||
|
case 0x00: return "Unclassified";
|
||||||
|
case 0x01: return "Mass Storage Controller";
|
||||||
|
case 0x02: return "Network Controller";
|
||||||
|
case 0x03: return "Display Controller";
|
||||||
|
case 0x04: return "Multimedia Controller";
|
||||||
|
case 0x05: return "Memory Controller";
|
||||||
|
case 0x06: return "Bridge Device";
|
||||||
|
case 0x07: return "Simple Communication Controller";
|
||||||
|
case 0x08: return "Base System Peripheral";
|
||||||
|
case 0x09: return "Input Device Controller";
|
||||||
|
case 0x0A: return "Docking Station";
|
||||||
|
case 0x0B: return "Processor";
|
||||||
|
case 0x0C: return "Serial Bus Controller";
|
||||||
|
case 0x0D: return "Wireless Controller";
|
||||||
|
case 0x0E: return "Intelligent Controller";
|
||||||
|
case 0x0F: return "Satellite Communication Controller";
|
||||||
|
case 0x10: return "Encryption Controller";
|
||||||
|
case 0x11: return "Signal Processing Controller";
|
||||||
|
case 0x12: return "Processing Accelerator";
|
||||||
|
case 0x13: return "Non-Essential Instrumentation";
|
||||||
|
case 0x14: return "Reserved";
|
||||||
|
case 0x40: return "Co-Processor";
|
||||||
|
case 0x41: return "Reserved";
|
||||||
|
case 0xFF: return "Unassigned Class";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user