aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2022-06-16 16:14:56 +0200
committerPali Rohár <pali@kernel.org>2022-10-30 13:48:05 +0100
commit94a53fc6ec2ee74ff36e4a13ec8081d6697f630f (patch)
tree6a08b046bd11aa457c5fa5819315b8e849dccb81
parent13b4913199b513b9cdce1ac05c7237e9cb31b8e2 (diff)
downloadpciutils-94a53fc6ec2ee74ff36e4a13ec8081d6697f630f.tar.gz
setpci: Check if standard register on device exist
Some standard registers are available only on device with header type 0, some only on header type 1, some other only on header type 2 and some on header type 0 and 1. Add definitions which registers are available on which header type and add check to access only available registers.
-rw-r--r--setpci.c262
1 files changed, 137 insertions, 125 deletions
diff --git a/setpci.c b/setpci.c
index 1a0a736..ca1f31d 100644
--- a/setpci.c
+++ b/setpci.c
@@ -33,6 +33,8 @@ struct op {
struct op *next;
u16 cap_type; /* PCI_CAP_xxx or 0 */
u16 cap_id;
+ const char *name;
+ unsigned int hdr_type_mask;
unsigned int addr;
unsigned int width; /* Byte width of the access */
unsigned int num_values; /* Number of values to write; 0=read */
@@ -144,6 +146,13 @@ exec_op(struct op *op, struct pci_dev *dev)
if (addr + width > 0x1000)
die("%s: Access of width %d to register %04x out of range", slot, width, addr);
+ if (op->hdr_type_mask)
+ {
+ unsigned int hdr_type = pci_read_byte(dev, PCI_HEADER_TYPE) & 0x7f;
+ if (hdr_type > 2 || !((1 << hdr_type) & op->hdr_type_mask))
+ die("%s: Does not have register %s.", slot, op->name);
+ }
+
if (op->num_values)
{
for (i=0; i<op->num_values; i++)
@@ -256,135 +265,136 @@ struct reg_name {
unsigned int cap;
unsigned int offset;
unsigned int width;
+ unsigned int hdr_type_mask;
const char *name;
};
static const struct reg_name pci_reg_names[] = {
- { 0, 0x00, 2, "VENDOR_ID" },
- { 0, 0x02, 2, "DEVICE_ID" },
- { 0, 0x04, 2, "COMMAND" },
- { 0, 0x06, 2, "STATUS" },
- { 0, 0x08, 1, "REVISION" },
- { 0, 0x09, 1, "CLASS_PROG" },
- { 0, 0x0a, 2, "CLASS_DEVICE" },
- { 0, 0x0c, 1, "CACHE_LINE_SIZE" },
- { 0, 0x0d, 1, "LATENCY_TIMER" },
- { 0, 0x0e, 1, "HEADER_TYPE" },
- { 0, 0x0f, 1, "BIST" },
- { 0, 0x10, 4, "BASE_ADDRESS_0" },
- { 0, 0x14, 4, "BASE_ADDRESS_1" },
- { 0, 0x18, 4, "BASE_ADDRESS_2" },
- { 0, 0x1c, 4, "BASE_ADDRESS_3" },
- { 0, 0x20, 4, "BASE_ADDRESS_4" },
- { 0, 0x24, 4, "BASE_ADDRESS_5" },
- { 0, 0x28, 4, "CARDBUS_CIS" },
- { 0, 0x2c, 2, "SUBSYSTEM_VENDOR_ID" },
- { 0, 0x2e, 2, "SUBSYSTEM_ID" },
- { 0, 0x30, 4, "ROM_ADDRESS" },
- { 0, 0x34, 1, "CAPABILITIES" },
- { 0, 0x3c, 1, "INTERRUPT_LINE" },
- { 0, 0x3d, 1, "INTERRUPT_PIN" },
- { 0, 0x3e, 1, "MIN_GNT" },
- { 0, 0x3f, 1, "MAX_LAT" },
- { 0, 0x18, 1, "PRIMARY_BUS" },
- { 0, 0x19, 1, "SECONDARY_BUS" },
- { 0, 0x1a, 1, "SUBORDINATE_BUS" },
- { 0, 0x1b, 1, "SEC_LATENCY_TIMER" },
- { 0, 0x1c, 1, "IO_BASE" },
- { 0, 0x1d, 1, "IO_LIMIT" },
- { 0, 0x1e, 2, "SEC_STATUS" },
- { 0, 0x20, 2, "MEMORY_BASE" },
- { 0, 0x22, 2, "MEMORY_LIMIT" },
- { 0, 0x24, 2, "PREF_MEMORY_BASE" },
- { 0, 0x26, 2, "PREF_MEMORY_LIMIT" },
- { 0, 0x28, 4, "PREF_BASE_UPPER32" },
- { 0, 0x2c, 4, "PREF_LIMIT_UPPER32" },
- { 0, 0x30, 2, "IO_BASE_UPPER16" },
- { 0, 0x32, 2, "IO_LIMIT_UPPER16" },
- { 0, 0x38, 4, "BRIDGE_ROM_ADDRESS" },
- { 0, 0x3e, 2, "BRIDGE_CONTROL" },
- { 0, 0x10, 4, "CB_CARDBUS_BASE" },
- { 0, 0x14, 2, "CB_CAPABILITIES" },
- { 0, 0x16, 2, "CB_SEC_STATUS" },
- { 0, 0x18, 1, "CB_BUS_NUMBER" },
- { 0, 0x19, 1, "CB_CARDBUS_NUMBER" },
- { 0, 0x1a, 1, "CB_SUBORDINATE_BUS" },
- { 0, 0x1b, 1, "CB_CARDBUS_LATENCY" },
- { 0, 0x1c, 4, "CB_MEMORY_BASE_0" },
- { 0, 0x20, 4, "CB_MEMORY_LIMIT_0" },
- { 0, 0x24, 4, "CB_MEMORY_BASE_1" },
- { 0, 0x28, 4, "CB_MEMORY_LIMIT_1" },
- { 0, 0x2c, 2, "CB_IO_BASE_0" },
- { 0, 0x2e, 2, "CB_IO_BASE_0_HI" },
- { 0, 0x30, 2, "CB_IO_LIMIT_0" },
- { 0, 0x32, 2, "CB_IO_LIMIT_0_HI" },
- { 0, 0x34, 2, "CB_IO_BASE_1" },
- { 0, 0x36, 2, "CB_IO_BASE_1_HI" },
- { 0, 0x38, 2, "CB_IO_LIMIT_1" },
- { 0, 0x3a, 2, "CB_IO_LIMIT_1_HI" },
- { 0, 0x40, 2, "CB_SUBSYSTEM_VENDOR_ID" },
- { 0, 0x42, 2, "CB_SUBSYSTEM_ID" },
- { 0, 0x44, 4, "CB_LEGACY_MODE_BASE" },
- { 0x10001, 0, 0, "CAP_PM" },
- { 0x10002, 0, 0, "CAP_AGP" },
- { 0x10003, 0, 0, "CAP_VPD" },
- { 0x10004, 0, 0, "CAP_SLOTID" },
- { 0x10005, 0, 0, "CAP_MSI" },
- { 0x10006, 0, 0, "CAP_CHSWP" },
- { 0x10007, 0, 0, "CAP_PCIX" },
- { 0x10008, 0, 0, "CAP_HT" },
- { 0x10009, 0, 0, "CAP_VNDR" },
- { 0x1000a, 0, 0, "CAP_DBG" },
- { 0x1000b, 0, 0, "CAP_CCRC" },
- { 0x1000c, 0, 0, "CAP_HOTPLUG" },
- { 0x1000d, 0, 0, "CAP_SSVID" },
- { 0x1000e, 0, 0, "CAP_AGP3" },
- { 0x1000f, 0, 0, "CAP_SECURE" },
- { 0x10010, 0, 0, "CAP_EXP" },
- { 0x10011, 0, 0, "CAP_MSIX" },
- { 0x10012, 0, 0, "CAP_SATA" },
- { 0x10013, 0, 0, "CAP_AF" },
- { 0x10014, 0, 0, "CAP_EA" },
- { 0x20001, 0, 0, "ECAP_AER" },
- { 0x20002, 0, 0, "ECAP_VC" },
- { 0x20003, 0, 0, "ECAP_DSN" },
- { 0x20004, 0, 0, "ECAP_PB" },
- { 0x20005, 0, 0, "ECAP_RCLINK" },
- { 0x20006, 0, 0, "ECAP_RCILINK" },
- { 0x20007, 0, 0, "ECAP_RCEC" },
- { 0x20008, 0, 0, "ECAP_MFVC" },
- { 0x20009, 0, 0, "ECAP_VC2" },
- { 0x2000a, 0, 0, "ECAP_RBCB" },
- { 0x2000b, 0, 0, "ECAP_VNDR" },
- { 0x2000d, 0, 0, "ECAP_ACS" },
- { 0x2000e, 0, 0, "ECAP_ARI" },
- { 0x2000f, 0, 0, "ECAP_ATS" },
- { 0x20010, 0, 0, "ECAP_SRIOV" },
- { 0x20011, 0, 0, "ECAP_MRIOV" },
- { 0x20012, 0, 0, "ECAP_MCAST" },
- { 0x20013, 0, 0, "ECAP_PRI" },
- { 0x20015, 0, 0, "ECAP_REBAR" },
- { 0x20016, 0, 0, "ECAP_DPA" },
- { 0x20017, 0, 0, "ECAP_TPH" },
- { 0x20018, 0, 0, "ECAP_LTR" },
- { 0x20019, 0, 0, "ECAP_SECPCI" },
- { 0x2001a, 0, 0, "ECAP_PMUX" },
- { 0x2001b, 0, 0, "ECAP_PASID" },
- { 0x2001c, 0, 0, "ECAP_LNR" },
- { 0x2001d, 0, 0, "ECAP_DPC" },
- { 0x2001e, 0, 0, "ECAP_L1PM" },
- { 0x2001f, 0, 0, "ECAP_PTM" },
- { 0x20020, 0, 0, "ECAP_M_PCIE" },
- { 0x20021, 0, 0, "ECAP_FRS" },
- { 0x20022, 0, 0, "ECAP_RTR" },
- { 0x20023, 0, 0, "ECAP_DVSEC" },
- { 0x20024, 0, 0, "ECAP_VF_REBAR" },
- { 0x20025, 0, 0, "ECAP_DLNK" },
- { 0x20026, 0, 0, "ECAP_16GT" },
- { 0x20027, 0, 0, "ECAP_LMR" },
- { 0x20028, 0, 0, "ECAP_HIER_ID" },
- { 0x20029, 0, 0, "ECAP_NPEM" },
- { 0, 0, 0, NULL }
+ { 0, 0x00, 2, 0x0, "VENDOR_ID" },
+ { 0, 0x02, 2, 0x0, "DEVICE_ID" },
+ { 0, 0x04, 2, 0x0, "COMMAND" },
+ { 0, 0x06, 2, 0x0, "STATUS" },
+ { 0, 0x08, 1, 0x0, "REVISION" },
+ { 0, 0x09, 1, 0x0, "CLASS_PROG" },
+ { 0, 0x0a, 2, 0x0, "CLASS_DEVICE" },
+ { 0, 0x0c, 1, 0x0, "CACHE_LINE_SIZE" },
+ { 0, 0x0d, 1, 0x0, "LATENCY_TIMER" },
+ { 0, 0x0e, 1, 0x0, "HEADER_TYPE" },
+ { 0, 0x0f, 1, 0x0, "BIST" },
+ { 0, 0x10, 4, 0x3, "BASE_ADDRESS_0" },
+ { 0, 0x14, 4, 0x3, "BASE_ADDRESS_1" },
+ { 0, 0x18, 4, 0x1, "BASE_ADDRESS_2" },
+ { 0, 0x1c, 4, 0x1, "BASE_ADDRESS_3" },
+ { 0, 0x20, 4, 0x1, "BASE_ADDRESS_4" },
+ { 0, 0x24, 4, 0x1, "BASE_ADDRESS_5" },
+ { 0, 0x28, 4, 0x1, "CARDBUS_CIS" },
+ { 0, 0x2c, 2, 0x1, "SUBSYSTEM_VENDOR_ID" },
+ { 0, 0x2e, 2, 0x1, "SUBSYSTEM_ID" },
+ { 0, 0x30, 4, 0x1, "ROM_ADDRESS" },
+ { 0, 0x34, 1, 0x3, "CAPABILITIES" },
+ { 0, 0x3c, 1, 0x3, "INTERRUPT_LINE" },
+ { 0, 0x3d, 1, 0x3, "INTERRUPT_PIN" },
+ { 0, 0x3e, 1, 0x1, "MIN_GNT" },
+ { 0, 0x3f, 1, 0x1, "MAX_LAT" },
+ { 0, 0x18, 1, 0x2, "PRIMARY_BUS" },
+ { 0, 0x19, 1, 0x2, "SECONDARY_BUS" },
+ { 0, 0x1a, 1, 0x2, "SUBORDINATE_BUS" },
+ { 0, 0x1b, 1, 0x2, "SEC_LATENCY_TIMER" },
+ { 0, 0x1c, 1, 0x2, "IO_BASE" },
+ { 0, 0x1d, 1, 0x2, "IO_LIMIT" },
+ { 0, 0x1e, 2, 0x2, "SEC_STATUS" },
+ { 0, 0x20, 2, 0x2, "MEMORY_BASE" },
+ { 0, 0x22, 2, 0x2, "MEMORY_LIMIT" },
+ { 0, 0x24, 2, 0x2, "PREF_MEMORY_BASE" },
+ { 0, 0x26, 2, 0x2, "PREF_MEMORY_LIMIT" },
+ { 0, 0x28, 4, 0x2, "PREF_BASE_UPPER32" },
+ { 0, 0x2c, 4, 0x2, "PREF_LIMIT_UPPER32" },
+ { 0, 0x30, 2, 0x2, "IO_BASE_UPPER16" },
+ { 0, 0x32, 2, 0x2, "IO_LIMIT_UPPER16" },
+ { 0, 0x38, 4, 0x2, "BRIDGE_ROM_ADDRESS" },
+ { 0, 0x3e, 2, 0x2, "BRIDGE_CONTROL" },
+ { 0, 0x10, 4, 0x4, "CB_CARDBUS_BASE" },
+ { 0, 0x14, 2, 0x4, "CB_CAPABILITIES" },
+ { 0, 0x16, 2, 0x4, "CB_SEC_STATUS" },
+ { 0, 0x18, 1, 0x4, "CB_BUS_NUMBER" },
+ { 0, 0x19, 1, 0x4, "CB_CARDBUS_NUMBER" },
+ { 0, 0x1a, 1, 0x4, "CB_SUBORDINATE_BUS" },
+ { 0, 0x1b, 1, 0x4, "CB_CARDBUS_LATENCY" },
+ { 0, 0x1c, 4, 0x4, "CB_MEMORY_BASE_0" },
+ { 0, 0x20, 4, 0x4, "CB_MEMORY_LIMIT_0" },
+ { 0, 0x24, 4, 0x4, "CB_MEMORY_BASE_1" },
+ { 0, 0x28, 4, 0x4, "CB_MEMORY_LIMIT_1" },
+ { 0, 0x2c, 2, 0x4, "CB_IO_BASE_0" },
+ { 0, 0x2e, 2, 0x4, "CB_IO_BASE_0_HI" },
+ { 0, 0x30, 2, 0x4, "CB_IO_LIMIT_0" },
+ { 0, 0x32, 2, 0x4, "CB_IO_LIMIT_0_HI" },
+ { 0, 0x34, 2, 0x4, "CB_IO_BASE_1" },
+ { 0, 0x36, 2, 0x4, "CB_IO_BASE_1_HI" },
+ { 0, 0x38, 2, 0x4, "CB_IO_LIMIT_1" },
+ { 0, 0x3a, 2, 0x4, "CB_IO_LIMIT_1_HI" },
+ { 0, 0x40, 2, 0x4, "CB_SUBSYSTEM_VENDOR_ID" },
+ { 0, 0x42, 2, 0x4, "CB_SUBSYSTEM_ID" },
+ { 0, 0x44, 4, 0x4, "CB_LEGACY_MODE_BASE" },
+ { 0x10001, 0, 0, 0x0, "CAP_PM" },
+ { 0x10002, 0, 0, 0x0, "CAP_AGP" },
+ { 0x10003, 0, 0, 0x0, "CAP_VPD" },
+ { 0x10004, 0, 0, 0x0, "CAP_SLOTID" },
+ { 0x10005, 0, 0, 0x0, "CAP_MSI" },
+ { 0x10006, 0, 0, 0x0, "CAP_CHSWP" },
+ { 0x10007, 0, 0, 0x0, "CAP_PCIX" },
+ { 0x10008, 0, 0, 0x0, "CAP_HT" },
+ { 0x10009, 0, 0, 0x0, "CAP_VNDR" },
+ { 0x1000a, 0, 0, 0x0, "CAP_DBG" },
+ { 0x1000b, 0, 0, 0x0, "CAP_CCRC" },
+ { 0x1000c, 0, 0, 0x0, "CAP_HOTPLUG" },
+ { 0x1000d, 0, 0, 0x0, "CAP_SSVID" },
+ { 0x1000e, 0, 0, 0x0, "CAP_AGP3" },
+ { 0x1000f, 0, 0, 0x0, "CAP_SECURE" },
+ { 0x10010, 0, 0, 0x0, "CAP_EXP" },
+ { 0x10011, 0, 0, 0x0, "CAP_MSIX" },
+ { 0x10012, 0, 0, 0x0, "CAP_SATA" },
+ { 0x10013, 0, 0, 0x0, "CAP_AF" },
+ { 0x10014, 0, 0, 0x0, "CAP_EA" },
+ { 0x20001, 0, 0, 0x0, "ECAP_AER" },
+ { 0x20002, 0, 0, 0x0, "ECAP_VC" },
+ { 0x20003, 0, 0, 0x0, "ECAP_DSN" },
+ { 0x20004, 0, 0, 0x0, "ECAP_PB" },
+ { 0x20005, 0, 0, 0x0, "ECAP_RCLINK" },
+ { 0x20006, 0, 0, 0x0, "ECAP_RCILINK" },
+ { 0x20007, 0, 0, 0x0, "ECAP_RCEC" },
+ { 0x20008, 0, 0, 0x0, "ECAP_MFVC" },
+ { 0x20009, 0, 0, 0x0, "ECAP_VC2" },
+ { 0x2000a, 0, 0, 0x0, "ECAP_RBCB" },
+ { 0x2000b, 0, 0, 0x0, "ECAP_VNDR" },
+ { 0x2000d, 0, 0, 0x0, "ECAP_ACS" },
+ { 0x2000e, 0, 0, 0x0, "ECAP_ARI" },
+ { 0x2000f, 0, 0, 0x0, "ECAP_ATS" },
+ { 0x20010, 0, 0, 0x0, "ECAP_SRIOV" },
+ { 0x20011, 0, 0, 0x0, "ECAP_MRIOV" },
+ { 0x20012, 0, 0, 0x0, "ECAP_MCAST" },
+ { 0x20013, 0, 0, 0x0, "ECAP_PRI" },
+ { 0x20015, 0, 0, 0x0, "ECAP_REBAR" },
+ { 0x20016, 0, 0, 0x0, "ECAP_DPA" },
+ { 0x20017, 0, 0, 0x0, "ECAP_TPH" },
+ { 0x20018, 0, 0, 0x0, "ECAP_LTR" },
+ { 0x20019, 0, 0, 0x0, "ECAP_SECPCI" },
+ { 0x2001a, 0, 0, 0x0, "ECAP_PMUX" },
+ { 0x2001b, 0, 0, 0x0, "ECAP_PASID" },
+ { 0x2001c, 0, 0, 0x0, "ECAP_LNR" },
+ { 0x2001d, 0, 0, 0x0, "ECAP_DPC" },
+ { 0x2001e, 0, 0, 0x0, "ECAP_L1PM" },
+ { 0x2001f, 0, 0, 0x0, "ECAP_PTM" },
+ { 0x20020, 0, 0, 0x0, "ECAP_M_PCIE" },
+ { 0x20021, 0, 0, 0x0, "ECAP_FRS" },
+ { 0x20022, 0, 0, 0x0, "ECAP_RTR" },
+ { 0x20023, 0, 0, 0x0, "ECAP_DVSEC" },
+ { 0x20024, 0, 0, 0x0, "ECAP_VF_REBAR" },
+ { 0x20025, 0, 0, 0x0, "ECAP_DLNK" },
+ { 0x20026, 0, 0, 0x0, "ECAP_16GT" },
+ { 0x20027, 0, 0, 0x0, "ECAP_LMR" },
+ { 0x20028, 0, 0, 0x0, "ECAP_HIER_ID" },
+ { 0x20029, 0, 0, 0x0, "ECAP_NPEM" },
+ { 0, 0, 0, 0x0, NULL }
};
static void
@@ -615,6 +625,8 @@ static void parse_register(struct op *op, char *base)
}
op->cap_id = r->cap & 0xffff;
op->addr = r->offset;
+ op->hdr_type_mask = r->hdr_type_mask;
+ op->name = r->name;
if (r->width && !op->width)
op->width = r->width;
return;