]> mj.ucw.cz Git - pciutils.git/commitdiff
Add and use PCI_FILL_CLASS.
authorMartin Mares <mj@ucw.cz>
Tue, 27 Jun 2006 13:13:20 +0000 (15:13 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 27 Jun 2006 13:13:20 +0000 (15:13 +0200)
ChangeLog
lib/generic.c
lib/pci.h
lib/sysfs.c
lspci.c

index 6247337b6beec1605db6ebb4644c4eaaccd4dba6..02f9953337a9954cfdb876684415722395ca68e5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2006-06-27  Martin Mares  <mj@ucw.cz>
+
+       * lib/pci.h, lib/generic.c: Added PCI_FILL_CLASS.
+
+       * lib/sysfs.c: Fetch device ID and class from sysfs, because they can
+       be modified by kernel fixups.
+
+       * lspci.c: Use PCI_FILL_CLASS. Thanks to Matthew Willcox for the patch.
+
 2006-06-03  Martin Mares  <mj@ucw.cz>
 
        * lspci.c: Introduced the -nn switch. Thanks to David N. Welton
index a47bc15dcd17dbf667cef1a90b61343157e62132..b1b1c8ed01a32e329d8681beec4038125f2697e1 100644 (file)
@@ -86,6 +86,8 @@ pci_generic_fill_info(struct pci_dev *d, int flags)
       d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
       d->device_id = pci_read_word(d, PCI_DEVICE_ID);
     }
+  if (flags & PCI_FILL_CLASS)
+      d->device_class = pci_read_word(d, PCI_CLASS_DEVICE);
   if (flags & PCI_FILL_IRQ)
     d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
   if (flags & PCI_FILL_BASES)
index 22c336bca7c992b8943c2f33ca165fe65dfe0ad3..8c208b406fdba92aea08ee6243e23c502a9d808f 100644 (file)
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -86,6 +86,7 @@ struct pci_dev {
   /* These fields are set by pci_fill_info() */
   int known_fields;                    /* Set of info fields already known */
   u16 vendor_id, device_id;            /* Identity of the device */
+  u16 device_class;                    /* PCI device class */
   int irq;                             /* IRQ number */
   pciaddr_t base_addr[6];              /* Base addresses */
   pciaddr_t size[6];                   /* Region sizes */
@@ -120,6 +121,7 @@ int pci_fill_info(struct pci_dev *, int flags); /* Fill in device information */
 #define PCI_FILL_BASES         4
 #define PCI_FILL_ROM_BASE      8
 #define PCI_FILL_SIZES         16
+#define PCI_FILL_CLASS         32
 #define PCI_FILL_RESCAN                0x10000
 
 void pci_setup_cache(struct pci_dev *, u8 *cache, int len);
index 70419ecfca2a30b659a6430e6253b8776e155ac4..a6cbd57a6c753c278647fc2c859f1e4df475e18d 100644 (file)
@@ -163,18 +163,14 @@ static void sysfs_scan(struct pci_access *a)
        {
          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
+          *  We could read these faster from the config registers, but we want to give
+          *  the kernel a chance to fix up ID's and especially classes of broken devices.
           */
          d->vendor_id = sysfs_get_value(d, "vendor");
          d->device_id = sysfs_get_value(d, "device");
-         d->known_fields |= PCI_FILL_IDENT;
-#endif
+         d->device_class = sysfs_get_value(d, "class") >> 8;
+         d->known_fields = PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES;
        }
       pci_link_dev(a, d);
     }
diff --git a/lspci.c b/lspci.c
index 84a23e5b2b41b8718a64bf5114bf5bb08f835dc0..0d7c3a8bd63015adea3bd15d81abd1e565d8c671 100644 (file)
--- a/lspci.c
+++ b/lspci.c
@@ -130,7 +130,7 @@ scan_device(struct pci_dev *p)
        d->config_cached += 64;
     }
   pci_setup_cache(p, d->config, d->config_cached);
-  pci_fill_info(p, PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES);
+  pci_fill_info(p, PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES);
   return d;
 }
 
@@ -262,7 +262,7 @@ show_terse(struct device *d)
   printf(" %s: %s",
         pci_lookup_name(pacc, classbuf, sizeof(classbuf),
                         PCI_LOOKUP_CLASS,
-                        get_conf_word(d, PCI_CLASS_DEVICE)),
+                        p->device_class),
         pci_lookup_name(pacc, devbuf, sizeof(devbuf),
                         PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
                         p->vendor_id, p->device_id));
@@ -274,7 +274,7 @@ show_terse(struct device *d)
       c = get_conf_byte(d, PCI_CLASS_PROG);
       x = pci_lookup_name(pacc, devbuf, sizeof(devbuf),
                          PCI_LOOKUP_PROGIF | PCI_LOOKUP_NO_NUMBERS,
-                         get_conf_word(d, PCI_CLASS_DEVICE), c);
+                         p->device_class, c);
       if (c || x)
        {
          printf(" (prog-if %02x", c);
@@ -1592,7 +1592,7 @@ show_verbose(struct device *d)
   struct pci_dev *p = d->dev;
   word status = get_conf_word(d, PCI_STATUS);
   word cmd = get_conf_word(d, PCI_COMMAND);
-  word class = get_conf_word(d, PCI_CLASS_DEVICE);
+  word class = p->device_class;
   byte bist = get_conf_byte(d, PCI_BIST);
   byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
   byte latency = get_conf_byte(d, PCI_LATENCY_TIMER);
@@ -1790,7 +1790,7 @@ show_machine(struct device *d)
       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)));
+            pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, p->device_class));
       printf("Vendor:\t%s\n",
             pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR, p->vendor_id, p->device_id));
       printf("Device:\t%s\n",
@@ -1812,7 +1812,7 @@ show_machine(struct device *d)
       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)),
+                            p->device_class),
             pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR,
                             p->vendor_id, p->device_id),
             pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE,
@@ -1936,7 +1936,7 @@ grow_tree(void)
   last_br = &host_bridge.chain;
   for(d=first_dev; d; d=d->next)
     {
-      word class = get_conf_word(d, PCI_CLASS_DEVICE);
+      word class = d->dev->device_class;
       byte ht = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
       if (class == PCI_CLASS_BRIDGE_PCI &&
          (ht == PCI_HEADER_TYPE_BRIDGE || ht == PCI_HEADER_TYPE_CARDBUS))