]>
git.ipfire.org Git - thirdparty/pciutils.git/blob - ls-kernel.c
2 * The PCI Utilities -- Show Kernel Drivers
4 * Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
17 #include <sys/utsname.h>
20 struct pcimap_entry
*next
;
21 unsigned int vendor
, device
;
22 unsigned int subvendor
, subdevice
;
23 unsigned int class, class_mask
;
27 static struct pcimap_entry
*pcimap_head
;
32 static int tried_pcimap
;
34 char *name
, line
[1024];
41 if (name
= opt_pcimap
)
45 die("Cannot open pcimap file %s: %m", name
);
50 die("uname() failed: %m");
51 name
= alloca(64 + strlen(uts
.release
));
52 sprintf(name
, "/lib/modules/%s/modules.pcimap", uts
.release
);
58 while (fgets(line
, sizeof(line
), f
))
60 char *c
= strchr(line
, '\n');
61 struct pcimap_entry
*e
;
64 die("Unterminated or too long line in %s", name
);
66 if (!line
[0] || line
[0] == '#')
70 while (*c
&& *c
!= ' ' && *c
!= '\t')
73 continue; /* FIXME: Emit warnings! */
76 e
= xmalloc(sizeof(*e
) + strlen(line
));
77 if (sscanf(c
, "%i%i%i%i%i%i",
78 &e
->vendor
, &e
->device
,
79 &e
->subvendor
, &e
->subdevice
,
80 &e
->class, &e
->class_mask
) != 6)
82 e
->next
= pcimap_head
;
84 strcpy(e
->module
, line
);
90 match_pcimap(struct device
*d
, struct pcimap_entry
*e
)
92 struct pci_dev
*dev
= d
->dev
;
93 unsigned int class = get_conf_long(d
, PCI_REVISION_ID
) >> 8;
96 #define MATCH(x, y) ((y) > 0xffff || (x) == (y))
97 get_subid(d
, &subv
, &subd
);
99 MATCH(dev
->vendor_id
, e
->vendor
) &&
100 MATCH(dev
->device_id
, e
->device
) &&
101 MATCH(subv
, e
->subvendor
) &&
102 MATCH(subd
, e
->subdevice
) &&
103 (class & e
->class_mask
) == e
->class;
107 #define DRIVER_BUF_SIZE 1024
110 find_driver(struct device
*d
, char *buf
)
112 struct pci_dev
*dev
= d
->dev
;
113 char name
[1024], *drv
, *base
;
116 if (dev
->access
->method
!= PCI_ACCESS_SYS_BUS_PCI
)
119 base
= pci_get_param(dev
->access
, "sysfs.path");
120 if (!base
|| !base
[0])
123 n
= snprintf(name
, sizeof(name
), "%s/devices/%04x:%02x:%02x.%d/driver",
124 base
, dev
->domain
, dev
->bus
, dev
->dev
, dev
->func
);
125 if (n
< 0 || n
>= (int)sizeof(name
))
126 die("show_driver: sysfs device name too long, why?");
128 n
= readlink(name
, buf
, DRIVER_BUF_SIZE
);
131 if (n
>= DRIVER_BUF_SIZE
)
132 return "<name-too-long>";
135 if (drv
= strrchr(buf
, '/'))
142 show_kernel(struct device
*d
)
144 char buf
[DRIVER_BUF_SIZE
];
146 struct pcimap_entry
*e
, *last
= NULL
;
148 if (driver
= find_driver(d
, buf
))
149 printf("\tKernel driver in use: %s\n", driver
);
152 for (e
=pcimap_head
; e
; e
=e
->next
)
153 if (match_pcimap(d
, e
) && (!last
|| strcmp(last
->module
, e
->module
)))
155 printf("%s %s", (last
? "," : "\tKernel modules:"), e
->module
);
163 show_kernel_machine(struct device
*d
)
165 char buf
[DRIVER_BUF_SIZE
];
167 struct pcimap_entry
*e
, *last
= NULL
;
169 if (driver
= find_driver(d
, buf
))
170 printf("Driver:\t%s\n", driver
);
173 for (e
=pcimap_head
; e
; e
=e
->next
)
174 if (match_pcimap(d
, e
) && (!last
|| strcmp(last
->module
, e
->module
)))
176 printf("Module:\t%s\n", e
->module
);
184 show_kernel(struct device
*d UNUSED
)
189 show_kernel_machine(struct device
*d UNUSED
)