From bc2eed2d4fab4369174d45ab7c07c5128c712e42 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sat, 3 Jun 2006 19:36:35 +0200 Subject: [PATCH] Introduced the -nn switch. --- ChangeLog | 8 ++ lib/names.c | 234 ++++++++++++++++++++++++---------------------------- lib/pci.h | 6 +- lspci.c | 3 +- lspci.man | 3 + 5 files changed, 125 insertions(+), 129 deletions(-) diff --git a/ChangeLog b/ChangeLog index 45545e1..7fd6a51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2006-06-03 Martin Mares + + * lspci.c: Introduced the -nn switch. Thanks to David N. Welton + for the idea. + + * lib/names.c (pci_lookup_name): Introduced PCI_LOOKUP_MIXED and + cleaned up the name selection code. + 2006-05-31 Martin Mares * setpci.c (main): Don't crash when an invalid width is specified. diff --git a/lib/names.c b/lib/names.c index a60cb38..cfda85d 100644 --- a/lib/names.c +++ b/lib/names.c @@ -81,16 +81,18 @@ static inline unsigned int id_hash(int cat, u32 id12, u32 id34) return h % HASH_SIZE; } -static struct id_entry *id_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4) +static byte *id_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4) { struct id_entry *n; u32 id12 = id_pair(id1, id2); u32 id34 = id_pair(id3, id4); + if (!a->id_hash) + return NULL; n = a->id_hash[id_hash(cat, id12, id34)]; while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) n = n->next; - return n; + return n ? n->name : NULL; } static int id_insert(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, byte *text) @@ -278,6 +280,7 @@ pci_load_name_list(struct pci_access *a) const char *err; pci_free_name_list(a); + a->hash_load_failed = 1; if (!(f = fopen(a->id_file_name, "r"))) return 0; a->id_hash = pci_malloc(a, sizeof(struct id_entry *) * HASH_SIZE); @@ -288,6 +291,7 @@ pci_load_name_list(struct pci_access *a) fclose(f); if (err) a->error("%s at %s, line %d\n", err, a->id_file_name, lino); + a->hash_load_failed = 0; return 1; } @@ -304,9 +308,10 @@ pci_free_name_list(struct pci_access *a) } } -static struct id_entry *id_lookup_subsys(struct pci_access *a, int iv, int id, int isv, int isd) +static byte * +id_lookup_subsys(struct pci_access *a, int iv, int id, int isv, int isd) { - struct id_entry *d = NULL; + byte *d = NULL; if (iv > 0 && id > 0) /* Per-device lookup */ d = id_lookup(a, ID_SUBSYSTEM, iv, id, isv, isd); if (!d) /* Generic lookup */ @@ -316,168 +321,145 @@ static struct id_entry *id_lookup_subsys(struct pci_access *a, int iv, int id, i return d; } +static byte * +format_name(char *buf, int size, int flags, byte *name, byte *num, byte *unknown) +{ + int res; + if ((flags & PCI_LOOKUP_NO_NUMBERS) && !name) + return NULL; + else if (flags & PCI_LOOKUP_NUMERIC) + res = snprintf(buf, size, "%s", num); + else if (!name) + res = snprintf(buf, size, ((flags & PCI_LOOKUP_MIXED) ? "%s [%s]" : "%s %s"), unknown, num); + else if (!(flags & PCI_LOOKUP_MIXED)) + res = snprintf(buf, size, "%s", name); + else + res = snprintf(buf, size, "%s [%s]", name, num); + if (res < 0 || res >= size) + return ""; + else + return buf; +} + +static byte * +format_name_pair(char *buf, int size, int flags, byte *v, byte *d, byte *num) +{ + int res; + if ((flags & PCI_LOOKUP_NO_NUMBERS) && (!v || !d)) + return NULL; + if (flags & PCI_LOOKUP_NUMERIC) + res = snprintf(buf, size, "%s", num); + else if (flags & PCI_LOOKUP_MIXED) + { + if (v && d) + res = snprintf(buf, size, "%s %s [%s]", v, d, num); + else if (!v) + res = snprintf(buf, size, "Unknown device [%s]", num); + else /* v && !d */ + res = snprintf(buf, size, "%s Unknown device [%s]", v, num); + } + else + { + if (v && d) + res = snprintf(buf, size, "%s %s", v, d); + else if (!v) + res = snprintf(buf, size, "Unknown device %s", num); + else /* v && !d */ + res = snprintf(buf, size, "%s Unknown device %s", v, num+5); + } + if (res < 0 || res >= size) + return ""; + else + return buf; +} + char * pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, ...) { va_list args; - int num, res, synth; - struct id_entry *v, *d, *cls, *pif; + byte *v, *d, *cls, *pif; int iv, id, isv, isd, icls, ipif; + byte numbuf[16], pifbuf[32]; va_start(args, flags); - num = 0; - if ((flags & PCI_LOOKUP_NUMERIC) || a->numeric_ids) - { - flags &= ~PCI_LOOKUP_NUMERIC; - num = 1; - } - else if (!a->id_hash) - { - if (!pci_load_name_list(a)) - num = a->numeric_ids = 1; - } + if (a->numeric_ids > 1) + flags |= PCI_LOOKUP_MIXED; + else if (a->numeric_ids) + flags |= PCI_LOOKUP_NUMERIC; + if (flags & PCI_LOOKUP_MIXED) + flags &= ~PCI_LOOKUP_NUMERIC; - if (flags & PCI_LOOKUP_NO_NUMBERS) - { - flags &= ~PCI_LOOKUP_NO_NUMBERS; - synth = 0; - if (num) - return NULL; - } - else - synth = 1; + if (!a->id_hash && !(flags & PCI_LOOKUP_NUMERIC) && !a->hash_load_failed) + pci_load_name_list(a); - switch (flags) + switch (flags & 0xffff) { case PCI_LOOKUP_VENDOR: iv = va_arg(args, int); - if (num) - res = snprintf(buf, size, "%04x", iv); - else if (v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0)) - return v->name; - else - res = snprintf(buf, size, "Unknown vendor %04x", iv); - break; + sprintf(numbuf, "%04x", iv); + return format_name(buf, size, flags, id_lookup(a, ID_VENDOR, iv, 0, 0, 0), numbuf, "Unknown vendor"); case PCI_LOOKUP_DEVICE: iv = va_arg(args, int); id = va_arg(args, int); - if (num) - res = snprintf(buf, size, "%04x", id); - else if (d = id_lookup(a, ID_DEVICE, iv, id, 0, 0)) - return d->name; - else if (synth) - res = snprintf(buf, size, "Unknown device %04x", id); - else - return NULL; - break; + sprintf(numbuf, "%04x", id); + return format_name(buf, size, flags, id_lookup(a, ID_DEVICE, iv, id, 0, 0), numbuf, "Unknown device"); case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE: iv = va_arg(args, int); id = va_arg(args, int); - if (num) - res = snprintf(buf, size, "%04x:%04x", iv, id); - else - { - v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0); - d = id_lookup(a, ID_DEVICE, iv, id, 0, 0); - if (v && d) - res = snprintf(buf, size, "%s %s", v->name, d->name); - else if (!synth) - return NULL; - else if (!v) - res = snprintf(buf, size, "Unknown device %04x:%04x", iv, id); - else /* !d */ - res = snprintf(buf, size, "%s Unknown device %04x", v->name, id); - } - break; + sprintf(numbuf, "%04x:%04x", iv, id); + v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0); + d = id_lookup(a, ID_DEVICE, iv, id, 0, 0); + return format_name_pair(buf, size, flags, v, d, numbuf); case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR: isv = va_arg(args, int); - if (num) - res = snprintf(buf, size, "%04x", isv); - else if (v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0)) - return v->name; - else if (synth) - res = snprintf(buf, size, "Unknown vendor %04x", isv); - else - return NULL; - break; + sprintf(numbuf, "%04x", isv); + v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0); + return format_name(buf, size, flags, v, numbuf, "Unknown vendor"); case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE: iv = va_arg(args, int); id = va_arg(args, int); isv = va_arg(args, int); isd = va_arg(args, int); - if (num) - res = snprintf(buf, size, "%04x", isd); - else if (d = id_lookup_subsys(a, iv, id, isv, isd)) - return d->name; - else if (synth) - res = snprintf(buf, size, "Unknown device %04x", isd); - else - return NULL; - break; + sprintf(numbuf, "%04x", isd); + return format_name(buf, size, flags, id_lookup_subsys(a, iv, id, isv, isd), numbuf, "Unknown device"); case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM: iv = va_arg(args, int); id = va_arg(args, int); isv = va_arg(args, int); isd = va_arg(args, int); - if (num) - res = snprintf(buf, size, "%04x:%04x", isv, isd); - else - { - v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0); - d = id_lookup_subsys(a, iv, id, isv, isd); - if (v && d) - res = snprintf(buf, size, "%s %s", v->name, d->name); - else if (!synth) - return NULL; - else if (!v) - res = snprintf(buf, size, "Unknown device %04x:%04x", isv, isd); - else /* !d */ - res = snprintf(buf, size, "%s Unknown device %04x", v->name, isd); - } - break; + v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0); + d = id_lookup_subsys(a, iv, id, isv, isd); + sprintf(numbuf, "%04x:%04x", isv, isd); + return format_name_pair(buf, size, flags, v, d, numbuf); case PCI_LOOKUP_CLASS: icls = va_arg(args, int); - if (num) - res = snprintf(buf, size, "%04x", icls); - else if (cls = id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 0, 0)) - return cls->name; - else if (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0)) - res = snprintf(buf, size, "%s [%04x]", cls->name, icls); - else if (synth) - res = snprintf(buf, size, "Class %04x", icls); - else - return NULL; - break; + sprintf(numbuf, "%04x", icls); + cls = id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 0, 0); + if (!cls && (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0))) + { + if (!(flags & PCI_LOOKUP_NUMERIC)) /* Include full class number */ + flags |= PCI_LOOKUP_MIXED; + } + return format_name(buf, size, flags, cls, numbuf, ((flags & PCI_LOOKUP_MIXED) ? "Unknown class" : "Class")); case PCI_LOOKUP_PROGIF: icls = va_arg(args, int); ipif = va_arg(args, int); - if (num) - res = snprintf(buf, size, "%02x", ipif); - else if (pif = id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, ipif, 0)) - return pif->name; - else if (icls == 0x0101 && !(ipif & 0x70)) + sprintf(numbuf, "%02x", ipif); + pif = id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, ipif, 0); + if (!pif && icls == 0x0101 && !(ipif & 0x70)) { /* IDE controllers have complex prog-if semantics */ - res = snprintf(buf, size, "%s%s%s%s%s", - (ipif & 0x80) ? "Master " : "", - (ipif & 0x08) ? "SecP " : "", - (ipif & 0x04) ? "SecO " : "", - (ipif & 0x02) ? "PriP " : "", - (ipif & 0x01) ? "PriO " : ""); - if (res > 0 && res < size) - buf[--res] = 0; + sprintf(pifbuf, "%s%s%s%s%s", + (ipif & 0x80) ? "Master " : "", + (ipif & 0x08) ? "SecP " : "", + (ipif & 0x04) ? "SecO " : "", + (ipif & 0x02) ? "PriP " : "", + (ipif & 0x01) ? "PriO " : ""); + pif = pifbuf; } - else if (synth) - res = snprintf(buf, size, "ProgIf %02x", ipif); - else - return NULL; - break; + return format_name(buf, size, flags, pif, numbuf, "ProgIf"); default: return ""; } - if (res < 0 || res >= size) - return ""; - else - return buf; } diff --git a/lib/pci.h b/lib/pci.h index 7fa1de6..8618df5 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -43,7 +43,7 @@ struct pci_access { int writeable; /* Open in read/write mode */ int buscentric; /* Bus-centric view of the world */ char *id_file_name; /* Name of ID list file */ - int numeric_ids; /* Don't resolve device IDs to names */ + int numeric_ids; /* Enforce PCI_LOOKUP_NUMERIC (>1 => PCI_LOOKUP_MIXED) */ int debugging; /* Turn on debugging messages */ /* Functions you can override: */ @@ -57,6 +57,7 @@ struct pci_access { struct pci_methods *methods; struct id_entry **id_hash; /* names.c */ struct id_bucket *current_id_bucket; + int hash_load_failed; int fd; /* proc: fd */ int fd_rw; /* proc: fd opened read-write */ struct pci_dev *cached_dev; /* proc: device the fd is for */ @@ -165,7 +166,8 @@ enum pci_lookup_mode { PCI_LOOKUP_SUBSYSTEM = 8, PCI_LOOKUP_PROGIF = 16, /* Programming interface (args: classID, prog_if) */ PCI_LOOKUP_NUMERIC = 0x10000, /* Want only formatted numbers; default if access->numeric_ids is set */ - PCI_LOOKUP_NO_NUMBERS = 0x20000 /* Return NULL if not found in the database; default is to print numerically */ + PCI_LOOKUP_NO_NUMBERS = 0x20000, /* Return NULL if not found in the database; default is to print numerically */ + PCI_LOOKUP_MIXED = 0x40000, /* Include both numbers and names */ }; #endif diff --git a/lspci.c b/lspci.c index f5fd7cd..84a23e5 100644 --- a/lspci.c +++ b/lspci.c @@ -34,6 +34,7 @@ Usage: lspci []\n\ \n\ -v\t\tBe verbose\n\ -n\t\tShow numeric ID's\n\ +-nn\t\tShow both textual and numeric ID's (names & numbers)\n\ -b\t\tBus-centric view (PCI addresses and IRQ's instead of those seen by the CPU)\n\ -x\t\tShow hex-dump of the standard portion of config space\n\ -xxx\t\tShow hex-dump of the whole config space (dangerous; root only)\n\ @@ -2291,7 +2292,7 @@ main(int argc, char **argv) switch (i) { case 'n': - pacc->numeric_ids = 1; + pacc->numeric_ids++; break; case 'v': verbose++; diff --git a/lspci.man b/lspci.man index c28deb4..db7fce8 100644 --- a/lspci.man +++ b/lspci.man @@ -54,6 +54,9 @@ even if it doesn't look interesting at all (e.g., undefined memory regions). Show PCI vendor and device codes as numbers instead of looking them up in the PCI ID list. .TP +.B -nn +Show PCI vendor and device codes as both numbers and names. +.TP .B -x Show hexadecimal dump of the standard part of the configuration space (the first 64 bytes or 128 bytes for CardBus bridges). -- 2.39.2