]> mj.ucw.cz Git - pciutils.git/blobdiff - lspci.c
By mistake, we were setting PCI_USE_DNS on Linux automatically.
[pciutils.git] / lspci.c
diff --git a/lspci.c b/lspci.c
index f933235e5e9c551720b217f3c1ec99735abb533f..0515fcd6ad8d89c64bcc54fdf5d61da73163285b 100644 (file)
--- a/lspci.c
+++ b/lspci.c
@@ -1,7 +1,7 @@
 /*
  *     The PCI Utilities -- List All PCI Devices
  *
- *     Copyright (c) 1997--2007 Martin Mares <mj@ucw.cz>
+ *     Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -12,6 +12,7 @@
 #include <stdarg.h>
 #include <unistd.h>
 
+#define PCIUTILS_LSPCI
 #include "pciutils.h"
 
 /* Options */
@@ -24,34 +25,54 @@ static int opt_tree;                        /* Show bus tree */
 static int opt_machine;                        /* Generate machine-readable output */
 static int opt_map_mode;               /* Bus mapping mode enabled */
 static int opt_domains;                        /* Show domain numbers (0=disabled, 1=auto-detected, 2=requested) */
+static int opt_kernel;                 /* Show kernel drivers */
+static int opt_query_dns;              /* Query the DNS (0=disabled, 1=enabled, 2=refresh cache) */
+static int opt_query_all;              /* Query the DNS for all entries */
 static char *opt_pcimap;               /* Override path to Linux modules.pcimap */
 
 const char program_name[] = "lspci";
 
-static char options[] = "nvbxs:d:ti:mgp:MD" GENERIC_OPTIONS ;
-
-static char help_msg[] = "\
-Usage: lspci [<switches>]\n\
-\n\
--v\t\tBe verbose\n\
--n\t\tShow numeric ID's\n\
--nn\t\tShow both textual and numeric ID's (names & numbers)\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\
--xxxx\t\tShow hex-dump of the 4096-byte extended config space (root only)\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\
--i <file>\tUse specified ID database instead of %s\n"
+static char options[] = "nvbxs:d:ti:mgp:qkMDQ" GENERIC_OPTIONS ;
+
+static char help_msg[] =
+"Usage: lspci [<switches>]\n"
+"\n"
+"Basic display modes:\n"
+"-mm\t\tProduce machine-readable output (single -m for an obsolete format)\n"
+"-t\t\tShow bus tree\n"
+"\n"
+"Display options:\n"
+"-v\t\tBe verbose (-vv for very verbose)\n"
 #ifdef PCI_OS_LINUX
-"\
--p <file>\tLook up kernel modules in a given file instead of default modules.pcimap\n"
+"-k\t\tShow kernel drivers handling each device\n"
 #endif
-"\
--D\t\tAlways show domain numbers\n\
--M\t\tEnable `bus mapping' mode (dangerous; root only)\n"
+"-x\t\tShow hex-dump of the standard part of the config space\n"
+"-xxx\t\tShow hex-dump of the whole config space (dangerous; root only)\n"
+"-xxxx\t\tShow hex-dump of the 4096-byte extended config space (root only)\n"
+"-b\t\tBus-centric view (addresses and IRQ's as seen by the bus)\n"
+"-D\t\tAlways show domain numbers\n"
+"\n"
+"Resolving of device ID's to names:\n"
+"-n\t\tShow numeric ID's\n"
+"-nn\t\tShow both textual and numeric ID's (names & numbers)\n"
+#ifdef PCI_USE_DNS
+"-q\t\tQuery the PCI ID database for unknown ID's via DNS\n"
+"-qq\t\tAs above, but re-query locally cached entries\n"
+"-Q\t\tQuery the PCI ID database for all ID's via DNS\n"
+#endif
+"\n"
+"Selection of devices:\n"
+"-s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n"
+"-d [<vendor>]:[<device>]\t\t\tShow only devices with specified ID's\n"
+"\n"
+"Other options:\n"
+"-i <file>\tUse specified ID database instead of %s\n"
+#ifdef PCI_OS_LINUX
+"-p <file>\tLook up kernel modules in a given file instead of default modules.pcimap\n"
+#endif
+"-M\t\tEnable `bus mapping' mode (dangerous; root only)\n"
+"\n"
+"PCI access options:\n"
 GENERIC_HELP
 ;
 
@@ -1571,44 +1592,50 @@ match_pcimap(struct device *d, struct pcimap_entry *e)
 #undef MATCH
 }
 
