X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Faccess.c;h=b8fdbe2319b5a717ddadd6eda22dc9e039205508;hb=0766bfa0f557430a6dd3256d45a5b756499f9f7b;hp=17b8bed1230bce94c074d51e77977bfccc1d575d;hpb=8442ab4bc6a775a5fea8132c133e49f9b9bf71d5;p=pciutils.git diff --git a/lib/access.c b/lib/access.c index 17b8bed..b8fdbe2 100644 --- a/lib/access.c +++ b/lib/access.c @@ -1,7 +1,7 @@ /* * The PCI Library -- User Access * - * Copyright (c) 1997--2014 Martin Mares + * Copyright (c) 1997--2022 Martin Mares * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -40,6 +40,18 @@ pci_link_dev(struct pci_access *a, struct pci_dev *d) d->next = a->devices; a->devices = d; + /* + * Applications compiled with older versions of libpci do not expect + * 32-bit domain numbers. To keep them working, we keep a 16-bit + * version of the domain number at the previous location in struct + * pci_dev. This will keep backward compatibility on systems which + * don't require large domain numbers. + */ + if (d->domain > 0xffff) + d->domain_16 = 0xffff; + else + d->domain_16 = d->domain; + return 1; } @@ -55,14 +67,25 @@ pci_get_dev(struct pci_access *a, int domain, int bus, int dev, int func) return d; } +static void +pci_free_properties(struct pci_dev *d) +{ + struct pci_property *p; + + while (p = d->properties) + { + d->properties = p->next; + pci_mfree(p); + } +} + void pci_free_dev(struct pci_dev *d) { if (d->methods->cleanup_dev) d->methods->cleanup_dev(d); + pci_free_caps(d); - pci_mfree(d->module_alias); - pci_mfree(d->label); - pci_mfree(d->phy_slot); + pci_free_properties(d); pci_mfree(d); } @@ -154,34 +177,47 @@ pci_write_block(struct pci_dev *d, int pos, byte *buf, int len) return d->methods->write(d, pos, buf, len); } +static void +pci_reset_properties(struct pci_dev *d) +{ + d->known_fields = 0; + d->phy_slot = NULL; + d->module_alias = NULL; + d->label = NULL; + pci_free_caps(d); + pci_free_properties(d); +} + int -pci_fill_info_v35(struct pci_dev *d, int flags) +pci_fill_info_v38(struct pci_dev *d, int flags) { - if (flags & PCI_FILL_RESCAN) + unsigned int uflags = flags; + if (uflags & PCI_FILL_RESCAN) { - flags &= ~PCI_FILL_RESCAN; - d->known_fields = 0; - pci_free_caps(d); + uflags &= ~PCI_FILL_RESCAN; + pci_reset_properties(d); } - if (flags & ~d->known_fields) - d->known_fields |= d->methods->fill_info(d, flags & ~d->known_fields); + if (uflags & ~d->known_fields) + d->methods->fill_info(d, uflags); return d->known_fields; } /* In version 3.1, pci_fill_info got new flags => versioned alias */ -/* In versions 3.2, 3.3, 3.4 and 3.5, the same has happened */ -STATIC_ALIAS(int pci_fill_info(struct pci_dev *d, int flags), pci_fill_info_v35(d, flags)); -DEFINE_ALIAS(int pci_fill_info_v30(struct pci_dev *d, int flags), pci_fill_info_v35); -DEFINE_ALIAS(int pci_fill_info_v31(struct pci_dev *d, int flags), pci_fill_info_v35); -DEFINE_ALIAS(int pci_fill_info_v32(struct pci_dev *d, int flags), pci_fill_info_v35); -DEFINE_ALIAS(int pci_fill_info_v33(struct pci_dev *d, int flags), pci_fill_info_v35); -DEFINE_ALIAS(int pci_fill_info_v34(struct pci_dev *d, int flags), pci_fill_info_v35); +/* In versions 3.2, 3.3, 3.4, 3.5 and 3.8, the same has happened */ +STATIC_ALIAS(int pci_fill_info(struct pci_dev *d, int flags), pci_fill_info_v38(d, flags)); +DEFINE_ALIAS(int pci_fill_info_v30(struct pci_dev *d, int flags), pci_fill_info_v38); +DEFINE_ALIAS(int pci_fill_info_v31(struct pci_dev *d, int flags), pci_fill_info_v38); +DEFINE_ALIAS(int pci_fill_info_v32(struct pci_dev *d, int flags), pci_fill_info_v38); +DEFINE_ALIAS(int pci_fill_info_v33(struct pci_dev *d, int flags), pci_fill_info_v38); +DEFINE_ALIAS(int pci_fill_info_v34(struct pci_dev *d, int flags), pci_fill_info_v38); +DEFINE_ALIAS(int pci_fill_info_v35(struct pci_dev *d, int flags), pci_fill_info_v38); 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_v33, pci_fill_info@LIBPCI_3.3); SYMBOL_VERSION(pci_fill_info_v34, pci_fill_info@LIBPCI_3.4); -SYMBOL_VERSION(pci_fill_info_v35, pci_fill_info@@LIBPCI_3.5); +SYMBOL_VERSION(pci_fill_info_v35, pci_fill_info@LIBPCI_3.5); +SYMBOL_VERSION(pci_fill_info_v38, pci_fill_info@@LIBPCI_3.8); void pci_setup_cache(struct pci_dev *d, byte *cache, int len) @@ -189,3 +225,44 @@ pci_setup_cache(struct pci_dev *d, byte *cache, int len) d->cache = cache; d->cache_len = len; } + +char * +pci_set_property(struct pci_dev *d, u32 key, char *value) +{ + struct pci_property *p; + struct pci_property **pp = &d->properties; + + while (p = *pp) + { + if (p->key == key) + { + *pp = p->next; + pci_mfree(p); + } + else + pp = &p->next; + } + + if (!value) + return NULL; + + p = pci_malloc(d->access, sizeof(*p) + strlen(value)); + *pp = p; + p->next = NULL; + p->key = key; + strcpy(p->value, value); + + return p->value; +} + +char * +pci_get_string_property(struct pci_dev *d, u32 prop) +{ + struct pci_property *p; + + for (p = d->properties; p; p = p->next) + if (p->key == prop) + return p->value; + + return NULL; +}