diff -ruN pciutils-2.2.8/ChangeLog pciutils-2.2.9/ChangeLog
--- pciutils-2.2.8/ChangeLog	2007-10-19 12:12:33.000000000 +0200
+++ pciutils-2.2.9/ChangeLog	2007-11-06 22:27:34.000000000 +0100
@@ -1,3 +1,22 @@
+2007-11-06  Martin Mares <mj@ucw.cz>
+
+	* Released as 2.2.9.
+
+	* 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 <anicka@anicka.net>
+	for help.
+
+2007-10-19  Martin Mares <mj@ucw.cz>
+
+	* Makefile, lib/Makefile: Moved -lz from LDFLAGS to LDLIBS.
+	Also added an explicit pattern rule for linking to make sure
+	that LDLIBS is used on all platforms. Thanks to Dan Nicholson
+	for the suggestion.
+
 2007-10-19  Martin Mares <mj@ucw.cz>
 
 	* Released as 2.2.8.
diff -ruN pciutils-2.2.8/Makefile pciutils-2.2.9/Makefile
--- pciutils-2.2.8/Makefile	2007-10-19 12:12:24.000000000 +0200
+++ pciutils-2.2.9/Makefile	2007-11-06 22:29:09.000000000 +0100
@@ -4,8 +4,8 @@
 OPT=-O2
 CFLAGS=$(OPT) -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes
 
-VERSION=2.2.8
-DATE=2007-10-19
+VERSION=2.2.9
+DATE=2007-11-06
 
 PREFIX=/usr/local
 SBINDIR=$(PREFIX)/sbin
@@ -52,6 +52,9 @@
 	sed <$< >$@ "s@^DEST=.*@DEST=$(IDSDIR)/$(PCI_IDS)@;s@^PCI_COMPRESSED_IDS=.*@PCI_COMPRESSED_IDS=$(PCI_COMPRESSED_IDS)@"
 	chmod +x $@
 
+%: %.o
+	$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
+
 %.8: %.man
 	M=`echo $(DATE) | sed 's/-01-/-January-/;s/-02-/-February-/;s/-03-/-March-/;s/-04-/-April-/;s/-05-/-May-/;s/-06-/-June-/;s/-07-/-July-/;s/-08-/-August-/;s/-09-/-September-/;s/-10-/-October-/;s/-11-/-November-/;s/-12-/-December-/;s/\(.*\)-\(.*\)-\(.*\)/\3 \2 \1/'` ; sed <$< >$@ "s/@TODAY@/$$M/;s/@VERSION@/pciutils-$(VERSION)/;s#@IDSDIR@#$(IDSDIR)#"
 
diff -ruN pciutils-2.2.8/README pciutils-2.2.9/README
--- pciutils-2.2.8/README	2007-10-19 12:13:10.000000000 +0200
+++ pciutils-2.2.9/README	2007-11-06 22:29:27.000000000 +0100
@@ -1,6 +1,6 @@
-This package contains the PCI Utilities, version 2.2.8.
+This package contains the PCI Utilities, version 2.2.9.
 
-Copyright (c) 1997--2006 Martin Mares <mj@ucw.cz>
+Copyright (c) 1997--2007 Martin Mares <mj@ucw.cz>
 
 All files in this package can be freely distributed and used according
 to the terms of the GNU General Public License, either version 2 or
@@ -112,7 +112,7 @@
 7. Miscellanea
 ~~~~~~~~~~~~~~
 You also might want to look at the pciutils web page containing release
-notes and other news: http://atrey.karlin.mff.cuni.cz/~mj/pciutils.shtml .
+notes and other news: http://mj.ucw.cz/pciutils.shtml .
 
 There also exists a utility called PowerTweak which is able to fine tune
 parameters of many chipsets much better than the Bridge Optimization code
diff -ruN pciutils-2.2.8/TODO pciutils-2.2.9/TODO
--- pciutils-2.2.8/TODO	2007-10-19 12:02:48.000000000 +0200
+++ pciutils-2.2.9/TODO	2007-10-19 12:15:27.000000000 +0200
@@ -1,3 +1,5 @@
+- review class names
+
 Capabilities with partial decoding:
 - PCIe 2nd set of control/status registers (have spec)
 - HyperTransport caps (have spec)
diff -ruN pciutils-2.2.8/lib/Makefile pciutils-2.2.9/lib/Makefile
--- pciutils-2.2.8/lib/Makefile	2007-10-19 11:17:40.000000000 +0200
+++ pciutils-2.2.9/lib/Makefile	2007-10-19 14:41:34.000000000 +0200
@@ -62,7 +62,7 @@
 		-e 's,@LIBZ@,$(LIBZ),'
 
 access.o: access.c $(INCL)
