]> mj.ucw.cz Git - pciutils.git/blobdiff - lib/caps.c
Fix stripping in cross-compiling mode
[pciutils.git] / lib / caps.c
index 13e395617758ad90befac56c4d31e8b6ecffc258..039c86f7e206a6bf5ec7a7bb0b85491a65eaacfa 100644 (file)
@@ -15,8 +15,12 @@ pci_add_cap(struct pci_dev *d, unsigned int addr, unsigned int id, unsigned int
 {
   struct pci_cap *cap = pci_malloc(d->access, sizeof(*cap));
 
 {
   struct pci_cap *cap = pci_malloc(d->access, sizeof(*cap));
 
-  cap->next = d->first_cap;
-  d->first_cap = cap;
+  if (d->last_cap)
+    d->last_cap->next = cap;
+  else
+    d->first_cap = cap;
+  d->last_cap = cap;
+  cap->next = NULL;
   cap->addr = addr;
   cap->id = id;
   cap->type = type;
   cap->addr = addr;
   cap->id = id;
   cap->type = type;
@@ -71,22 +75,21 @@ pci_scan_ext_caps(struct pci_dev *d)
       if (been_there[where]++)
        break;
       pci_add_cap(d, where, id, PCI_CAP_EXTENDED);
       if (been_there[where]++)
        break;
       pci_add_cap(d, where, id, PCI_CAP_EXTENDED);
-      where = header >> 20;
+      where = (header >> 20) & ~3;
     }
   while (where);
 }
 
     }
   while (where);
 }
 
-unsigned int
+void
 pci_scan_caps(struct pci_dev *d, unsigned int want_fields)
 {
 pci_scan_caps(struct pci_dev *d, unsigned int want_fields)
 {
-  if ((want_fields & PCI_FILL_EXT_CAPS) && !(d->known_fields & PCI_FILL_CAPS))
+  if (want_fields & PCI_FILL_EXT_CAPS)
     want_fields |= PCI_FILL_CAPS;
 
     want_fields |= PCI_FILL_CAPS;
 
-  if (want_fields & PCI_FILL_CAPS)
+  if (want_fill(d, want_fields, PCI_FILL_CAPS))
     pci_scan_trad_caps(d);
     pci_scan_trad_caps(d);
-  if (want_fields & PCI_FILL_EXT_CAPS)
+  if (want_fill(d, want_fields, PCI_FILL_EXT_CAPS))
     pci_scan_ext_caps(d);
     pci_scan_ext_caps(d);
-  return want_fields;
 }
 
 void
 }
 
 void
@@ -96,19 +99,48 @@ pci_free_caps(struct pci_dev *d)
 
   while (cap = d->first_cap)
     {
 
   while (cap = d->first_cap)
     {
-      d->first_cap = cap;
-      pci_mfree(d);
+      d->first_cap = cap->next;
+      pci_mfree(cap);
     }
 }
 
 struct pci_cap *
 pci_find_cap(struct pci_dev *d, unsigned int id, unsigned int type)
     }
 }
 
 struct pci_cap *
 pci_find_cap(struct pci_dev *d, unsigned int id, unsigned int type)
+{
+  return pci_find_cap_nr(d, id, type, NULL);
+}
+
+/**
+ * Finds a particular capability of a device
+ *
+ * To select one capability if there are more than one with the same id, you
+ * can provide a pointer to an unsigned int that contains the index which you
+ * want as cap_number. If you don't care and are fine with the first one you
+ * can supply NULL. The cap_number will be replaced by the actual number
+ * of capabilities with that id.
+ */
+struct pci_cap *
+pci_find_cap_nr(struct pci_dev *d, unsigned int id, unsigned int type,
+                unsigned int *cap_number)
 {
   struct pci_cap *c;
 {
   struct pci_cap *c;
+  struct pci_cap *found = NULL;
+  unsigned int target = (cap_number ? *cap_number : 0);
+  unsigned int index = 0;
+
+  pci_fill_info_v38(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
 
 
-  pci_fill_info(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
   for (c=d->first_cap; c; c=c->next)
   for (c=d->first_cap; c; c=c->next)
-    if (c->type == type && c->id == id)
-      return c;
-  return NULL;
+    {
+      if (c->type == type && c->id == id)
+       {
+         if (target == index)
+           found = c;
+         index++;
+       }
+    }
+
+  if (cap_number)
+    *cap_number = index;
+  return found;
 }
 }