]> mj.ucw.cz Git - pciutils.git/blobdiff - setpci.c
Cleaned up pci_find_cap_nr()
[pciutils.git] / setpci.c
index 5f8f658e846838d70edc1781d2397435dcc6dbbe..13b6a6b4079538334a16eb099917748541e03d8c 100644 (file)
--- a/setpci.c
+++ b/setpci.c
@@ -10,7 +10,6 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
-#include <unistd.h>
 #include <errno.h>
 
 #define PCIUTILS_SETPCI
@@ -37,6 +36,7 @@ struct op {
   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];
 };
 
@@ -85,11 +85,19 @@ exec_op(struct op *op, struct pci_dev *dev)
   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;
@@ -223,7 +231,7 @@ static const struct reg_name pci_reg_names[] = {
   {       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" },
@@ -302,6 +310,7 @@ static const struct reg_name pci_reg_names[] = {
   { 0x2000e,   0, 0, "ECAP_ARI" },
   { 0x2000f,   0, 0, "ECAP_ATS" },
   { 0x20010,   0, 0, "ECAP_SRIOV" },
+  { 0x2001d,   0, 0, "ECAP_DPC" },
   {       0,    0, 0, NULL }
 };
 
@@ -341,7 +350,7 @@ GENERIC_HELP
 "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"
@@ -374,10 +383,15 @@ parse_options(int argc, char **argv)
       if (!strcmp(argv[1], "--help"))
        usage();
       if (!strcmp(argv[1], "--version"))
-       puts("setpci version " PCIUTILS_VERSION);
+       {
+         puts("setpci version " PCIUTILS_VERSION);
+         exit(0);
+       }
       if (!strcmp(argv[1], "--dumpregs"))
-       dump_registers();
-      exit(0);
+       {
+         dump_registers();
+         exit(0);
+       }
     }
 
   while (i < argc && argv[i][0] == '-')
@@ -477,11 +491,12 @@ static const struct reg_name *parse_reg_name(char *name)
 static int parse_x32(char *c, char **stopp, unsigned int *resp)
 {
   char *stop;
+  unsigned long int l;
 
   if (!*c)
     return -1;
   errno = 0;
-  unsigned long int l = strtoul(c, &stop, 16);
+  l = strtoul(c, &stop, 16);
   if (errno)
     return -1;
   if ((l & ~0U) != l)
@@ -494,7 +509,11 @@ static int parse_x32(char *c, char **stopp, unsigned int *resp)
       return 0;
     }
   else
-    return 1;
+    {
+      if (stopp)
+       *stopp = NULL;
+      return 1;
+    }
 }
 
 static void parse_register(struct op *op, char *base)
@@ -547,7 +566,7 @@ static void parse_register(struct op *op, char *base)
 
 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;
@@ -556,6 +575,8 @@ static void parse_op(char *c, struct pci_dev **selected_devices)
   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, '+'))
@@ -598,6 +619,18 @@ static void parse_op(char *c, struct pci_dev **selected_devices)
   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)
@@ -625,17 +658,17 @@ static void parse_op(char *c, struct pci_dev **selected_devices)
       e = strchr(value, ',');
       if (e)
        *e++ = 0;
-      if (parse_x32(value, &f, &ll) < 0 || *f && *f != ':')
+      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 == ':')
+      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;