]>
git.ipfire.org Git - thirdparty/pciutils.git/blob - ls-kernel.c
2 * The PCI Utilities -- Show Kernel Drivers
4 * Copyright (c) 1997--2013 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
17 #include <sys/utsname.h>
19 #ifdef PCI_USE_LIBKMOD
23 static struct kmod_ctx
*kmod_ctx
;
26 show_kernel_init(void)
28 static int show_kernel_inited
= -1;
29 if (show_kernel_inited
>= 0)
30 return show_kernel_inited
;
34 die("uname() failed: %m");
35 char *name
= alloca(64 + strlen(uts
.release
));
36 sprintf(name
, "/lib/modules/%s", uts
.release
);
38 kmod_ctx
= kmod_new(name
, NULL
);
41 fprintf(stderr
, "lspci: Unable to initialize libkmod context\n");
46 if ((err
= kmod_load_resources(kmod_ctx
)) < 0)
48 fprintf(stderr
, "lspci: Unable to load libkmod resources: error %d\n", err
);
52 show_kernel_inited
= 1;
56 show_kernel_inited
= 0;
61 show_kernel_cleanup(void)
67 static const char *next_module(struct device
*d
)
69 static struct kmod_list
*klist
, *kcurrent
;
70 static struct kmod_module
*kmodule
;
74 kmod_module_unref(kmodule
);
80 pci_fill_info(d
->dev
, PCI_FILL_MODULE_ALIAS
);
81 if (!d
->dev
->module_alias
)
83 int err
= kmod_module_new_from_lookup(kmod_ctx
, d
->dev
->module_alias
, &klist
);
86 fprintf(stderr
, "lspci: libkmod lookup failed: error %d\n", err
);
92 kcurrent
= kmod_list_next(klist
, kcurrent
);
96 kmodule
= kmod_module_get_module(kcurrent
);
97 return kmod_module_get_name(kmodule
);
100 kmod_module_unref_list(klist
);
107 struct pcimap_entry
{
108 struct pcimap_entry
*next
;
109 unsigned int vendor
, device
;
110 unsigned int subvendor
, subdevice
;
111 unsigned int class, class_mask
;
115 static struct pcimap_entry
*pcimap_head
;
118 show_kernel_init(void)
120 static int tried_pcimap
;
122 char *name
, line
[1024];
129 if (name
= opt_pcimap
)
131 f
= fopen(name
, "r");
133 die("Cannot open pcimap file %s: %m", name
);
138 die("uname() failed: %m");
139 name
= alloca(64 + strlen(uts
.release
));
140 sprintf(name
, "/lib/modules/%s/modules.pcimap", uts
.release
);
141 f
= fopen(name
, "r");
146 while (fgets(line
, sizeof(line
), f
))
148 char *c
= strchr(line
, '\n');
149 struct pcimap_entry
*e
;
152 die("Unterminated or too long line in %s", name
);
154 if (!line
[0] || line
[0] == '#')
158 while (*c
&& *c
!= ' ' && *c
!= '\t')
161 continue; /* FIXME: Emit warnings! */
164 e
= xmalloc(sizeof(*e
) + strlen(line
));
165 if (sscanf(c
, "%i%i%i%i%i%i",
166 &e
->vendor
, &e
->device
,
167 &e
->subvendor
, &e
->subdevice
,
168 &e
->class, &e
->class_mask
) != 6)
170 e
->next
= pcimap_head
;
172 strcpy(e
->module
, line
);
180 match_pcimap(struct device
*d
, struct pcimap_entry
*e
)
182 struct pci_dev
*dev
= d
->dev
;
183 unsigned int class = get_conf_long(d
, PCI_REVISION_ID
) >> 8;
186 #define MATCH(x, y) ((y) > 0xffff || (x) == (y))
187 get_subid(d
, &subv
, &subd
);
189 MATCH(dev
->vendor_id
, e
->vendor
) &&
190 MATCH(dev
->device_id
, e
->device
) &&
191 MATCH(subv
, e
->subvendor
) &&
192 MATCH(subd
, e
->subdevice
) &&
193 (class & e
->class_mask
) == e
->class;
197 static const char *next_module(struct device
*d
)
199 static struct pcimap_entry
*current
;
202 current
= pcimap_head
;
204 current
= current
->next
;
208 if (match_pcimap(d
, current
))
209 return current
->module
;
210 current
= current
->next
;
217 show_kernel_cleanup(void)
223 #define DRIVER_BUF_SIZE 1024
226 find_driver(struct device
*d
, char *buf
)
228 struct pci_dev
*dev
= d
->dev
;
229 char name
[1024], *drv
, *base
;
232 if (dev
->access
->method
!= PCI_ACCESS_SYS_BUS_PCI
)
235 base
= pci_get_param(dev
->access
, "sysfs.path");
236 if (!base
|| !base
[0])
239 n
= snprintf(name
, sizeof(name
), "%s/devices/%04x:%02x:%02x.%d/driver",
240 base
, dev
->domain
, dev
->bus
, dev
->dev
, dev
->func
);
241 if (n
< 0 || n
>= (int)sizeof(name
))
242 die("show_driver: sysfs device name too long, why?");
244 n
= readlink(name
, buf
, DRIVER_BUF_SIZE
);
247 if (n
>= DRIVER_BUF_SIZE
)
248 return "<name-too-long>";
251 if (drv
= strrchr(buf
, '/'))
258 next_module_filtered(struct device
*d
)
260 static char prev_module
[256];
263 while (module
= next_module(d
))
265 if (strcmp(module
, prev_module
))
267 strncpy(prev_module
, module
, sizeof(prev_module
));
268 prev_module
[sizeof(prev_module
) - 1] = 0;
277 show_kernel(struct device
*d
)
279 char buf
[DRIVER_BUF_SIZE
];
280 const char *driver
, *module
;
282 if (driver
= find_driver(d
, buf
))
283 printf("\tKernel driver in use: %s\n", driver
);
285 if (!show_kernel_init())
289 while (module
= next_module_filtered(d
))
290 printf("%s %s", (cnt
++ ? "," : "\tKernel modules:"), module
);
296 show_kernel_machine(struct device
*d
)
298 char buf
[DRIVER_BUF_SIZE
];
299 const char *driver
, *module
;
301 if (driver
= find_driver(d
, buf
))
302 printf("Driver:\t%s\n", driver
);
304 if (!show_kernel_init())
307 while (module
= next_module_filtered(d
))
308 printf("Module:\t%s\n", module
);
314 show_kernel(struct device
*d UNUSED
)
319 show_kernel_machine(struct device
*d UNUSED
)
324 show_kernel_cleanup(void)