-i386-ports.o: i386-ports.c $(INCL) i386-io-hurd.h i386-io-linux.h i386-io-sunos.h
+i386-ports.o: i386-ports.c $(INCL) i386-io-hurd.h i386-io-linux.h i386-io-sunos.h i386-io-windows.h
 proc.o: proc.c $(INCL) pread.h
 sysfs.o: sysfs.c $(INCL) pread.h
 generic.o: generic.c $(INCL)
diff -ruN pciutils-2.2.8/lib/configure pciutils-2.2.9/lib/configure
--- pciutils-2.2.8/lib/configure	2007-09-12 21:24:40.000000000 +0200
+++ pciutils-2.2.9/lib/configure	2007-10-19 15:38:23.000000000 +0200
@@ -92,7 +92,7 @@
 		echo >>$c '#define PCI_HAVE_PM_NBSD_LIBPCI'
 		echo >>$c '#define PCI_PATH_NBSD_DEVICE "/dev/pci0"'
 		echo >>$m 'PCILIB=lib/libpciutils.a'
-		echo >>$m 'LDFLAGS+=-lpci'
+		echo >>$m 'LDLIBS+=-lpci'
 		;;
     	gnu)
 		echo_n " i386-ports"
@@ -122,7 +122,7 @@
 	echo >>$c '#define PCI_COMPRESSED_IDS'
 	echo >>$c '#define PCI_IDS "pci.ids.gz"'
 	echo >>$m 'LIBZ=-lz'
-	echo >>$m 'LDFLAGS+=$(LIBZ)'
+	echo >>$m 'LDLIBS+=$(LIBZ)'
 else
 	echo >>$c '#define PCI_IDS "pci.ids"'
 fi
diff -ruN pciutils-2.2.8/lspci.c pciutils-2.2.9/lspci.c
--- pciutils-2.2.8/lspci.c	2007-10-19 12:01:33.000000000 +0200
+++ pciutils-2.2.9/lspci.c	2007-11-06 22:27:24.000000000 +0100
@@ -24,10 +24,12 @@
 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:mgMD" GENERIC_OPTIONS ;
+static char options[] = "nvbxs:d:ti:mgp:kMD" GENERIC_OPTIONS ;
 
 static char help_msg[] = "\
 Usage: lspci [<switches>]\n\
@@ -43,7 +45,13 @@
 -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\
+-i <file>\tUse specified ID database instead of %s\n"
+#ifdef PCI_OS_LINUX
+"\
+-k\t\tShow kernel drivers handling each device\n\
+-p <file>\tLook up kernel modules in a given file instead of default modules.pcimap\n"
+#endif
+"\
 -D\t\tAlways show domain numbers\n\
 -M\t\tEnable `bus mapping' mode (dangerous; root only)\n"
 GENERIC_HELP
@@ -295,6 +303,25 @@
   putchar('\n');
 }
 
+static void
+get_subid(struct device *d, word *subvp, word *subdp)
+{
+  byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
+
+  if (htype == PCI_HEADER_TYPE_NORMAL)
+    {
+      *subvp = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID);
+      *subdp = get_conf_word(d, PCI_SUBSYSTEM_ID);
+    }
+  else if (htype == PCI_HEADER_TYPE_CARDBUS && d->config_cached >= 128)
+    {
+      *subvp = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
+      *subdp = get_conf_word(d, PCI_CB_SUBSYSTEM_ID);
+    }
+  else
+    *subvp = *subdp = 0xffff;
+}
+
 /*** Capabilities ***/
 
 static void
@@ -1452,6 +1479,185 @@
     show_ext_caps(d);
 }
 
