From 11339c0d3d0c9064717983fa283bafcdc5298fe7 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 6 Nov 2007 22:26:48 +0100 Subject: Finished support for displaying of kernel drivers/modules. --- ChangeLog | 10 ++++++++ lspci.c | 85 +++++++++++++++++++++++++++++++++++++++++++-------------------- lspci.man | 27 +++++++++++++++++++- 3 files changed, 94 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index cca39ca..b94c85a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-11-06 Martin Mares + + * lspci.c: Added a new switch `-k' which requests printing + of information on kernel drivers attached to each device + and on kernel modules reporting the ability to handle the + device. So far, this is supported only on Linux with the + sysfs back-end, so it is implemented internally in the lspci + instead of the libpci. Thanks to Anicka + for help. + 2007-10-19 Martin Mares * Makefile, lib/Makefile: Moved -lz from LDFLAGS to LDLIBS. diff --git a/lspci.c b/lspci.c index f933235..3110ea0 100644 --- a/lspci.c +++ b/lspci.c @@ -24,11 +24,12 @@ 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 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 options[] = "nvbxs:d:ti:mgp:kMD" GENERIC_OPTIONS ; static char help_msg[] = "\ Usage: lspci []\n\ @@ -47,6 +48,7 @@ Usage: lspci []\n\ -i \tUse specified ID database instead of %s\n" #ifdef PCI_OS_LINUX "\ +-k\t\tShow kernel drivers handling each device\n\ -p \tLook up kernel modules in a given file instead of default modules.pcimap\n" #endif "\ @@ -1571,44 +1573,47 @@ 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; int n; if (dev->access->method != PCI_ACCESS_SYS_BUS_PCI) - return; + 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 +1625,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 +2123,6 @@ show_verbose(struct device *d) show_htype2(d); break; } - - show_driver(d); - show_module(d); } /*** Machine-readable dumps ***/ @@ -2174,6 +2195,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 +2226,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,6 +2719,9 @@ main(int argc, char **argv) case 'p': opt_pcimap = optarg; break; + case 'k': + opt_kernel++; + break; case 'M': opt_map_mode++; break; diff --git a/lspci.man b/lspci.man index 1d5583b..5ce14f0 100644 --- a/lspci.man +++ b/lspci.man @@ -73,6 +73,13 @@ devices are rare, so you needn't worry much. Show hexadecimal dump of the extended (4096-byte) PCI configuration space available on PCI-X 2.0 and PCI Express buses. .TP +.B -k +Show kernel drivers handling each device and also kernel modules capable of handling it. +Turned on by default when +.B -v +is given in the normal mode of output. +(Currently works only on Linux with kernel 2.6 or newer.) +.TP .B -b Bus-centric view. Show all IRQ numbers and addresses as seen by the cards on the PCI bus instead of as seen by the kernel. @@ -100,6 +107,14 @@ Use as the PCI ID list instead of @IDSDIR@/pci.ids. .TP +.B -p +Use +.B + +as the map of PCI ID's handled by kernel modules. By default, lspci uses +.RI /lib/modules/ kernel_version /modules.pcimap. +Applies only to Linux systems with recent enough module tools. +.TP .B -m Dump PCI device data in a backward-compatible machine readable form. See below for details. @@ -134,7 +149,8 @@ the following access methods: The .B /sys filesystem on Linux 2.6 and newer. The standard header of the config space is available -to all users, the rest only to root. Supports extended configuration space and PCI domains. +to all users, the rest only to root. Supports extended configuration space, PCI domains +and information on attached kernel drivers. .TP .B linux_proc The @@ -285,6 +301,15 @@ Revision number (optional). .B ProgIf Programming interface (optional). +.TP +.B Driver +Kernel driver currently handling the device (optional, Linux only). + +.TP +.B Module +Kernel module reporting that it is capable of handling the device +(optional, Linux only). + .P New tags can be added in future versions, so you should silently ignore any tags you don't recognize. -- cgit v1.2.1