/*
* 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.
*/
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)
{
}
/* 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)
/*
* 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), '.');
/* 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;
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) ||
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);
// 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)
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);