From: frank <frank....@amd.com>

v3: switch to udev/sysfs for the enumeration

Signed-off-by: Frank Min <frank.min at amd.com>
Reviewed-by: Christian König <christian.koenig at amd.com>
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
Reviewed-by: Jammy Zhou <Jammy.Zhou at amd.com>
---
 Makefile.am |   7 +++--
 xf86drm.c   | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 xf86drm.h   |  19 +++++++++++
 3 files changed, 127 insertions(+), 2 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 13df80c..ffd334a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -95,12 +95,15 @@ SUBDIRS = \
 libdrm_la_LTLIBRARIES = libdrm.la
 libdrm_ladir = $(libdir)
 libdrm_la_LDFLAGS = -version-number 2:4:0 -no-undefined
-libdrm_la_LIBADD = @CLOCK_LIB@
+libdrm_la_LIBADD = \
+               @CLOCK_LIB@ \
+               @LIBUDEV_LIBS@

 libdrm_la_CPPFLAGS = -I$(top_srcdir)/include/drm
 AM_CFLAGS = \
        $(WARN_CFLAGS) \
-       $(VALGRIND_CFLAGS)
+       $(VALGRIND_CFLAGS) \
+       $(LIBUDEV_CFLAGS)

 libdrm_la_SOURCES = $(LIBDRM_FILES)

diff --git a/xf86drm.c b/xf86drm.c
index f7c45f8..d2704de 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -63,6 +63,7 @@

 #include "xf86drm.h"
 #include "libdrm_macros.h"
+#include "libudev.h"

 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || 
defined(__DragonFly__)
 #define DRM_MAJOR 145
@@ -2817,3 +2818,105 @@ char *drmGetRenderDeviceNameFromFd(int fd)
 {
        return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
 }
+
+/**
+* Enumerate the GPU devices on the system
+*
+* \param devs device array set to return the device information
+* (if NULL, the number of device is returned)
+* \param vendor the vendor ID for GPU devices to list
+* (optional, if not specified, all GPU devices are returned)
+*
+* \return the number of GPU devices
+*/
+int drmGetPciDevices(drmPciDevicePtr devSet, uint16_t vendorId)
+{
+       struct udev *udev = NULL;
+       struct udev_enumerate *udev_enumerate;
+       struct udev_list_entry *list_entry;
+       struct udev_device *device;
+       int drmDevCount = 0;
+       int vendor = 0;
+       int devid = 0;
+       int devclass = 0;
+       int subvendor = 0;
+       int subdevid = 0;
+       int revid = 0xff;
+       int domain = 0;
+       int bus = 0;
+       int dev = 0;
+       int func = 0;
+       char config[64] = {0};
+       char node[128] = {'\0'};
+       char slot[] = "0000:00:00.0";
+       char *info = NULL;
+       int minor = 0xff;
+       int fd = 0;
+       int ret = 0;
+
+       udev = udev_new();
+       if (udev == NULL) {
+               fprintf(stderr, "no context\n");
+               return -EINVAL;
+       }
+       udev_enumerate = udev_enumerate_new(udev);
+       if (udev_enumerate == NULL)
+               return -EINVAL;
+       udev_enumerate_add_match_subsystem(udev_enumerate, "drm");
+       udev_enumerate_add_match_property(udev_enumerate, "DEVTYPE", 
"drm_minor");
+
+       udev_enumerate_scan_devices(udev_enumerate);
+
+       udev_list_entry_foreach(list_entry, 
udev_enumerate_get_list_entry(udev_enumerate)) {
+               device = 
udev_device_new_from_syspath(udev_enumerate_get_udev(udev_enumerate),
+                                                     
udev_list_entry_get_name(list_entry));
+               if (device != NULL) {
+                       info = udev_device_get_property_value(device, "MINOR");
+                       if (!strcmp(info, "0")) {
+                       strcpy(node, udev_device_get_syspath(device));
+                       info = strstr(node, "/drm");
+                       strncpy(slot, info - strlen(slot), strlen(slot));
+                       if (sscanf(slot, "%4x:%2x:%2x.%1x", &domain, &bus, 
&dev, &func) != 4) {
+                               domain = 0;
+                               bus = 0;
+                               dev = 0;
+                               func = 0;
+                       }
+                       strcpy(node + strlen(node), "/device/config");
+
+                       fd = open(node, O_RDONLY);
+                       if (fd >= 0) {
+                               ret = read(fd, config, 64);
+                               if (ret == 64) {
+                                       vendor = config[0] + (config[1] << 8);
+                                       devid = config[2] + (config[3] << 8);
+                                       revid = config[8];
+                                       devclass = config[9] + (config[10] << 
8) + (config[11] << 16);
+                                       subdevid = config[44] + (config[45] << 
8);
+                               }
+                               close(fd);
+                       }
+
+                       if((vendorId == 0) || (vendorId == vendor)) {
+                               if(devSet != NULL) {
+                                       devSet[drmDevCount].domain = domain;
+                                       devSet[drmDevCount].bus = bus;
+                                       devSet[drmDevCount].dev = dev;
+                                       devSet[drmDevCount].func = func;
+                                       devSet[drmDevCount].vendor_id = vendor;
+                                       devSet[drmDevCount].device_id = devid;
+                                       devSet[drmDevCount].subdevice_id = 
subdevid;
+                                       devSet[drmDevCount].subvendor_id = 
subvendor;
+                                       devSet[drmDevCount].revision_id = revid;
+                               }
+                               drmDevCount++;
+                       }
+               }
+               }
+               udev_device_unref(device);
+       }
+       udev_enumerate_unref(udev_enumerate);
+       udev_unref(udev);
+
+       return drmDevCount;
+}
diff --git a/xf86drm.h b/xf86drm.h
index 40c55c9..2610934 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -342,6 +342,24 @@ typedef struct _drmSetVersion {
        int drm_dd_minor;
 } drmSetVersion, *drmSetVersionPtr;

+/**
+ * Structure to a general pci gpu device
+ *
+ * \sa drmGetDevices()
+ *
+*/
+typedef struct _drmPciDevice {
+               uint16_t domain;
+               uint8_t bus;
+               uint8_t dev;
+               uint8_t func;
+               uint16_t vendor_id;
+               uint16_t device_id;
+               uint16_t subvendor_id;
+               uint16_t subdevice_id;
+               uint8_t revision_id;
+} drmPciDevice, *drmPciDevicePtr;
+
 #define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock)

 #define DRM_LOCK_HELD  0x80000000U /**< Hardware lock is held */
@@ -552,6 +570,7 @@ do {        register unsigned int __old __asm("o0");        
        \
 /* General user-level programmer's API: unprivileged */
 extern int           drmAvailable(void);
 extern int           drmOpen(const char *name, const char *busid);
+extern int           drmGetPciDevices(drmPciDevicePtr devSet, uint16_t 
vendorId);

 #define DRM_NODE_PRIMARY 0
 #define DRM_NODE_CONTROL 1
-- 
1.9.1

Reply via email to