X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=setpci.c;h=d2df573400205b268792c162a45758b6c5037bc8;hb=2e05a86bf0c9d3d383f93517581395a1d2f17b6f;hp=1a0a73681bfffe002769935daf847dd04ccad5c0;hpb=13b4913199b513b9cdce1ac05c7237e9cb31b8e2;p=pciutils.git diff --git a/setpci.c b/setpci.c index 1a0a736..d2df573 100644 --- a/setpci.c +++ b/setpci.c @@ -3,7 +3,9 @@ * * Copyright (c) 1998--2020 Martin Mares * - * Can be freely distributed and used under the terms of the GNU GPL. + * Can be freely distributed and used under the terms of the GNU GPL v2+. + * + * SPDX-License-Identifier: GPL-2.0-or-later */ #include @@ -33,6 +35,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 +148,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; inum_values; i++) @@ -256,135 +267,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 +627,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;