summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-07-16 15:36:30 +1000
committerDave Airlie <airlied@redhat.com>2009-07-16 15:36:30 +1000
commit5d1bdf0cb51c19efd6e2b2c0a463ace9443c48d9 (patch)
treef0f680c7a9f349cea7ff339cb260ac47b56ca24f
parent9ae22c87743c624bda593a1ef4bd4eca01c65655 (diff)
add support for finding if something has a kernel driver
-rw-r--r--include/pciaccess.h2
-rw-r--r--src/common_interface.c15
-rw-r--r--src/linux_sysfs.c21
-rw-r--r--src/pciaccess_private.h1
4 files changed, 39 insertions, 0 deletions
diff --git a/include/pciaccess.h b/include/pciaccess.h
index 2230b27..13d92d7 100644
--- a/include/pciaccess.h
+++ b/include/pciaccess.h
@@ -75,6 +75,8 @@ struct pci_slot_match;
extern "C" {
#endif
+int pci_device_has_kernel_driver(struct pci_device *dev);
+
int pci_device_is_boot_vga(struct pci_device *dev);
int pci_device_read_rom(struct pci_device *dev, void *buffer);
diff --git a/src/common_interface.c b/src/common_interface.c
index 5dcc707..d46feab 100644
--- a/src/common_interface.c
+++ b/src/common_interface.c
@@ -124,6 +124,21 @@ pci_device_is_boot_vga( struct pci_device * dev )
}
/**
+ * Probe a PCI device to determine if a kernel driver is attached.
+ *
+ * \param dev Device to query
+ * \return
+ * Zero if no driver attached, 1 if attached kernel drviver
+ */
+int
+pci_device_has_kernel_driver( struct pci_device * dev )
+{
+ if (!pci_sys->methods->has_kernel_driver)
+ return 0;
+ return pci_sys->methods->has_kernel_driver( dev );
+}
+
+/**
* Probe a PCI device to learn information about the device.
*
* Probes a PCI device to learn various information about the device. Before
diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c
index 1ae9e52..65e1cf6 100644
--- a/src/linux_sysfs.c
+++ b/src/linux_sysfs.c
@@ -76,6 +76,7 @@ static int pci_device_linux_sysfs_write( struct pci_device * dev,
pciaddr_t * bytes_written );
static int pci_device_linux_sysfs_boot_vga( struct pci_device * dev );
+static int pci_device_linux_sysfs_has_kernel_driver(struct pci_device *dev);
static const struct pci_system_methods linux_sysfs_methods = {
.destroy = NULL,
@@ -91,6 +92,7 @@ static const struct pci_system_methods linux_sysfs_methods = {
.fill_capabilities = pci_fill_capabilities_generic,
.enable = pci_device_linux_sysfs_enable,
.boot_vga = pci_device_linux_sysfs_boot_vga,
+ .has_kernel_driver = pci_device_linux_sysfs_has_kernel_driver,
};
#define SYS_BUS_PCI "/sys/bus/pci/devices"
@@ -729,3 +731,22 @@ out:
close(fd);
return ret;
}
+
+static int pci_device_linux_sysfs_has_kernel_driver(struct pci_device *dev)
+{
+ char name[256];
+ struct stat dummy;
+ int ret;
+
+ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/driver",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func );
+
+ ret = stat(name, &dummy);
+ if (ret < 0)
+ return 0;
+ return 1;
+}
diff --git a/src/pciaccess_private.h b/src/pciaccess_private.h
index 220673d..a45fa8f 100644
--- a/src/pciaccess_private.h
+++ b/src/pciaccess_private.h
@@ -61,6 +61,7 @@ struct pci_system_methods {
int (*fill_capabilities)( struct pci_device * dev );
void (*enable)( struct pci_device *dev );
int (*boot_vga)( struct pci_device *dev );
+ int (*has_kernel_driver)( struct pci_device *dev );
};
struct pci_device_mapping {