]> mj.ucw.cz Git - pciutils.git/blob - ls-kernel.c
libpci: ecam: Fix detect sequence when addresses are not specified
[pciutils.git] / ls-kernel.c
1 /*
2  *      The PCI Utilities -- Show Kernel Drivers
3  *
4  *      Copyright (c) 1997--2013 Martin Mares <mj@ucw.cz>
5  *
6  *      Can be freely distributed and used under the terms of the GNU GPL v2+.
7  *
8  *      SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include <stdio.h>
12 #include <string.h>
13
14 #include "lspci.h"
15
16 #ifdef PCI_OS_LINUX
17
18 #include <sys/utsname.h>
19
20 #ifdef PCI_USE_LIBKMOD
21
22 #include <libkmod.h>
23
24 static struct kmod_ctx *kmod_ctx;
25
26 static int
27 show_kernel_init(void)
28 {
29   static int show_kernel_inited = -1;
30   if (show_kernel_inited >= 0)
31     return show_kernel_inited;
32
33   kmod_ctx = kmod_new(NULL, NULL);
34   if (!kmod_ctx)
35     {
36       fprintf(stderr, "lspci: Unable to initialize libkmod context\n");
37       goto failed;
38     }
39
40   int err;
41   if ((err = kmod_load_resources(kmod_ctx)) < 0)
42     {
43       fprintf(stderr, "lspci: Unable to load libkmod resources: error %d\n", err);
44       goto failed;
45     }
46
47   show_kernel_inited = 1;
48   return 1;
49
50 failed:
51   show_kernel_inited = 0;
52   return 0;
53 }
54
55 void
56 show_kernel_cleanup(void)
57 {
58   if (kmod_ctx)
59     kmod_unref(kmod_ctx);
60 }
61
62 static const char *next_module(struct device *d)
63 {
64   static struct kmod_list *klist, *kcurrent;
65   static struct kmod_module *kmodule;
66
67   if (kmodule)
68     {
69       kmod_module_unref(kmodule);
70       kmodule = NULL;
71     }
72
73   if (!klist)
74     {
75       pci_fill_info(d->dev, PCI_FILL_MODULE_ALIAS);
76       if (!d->dev->module_alias)
77         return NULL;
78       int err = kmod_module_new_from_lookup(kmod_ctx, d->dev->module_alias, &klist);
79       if (err < 0)
80         {
81           fprintf(stderr, "lspci: libkmod lookup failed: error %d\n", err);
82           return NULL;
83         }
84       kcurrent = klist;
85     }
86   else
87     kcurrent = kmod_list_next(klist, kcurrent);
88
89   if (kcurrent)
90     {
91       kmodule = kmod_module_get_module(kcurrent);
92       return kmod_module_get_name(kmodule);
93     }
94
95   kmod_module_unref_list(klist);
96   klist = NULL;
97   return NULL;
98 }
99
100 #else
101
102 struct pcimap_entry {
103   struct pcimap_entry *next;
104   unsigned int vendor, device;
105   unsigned int subvendor, subdevice;
106   unsigned int class, class_mask;
107   char module[1];
108 };
109
110 static struct pcimap_entry *pcimap_head;
111
112 static int
113 show_kernel_init(void)
114 {
115   static int tried_pcimap;
116   struct utsname uts;
117   char *name, line[1024];
118   FILE *f;
119
120   if (tried_pcimap)
121     return 1;
122   tried_pcimap = 1;
123
124   if (name = opt_pcimap)
125     {
126       f = fopen(name, "r");
127       if (!f)
128         die("Cannot open pcimap file %s: %m", name);
129     }
130   else
131     {
132       if (uname(&uts) < 0)
133         die("uname() failed: %m");
134       name = alloca(64 + strlen(uts.release));
135       sprintf(name, "/lib/modules/%s/modules.pcimap", uts.release);
136       f = fopen(name, "r");
137       if (!f)
138         return 1;
139     }
140
141   while (fgets(line, sizeof(line), f))
142     {
143       char *c = strchr(line, '\n');
144       struct pcimap_entry *e;
145
146       if (!c)
147         die("Unterminated or too long line in %s", name);
148       *c = 0;
149       if (!line[0] || line[0] == '#')
150         continue;
151
152       c = line;
153       while (*c && *c != ' ' && *c != '\t')
154         c++;
155       if (!*c)
156         continue;       /* FIXME: Emit warnings! */
157       *c++ = 0;
158
159       e = xmalloc(sizeof(*e) + strlen(line));
160       if (sscanf(c, "%i%i%i%i%i%i",
161                  &e->vendor, &e->device,
162                  &e->subvendor, &e->subdevice,
163                  &e->class, &e->class_mask) != 6)
164         continue;
165       e->next = pcimap_head;
166       pcimap_head = e;
167       strcpy(e->module, line);
168     }
169   fclose(f);
170
171   return 1;
172 }
173
174 static int
175 match_pcimap(struct device *d, struct pcimap_entry *e)
176 {
177   struct pci_dev *dev = d->dev;
178   unsigned int class = (((unsigned int)dev->device_class << 8) | dev->prog_if);
179
180 #define MATCH(x, y) ((y) > 0xffff || (x) == (y))
181   return
182     MATCH(dev->vendor_id, e->vendor) &&
183     MATCH(dev->device_id, e->device) &&
184     MATCH(dev->subsys_vendor_id, e->subvendor) &&
185     MATCH(dev->subsys_id, e->subdevice) &&
186     (class & e->class_mask) == e->class;
187 #undef MATCH
188 }
189
190 static const char *next_module(struct device *d)
191 {
192   static struct pcimap_entry *current;
193
194   if (!current)
195     current = pcimap_head;
196   else
197     current = current->next;
198
199   while (current)
200     {
201       if (match_pcimap(d, current))
202         return current->module;
203       current = current->next;
204     }
205
206   return NULL;
207 }
208
209 void
210 show_kernel_cleanup(void)
211 {
212 }
213
214 #endif
215
216 static const char *
217 next_module_filtered(struct device *d)
218 {
219   static char prev_module[256];
220   const char *module;
221
222   while (module = next_module(d))
223     {
224       if (strcmp(module, prev_module))
225         {
226           strncpy(prev_module, module, sizeof(prev_module));
227           prev_module[sizeof(prev_module) - 1] = 0;
228           return module;
229         }
230     }
231   prev_module[0] = 0;
232   return NULL;
233 }
234
235 void
236 show_kernel(struct device *d)
237 {
238   const char *driver, *module;
239
240   pci_fill_info(d->dev, PCI_FILL_DRIVER);
241   if (driver = pci_get_string_property(d->dev, PCI_FILL_DRIVER))
242     printf("\tKernel driver in use: %s\n", driver);
243
244   if (!show_kernel_init())
245     return;
246
247   int cnt = 0;
248   while (module = next_module_filtered(d))
249     printf("%s %s", (cnt++ ? "," : "\tKernel modules:"), module);
250   if (cnt)
251     putchar('\n');
252 }
253
254 void
255 show_kernel_machine(struct device *d)
256 {
257   const char *driver, *module;
258
259   pci_fill_info(d->dev, PCI_FILL_DRIVER);
260   if (driver = pci_get_string_property(d->dev, PCI_FILL_DRIVER))
261     printf("Driver:\t%s\n", driver);
262
263   if (!show_kernel_init())
264     return;
265
266   while (module = next_module_filtered(d))
267     printf("Module:\t%s\n", module);
268 }
269
270 #else
271
272 void
273 show_kernel(struct device *d)
274 {
275   const char *driver;
276
277   pci_fill_info(d->dev, PCI_FILL_DRIVER);
278   if (driver = pci_get_string_property(d->dev, PCI_FILL_DRIVER))
279     printf("\tDriver in use: %s\n", driver);
280 }
281
282 void
283 show_kernel_machine(struct device *d)
284 {
285   const char *driver;
286
287   pci_fill_info(d->dev, PCI_FILL_DRIVER);
288   if (driver = pci_get_string_property(d->dev, PCI_FILL_DRIVER))
289     printf("Driver:\t%s\n", driver);
290 }
291
292 void
293 show_kernel_cleanup(void)
294 {
295 }
296
297 #endif
298