struct pci_device_config {
- ushort_t device_id;
ushort_t vendor_id;
- ushort_t status;
+ ushort_t device_id;
ushort_t command;
- uchar_t class_code;
- uchar_t subclass;
- ushort_t revision;
- uchar_t BIST;
- uchar_t header_type;
- uchar_t latency_time;
+ ushort_t status;
+ uchar_t revision;
+ uchar_t class_code[3]; // in order: programming interface, subclass, class code
+
+#define PROG_INTERFACE(x) ((x)[0])
+#define SUBCLASS(x) ((x)[1])
+#define CLASSCODE(x) ((x)[2])
+
+
uchar_t cache_line_size;
- uint_t BAR[6];
- uint_t cardbus_cis_pointer;
- ushort_t subsystem_id;
- ushort_t subsystem_vendor_id;
- uint_t expansion_rom_address;
- uint_t reserved[2];
- uchar_t max_latency;
- uchar_t min_grant;
- uchar_t intr_pin;
- uchar_t intr_line;
-} __attribute__((__packed__)) ;
+ uchar_t latency_time;
+ uchar_t header_type; // bits 6-0: 00: other, 01: pci-pci bridge, 02: pci-cardbus; bit 7: 1=multifunction
+
+#define HEADER_TYPE(x) ((x)&0x7f)
+
+#define PCI_DEVICE 0x0
+#define PCI_PCI_BRIDGE 0x1
+#define PCI_CARDBUS_BRIDGE 0x2
+
+#define MULTIFUNCTION(x) ((x)&0x80)
+
+#define IS_DEVICE(x) (HEADER_TYPE(x)==0x0)
+#define IS_PCI_PCI_BRIDGE(x) (HEADER_TYPE(x)==0x1)
+#define IS_PCI_CARDBUS_BRIDGE(x) (HEADER_TYPE(x)==0x2)
+
+ uchar_t BIST;
+
+ union {
+
+ // header = 00 (Device)
+ struct {
+ uint_t BAR[6];
+
+#define IS_IO_ADDR(x) ((x)&0x1)
+#define IS_MEM_ADDR(x) (!((x)&0x1))
+#define GET_IO_ADDR(x) (((uint_t)(x))&0xfffffffc)
+#define GET_MEM_ADDR(x) (((uint_t)(x))&0xfffffff0)
+#define GET_MEM_TYPE(x) (((x)&0x6)>>2)
+#define GET_MEM_PREFETCHABLE(x) ((x)&0x8)
+
+ uint_t cardbus_cis_pointer;
+ ushort_t subsystem_vendor_id;
+ ushort_t subsystem_id;
+ uint_t expansion_rom_address;
+ uchar_t cap_ptr; // capabilities list offset in config space
+ uchar_t reserved[7];
+ uchar_t intr_line; // 00=none, 01=IRQ1, etc.
+ uchar_t intr_pin; // 00=none, otherwise INTA# to INTD#
+ uchar_t min_grant; // min busmaster time - units of 250ns
+ uchar_t max_latency; // units of 250ns - busmasters
+ uint_t device_data[48];
+ } __attribute__((__packed__)) pci_device_config;
+
+ // header = 01 (pci-pci bridge)
+ struct {
+ uint_t BAR[2];
+ uchar_t primary_bus; // the one closer to the processor
+ uchar_t secondary_bus; // the one further away
+ uchar_t subordinate_bus;
+ uchar_t secondary_lat_timer;
+ uchar_t io_base;
+ uchar_t io_limit;
+ ushort_t secondary_status;
+ ushort_t memory_base;
+ ushort_t memory_limit;
+ ushort_t prefetchable_memory_base;
+ ushort_t prefetchable_memory_limit;
+ uint_t prefetchable_memory_base_upper; // for 64 bit?
+ uint_t prefetchable_memory_limit_upper;
+ ushort_t io_base_upper; // upper 16
+ ushort_t io_limit_upper;
+ uint_t reserved;
+ uint_t expansion_rom_address;
+ uchar_t intr_line;
+ uchar_t intr_pin;
+ ushort_t bridge_ctl;
+ uint_t device_data[48];
+ } __attribute__((__packed__)) pci_pci_bridge_config;
+
+
+ // header = 02 (pci-cardbus bridge)
+ struct {
+ uint_t cardbus_base_addr;
+ uchar_t cap_ptr;
+ uchar_t reserved;
+ ushort_t secondary_status;
+ uchar_t pci_bus;
+ uchar_t cardbus_bus;
+ uchar_t subordinate_bus;
+ uchar_t cardbus_lat_timer;
+ uint_t memory_base0;
+ uint_t memory_limit0;
+ uint_t memory_base1;
+ uint_t memory_limit1;
+ ushort_t io_base0;
+ ushort_t io_base0_upper;
+ ushort_t io_limit0;
+ ushort_t io_limit0_upper;
+ ushort_t io_base1;
+ ushort_t io_base1_upper;
+ ushort_t io_limit1;
+ ushort_t io_limit1_upper;
+ uchar_t intr_line;
+ uchar_t intr_pin;
+ ushort_t bridge_ctl;
+ ushort_t subsystem_vendor_id;
+ ushort_t subsystem_device_id;
+ uint_t legacy_16bit_base_addr;
+ uint_t reserved2[14];
+ uint_t device_data[32];
+ } __attribute__((__packed__)) pci_cardbus_bridge_config;
+
+ } __attribute__((__packed__)) u;
+
+};
struct pci_bus {
uint_t number;
return thepci;
}
-static void PrintPCIDevice(struct pci_device *thedev)
+static void PrintPCIShared(struct pci_device *thedev)
{
- PrintBoth(" PCI Device: \n");
PrintBoth(" Slot: %u\n",thedev->number);
- PrintBoth(" device_id: 0x%x\n", (uint_t) thedev->config.device_id);
PrintBoth(" vendor_id: 0x%x\n", (uint_t) thedev->config.vendor_id);
- PrintBoth(" status: 0x%x\n", (uint_t) thedev->config.status);
+ PrintBoth(" device_id: 0x%x\n", (uint_t) thedev->config.device_id);
PrintBoth(" command: 0x%x\n", (uint_t) thedev->config.command);
- PrintBoth(" class_code: 0x%x\n", (uint_t) thedev->config.class_code);
- PrintBoth(" subclass: 0x%x\n", (uint_t) thedev->config.subclass);
+ PrintBoth(" status: 0x%x\n", (uint_t) thedev->config.status);
PrintBoth(" revision: 0x%x\n", (uint_t) thedev->config.revision);
- PrintBoth(" BIST: 0x%x\n", (uint_t) thedev->config.BIST);
- PrintBoth(" header_type: 0x%x\n", (uint_t) thedev->config.header_type);
- PrintBoth(" latency_time: 0x%x\n", (uint_t) thedev->config.latency_time);
+ PrintBoth(" class_code: 0x%x%x%x (prog_interface 0x%x, subclass 0x%x, classcode 0x%x)\n",
+ (uint_t) thedev->config.class_code[0],
+ (uint_t) thedev->config.class_code[1],
+ (uint_t) thedev->config.class_code[2],
+ (uint_t) PROG_INTERFACE(thedev->config.class_code),
+ (uint_t) SUBCLASS(thedev->config.class_code),
+ (uint_t) CLASSCODE(thedev->config.class_code)
+ );
PrintBoth(" cache_line_size: 0x%x\n", (uint_t) thedev->config.cache_line_size);
- PrintBoth(" BAR[0]: 0x%x\n", (uint_t) thedev->config.BAR[0]);
- PrintBoth(" BAR[1]: 0x%x\n", (uint_t) thedev->config.BAR[1]);
- PrintBoth(" BAR[2]: 0x%x\n", (uint_t) thedev->config.BAR[2]);
- PrintBoth(" BAR[3]: 0x%x\n", (uint_t) thedev->config.BAR[3]);
- PrintBoth(" BAR[4]: 0x%x\n", (uint_t) thedev->config.BAR[4]);
- PrintBoth(" BAR[5]: 0x%x\n", (uint_t) thedev->config.BAR[5]);
- PrintBoth(" cardbus_cis_ptr: 0x%x\n", (uint_t) thedev->config.cardbus_cis_pointer);
- PrintBoth(" subsystem_id: 0x%x\n", (uint_t) thedev->config.subsystem_id);
- PrintBoth(" subsystem_vendor: 0x%x\n", (uint_t) thedev->config.subsystem_vendor_id);
- PrintBoth(" exp_rom_address: 0x%x\n", (uint_t) thedev->config.expansion_rom_address);
- PrintBoth(" reserved[0]: 0x%x\n", (uint_t) thedev->config.reserved[0]);
- PrintBoth(" reserved[1]: 0x%x\n", (uint_t) thedev->config.reserved[1]);
- PrintBoth(" max_latency: 0x%x\n", (uint_t) thedev->config.max_latency);
- PrintBoth(" min_grant: 0x%x\n", (uint_t) thedev->config.min_grant);
- PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.intr_pin);
- PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.intr_line);
+ PrintBoth(" latency_time: 0x%x\n", (uint_t) thedev->config.latency_time);
+ PrintBoth(" header_type: 0x%x (%s%s)\n", (uint_t) thedev->config.header_type,
+ HEADER_TYPE(thedev->config.header_type)==PCI_DEVICE ? "PCI Device" :
+ HEADER_TYPE(thedev->config.header_type)==PCI_PCI_BRIDGE ? "PCI-PCI Bridge" :
+ HEADER_TYPE(thedev->config.header_type)==PCI_CARDBUS_BRIDGE ? "PCI-Cardbus Bridge" : "UNKNOWN",
+ MULTIFUNCTION(thedev->config.header_type) ? " Multifunction" : ""
+ );
+ PrintBoth(" BIST: 0x%x\n", (uint_t) thedev->config.BIST);
}
+static void PrintPCIDevice(struct pci_device *thedev)
+{
+ int i;
+
+ PrintBoth(" PCI Device:\n");
+ PrintPCIShared(thedev);
+ for (i=0;i<6;i++) {
+ PrintBoth(" BAR[%d]: 0x%x (", i, (uint_t) thedev->config.u.pci_device_config.BAR[i]);
+ if (IS_IO_ADDR(thedev->config.u.pci_device_config.BAR[i])) {
+ PrintBoth("IO Address 0x%x)\n", GET_IO_ADDR(thedev->config.u.pci_device_config.BAR[i]));
+ } else if (IS_MEM_ADDR(thedev->config.u.pci_device_config.BAR[i])) {
+ PrintBoth("Memory Address 0x%x type=0x%x%s\n",
+ GET_MEM_ADDR(thedev->config.u.pci_device_config.BAR[i]),
+ GET_MEM_TYPE(thedev->config.u.pci_device_config.BAR[i]),
+ GET_MEM_PREFETCHABLE(thedev->config.u.pci_device_config.BAR[i]) ? " prefetchable)" : ")");
+ } else {
+ PrintBoth("UNKNOWN)\n");
+ }
+ }
+ PrintBoth(" cardbus_cis_ptr: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.cardbus_cis_pointer);
+ PrintBoth(" subsystem_vendor: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.subsystem_vendor_id);
+ PrintBoth(" subsystem_id: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.subsystem_id);
+ PrintBoth(" exp_rom_address: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.expansion_rom_address);
+ PrintBoth(" cap ptr 0x%x\n", (uint_t) thedev->config.u.pci_device_config.cap_ptr);
+ for (i=0;i<7;i++) {
+ PrintBoth(" reserved[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_device_config.reserved[i]);
+ }
+ PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.intr_line);
+ PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.intr_pin);
+ PrintBoth(" min_grant: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.min_grant);
+ PrintBoth(" max_latency: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.max_latency);
+ for (i=0;i<48;i++) {
+ PrintBoth(" device_data[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_device_config.device_data[i]);
+ }
+}
+
+static void PrintPCIPCIBridge(struct pci_device *thedev)
+{
+ int i;
+
+ PrintBoth(" PCI-PCI Bridge:\n");
+ PrintPCIShared(thedev);
+ for (i=0;i<2;i++) {
+ PrintBoth(" BAR[%d]: 0x%x (", i, (uint_t) thedev->config.u.pci_pci_bridge_config.BAR[i]);
+ if (IS_IO_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i])) {
+ PrintBoth("IO Address 0x%x)\n", GET_IO_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i]));
+ } else if (IS_MEM_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i])) {
+ PrintBoth("Memory Address 0x%x type=0x%x%s\n",
+ GET_MEM_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i]),
+ GET_MEM_TYPE(thedev->config.u.pci_pci_bridge_config.BAR[i]),
+ GET_MEM_PREFETCHABLE(thedev->config.u.pci_pci_bridge_config.BAR[i]) ? " prefetchable)" : ")");
+ } else {
+ PrintBoth("UNKNOWN)\n");
+ }
+ }
+ PrintBoth(" primary_bus: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.primary_bus);
+ PrintBoth(" secondary_bus: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_bus);
+ PrintBoth(" subordinate_bus: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.subordinate_bus);
+ PrintBoth(" second_lat_timer: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_lat_timer);
+ PrintBoth(" io_base: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_base);
+ PrintBoth(" io_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_limit);
+ PrintBoth(" secondary_status: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_status);
+ PrintBoth(" memory_base: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_base);
+ PrintBoth(" memory_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit);
+ PrintBoth(" prefetch_base: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_base);
+ PrintBoth(" prefetch_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_limit);
+ PrintBoth(" prefetch_base_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_base_upper);
+ PrintBoth(" prefetch_limit_u: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_limit_upper);
+ PrintBoth(" memory_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit);
+ PrintBoth(" memory_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit);
+ PrintBoth(" io_base_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_base_upper);
+ PrintBoth(" io_limit_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_limit_upper);
+ PrintBoth(" reserved: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.reserved);
+ PrintBoth(" exp_rom_address: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.expansion_rom_address);
+ PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.intr_line);
+ PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.intr_pin);
+ for (i=0;i<48;i++) {
+ PrintBoth(" device_data[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_pci_bridge_config.device_data[i]);
+ }
+}
+
+static void PrintPCICardbusBridge(struct pci_device *thedev)
+{
+ int i;
+
+ PrintBoth(" PCI-Cardbus Bridge:\n");
+ PrintPCIShared(thedev);
+ PrintBoth(" cardbus_base_add: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_base_addr);
+ PrintBoth(" cap_ptr: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cap_ptr);
+ PrintBoth(" reserved: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.reserved);
+ PrintBoth(" secondary_status 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.secondary_status);
+ PrintBoth(" pci_bus: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.pci_bus);
+ PrintBoth(" cardbus_bus: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_bus);
+ PrintBoth(" subordinate_bus: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subordinate_bus);
+ PrintBoth(" cardbus_lat_time: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_lat_timer);
+ PrintBoth(" memory_base0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_base0);
+ PrintBoth(" memory_limit0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_limit0);
+ PrintBoth(" memory_base1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_base1);
+ PrintBoth(" memory_limit1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_limit1);
+ PrintBoth(" io_base0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base0);
+ PrintBoth(" io_base0_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base0_upper);
+ PrintBoth(" io_limit0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit0);
+ PrintBoth(" io_limit0_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit0_upper);
+ PrintBoth(" io_base1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base1);
+ PrintBoth(" io_base1_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base1_upper);
+ PrintBoth(" io_limit1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit1);
+ PrintBoth(" io_limit1_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit1_upper);
+ PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.intr_line);
+ PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.intr_pin);
+ PrintBoth(" bridge_ctl: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.bridge_ctl);
+ PrintBoth(" subsys_vend_id: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subsystem_vendor_id);
+ PrintBoth(" subsys_dev_id: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subsystem_device_id);
+ PrintBoth(" legacy16_base: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.legacy_16bit_base_addr);
+ for (i=0;i<14;i++) {
+ PrintBoth(" reserved2[%d]: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.reserved2[i]);
+ }
+ for (i=0;i<48;i++) {
+ PrintBoth(" device_data[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_cardbus_bridge_config.device_data[i]);
+ }
+}
+
+static void PrintPCIUnknown(struct pci_device *thedev)
+{
+ PrintBoth(" PCI Unknown Element\n");
+ PrintPCIShared(thedev);
+}
+
+static void PrintPCIElement(struct pci_device *thedev)
+{
+ switch (HEADER_TYPE(thedev->config.header_type)) {
+ case PCI_DEVICE:
+ PrintPCIDevice(thedev);
+ break;
+ case PCI_PCI_BRIDGE:
+ PrintPCIPCIBridge(thedev);
+ break;
+ case PCI_CARDBUS_BRIDGE:
+ PrintPCICardbusBridge(thedev);
+ break;
+ default:
+ PrintPCIUnknown(thedev);
+ break;
+ }
+}
+
+
static void PrintPCIBus(struct pci_bus *thebus)
{
struct pci_device *thedev;
thedev=thebus->device_list;
while (thedev) {
- PrintPCIDevice(thedev);
+ PrintPCIElement(thedev);
thedev=thedev->next;
}
}