summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/linux_sysfs.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c
index cd2713d..8055e8d 100644
--- a/src/linux_sysfs.c
+++ b/src/linux_sysfs.c
@@ -146,6 +146,56 @@ scan_sys_pci_filter( const struct dirent * d )
}
+static int
+parse_separate_sysfs_files(struct pci_device * dev)
+{
+ static const char *attrs[] = {
+ "vendor",
+ "device",
+ "class",
+ "revision",
+ "subsystem_vendor",
+ "subsystem_device",
+ };
+ char name[256];
+ char resource[512];
+ uint64_t data[6];
+ int fd;
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ snprintf(name, 255, "%s/%04x:%02x:%02x.%1u/%s",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func,
+ attrs[i]);
+
+ fd = open(name, O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ return errno;
+ }
+
+ read(fd, resource, 512);
+ resource[511] = '\0';
+
+ close(fd);
+
+ data[i] = strtoull(resource, NULL, 16);
+ }
+
+ dev->vendor_id = data[0] & 0xffff;
+ dev->device_id = data[1] & 0xffff;
+ dev->device_class = data[2] & 0xffffff;
+ dev->revision = data[3] & 0xff;
+ dev->subvendor_id = data[4] & 0xffff;
+ dev->subdevice_id = data[5] & 0xffff;
+
+ return 0;
+}
+
+
int
populate_entries( struct pci_system * p )
{
@@ -178,6 +228,10 @@ populate_entries( struct pci_system * p )
device->base.func = func;
+ err = parse_separate_sysfs_files(& device->base);
+ if (!err)
+ continue;
+
err = pci_device_linux_sysfs_read(& device->base, config, 0,
48, & bytes);
if ((bytes == 48) && !err) {