#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
-#include <unistd.h>
#include <errno.h>
#define PCIUTILS_SETPCI
unsigned int addr;
unsigned int width; /* Byte width of the access */
unsigned int num_values; /* Number of values to write; 0=read */
+ unsigned int number; /* The n-th capability of that id */
struct value values[0];
};
if (op->cap_type)
{
struct pci_cap *cap;
- cap = pci_find_cap(dev, op->cap_id, op->cap_type);
+ unsigned int cap_nr = op->number;
+ cap = pci_find_cap_nr(dev, op->cap_id, op->cap_type, &cap_nr);
if (cap)
- addr = cap->addr;
+ addr = cap->addr;
+ else if (cap_nr == 0)
+ die("%s: Instance #%d of %s %04x not found - there are no capabilities with that id.", slot,
+ op->number, ((op->cap_type == PCI_CAP_NORMAL) ? "Capability" : "Extended capability"),
+ op->cap_id);
else
- die("%s: %s %04x not found", slot, ((op->cap_type == PCI_CAP_NORMAL) ? "Capability" : "Extended capability"), op->cap_id);
+ die("%s: Instance #%d of %s %04x not found - there %s only %d capability with that id.", slot,
+ op->number, ((op->cap_type == PCI_CAP_NORMAL) ? "Capability" : "Extended capability"),
+ op->cap_id, ((cap_nr == 1) ? "is" : "are"), cap_nr);
+
trace(((op->cap_type == PCI_CAP_NORMAL) ? "(cap %02x @%02x) " : "(ecap %04x @%03x) "), op->cap_id, addr);
}
addr += op->addr;
{ 0, 0x20, 4, "BASE_ADDRESS_4" },
{ 0, 0x24, 4, "BASE_ADDRESS_5" },
{ 0, 0x28, 4, "CARDBUS_CIS" },
- { 0, 0x2c, 4, "SUBSYSTEM_VENDOR_ID" },
+ { 0, 0x2c, 2, "SUBSYSTEM_VENDOR_ID" },
{ 0, 0x2e, 2, "SUBSYSTEM_ID" },
{ 0, 0x30, 4, "ROM_ADDRESS" },
{ 0, 0x3c, 1, "INTERRUPT_LINE" },
{ 0x2000e, 0, 0, "ECAP_ARI" },
{ 0x2000f, 0, 0, "ECAP_ATS" },
{ 0x20010, 0, 0, "ECAP_SRIOV" },
+ { 0x2001d, 0, 0, "ECAP_DPC" },
{ 0, 0, 0, NULL }
};
"Setting commands:\n"
"<device>:\t-s [[[<domain>]:][<bus>]:][<slot>][.[<func>]]\n"
"\t\t-d [<vendor>]:[<device>]\n"
-"<reg>:\t\t<base>[+<offset>][.(B|W|L)]\n"
+"<reg>:\t\t<base>[+<offset>][.(B|W|L)][@<number>]\n"
"<base>:\t\t<address>\n"
"\t\t<named-register>\n"
"\t\t[E]CAP_<capability-name>\n"
static void parse_op(char *c, struct pci_dev **selected_devices)
{
- char *base, *offset, *width, *value;
+ char *base, *offset, *width, *value, *number;
char *e, *f;
int n, j;
struct op *op;
base = xstrdup(c);
if (value = strchr(base, '='))
*value++ = 0;
+ if (number = strchr(base, '@'))
+ *number++ = 0;
if (width = strchr(base, '.'))
*width++ = 0;
if (offset = strchr(base, '+'))
else
op->width = 0;
+ /* Check which n-th capability of the same id we want */
+ if (number)
+ {
+ unsigned int num;
+ if (parse_x32(number, NULL, &num) <= 0 || (int) num < 0)
+ parse_err("Invalid number \"%s\"", number);
+ op->number = num;
+
+ }
+ else
+ op->number = 0;
+
/* Find the register */
parse_register(op, base);
if (!op->width)
if (parse_x32(value, &f, &ll) < 0 || f && *f != ':')
parse_err("Invalid value \"%s\"", value);
lim = max_values[op->width];
- if (ll > lim && ll < ~0UL - lim)
+ if (ll > lim && ll < ~0U - lim)
parse_err("Value \"%s\" is out of range", value);
op->values[j].value = ll;
if (f && *f == ':')
{
if (parse_x32(f+1, NULL, &ll) <= 0)
parse_err("Invalid mask \"%s\"", f+1);
- if (ll > lim && ll < ~0UL - lim)
+ if (ll > lim && ll < ~0U - lim)
parse_err("Mask \"%s\" is out of range", f+1);
op->values[j].mask = ll;
op->values[j].value &= ll;