-static void
-show_driver(struct device *d)
+#define DRIVER_BUF_SIZE 1024
+
+static char *
+find_driver(struct device *d, char *buf)
 {
   struct pci_dev *dev = d->dev;
-  char *base = dev->access->method_params[PCI_ACCESS_SYS_BUS_PCI];
-  char name[1024], driver[1024], *drv;
+  char name[1024], *drv, *base;
   int n;
 
   if (dev->access->method != PCI_ACCESS_SYS_BUS_PCI)
-    return;
+    return NULL;
+
+  base = pci_get_param(dev->access, "sysfs.path");
+  if (!base || !base[0])
+    return NULL;
 
   n = snprintf(name, sizeof(name), "%s/devices/%04x:%02x:%02x.%d/driver",
               base, dev->domain, dev->bus, dev->dev, dev->func);
-  if (n < 0 || n >= 1024)
+  if (n < 0 || n >= (int)sizeof(name))
     die("show_driver: sysfs device name too long, why?");
 
-  n = readlink(name, driver, sizeof(driver));
+  n = readlink(name, buf, DRIVER_BUF_SIZE);
   if (n < 0)
-    return;
-  if (n >= (int)sizeof(driver))
-    {
-      printf("\t!!! Driver name too long\n");
-      return;
-    }
-  driver[n] = 0;
+    return NULL;
+  if (n >= DRIVER_BUF_SIZE)
+    return "<name-too-long>";
+  buf[n] = 0;
 
-  if (drv = strrchr(driver, '/'))
-    drv++;
+  if (drv = strrchr(buf, '/'))
+    return drv+1;
   else
-    drv = driver;
-  printf("\tKernel driver in use: %s\n", drv);
+    return buf;
 }
 
 static void
-show_module(struct device *d)
+show_kernel(struct device *d)
 {
+  char buf[DRIVER_BUF_SIZE];
+  char *driver;
   struct pcimap_entry *e, *last = NULL;
 
+  if (driver = find_driver(d, buf))
+    printf("\tKernel driver in use: %s\n", driver);
+
   load_pcimap();
   for (e=pcimap_head; e; e=e->next)
     if (match_pcimap(d, e) && (!last || strcmp(last->module, e->module)))
@@ -1620,15 +1647,34 @@ show_module(struct device *d)
     putchar('\n');
 }
 
+static void
+show_kernel_machine(struct device *d)
+{
+  char buf[DRIVER_BUF_SIZE];
+  char *driver;
+  struct pcimap_entry *e, *last = NULL;
+
+  if (driver = find_driver(d, buf))
+    printf("Driver:\t%s\n", driver);
+
+  load_pcimap();
+  for (e=pcimap_head; e; e=e->next)
+    if (match_pcimap(d, e) && (!last || strcmp(last->module, e->module)))
+      {
+       printf("Module:\t%s\n", e->module);
+       last = e;
+      }
+}
+
 #else
 
 static void
-show_driver(void)
+show_kernel(struct device *d UNUSED)
 {
 }
 
 static void
-show_module(void)
+show_kernel_machine(struct device *d UNUSED)
 {
 }
 
@@ -2099,9 +2145,6 @@ show_verbose(struct device *d)
       show_htype2(d);
       break;
     }
-
-  show_driver(d);
-  show_module(d);
 }
 
 /*** Machine-readable dumps ***/
@@ -2174,6 +2217,8 @@ show_machine(struct device *d)
        printf("Rev:\t%02x\n", c);
       if (c = get_conf_byte(d, PCI_CLASS_PROG))
        printf("ProgIf:\t%02x\n", c);
+      if (opt_kernel)
+       show_kernel_machine(d);
     }
   else
     {
@@ -2203,10 +2248,15 @@ show_device(struct device *d)
 {
   if (opt_machine)
     show_machine(d);
-  else if (verbose)
-    show_verbose(d);
   else
-    show_terse(d);
+    {
+      if (verbose)
+       show_verbose(d);
+      else
+       show_terse(d);
+      if (opt_kernel || verbose)
+       show_kernel(d);
+    }
   if (opt_hex)
     show_hex_dump(d);
   if (verbose || opt_hex)
@@ -2691,12 +2741,29 @@ main(int argc, char **argv)
       case 'p':
        opt_pcimap = optarg;
        break;
+#ifdef PCI_OS_LINUX
+      case 'k':
+       opt_kernel++;
+       break;
+#endif
       case 'M':
        opt_map_mode++;
        break;
       case 'D':
        opt_domains = 2;
        break;
+#ifdef PCI_USE_DNS
+      case 'q':
+       opt_query_dns++;
+       break;
+      case 'Q':
+       opt_query_all = 1;
+       break;
+#else
+      case 'q':
+      case 'Q':
+       die("DNS queries are not available in this version");
+#endif
       default:
        if (parse_generic_option(i, pacc, optarg))
          break;
@@ -2707,6 +2774,15 @@ main(int argc, char **argv)
   if (optind < argc)
     goto bad;
 
+  if (opt_query_dns)
+    {
+      pacc->id_lookup_mode |= PCI_LOOKUP_NETWORK;
+      if (opt_query_dns > 1)
+       pacc->id_lookup_mode |= PCI_LOOKUP_REFRESH_CACHE;
+    }
+  if (opt_query_all)
+    pacc->id_lookup_mode |= PCI_LOOKUP_NETWORK | PCI_LOOKUP_SKIP_LOCAL;
+
   pci_init(pacc);
   if (opt_map_mode)
     map_the_bus();