]> mj.ucw.cz Git - pciutils.git/blobdiff - setpci.c
setpci: Even better tracing messages.
[pciutils.git] / setpci.c
index 7e84acbf6ebb70698d3365ef6df5915407acadf6..50d2a898c7bb81db3c641108134adbd931f2fe16 100644 (file)
--- a/setpci.c
+++ b/setpci.c
@@ -32,7 +32,8 @@ struct value {
 struct op {
   struct op *next;
   struct pci_dev **dev_vector;
-  unsigned int cap;                    /* Capability: 0=none, 10000-100ff=normal, 20000-2ffff=extended */
+  u16 cap_type;                                /* PCI_CAP_xxx or 0 */
+  u16 cap_id;
   unsigned int addr;
   unsigned int width;                  /* Byte width of the access */
   unsigned int num_values;             /* Number of values to write; 0=read */
@@ -59,57 +60,55 @@ select_devices(struct pci_filter *filt)
   return b;
 }
 
+static void
+trace(const char *fmt, ...)
+{
+  va_list args;
+  va_start(args, fmt);
+  if (verbose)
+    vprintf(fmt, args);
+  va_end(args);
+}
+
 static void
 exec_op(struct op *op, struct pci_dev *dev)
 {
-  char *formats[] = { NULL, "%02x", "%04x", NULL, "%08x" };
-  char *mask_formats[] = { NULL, "%02x->(%02x:%02x)->%02x", "%04x->(%04x:%04x)->%04x", NULL, "%08x->(%08x:%08x)->%08x" };
+  const char * const formats[] = { NULL, " %02x", " %04x", NULL, " %08x" };
+  const char * const mask_formats[] = { NULL, " %02x->(%02x:%02x)->%02x", " %04x->(%04x:%04x)->%04x", NULL, " %08x->(%08x:%08x)->%08x" };
   unsigned int i, x, y;
   int addr = 0;
   int width = op->width;
+  char slot[16];
 
-  if (verbose)
-    printf("%02x:%02x.%x", dev->bus, dev->dev, dev->func);
-  if (op->cap)
+  sprintf(slot, "%04x:%02x:%02x.%x", dev->domain, dev->bus, dev->dev, dev->func);
+  trace("%s ", slot);
+  if (op->cap_type)
     {
       struct pci_cap *cap;
-      if (op->cap < 0x20000)
-       {
-         if (verbose)
-           printf("(cap %02x)", op->cap - 0x10000);
-         cap = pci_find_cap(dev, op->cap - 0x10000, PCI_CAP_NORMAL);
-       }
-      else
-       {
-         if (verbose)
-           printf("(ecap %04x)", op->cap - 0x20000);
-         cap = pci_find_cap(dev, op->cap - 0x20000, PCI_CAP_EXTENDED);
-       }
+      cap = pci_find_cap(dev, op->cap_id, op->cap_type);
       if (cap)
        addr = cap->addr;
       else
-       {
-         /* FIXME: Report the error properly */
-         die("Capability %08x not found", op->cap);
-       }
+       die("%s: %s %04x not found", slot, ((op->cap_type == PCI_CAP_NORMAL) ? "Capability" : "Extended capability"), op->cap_id);
+      trace(((op->cap_type == PCI_CAP_NORMAL) ? "(cap %02x @%02x) " : "(ecap %04x @%03x) "), op->cap_id, addr);
     }
   addr += op->addr;
-  if (verbose)
-    printf(":%02x", addr);
+  trace("@%02x", addr);
+
+  /* We have already checked it when parsing, but addressing relative to capabilities can change the address. */
+  if (addr & (width-1))
+    die("%s: Unaligned access of width %d to register %04x", slot, width, addr);
+  if (addr + width > 0x1000)
+    die("%s: Access of width %d to register %04x out of range", slot, width, addr);
+
   if (op->num_values)
     {
       for (i=0; i<op->num_values; i++)
        {
-         if (addr + width > 0x1000)
-           die("Out of range");        /* FIXME */
          if ((op->values[i].mask & max_values[width]) == max_values[width])
            {
              x = op->values[i].value;
-             if (verbose)
-               {
-                 putchar(' ');
-                 printf(formats[width], op->values[i].value);
-               }
+             trace(formats[width], op->values[i].value);
            }
          else
            {
@@ -126,11 +125,7 @@ exec_op(struct op *op, struct pci_dev *dev)
                  break;
                }
              x = (y & ~op->values[i].mask) | op->values[i].value;
-             if (verbose)
-               {
-                 putchar(' ');
-                 printf(mask_formats[width], y, op->values[i].value, op->values[i].mask, x);
-               }
+             trace(mask_formats[width], y, op->values[i].value, op->values[i].mask, x);
            }
          if (!demo_mode)
            {
@@ -149,15 +144,11 @@ exec_op(struct op *op, struct pci_dev *dev)
            }
          addr += width;
        }
-      if (verbose)
-       putchar('\n');
+      trace("\n");
     }
   else
     {
-      if (verbose)
-       printf(" = ");
-      if (addr + width > 0x1000)
-       die("Out of range");    /* FIXME */
+      trace(" = ");
       switch (width)
        {
        case 1:
@@ -170,7 +161,7 @@ exec_op(struct op *op, struct pci_dev *dev)
          x = pci_read_long(dev, addr);
          break;
        }
-      printf(formats[width], x);
+      printf(formats[width]+1, x);
       putchar('\n');
     }
 }
@@ -196,6 +187,8 @@ execute(struct op *op)
 static void
 scan_ops(struct op *op)
 {
+  if (demo_mode)
+    return;
   while (op)
     {
       if (op->num_values)
@@ -504,15 +497,23 @@ static int parse_x32(char *c, char **stopp, unsigned int *resp)
 static void parse_register(struct op *op, char *base)
 {
   const struct reg_name *r;
+  unsigned int cap;
 
+  op->cap_type = op->cap_id = 0;
   if (parse_x32(base, NULL, &op->addr) > 0)
-    {
-      op->cap = 0;
-      return;
-    }
+    return;
   else if (r = parse_reg_name(base))
     {
-      op->cap = r->cap;
+      switch (r->cap & 0xff0000)
+       {
+       case 0x10000:
+         op->cap_type = PCI_CAP_NORMAL;
+         break;
+       case 0x20000:
+         op->cap_type = PCI_CAP_EXTENDED;
+         break;
+       }
+      op->cap_id = r->cap & 0xffff;
       op->addr = r->offset;
       if (r->width && !op->width)
        op->width = r->width;
@@ -520,18 +521,20 @@ static void parse_register(struct op *op, char *base)
     }
   else if (!strncasecmp(base, "CAP", 3))
     {
-      if (parse_x32(base+3, NULL, &op->cap) > 0 && op->cap < 0x100)
+      if (parse_x32(base+3, NULL, &cap) > 0 && cap < 0x100)
        {
-         op->cap += 0x10000;
+         op->cap_type = PCI_CAP_NORMAL;
+         op->cap_id = cap;
          op->addr = 0;
          return;
        }
     }
   else if (!strncasecmp(base, "ECAP", 4))
     {
-      if (parse_x32(base+4, NULL, &op->cap) > 0 && op->cap < 0x1000)
+      if (parse_x32(base+4, NULL, &cap) > 0 && cap < 0x1000)
        {
-         op->cap += 0x20000;
+         op->cap_type = PCI_CAP_EXTENDED;
+         op->cap_id = cap;
          op->addr = 0;
          return;
        }