]> mj.ucw.cz Git - pciutils.git/commitdiff
Preliminary support for PCI domains
authorMartin Mares <mj@ucw.cz>
Sat, 27 Dec 2003 21:33:12 +0000 (21:33 +0000)
committerMartin Mares <mj@ucw.cz>
Fri, 5 May 2006 12:18:16 +0000 (14:18 +0200)
git-archimport-id: mj@ucw.cz--public/pciutils--main--2.2--patch-34

12 files changed:
ChangeLog
TODO
lib/access.c
lib/dump.c
lib/filter.c
lib/generic.c
lib/internal.h
lib/pci.h
lib/proc.c
lib/sysfs.c
lspci.c
setpci.c

index 1e51c6c76d7b2aaf1f01237545f24ae4487ef738..3b77271338a9e1fd78755fd351e943053b9351c5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,27 @@
 2003-12-27  Martin Mares  <mj@ucw.cz>
 
+       * lspci.c: Devices in domains different from 0 have their slot number
+       printed as "<domain>:<bus>:<slot>.<func>".
+
+       * lib/filter.c: Slot filters understand domains.
+
+       * lib/generic.c: Mention the domain in slot numbers in all error messages.
+
+       * lib/internal.h: The #ifdef for Linux <asm/byteorder.h> was wrong.
+
+       * lib/access.c (pci_get_dev): Added support for domains.
+
+       * lib/sysfs.c (sysfs_scan): Read vendor and device ID from the config
+       registers (or to be precise, leave it for the generic parts of the pcilib
+       to do so) instead of reading them from the sysfs. It's faster this way.
+
+       * lspci.c (show_pcix): Don't touch pci_dev->hdrtype, it's an internal
+       variable. Better read it from the config registers (it's cached anyway).
+
+       * lib/sysfs.c (sysfs_scan), lib/proc.c (proc_scan): Don't read the hdrtype.
+         lib/generic.c (pci_generic_fill_info): If hdrtype is -1 (unset), read it.
+         Saves lots of unnecessary file accesses.
+
        * lib/pci.h (PCIADDR_PORT_FMT): Use %llx instead of %Lx, because the latter
        is not supported by all C libraries.
 
diff --git a/TODO b/TODO
index 86c2b090a0d51347ae4be27de7480e378ec521a1..9e39125e2a990d7916aa69afcd9e9b512f9589cb 100644 (file)
--- a/TODO
+++ b/TODO
@@ -6,5 +6,7 @@
 - names.c: rewrite
 
 - support for domains:
-       - pci_get_dev
-       - filters
+       - filters: doc and helps
+       - reading of dumps
+       - tree view
+       - map mode
index 55060b5dd79f6c0e0ec6d1fdf6d11cde1e927dc0..eee22d2d8b07221675436eec5b15d90805befbb5 100644 (file)
@@ -194,6 +194,7 @@ pci_alloc_dev(struct pci_access *a)
   bzero(d, sizeof(*d));
   d->access = a;
   d->methods = a->methods;
+  d->hdrtype = -1;
   if (d->methods->init_dev)
     d->methods->init_dev(d);
   return d;
@@ -209,10 +210,11 @@ pci_link_dev(struct pci_access *a, struct pci_dev *d)
 }
 
 struct pci_dev *