+/*** Kernel drivers ***/
+
+#ifdef PCI_OS_LINUX
+
+#include <sys/utsname.h>
+
+struct pcimap_entry {
+  struct pcimap_entry *next;
+  unsigned int vendor, device;
+  unsigned int subvendor, subdevice;
+  unsigned int class, class_mask;
+  char module[1];
+};
+
+static struct pcimap_entry *pcimap_head;
+
+static void
+load_pcimap(void)
+{
+  static int tried_pcimap;
+  struct utsname uts;
+  char *name, line[1024];
+  FILE *f;
+
+  if (tried_pcimap)
+    return;
+  tried_pcimap = 1;
+
+  if (name = opt_pcimap)
+    {
+      f = fopen(name, "r");
+      if (!f)
+	die("Cannot open pcimap file %s: %m", name);
+    }
+  else
+    {
+      if (uname(&uts) < 0)
+	die("uname() failed: %m");
+      name = alloca(64 + strlen(uts.release));
+      sprintf(name, "/lib/modules/%s/modules.pcimap", uts.release);
+      f = fopen(name, "r");
+      if (!f)
+	return;
+    }
+
+  while (fgets(line, sizeof(line), f))
+    {
+      char *c = strchr(line, '\n');
+      struct pcimap_entry *e;
+
+      if (!c)
+	die("Unterminated or too long line in %s", name);
+      *c = 0;
+      if (!line[0] || line[0] == '#')
+	continue;
+
+      c = line;
+      while (*c && *c != ' ' && *c != '\t')
+	c++;
+      if (!*c)
+	continue;	/* FIXME: Emit warnings! */
+      *c++ = 0;
+
+      e = xmalloc(sizeof(*e) + strlen(line));
+      if (sscanf(c, "%i%i%i%i%i%i",
+		 &e->vendor, &e->device,
+		 &e->subvendor, &e->subdevice,
+		 &e->class, &e->class_mask) != 6)
+	continue;
+      e->next = pcimap_head;
+      pcimap_head = e;
+      strcpy(e->module, line);
+    }
+  fclose(f);
+}
+
+static int
+match_pcimap(struct device *d, struct pcimap_entry *e)
+{
+  struct pci_dev *dev = d->dev;
+  unsigned int class = get_conf_long(d, PCI_REVISION_ID) >> 8;
+  word subv, subd;
+
+#define MATCH(x, y) ((y) > 0xffff || (x) == (y))
+  get_subid(d, &subv, &subd);
+  return
+    MATCH(dev->vendor_id, e->vendor) &&
+    MATCH(dev->device_id, e->device) &&
+    MATCH(subv, e->subvendor) &&
+    MATCH(subd, e->subdevice) &&
+    (class & e->class_mask) == e->class;
+#undef MATCH
+}
+
+#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], *drv;
+  int n;
+
+  if (dev->access->method != PCI_ACCESS_SYS_BUS_PCI)
+    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 >= (int)sizeof(name))
+    die("show_driver: sysfs device name too long, why?");
+
+  n = readlink(name, buf, DRIVER_BUF_SIZE);
+  if (n < 0)
+    return NULL;
+  if (n >= DRIVER_BUF_SIZE)
+    return "<name-too-long>";
+  buf[n] = 0;
+
+  if (drv = strrchr(buf, '/'))
+    return drv+1;
+  else
+    return buf;
+}
+
+static void
+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)))
+      {
+	printf("%s %s", (last ? "," : "\tKernel modules:"), e->module);
+	last = e;
+      }
+  if (last)
+    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_kernel(struct device *d UNUSED)
+{
+}
+
+static void
+show_kernel_machine(struct device *d UNUSED)
+{
+}
+
+#endif
+
 /*** Verbose output ***/
 
 static void
@@ -1785,7 +1991,7 @@
   byte max_lat, min_gnt;
   byte int_pin = get_conf_byte(d, PCI_INTERRUPT_PIN);
   unsigned int irq = p->irq;
-  word subsys_v = 0, subsys_d = 0;
+  word subsys_v, subsys_d;
   char ssnamebuf[256];
 
   show_terse(d);
@@ -1797,8 +2003,6 @@
 	printf("\t!!! Invalid class %04x for header type %02x\n", class, htype);
       max_lat = get_conf_byte(d, PCI_MAX_LAT);
       min_gnt = get_conf_byte(d, PCI_MIN_GNT);
-      subsys_v = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID);
-      subsys_d = get_conf_word(d, PCI_SUBSYSTEM_ID);
       break;
     case PCI_HEADER_TYPE_BRIDGE:
       if ((class >> 8) != PCI_BASE_CLASS_BRIDGE)
@@ -1809,17 +2013,13 @@
       if ((class >> 8) != PCI_BASE_CLASS_BRIDGE)
 	printf("\t!!! Invalid class %04x for header type %02x\n", class, htype);
       min_gnt = max_lat = 0;
-      if (d->config_cached >= 128)
-	{
-	  subsys_v = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
-	  subsys_d = get_conf_word(d, PCI_CB_SUBSYSTEM_ID);
-	}
       break;
     default:
       printf("\t!!! Unknown header type %02x\n", htype);
       return;
     }
 
