X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lspci.c;h=0515fcd6ad8d89c64bcc54fdf5d61da73163285b;hb=69388a6a3cc4c615ac89b9b298c8e70a6ba6e311;hp=f933235e5e9c551720b217f3c1ec99735abb533f;hpb=c1c952d26d4913359075d615550e71fa8d2abf22;p=pciutils.git diff --git a/lspci.c b/lspci.c index f933235..0515fcd 100644 --- a/lspci.c +++ b/lspci.c @@ -1,7 +1,7 @@ /* * The PCI Utilities -- List All PCI Devices * - * Copyright (c) 1997--2007 Martin Mares + * Copyright (c) 1997--2008 Martin Mares * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -12,6 +12,7 @@ #include #include +#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 []\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 [[[[]:]]:][][.[]]\tShow only devices in selected slots\n\ --d []:[]\tShow only selected devices\n\ --t\t\tShow bus tree\n\ --m\t\tProduce machine-readable output\n\ --i \tUse specified ID database instead of %s\n" +static char options[] = "nvbxs:d:ti:mgp:qkMDQ" GENERIC_OPTIONS ; + +static char help_msg[] = +"Usage: lspci []\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 \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 [[[[]:]]:][][.[]]\tShow only devices in selected slots\n" +"-d []:[]\t\t\tShow only devices with specified ID's\n" +"\n" +"Other options:\n" +"-i \tUse specified ID database instead of %s\n" +#ifdef PCI_OS_LINUX +"-p \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 ""; + 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();