-pci_get_dev(struct pci_access *a, int bus, int dev, int func)
+pci_get_dev(struct pci_access *a, int domain, int bus, int dev, int func)
 {
   struct pci_dev *d = pci_alloc_dev(a);
 
+  d->domain = domain;
   d->bus = bus;
   d->dev = dev;
   d->func = func;
index 90293e44e98bd9f0dfdd63586910584485c930de..d3b154f0f79d455051bce634eb14302c27b04d7d 100644 (file)
@@ -44,7 +44,7 @@ dump_init(struct pci_access *a)
       if (len >= 8 && buf[2] == ':' && buf[5] == '.' && buf[7] == ' ' &&
          sscanf(buf, "%x:%x.%d ", &bn, &dn, &fn) == 3)
        {
-         dev = pci_get_dev(a, bn, dn, fn);
+         dev = pci_get_dev(a, 0, bn, dn, fn);
          dev->aux = pci_malloc(a, 256);
          memset(dev->aux, 0xff, 256);
          pci_link_dev(a, dev);
index 848eed23ff9e001396b50c69fe852c18146ac43b..e66a470e075dc2617edb12b0a281d09e13b2c472 100644 (file)
 void
 pci_filter_init(struct pci_access *a UNUSED, struct pci_filter *f)
 {
-  f->bus = f->slot = f->func = -1;
+  f->domain = f->bus = f->slot = f->func = -1;
   f->vendor = f->device = -1;
 }
 
-/* Slot filter syntax: [[bus]:][slot][.[func]] */
+/* Slot filter syntax: [[[domain]:][bus]:][slot][.[func]] */
 
 char *
 pci_filter_parse_slot(struct pci_filter *f, char *str)
 {
-  char *colon = strchr(str, ':');
+  char *colon = strrchr(str, ':');
   char *dot = strchr((colon ? colon + 1 : str), '.');
   char *mid = str;
-  char *e;
+  char *e, *bus, *colon2;
 
   if (colon)
     {
       *colon++ = 0;
       mid = colon;
-      if (str[0] && strcmp(str, "*"))
+      colon2 = strchr(str, ':');
+      if (colon2)
        {
-         long int x = strtol(str, &e, 16);
+         *colon2++ = 0;
+         bus = colon2;
+         if (str[0] && strcmp(str, "*"))
+           {
+             long int x = strtol(bus, &e, 16);
+             if ((e && *e) || (x < 0 || x > 0xffff))
+               return "Invalid domain number";
+             f->domain = x;
+           }
+       }
+      else
+       bus = str;
+      if (bus[0] && strcmp(bus, "*"))
+       {
+         long int x = strtol(bus, &e, 16);
          if ((e && *e) || (x < 0 || x > 0xff))
            return "Invalid bus number";
          f->bus = x;
@@ -92,7 +107,8 @@ pci_filter_parse_id(struct pci_filter *f, char *str)
 int
 pci_filter_match(struct pci_filter *f, struct pci_dev *d)
 {
-  if ((f->bus >= 0 && f->bus != d->bus) ||
+  if ((f->domain >= 0 && f->domain != d->domain) ||
+      (f->bus >= 0 && f->bus != d->bus) ||
       (f->slot >= 0 && f->slot != d->dev) ||
       (f->func >= 0 && f->func != d->func))
     return 0;
index d4f26000f87c5fbaca8bedccc0cef4a8b1f3e3a5..25d3faab2d65923b484d86cf1b9e4f6e799e7e22 100644 (file)
@@ -58,7 +58,7 @@ pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
              pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
              break;
            default:
-             a->debug("Device %02x:%02x.%d has unknown header type %02x.\n", d->bus, d->dev, d->func, ht);
+             a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht);
            }
        }
     }
@@ -79,6 +79,8 @@ pci_generic_fill_info(struct pci_dev *d, int flags)
 {
   struct pci_access *a = d->access;
 
+  if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0)
+    d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE);
   if (flags & PCI_FILL_IDENT)
     {
       d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
@@ -121,7 +123,7 @@ pci_generic_fill_info(struct pci_dev *d, int flags)
                  if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
                    {
                      if (i >= cnt-1)
-                       a->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d->bus, d->dev, d->func);
+                       a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen.", d->domain, d->bus, d->dev, d->func);
                      else
                        {
                          u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
@@ -130,7 +132,7 @@ pci_generic_fill_info(struct pci_dev *d, int flags)
 #else
                          if (y)
                            {
-                             a->warning("%02x:%02x.%d 64-bit device address ignored.", d->bus, d->dev, d->func);
+                             a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func);
                              d->base_addr[i-1] = 0;
                            }
 #endif
index b18ccd17acfc2401b7ab7a473b35128d9a91c0b1..41ad612b62ade899fa446e3b3403af7c9b8a3347 100644 (file)
@@ -15,7 +15,7 @@
 #define inline
 #endif
 
-#ifdef HAVE_PM_LINUX_BYTEORDER_H
+#ifdef HAVE_LINUX_BYTEORDER_H
 
 #include <asm/byteorder.h>
 #define cpu_to_le16 __cpu_to_le16
index 50c29615b314de78402a4821bc23939b4edc1ea9..b031f53b705c371b57cb58780d554d7db08b3662 100644 (file)
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -106,7 +106,7 @@ void pci_cleanup(struct pci_access *);
 
 /* Scanning of devices */
 void pci_scan_bus(struct pci_access *acc);
-struct pci_dev *pci_get_dev(struct pci_access *acc, int bus, int dev, int func); /* Raw access to specified device */
+struct pci_dev *pci_get_dev(struct pci_access *acc, int domain, int bus, int dev, int func); /* Raw access to specified device */
 void pci_free_dev(struct pci_dev *);
 
 /*
@@ -115,9 +115,8 @@ void pci_free_dev(struct pci_dev *);
 
 struct pci_dev {
   struct pci_dev *next;                        /* Next device in the chain */
-  word domain;                         /* PCI domain (host bridge) */
-  byte bus;                            /* Bus inside domain */
-  byte dev, func;                      /* Device and function */
+  u16 domain;                          /* PCI domain (host bridge) */
+  byte bus, dev, func;                 /* Bus inside domain, device and function */
 
   /* These fields are set by pci_fill_info() */
   int known_fields;                    /* Set of info fields already known */
@@ -131,9 +130,9 @@ struct pci_dev {
   /* Fields used internally: */
   struct pci_access *access;
   struct pci_methods *methods;
-  byte *cache;                         /* Cached information */
+  byte *cache;                         /* Cached config registers */
   int cache_len;
-  int hdrtype;                         /* Direct methods: header type */
+  int hdrtype;                         /* Cached header type, -1 if unknown */
   void *aux;                           /* Auxillary data */
 };
 
@@ -165,7 +164,7 @@ void pci_setup_cache(struct pci_dev *, byte *cache, int len);
  */
 
 struct pci_filter {
-  int bus, slot, func;                 /* -1 = ANY */
+  int domain, bus, slot, func;                 /* -1 = ANY */
   int vendor, device;
 };
 
index 8afe7a3bd3197936d7b0b95485ed5045bddbb083..0262143a7b62a4e95561574c919b1429013788cf 100644 (file)
@@ -97,7 +97,6 @@ proc_scan(struct pci_access *a)
       d->func = PCI_FUNC(dfn & 0xff);
       d->vendor_id = vend >> 16U;
       d->device_id = vend & 0xffff;
-      d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
       known = PCI_FILL_IDENT;
       if (!a->buscentric)
        {
index 70511b1fc3eed79f2e63bf614409afd2698b9e40..c0cf5a3bfef5202db1f69a689fbee9811e03b0ef 100644 (file)
@@ -39,7 +39,7 @@ sysfs_detect(struct pci_access *a)
 {
   if (access(sysfs_name(a), R_OK))
     {
-      a->debug("Cannot open %s", sysfs_name(a));
+      a->debug("...cannot open %s", sysfs_name(a));
       return 0;
     }
   a->debug("...using %s", sysfs_name(a));
@@ -165,14 +165,22 @@ static void sysfs_scan(struct pci_access *a)
       d->bus = bus;
       d->dev = dev;
       d->func = func;
-      d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
       if (!a->buscentric)
        {
          sysfs_get_resources(d);
+         d->irq = sysfs_get_value(d, "irq");
+         d->known_fields = PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES;
+#if 0
+         /*
+          *  We prefer reading these from the config registers, it's faster.
+          *  However, it would be possible and maybe even useful to hack the kernel
+          *  to believe that some device has a different ID. If you do it, just
+          *  enable this piece of code.  --mj
+          */
          d->vendor_id = sysfs_get_value(d, "vendor");
          d->device_id = sysfs_get_value(d, "device");
-         d->irq = sysfs_get_value(d, "irq");
-         d->known_fields = PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES;
+         d->known_fields |= PCI_FILL_IDENT;
+#endif
        }
       pci_link_dev(a, d);
     }
diff --git a/lspci.c b/lspci.c
index 242f497e0795f900fa903a05b0f84153b180a5a2..2368cebd1580217dcecb482d543782bf5c17baa1 100644 (file)
--- a/lspci.c
+++ b/lspci.c
@@ -34,7 +34,7 @@ Usage: lspci [<switches>]\n\
 -b\t\tBus-centric view (PCI addresses and IRQ's instead of those seen by the CPU)\n\
 -x\t\tShow hex-dump of the standard portion of config space\n\
 -xxx\t\tShow hex-dump of the whole config space (dangerous; root only)\n\
--s [[<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n\
+-s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n\
 -d [<vendor>]:[<device>]\tShow only selected devices\n\
 -t\t\tShow bus tree\n\
 -m\t\tProduce machine-readable output\n\
@@ -160,6 +160,10 @@ compare_them(const void *A, const void *B)
   const struct pci_dev *a = (*(const struct device **)A)->dev;
   const struct pci_dev *b = (*(const struct device **)B)->dev;
 
+  if (a->domain < b->domain)
+    return -1;
+  if (a->domain > b->domain)
+    return 1;
   if (a->bus < b->bus)
     return -1;
   if (a->bus > b->bus)
@@ -204,6 +208,16 @@ sort_them(void)
 
 #define FLAG(x,y) ((x & y) ? '+' : '-')
 
+static void
+show_slot_name(struct device *d)
+{
+  struct pci_dev *p = d->dev;
+
+  if (p->domain)
+    printf("%04x:", p->domain);
+  printf("%02x:%02x.%d", p->bus, p->dev, p->func);
+}
+
 static void
 show_terse(struct device *d)
 {
@@ -211,10 +225,8 @@ show_terse(struct device *d)
   struct pci_dev *p = d->dev;
   byte classbuf[128], devbuf[128];
 
-  printf("%02x:%02x.%x %s: %s",
-        p->bus,
-        p->dev,
-        p->func,
+  show_slot_name(d);
+  printf(" %s: %s",
         pci_lookup_name(pacc, classbuf, sizeof(classbuf),
                         PCI_LOOKUP_CLASS,
                         get_conf_word(d, PCI_CLASS_DEVICE), 0, 0, 0),
@@ -531,7 +543,7 @@ show_pcix_bridge(struct device *d, int where)
 static void
 show_pcix(struct device *d, int where)
 {
-  switch (d->dev->hdrtype)
+  switch (get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f)
     {
     case PCI_HEADER_TYPE_NORMAL:
       show_pcix_nobridge(d, where);
@@ -996,7 +1008,9 @@ show_machine(struct device *d)
 
   if (verbose)
     {
-      printf("Device:\t%02x:%02x.%x\n", p->bus, p->dev, p->func);
+      printf("Device:\t");
+      show_slot_name(d);
+      putchar('\n');
       printf("Class:\t%s\n",
             pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, get_conf_word(d, PCI_CLASS_DEVICE), 0, 0, 0));
       printf("Vendor:\t%s\n",
@@ -1017,8 +1031,8 @@ show_machine(struct device *d)
     }
   else
     {
-      printf("%02x:%02x.%x ", p->bus, p->dev, p->func);
-      printf("\"%s\" \"%s\" \"%s\"",
+      show_slot_name(d);
+      printf(" \"%s\" \"%s\" \"%s\"",
             pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS,
                             get_conf_word(d, PCI_CLASS_DEVICE), 0, 0, 0),
             pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR,
@@ -1362,7 +1376,7 @@ do_map_bus(int bus)
        for(func = 0; func < func_limit; func++)
          if (filter.func < 0 || filter.func == func)
            {
-             struct pci_dev *p = pci_get_dev(pacc, bus, dev, func);
+             struct pci_dev *p = pci_get_dev(pacc, 0, bus, dev, func);
              u16 vendor = pci_read_word(p, PCI_VENDOR_ID);
              if (vendor && vendor != 0xffff)
                {
index ce324735477365d6c66cea2f3b12be49672be2cf..9c781760063141f6890e1973e46593721d065c8b 100644 (file)
--- a/setpci.c
+++ b/setpci.c
@@ -261,7 +261,7 @@ usage(char *msg, ...)
 -v\t\tBe verbose\n\
 -D\t\tList changes, don't commit them\n"
 GENERIC_HELP
-"<device>:\t-s [[<bus>]:][<slot>][.[<func>]]\n"
+"<device>:\t-s [[[<domain>]:][<bus>]:][<slot>][.[<func>]]\n"
 "\t|\t-d [<vendor>]:[<device>]\n"
 "<reg>:\t\t<number>[.(B|W|L)]\n"
 "     |\t\t<name>\n"