+  get_subid(d, &subsys_v, &subsys_d);
   if (subsys_v && subsys_v != 0xffff)
     printf("\tSubsystem: %s\n",
 	   pci_lookup_name(pacc, ssnamebuf, sizeof(ssnamebuf),
@@ -1968,23 +2168,10 @@
 {
   struct pci_dev *p = d->dev;
   int c;
-  word sv_id=0, sd_id=0;
+  word sv_id, sd_id;
   char classbuf[128], vendbuf[128], devbuf[128], svbuf[128], sdbuf[128];
 
-  switch (get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f)
-    {
-    case PCI_HEADER_TYPE_NORMAL:
-      sv_id = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID);
-      sd_id = get_conf_word(d, PCI_SUBSYSTEM_ID);
-      break;
-    case PCI_HEADER_TYPE_CARDBUS:
-      if (d->config_cached >= 128)
-	{
-	  sv_id = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
-	  sd_id = get_conf_word(d, PCI_CB_SUBSYSTEM_ID);
-	}
-      break;
-    }
+  get_subid(d, &sv_id, &sd_id);
 
   if (verbose)
     {
@@ -2008,6 +2195,8 @@
 	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
     {
@@ -2037,10 +2226,15 @@
 {
   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)
@@ -2522,6 +2716,12 @@
       case 'm':
 	opt_machine++;
 	break;
+      case 'p':
+	opt_pcimap = optarg;
+	break;
+      case 'k':
+	opt_kernel++;
+	break;
       case 'M':
 	opt_map_mode++;
 	break;
diff -ruN pciutils-2.2.8/lspci.man pciutils-2.2.9/lspci.man
--- pciutils-2.2.8/lspci.man	2007-10-19 11:18:21.000000000 +0200
+++ pciutils-2.2.9/lspci.man	2007-11-06 22:27:24.000000000 +0100
@@ -73,6 +73,13 @@
 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 @@
 <file>
 as the PCI ID list instead of @IDSDIR@/pci.ids.
 .TP
+.B -p <file>
+Use
+.B
+<file>
+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
 .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 @@
 .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.
 
diff -ruN pciutils-2.2.8/pciutils.lsm pciutils-2.2.9/pciutils.lsm
--- pciutils-2.2.8/pciutils.lsm	2007-10-19 12:13:10.000000000 +0200
+++ pciutils-2.2.9/pciutils.lsm	2007-11-06 22:29:27.000000000 +0100
@@ -1,14 +1,14 @@
 Begin3
 Title:          The PCI Utilities
-Version:        2.2.8
-Entered-date:   071019
+Version:        2.2.9
+Entered-date:   071106
 Description:    This package contains various utilities for inspecting and
 		setting of devices connected to the PCI bus.
 Keywords:       kernel, pci, lspci, setpci, libpci
 Author:         mj@ucw.cz (Martin Mares)
 Maintained-by:  mj@ucw.cz (Martin Mares)
-Primary-site:   atrey.karlin.mff.cuni.cz pub/linux/pci/pciutils-2.2.8.tar.gz
-Alternate-site: ftp.kernel.org pub/software/utils/pciutils/pciutils-2.2.8.tar.gz
-Alternate-site: metalab.unc.edu pub/Linux/hardware/pciutils-2.2.8.tar.gz
+Primary-site:   atrey.karlin.mff.cuni.cz pub/linux/pci/pciutils-2.2.9.tar.gz
+Alternate-site: ftp.kernel.org pub/software/utils/pciutils/pciutils-2.2.9.tar.gz
+Alternate-site: metalab.unc.edu pub/Linux/hardware/pciutils-2.2.9.tar.gz
 Copying-policy: GPL
 End
diff -ruN pciutils-2.2.8/pciutils.spec pciutils-2.2.9/pciutils.spec
--- pciutils-2.2.8/pciutils.spec	2007-10-19 12:13:10.000000000 +0200
+++ pciutils-2.2.9/pciutils.spec	2007-11-06 22:29:28.000000000 +0100
@@ -1,5 +1,5 @@
 Name:		pciutils
-Version:	2.2.8
+Version:	2.2.9
 Release: 	1
 Source:		ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/%{name}-%{version}.tar.gz
 Copyright:	GNU GPL
diff -ruN pciutils-2.2.8/win32/config.h pciutils-2.2.9/win32/config.h
--- pciutils-2.2.8/win32/config.h	2007-10-19 12:13:10.000000000 +0200
+++ pciutils-2.2.9/win32/config.h	2007-11-06 22:29:28.000000000 +0100
@@ -3,4 +3,4 @@
 #define PCI_HAVE_PM_INTEL_CONF
 #define PCI_IDS "pci.ids"
 #define PCI_PATH_IDS_DIR "."
-#define PCILIB_VERSION "2.2.8"
+#define PCILIB_VERSION "2.2.9"
