2 * pcimodules: Load all kernel modules for PCI device currently
3 * plugged into any PCI slot.
5 * Copyright 2000 Yggdrasil Computing, Incorporated
6 * This file may be copied under the terms and conditions of version
7 * two of the GNU General Public License, as published by the Free
8 * Software Foundation (Cambridge, Massachusetts, USA).
10 * This file is based on pciutils/lib/example.c, which has the following
11 * authorship and copyright statement:
13 * Written by Martin Mares and put to public domain. You can do
14 * with it anything you want, but I don't give you any warranty.
22 #include <sys/utsname.h>
23 #include <sys/param.h>
24 #include <sys/types.h>
31 const char program_name[] = "pcimodules";
33 #define MODDIR "/lib/modules"
34 #define PCIMAP "modules.pcimap"
36 #define LINELENGTH 8000
38 #define DEVICE_ANY 0xffffffff
39 #define VENDOR_ANY 0xffffffff
44 unsigned int vendor, subsys_vendor, dev, subsys_dev, class, class_mask;
46 struct pcimap_entry *next;
49 static struct pcimap_entry *pcimap_list = NULL;
51 #define OPT_STRING "h"
52 static struct option long_options[] = {
53 {"class", required_argument, NULL, 'c'},
54 {"classmask", required_argument, NULL, 'm'},
55 {"help", no_argument, NULL, 'h'},
59 static unsigned long desired_class;
60 static unsigned long desired_classmask; /* Default is 0: accept all classes.*/
65 struct utsname utsname;
66 char filename[MAXPATHLEN];
68 char line[LINELENGTH];
69 struct pcimap_entry *entry;
70 unsigned int driver_data;
71 char *prevmodule = "";
72 char module[LINELENGTH];
74 if (uname(&utsname) < 0) {
78 sprintf(filename, "%s/%s/%s", MODDIR, utsname.release, PCIMAP);
79 if ((pcimap_file = fopen(filename, "r")) == NULL) {
84 while(fgets(line, LINELENGTH, pcimap_file) != NULL) {
88 entry = xmalloc(sizeof(struct pcimap_entry));
90 if (sscanf(line, "%s 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
92 &entry->vendor, &entry->dev,
93 &entry->subsys_vendor, &entry->subsys_dev,
94 &entry->class, &entry->class_mask,
97 "modules.pcimap unparsable line: %s.\n", line);
102 /* Optimize memory allocation a bit, in case someday we
103 have Linux systems with ~100,000 modules. It also
104 allows us to just compare pointers to avoid trying
105 to load a module twice. */
106 if (strcmp(module, prevmodule) != 0) {
107 prevmodule = xmalloc(strlen(module)+1);
108 strcpy(prevmodule, module);
110 entry->module = prevmodule;
111 entry->next = pcimap_list;
117 /* Return a filled in pci_access->dev tree, with the device classes
121 match_pci_modules(void)
123 struct pci_access *pacc;
125 unsigned int class, subsys_dev, subsys_vendor;
126 struct pcimap_entry *map;
127 const char *prevmodule = "";
129 pacc = pci_alloc(); /* Get the pci_access structure */
130 /* Set all options you want -- here we stick with the defaults */
131 pci_init(pacc); /* Initialize the PCI library */
132 pci_scan_bus(pacc); /* We want to get the list of devices */
133 for(dev=pacc->devices; dev; dev=dev->next) {
134 pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES);
135 class = (pci_read_word(dev, PCI_CLASS_DEVICE) << 8)
136 | pci_read_byte(dev, PCI_CLASS_PROG);
137 subsys_dev = pci_read_word(dev, PCI_SUBSYSTEM_ID);
138 subsys_vendor = pci_read_word(dev,PCI_SUBSYSTEM_VENDOR_ID);
139 for(map = pcimap_list; map != NULL; map = map->next) {
140 if (((map->class ^ class) & map->class_mask) == 0 &&
141 ((desired_class ^ class) & desired_classmask)==0 &&
142 (map->dev == DEVICE_ANY ||
143 map->dev == dev->device_id) &&
144 (map->vendor == VENDOR_ANY ||
145 map->vendor == dev->vendor_id) &&
146 (map->subsys_dev == DEVICE_ANY ||
147 map->subsys_dev == subsys_dev) &&
148 (map->subsys_vendor == VENDOR_ANY ||
149 map->subsys_vendor == subsys_vendor) &&
150 prevmodule != map->module) {
151 printf("%s\n", map->module);
152 prevmodule = map->module;
161 main (int argc, char **argv)
166 while ((opt = getopt_long(argc, argv, OPT_STRING, long_options,
167 &opt_index)) != -1) {
170 desired_class = strtol(optarg, NULL, 0);
173 desired_classmask = strtol(optarg, NULL, 0);
176 printf ("Usage: pcimodules [--help]\n"
177 " Lists kernel modules corresponding to PCI devices currently plugged"
178 " into the computer.\n");