]>
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
;
32 kmod_ctx
= kmod_new(NULL
, NULL
);
35 fprintf(stderr
, "lspci: Unable to initialize libkmod context\n");
40 if ((err
= kmod_load_resources(kmod_ctx
)) < 0)
42 fprintf(stderr
, "lspci: Unable to load libkmod resources: error %d\n", err
);
46 show_kernel_inited
= 1;
50 show_kernel_inited
= 0;
55 show_kernel_cleanup(void)
61 static const char *next_module(struct device
*d
)
63 static struct kmod_list
*klist
, *kcurrent
;
64 static struct kmod_module
*kmodule
;
68 kmod_module_unref(kmodule
);
74 pci_fill_info(d
->dev
, PCI_FILL_MODULE_ALIAS
);
75 if (!d
->dev
->module_alias
)
77 int err
= kmod_module_new_from_lookup(kmod_ctx
, d
->dev
->module_alias
, &klist
);
80 fprintf(stderr
, "lspci: libkmod lookup failed: error %d\n", err
);
86 kcurrent
= kmod_list_next(klist
, kcurrent
);
90 kmodule
= kmod_module_get_module(kcurrent
);
91 return kmod_module_get_name(kmodule
);
94 kmod_module_unref_list(klist
);
101 struct pcimap_entry
{
102 struct pcimap_entry
*next
;
103 unsigned int vendor
, device
;
104 unsigned int subvendor
, subdevice
;
105 unsigned int class, class_mask
;
109 static struct pcimap_entry
*pcimap_head
;
112 show_kernel_init(void)
114 static int tried_pcimap
;
116 char *name
, line
[1024];
123 if (name
= opt_pcimap
)
125 f
= fopen(name
, "r");
127 die("Cannot open pcimap file %s: %m", name
);
132 die("uname() failed: %m");
133 name
= alloca(64 + strlen(uts
.release
));
134 sprintf(name
, "/lib/modules/%s/modules.pcimap", uts
.release
);
135 f
= fopen(name
, "r");
140 while (fgets(line
, sizeof(line
), f
))
142 char *c
= strchr(line
, '\n');
143 struct pcimap_entry
*e
;
146 die("Unterminated or too long line in %s", name
);
148 if (!line
[0] || line
[0] == '#')
152 while (*c
&& *c
!= ' ' && *c
!= '\t')
155 continue; /* FIXME: Emit warnings! */
158 e
= xmalloc(sizeof(*e
) + strlen(line
));
159 if (sscanf(c
, "%i%i%i%i%i%i",
160 &e
->vendor
, &e
->device
,
161 &e
->subvendor
, &e
->subdevice
,
162 &e
->class, &e
->class_mask
) != 6)
164 e
->next
= pcimap_head
;
166 strcpy(e
->module
, line
);
174 match_pcimap(struct device
*d
, struct pcimap_entry
*e
)
176 struct pci_dev
*dev
= d
->dev
;
177 unsigned int class = get_conf_long(d
, PCI_REVISION_ID
) >> 8;
180 #define MATCH(x, y) ((y) > 0xffff || (x) == (y))
181 get_subid(d
, &subv
, &subd
);
183 MATCH(dev
->vendor_id
, e
->vendor
) &&
184 MATCH(dev
->device_id
, e
->device
) &&
185 MATCH(subv
, e
->subvendor
) &&
186 MATCH(subd
, e
->subdevice
) &&
187 (class & e
->class_mask
) == e
->class;
191 static const char *next_module(struct device
*d
)
193 static struct pcimap_entry
*current
;
196 current
= pcimap_head
;
198 current
= current
->next
;
202 if (match_pcimap(d
, current
))
203 return current
->module
;
204 current
= current
->next
;
211 show_kernel_cleanup(void)
217 #define DRIVER_BUF_SIZE 1024
220 find_driver(struct device
*d
, char *buf
)
222 struct pci_dev
*dev
= d
->dev
;
223 char name
[1024], *drv
, *base
;
226 if (dev
->access
->method
!= PCI_ACCESS_SYS_BUS_PCI
)
229 base
= pci_get_param(dev
->access
, "sysfs.path");
230 if (!base
|| !base
[0])
233 n
= snprintf(name
, sizeof(name
), "%s/devices/%04x:%02x:%02x.%d/driver",
234 base
, dev
->domain
, dev
->bus
, dev
->dev
, dev
->func
);
235 if (n
< 0 || n
>= (int)sizeof(name
))
236 die("show_driver: sysfs device name too long, why?");
238 n
= readlink(name
, buf
, DRIVER_BUF_SIZE
);
241 if (n
>= DRIVER_BUF_SIZE
)
242 return "<name-too-long>";
245 if (drv
= strrchr(buf
, '/'))
252 next_module_filtered(struct device
*d
)
254 static char prev_module
[256];
257 while (module
= next_module(d
))
259 if (strcmp(module
, prev_module
))
261 strncpy(prev_module
, module
, sizeof(prev_module
));
262 prev_module
[sizeof(prev_module
) - 1] = 0;
271 show_kernel(struct device
*d
)
273 char buf
[DRIVER_BUF_SIZE
];
274 const char *driver
, *module
;
276 if (driver
= find_driver(d
, buf
))
277 printf("\tKernel driver in use: %s\n", driver
);
279 if (!show_kernel_init())
283 while (module
= next_module_filtered(d
))
284 printf("%s %s", (cnt
++ ? "," : "\tKernel modules:"), module
);
290 show_kernel_machine(struct device
*d
)
292 char buf
[DRIVER_BUF_SIZE
];
293 const char *driver
, *module
;
295 if (driver
= find_driver(d
, buf
))
296 printf("Driver:\t%s\n", driver
);
298 if (!show_kernel_init())
301 while (module
= next_module_filtered(d
))
302 printf("Module:\t%s\n", module
);
308 show_kernel(struct device
*d UNUSED
)
313 show_kernel_machine(struct device
*d UNUSED
)
318 show_kernel_cleanup(void)