--- pciutils-2.1.10/lib/Makefile.ORI Fri Oct 11 17:23:36 2002 +++ pciutils-2.1.10/lib/Makefile Fri Oct 11 17:24:02 2002 @@ -4,7 +4,7 @@ include config.mk -OBJS=access.o generic.o dump.o names.o filter.o +OBJS=access.o generic.o dump.o names.o filter.o modules.o INCL=internal.h pci.h config.h ifdef HAVE_PM_LINUX_PROC @@ -53,3 +53,4 @@ dump.o: dump.c $(INCL) names.o: names.c $(INCL) filter.o: filter.c $(INCL) +modules.o: modules.c $(INCL) --- pciutils-2.1.10/lib/access.c.ORI Fri Oct 11 17:22:19 2002 +++ pciutils-2.1.10/lib/access.c Fri Oct 11 17:24:35 2002 @@ -12,6 +12,7 @@ #include #include #include +#include #include "internal.h" @@ -51,17 +52,28 @@ #endif }; +#define PCIMAP_PATH_SIZE 1024 + struct pci_access * pci_alloc(void) { struct pci_access *a = malloc(sizeof(struct pci_access)); int i; + struct utsname _utsname; + char *pcimap = malloc(PCIMAP_PATH_SIZE); bzero(a, sizeof(*a)); a->id_file_name = PATH_PCI_IDS; for(i=0; iconfig) pci_methods[i]->config(a); + + if ( uname(&_utsname) == -1 ) + a->error("Cannot get uname information"); + snprintf(pcimap, PCIMAP_PATH_SIZE, "/lib/modules/%s/modules.pcimap", + _utsname.release); + a->modules_file_name = pcimap; + return a; } --- pciutils-2.1.10/lib/pci.h.ORI Fri Oct 11 17:40:53 2002 +++ pciutils-2.1.10/lib/pci.h Fri Oct 11 17:42:23 2002 @@ -83,6 +83,7 @@ int writeable; /* Open in read/write mode */ int buscentric; /* Bus-centric view of the world */ char *id_file_name; /* Name of ID list file */ + char *modules_file_name; /* Name of ID to modules list */ int numeric_ids; /* Don't resolve device IDs to names */ int debugging; /* Turn on debugging messages */ @@ -97,6 +98,8 @@ struct pci_methods *methods; char *nl_list; /* Name list cache */ struct nl_entry **nl_hash; + char *ml_list; /* Modules list cache */ + struct ml_entry **ml_hash; int fd; /* proc: fd */ int fd_rw; /* proc: fd opened read-write */ struct pci_dev *cached_dev; /* proc: device the fd is for */ @@ -184,6 +187,13 @@ char *pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, u32 arg1, u32 arg2, u32 arg3, u32 arg4); void pci_free_name_list(struct pci_access *a); +/* + * Modules names + */ + +char *pci_lookup_module(struct pci_access *a, int flags, u32 arg1, u32 arg2, u32 arg3, u32 arg4); +void pci_free_module_list(struct pci_access *a); + #define PCI_LOOKUP_VENDOR 1 #define PCI_LOOKUP_DEVICE 2 #define PCI_LOOKUP_CLASS 4 --- pciutils-2.1.10/lib/modules.c.ORI Fri Oct 11 17:57:09 2002 +++ pciutils-2.1.10/lib/modules.c Fri Oct 11 17:44:52 2002 @@ -0,0 +1,208 @@ +/* + * $Id$ + * + * The PCI Library -- ID To Module Translation + * + * Copyright (c) 2002 by Diego Torres Milano + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +#define DEBUG 0 + +struct ml_entry { + struct ml_entry *next; + word id1, id2, id3, id4; + byte *module; +}; + +#define HASH_SIZE 1024 + +static inline unsigned int ml_calc_hash(int id1, int id2, int id3, int id4) +{ + unsigned int h; + + h = id1 ^ id2 ^ id3 ^ id4; + h += (h >> 6); + return h & (HASH_SIZE-1); +} + +static struct ml_entry *ml_lookup(struct pci_access *a, int id1, int id2, int id3, int id4) +{ + unsigned int h; + struct ml_entry *n; + + h = ml_calc_hash(id1, id2, id3, id4); + n = a->ml_hash[h]; + while (n && (n->id1 != id1 || n->id2 != id2 || n->id3 != id3 || n->id4 != id4)) + n = n->next; +#if DEBUG + fprintf(stderr, "ml_lookup: returning n=%lp\n", n); + if ( n ) { + fprintf(stderr, "\tn->id1=%lx\n", n->id1); + fprintf(stderr, "\tn->id1=%lx\n", n->id2); + fprintf(stderr, "\tn->module='%s'\n", n->module); + } +#endif + return n; +} + +static struct ml_entry* ml_add(struct pci_access *a, unsigned int id1, unsigned int id2, unsigned int id3, unsigned int id4, byte *text) +{ + unsigned int h = ml_calc_hash(id1, id2, id3, id4); + struct ml_entry *n = a->ml_hash[h]; + +#if DEBUG + fprintf(stderr, "ml_add: id1=%lx id2=%lx id3=%lx id4=%lx\n", id1, id2, + id3, id4); +#endif + while (n && (n->id1 != id1 || n->id2 != id2 || n->id3 != id3 || n->id4 != id4)) + n = n->next; + if (n) + return n; + n = pci_malloc(a, sizeof(struct ml_entry)); + n->id1 = id1; + n->id2 = id2; + n->id3 = id3; + n->id4 = id4; + n->module = text; + n->next = a->ml_hash[h]; + a->ml_hash[h] = n; +#if DEBUG + if ( id1 == 0x0e11 ) { + fprintf(stderr, "%%%% ml_add: id1=%x id2=%x id3=%x id4=%x module=%s n=%lp\n", id1, id2, id3, id4, text, n); + } +#endif + return NULL; +} + +static void +err_module_list(struct pci_access *a, char *msg) +{ + a->error("%s: %s: %s\n", a->modules_file_name, msg, strerror(errno)); +} + +static void +parse_module_list(struct pci_access *a) +{ + byte *p = a->ml_list; + int lino = 0; + unsigned int id1=0, id2=0, id3=0, id4=0; + char buf[128]; + int n; + unsigned int sv_id; + unsigned int sd_id; + struct ml_entry *ml; + + while (*p) + { + buf[0] = '\0'; + lino++; + /*q = p;*/ + while (*p && *p != '\n') + { + if (*p == '#') + { + *p++ = 0; + while (*p && *p != '\n') + p++; + break; + } + p++; + } + if (*p == '\n') + *p++ = 0; + + sscanf(p, "%s %x %x %x %x %n", &buf, &id1, &id2, &id3, &id4, &n); +#if DEBUG + fprintf(stderr, "buf=%s %x %x %x %x comp=%d\n", buf, id1, id2, id3, id4, (id3 && id3 != 0xffffffff)); +#endif + if ( *p && buf[0] == '\0' ) + goto parserr; + + p+=n; + + sv_id = (id3 && id3 != 0xffffffff) ? id3 : 0; + sd_id = (sv_id) ? id4 : 0; + if ( (ml = ml_add(a, id1, id2, sv_id, sd_id, strdup(buf))) ) { +#if DEBUG + a->warning("%s, line %d: entry already exists for %s", + a->modules_file_name, lino, ml->module); +#endif + } + } + + return; + +parserr: + a->error("%s, line %d: parse error", a->modules_file_name, lino); +} + +static void +load_module_list(struct pci_access *a) +{ + int fd; + struct stat st; + + fd = open(a->modules_file_name, O_RDONLY); + if (fd < 0) + { + return; + } + if (fstat(fd, &st) < 0) + err_module_list(a, "stat"); + a->ml_list = pci_malloc(a, st.st_size + 1); + if (read(fd, a->ml_list, st.st_size) != st.st_size) + err_module_list(a, "read"); + a->ml_list[st.st_size] = 0; + a->ml_hash = pci_malloc(a, sizeof(struct ml_entry *) * HASH_SIZE); + bzero(a->ml_hash, sizeof(struct ml_entry *) * HASH_SIZE); + parse_module_list(a); + close(fd); +} + +void +pci_free_module_list(struct pci_access *a) +{ + pci_mfree(a->ml_list); + a->ml_list = NULL; + pci_mfree(a->ml_hash); + a->ml_hash = NULL; +} + +char * +pci_lookup_module(struct pci_access *a, int flags, u32 arg1, u32 arg2, u32 arg3, u32 arg4) +{ + int res; + struct ml_entry *n; + static char* unknown = "UNKNOWN"; + + if (!a->ml_hash) + { + load_module_list(a); + } + switch (flags) + { + case PCI_LOOKUP_DEVICE: +#if DEBUG + fprintf(stderr, "searching for %x %x %x %x\n", arg1, arg2, arg3, arg4); +#endif + if (n = ml_lookup(a, arg1, arg2, arg3, arg4)) + return n->module; + else + return unknown; + break; + } + + return unknown; +} --- pciutils-2.1.10/lspci.c.ORI Fri Oct 11 16:57:10 2002 +++ pciutils-2.1.10/lspci.c Fri Oct 11 17:10:40 2002 @@ -25,8 +25,9 @@ static int show_tree; /* Show bus tree */ static int machine_readable; /* Generate machine-readable output */ static int map_mode; /* Bus mapping mode enabled */ +static int show_kernel_module; /* Show the corresponding kernel module */ -static char options[] = "nvbxs:d:ti:mgM" GENERIC_OPTIONS ; +static char options[] = "nvbxs:d:ti:mgMk" GENERIC_OPTIONS ; static char help_msg[] = "\ Usage: lspci []\n\ @@ -40,7 +41,8 @@ -t\t\tShow bus tree\n\ -m\t\tProduce machine-readable output\n\ -i \tUse specified ID database instead of %s\n\ --M\t\tEnable `bus mapping' mode (dangerous; root only)\n" +-M\t\tEnable `bus mapping' mode (dangerous; root only)\n\ +-k\t\tShow kernel module\n" GENERIC_HELP ; @@ -265,6 +267,35 @@ putchar(')'); } } + + if ( show_kernel_module ) + { + word sv_id=0, sd_id=0; + + switch (get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f) + { + case PCI_HEADER_TYPE_NORMAL: + sv_id = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID); + sd_id = get_conf_word(d, PCI_SUBSYSTEM_ID); + break; + case PCI_HEADER_TYPE_CARDBUS: + sv_id = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID); + sd_id = get_conf_word(d, PCI_CB_SUBSYSTEM_ID); + break; + } + + sv_id = (sv_id && sv_id != 0xffffffff) ? sv_id : 0; + sd_id = (sv_id) ? sd_id : 0; + +#if DEBUG + fprintf(stderr, "\nI should search for %x %x\n", p->vendor_id, + p->device_id); +#endif + printf(" Kernel module: %s", + pci_lookup_module(pacc, PCI_LOOKUP_DEVICE, + p->vendor_id, p->device_id, 0, 0)); + } + putchar('\n'); } @@ -1008,6 +1039,12 @@ printf("Rev:\t%02x\n", c); if (c = get_conf_byte(d, PCI_CLASS_PROG)) printf("ProgIf:\t%02x\n", c); + if ( show_kernel_module ) + { + printf("Module:\t%s\n", + pci_lookup_module(pacc, PCI_LOOKUP_DEVICE, + p->vendor_id, p->device_id, sv_id, sd_id)); + } } else { @@ -1029,6 +1066,14 @@ pci_lookup_name(pacc, sdbuf, sizeof(sdbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id, sv_id, sd_id)); else printf(" \"\" \"\""); + + if ( show_kernel_module ) + { + printf(" \"%s\"", + pci_lookup_module(pacc, PCI_LOOKUP_DEVICE, + p->vendor_id, p->device_id, sv_id, sd_id)); + } + putchar('\n'); } } @@ -1524,6 +1569,9 @@ case 'M': map_mode++; break; + case 'k': + show_kernel_module++; + break; default: if (parse_generic_option(i, pacc, optarg)) break;