]> git.ipfire.org Git - thirdparty/pciutils.git/commitdiff
Backward ABI compatibility for new filters and pci_fill_info
authorMartin Mares <mj@ucw.cz>
Sun, 2 Nov 2014 11:11:05 +0000 (12:11 +0100)
committerMartin Mares <mj@ucw.cz>
Sun, 2 Nov 2014 11:11:05 +0000 (12:11 +0100)
This is tricky, because we have to translate between old and new
format of struct pci_filter. At least, I added several RFU fields
so this hopefully won't have to happen again soon.

lib/access.c
lib/caps.c
lib/filter.c
lib/internal.h
lib/libpci.ver
lib/pci.h

index 61b3530dc427dd31941357304c4af73d5c8d96d4..d292085c7374ad96912b738e968996723b0e69f9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     The PCI Library -- User Access
  *
- *     Copyright (c) 1997--2013 Martin Mares <mj@ucw.cz>
+ *     Copyright (c) 1997--2014 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -153,8 +153,8 @@ pci_write_block(struct pci_dev *d, int pos, byte *buf, int len)
   return d->methods->write(d, pos, buf, len);
 }
 
-int VERSIONED
-pci_fill_info_v32(struct pci_dev *d, int flags)
+int
+pci_fill_info_v33(struct pci_dev *d, int flags)
 {
   if (flags & PCI_FILL_RESCAN)
     {
@@ -168,13 +168,15 @@ pci_fill_info_v32(struct pci_dev *d, int flags)
 }
 
 /* In version 3.1, pci_fill_info got new flags => versioned alias */
-/* In version 3.2, the same has happened */
-STATIC_ALIAS(int pci_fill_info(struct pci_dev *d, int flags), pci_fill_info_v32(d, flags));
-DEFINE_ALIAS(int pci_fill_info_v30(struct pci_dev *d, int flags), pci_fill_info_v32);
-DEFINE_ALIAS(int pci_fill_info_v31(struct pci_dev *d, int flags), pci_fill_info_v32);
+/* In versions 3.2 and 3.3, the same has happened */
+STATIC_ALIAS(int pci_fill_info(struct pci_dev *d, int flags), pci_fill_info_v33(d, flags));
+DEFINE_ALIAS(int pci_fill_info_v30(struct pci_dev *d, int flags), pci_fill_info_v33);
+DEFINE_ALIAS(int pci_fill_info_v31(struct pci_dev *d, int flags), pci_fill_info_v33);
+DEFINE_ALIAS(int pci_fill_info_v32(struct pci_dev *d, int flags), pci_fill_info_v33);
 SYMBOL_VERSION(pci_fill_info_v30, pci_fill_info@LIBPCI_3.0);
 SYMBOL_VERSION(pci_fill_info_v31, pci_fill_info@LIBPCI_3.1);
-SYMBOL_VERSION(pci_fill_info_v32, pci_fill_info@@LIBPCI_3.2);
+SYMBOL_VERSION(pci_fill_info_v32, pci_fill_info@LIBPCI_3.2);
+SYMBOL_VERSION(pci_fill_info_v33, pci_fill_info@@LIBPCI_3.3);
 
 void
 pci_setup_cache(struct pci_dev *d, byte *cache, int len)
index 2378591fb739ed25d4b96449fef0b82331218c64..4cf9ad8ec33f191c5939394aee6adebffcd5be6d 100644 (file)
@@ -106,7 +106,7 @@ pci_find_cap(struct pci_dev *d, unsigned int id, unsigned int type)
 {
   struct pci_cap *c;
 
-  pci_fill_info_v32(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
+  pci_fill_info_v33(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
   for (c=d->first_cap; c; c=c->next)
     if (c->type == type && c->id == id)
       return c;
index fab0025bd7322ad7f836a5ec459f911f736614d3..55eb6826dadb0e5ed3127ed7a65d1efe4a234f47 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     The PCI Library -- Device Filtering
  *
- *     Copyright (c) 1998--2003 Martin Mares <mj@ucw.cz>
+ *     Copyright (c) 1998--2014 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
 
 #include "internal.h"
 
+void pci_filter_init_v33(struct pci_access *a UNUSED, struct pci_filter *f) VERSIONED_ABI;
+char *pci_filter_parse_slot_v33(struct pci_filter *f, char *str) VERSIONED_ABI;
+char *pci_filter_parse_id_v33(struct pci_filter *f, char *str) VERSIONED_ABI;
+int pci_filter_match_v33(struct pci_filter *f, struct pci_dev *d) VERSIONED_ABI;
+
 void
-pci_filter_init(struct pci_access *a UNUSED, struct pci_filter *f)
+pci_filter_init_v33(struct pci_access *a UNUSED, struct pci_filter *f)
 {
   f->domain = f->bus = f->slot = f->func = -1;
-  f->vendor = f->device = f->class = -1;
+  f->vendor = f->device = f->device_class = -1;
 }
 
 /* Slot filter syntax: [[[domain]:][bus]:][slot][.[func]] */
 
 char *
-pci_filter_parse_slot(struct pci_filter *f, char *str)
+pci_filter_parse_slot_v33(struct pci_filter *f, char *str)
 {
   char *colon = strrchr(str, ':');
   char *dot = strchr((colon ? colon + 1 : str), '.');
@@ -77,7 +82,7 @@ pci_filter_parse_slot(struct pci_filter *f, char *str)
 /* ID filter syntax: [vendor]:[device][:class] */
 
 char *
-pci_filter_parse_id(struct pci_filter *f, char *str)
+pci_filter_parse_id_v33(struct pci_filter *f, char *str)
 {
   char *s, *c, *e;
 
@@ -109,13 +114,13 @@ pci_filter_parse_id(struct pci_filter *f, char *str)
       long int x = strtol(c, &e, 16);
       if ((e && *e) || (x < 0 || x > 0xffff))
        return "Invalid class code";
-      f->class = x;
+      f->device_class = x;
     }
   return NULL;
 }
 
 int
-pci_filter_match(struct pci_filter *f, struct pci_dev *d)
+pci_filter_match_v33(struct pci_filter *f, struct pci_dev *d)
 {
   if ((f->domain >= 0 && f->domain != d->domain) ||
       (f->bus >= 0 && f->bus != d->bus) ||
@@ -124,16 +129,112 @@ pci_filter_match(struct pci_filter *f, struct pci_dev *d)
     return 0;
   if (f->device >= 0 || f->vendor >= 0)
     {
-      pci_fill_info_v32(d, PCI_FILL_IDENT);
+      pci_fill_info_v33(d, PCI_FILL_IDENT);
       if ((f->device >= 0 && f->device != d->device_id) ||
          (f->vendor >= 0 && f->vendor != d->vendor_id))
        return 0;
     }
-  if (f->class >= 0)
+  if (f->device_class >= 0)
     {
       pci_fill_info(d, PCI_FILL_CLASS);
-      if (f->class != d->device_class)
+      if (f->device_class != d->device_class)
        return 0;
     }
   return 1;
 }
+
+/*
+ * Before pciutils v3.3, struct pci_filter had fewer fields,
+ * so we have to provide compatibility wrappers.
+ */
+
+struct pci_filter_v30 {
+  int domain, bus, slot, func;                 /* -1 = ANY */
+  int vendor, device;
+};
+
+void pci_filter_init_v30(struct pci_access *a, struct pci_filter_v30 *f) VERSIONED_ABI;
+char *pci_filter_parse_slot_v30(struct pci_filter_v30 *f, char *str) VERSIONED_ABI;
+char *pci_filter_parse_id_v30(struct pci_filter_v30 *f, char *str) VERSIONED_ABI;
+int pci_filter_match_v30(struct pci_filter_v30 *f, struct pci_dev *d) VERSIONED_ABI;
+
+static void
+pci_filter_import_v30(struct pci_filter_v30 *old, struct pci_filter *new)
+{
+  new->domain = old->domain;
+  new->bus = old->bus;
+  new->slot = old->bus;
+  new->func = old->func;
+  new->vendor = old->vendor;
+  new->device = old->device;
+  new->device_class = -1;
+}
+
+static void
+pci_filter_export_v30(struct pci_filter *new, struct pci_filter_v30 *old)
+{
+  old->domain = new->domain;
+  old->bus = new->bus;
+  old->slot = new->bus;
+  old->func = new->func;
+  old->vendor = new->vendor;
+  old->device = new->device;
+}
+
+void
+pci_filter_init_v30(struct pci_access *a, struct pci_filter_v30 *f)
+{
+  struct pci_filter new;
+  pci_filter_init_v33(a, &new);
+  pci_filter_export_v30(&new, f);
+}
+
+char *
+pci_filter_parse_slot_v30(struct pci_filter_v30 *f, char *str)
+{
+  struct pci_filter new;
+  char *err;
+  pci_filter_import_v30(f, &new);
+  if (err = pci_filter_parse_slot_v33(&new, str))
+    return err;
+  pci_filter_export_v30(&new, f);
+  return NULL;
+}
+
+char *
+pci_filter_parse_id_v30(struct pci_filter_v30 *f, char *str)
+{
+  struct pci_filter new;
+  char *err;
+  pci_filter_import_v30(f, &new);
+  if (err = pci_filter_parse_id_v33(&new, str))
+    return err;
+  if (new.device_class >= 0)
+    return "Filtering by class not supported in this program";
+  pci_filter_export_v30(&new, f);
+  return NULL;
+}
+
+int
+pci_filter_match_v30(struct pci_filter_v30 *f, struct pci_dev *d)
+{
+  struct pci_filter new;
+  pci_filter_import_v30(f, &new);
+  return pci_filter_match_v33(&new, d);
+}
+
+STATIC_ALIAS(void pci_filter_init(struct pci_access *a, struct pci_filter *f), pci_filter_init_v33(a, f));
+SYMBOL_VERSION(pci_filter_init_v30, pci_filter_init@LIBPCI_3.0);
+SYMBOL_VERSION(pci_filter_init_v33, pci_filter_init@@LIBPCI_3.3);
+
+STATIC_ALIAS(char *pci_filter_parse_slot(struct pci_filter *f, char *str), pci_filter_parse_slot_v33(f, str));
+SYMBOL_VERSION(pci_filter_parse_slot_v30, pci_filter_parse_slot@LIBPCI_3.0);
+SYMBOL_VERSION(pci_filter_parse_slot_v33, pci_filter_parse_slot@@LIBPCI_3.3);
+
+STATIC_ALIAS(char *pci_filter_parse_id(struct pci_filter *f, char *str), pci_filter_parse_id_v33(f, str));
+SYMBOL_VERSION(pci_filter_parse_id_v30, pci_filter_parse_id@LIBPCI_3.0);
+SYMBOL_VERSION(pci_filter_parse_id_v33, pci_filter_parse_id@@LIBPCI_3.3);
+
+STATIC_ALIAS(int pci_filter_match(struct pci_filter *f, struct pci_dev *d), pci_filter_match_v33(f, d));
+SYMBOL_VERSION(pci_filter_match_v30, pci_filter_match@LIBPCI_3.0);
+SYMBOL_VERSION(pci_filter_match_v33, pci_filter_match@@LIBPCI_3.3);
index ea63738afc8d6d7585474040d572a257e92204e7..a3123858cf1e2fe13d3f323195247262bce7bedf 100644 (file)
 // Functions, which are bound to externally visible symbols by the versioning
 // mechanism, have to be declared as VERSIONED. Otherwise, GCC with global
 // optimizations is happy to optimize them away, leading to linker failures.
-#define VERSIONED __attribute__((used))
+#define VERSIONED_ABI __attribute__((used)) PCI_ABI
 #ifdef __APPLE__
 #define STATIC_ALIAS(_decl, _for) _decl PCI_ABI { return _for; }
-#define DEFINE_ALIAS(_decl, _for) extern _decl __attribute__((alias(#_for)))
-#define SYMBOL_VERSION(_int, _ext) asm(".symver " #_int "," #_ext)
-#else
-#define STATIC_ALIAS(_decl, _for)
 #define DEFINE_ALIAS(_decl, _for)
 #define SYMBOL_VERSION(_int, _ext)
+#else
+#define STATIC_ALIAS(_decl, _for)
+#define DEFINE_ALIAS(_decl, _for) extern _decl __attribute__((alias(#_for)))
+#define SYMBOL_VERSION(_int, _ext) asm(".symver " #_int "," #_ext)
 #endif
 #else
-#define VERSIONED
+#define VERSIONED_ABI
 #define STATIC_ALIAS(_decl, _for) _decl { return _for; }
 #define DEFINE_ALIAS(_decl, _for)
 #define SYMBOL_VERSION(_int, _ext)
@@ -65,9 +65,10 @@ char *pci_strdup(struct pci_access *a, const char *s);
 struct pci_dev *pci_alloc_dev(struct pci_access *);
 int pci_link_dev(struct pci_access *, struct pci_dev *);
 
-int pci_fill_info_v30(struct pci_dev *, int flags) PCI_ABI;
-int pci_fill_info_v31(struct pci_dev *, int flags) PCI_ABI;
-int pci_fill_info_v32(struct pci_dev *, int flags) PCI_ABI;
+int pci_fill_info_v30(struct pci_dev *, int flags) VERSIONED_ABI;
+int pci_fill_info_v31(struct pci_dev *, int flags) VERSIONED_ABI;
+int pci_fill_info_v32(struct pci_dev *, int flags) VERSIONED_ABI;
+int pci_fill_info_v33(struct pci_dev *, int flags) VERSIONED_ABI;
 
 /* params.c */
 void pci_define_param(struct pci_access *acc, char *param, char *val, char *help);
index 3f73fca749425b47aa0d3b7eec3a856fbf88f8bc..31f89fd6a4f6eb7327ed58fc23ad4d376dd0bac6 100644 (file)
@@ -52,3 +52,12 @@ LIBPCI_3.2 {
        global:
                pci_fill_info;
 };
+
+LIBPCI_3.3 {
+       global:
+               pci_fill_info;
+               pci_filter_init;
+               pci_filter_match;
+               pci_filter_parse_id;
+               pci_filter_parse_slot;
+};
index 0c57fddb589f7c110daafd36842a92c7d616e461..3933f3dc7375f1aa6fe058a1f9c86e764d7a21e5 100644 (file)
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -198,7 +198,8 @@ struct pci_cap *pci_find_cap(struct pci_dev *, unsigned int id, unsigned int typ
 
 struct pci_filter {
   int domain, bus, slot, func;                 /* -1 = ANY */
-  int vendor, device, class;
+  int vendor, device, device_class;
+  int rfu[3];
 };
 
 void pci_filter_init(struct pci_access *, struct pci_filter *) PCI_ABI;