#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
+#if HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
#include <math.h>
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/pciio.h>
+#endif
+
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/* Not all systems have MAP_FAILED defined */
#include "util_math.h"
-#ifdef __OpenBSD__
-#define DRM_PRIMARY_MINOR_NAME "drm"
-#define DRM_CONTROL_MINOR_NAME "drmC"
-#define DRM_RENDER_MINOR_NAME "drmR"
-#else
-#define DRM_PRIMARY_MINOR_NAME "card"
-#define DRM_CONTROL_MINOR_NAME "controlD"
-#define DRM_RENDER_MINOR_NAME "renderD"
-#endif
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+#ifdef __DragonFly__
#define DRM_MAJOR 145
#endif
static drmServerInfoPtr drm_server_info;
+static bool drmNodeIsDRM(int maj, int min);
+static char *drmGetMinorNameForFD(int fd, int type);
+
+static unsigned log2_int(unsigned x)
+{
+ unsigned l;
+
+ if (x < 2) {
+ return 0;
+ }
+ for (l = 2; ; l++) {
+ if ((unsigned)(1 << l) > x) {
+ return l - 1;
+ }
+ }
+ return 0;
+}
+
+
drm_public void drmSetServerInfo(drmServerInfoPtr info)
{
drm_server_info = info;
}
/**
- * Call ioctl, restarting if it is interupted
+ * Call ioctl, restarting if it is interrupted
*/
drm_public int
drmIoctl(int fd, unsigned long request, void *arg)
*
* \internal
* Checks for failure. If failure was caused by signal call chown again.
- * If any other failure happened then it will output error mesage using
+ * If any other failure happened then it will output error message using
* drmMsg() call.
*/
#if !UDEV
}
#endif
+static const char *drmGetDeviceName(int type)
+{
+ switch (type) {
+ case DRM_NODE_PRIMARY:
+ return DRM_DEV_NAME;
+ case DRM_NODE_CONTROL:
+ return DRM_CONTROL_DEV_NAME;
+ case DRM_NODE_RENDER:
+ return DRM_RENDER_DEV_NAME;
+ }
+ return NULL;
+}
+
/**
* Open the DRM device, creating it if necessary.
*
static int drmOpenDevice(dev_t dev, int minor, int type)
{
stat_t st;
- const char *dev_name;
- char buf[64];
+ const char *dev_name = drmGetDeviceName(type);
+ char buf[DRM_NODE_NAME_MAX];
int fd;
mode_t devmode = DRM_DEV_MODE, serv_mode;
gid_t serv_group;
gid_t group = DRM_DEV_GID;
#endif
- switch (type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
+ if (!dev_name)
return -EINVAL;
- };
sprintf(buf, dev_name, DRM_DIR_NAME, minor);
drmMsg("drmOpenDevice: node name is %s\n", buf);
static int drmOpenMinor(int minor, int create, int type)
{
int fd;
- char buf[64];
- const char *dev_name;
+ char buf[DRM_NODE_NAME_MAX];
+ const char *dev_name = drmGetDeviceName(type);
if (create)
return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
- switch (type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
+ if (!dev_name)
return -EINVAL;
- };
sprintf(buf, dev_name, DRM_DIR_NAME, minor);
if ((fd = open(buf, O_RDWR | O_CLOEXEC, 0)) >= 0)
};
}
-static int drmGetMinorType(int minor)
+static int drmGetMinorType(int major, int minor)
{
+#ifdef __FreeBSD__
+ char name[SPECNAMELEN];
+ int id;
+
+ if (!devname_r(makedev(major, minor), S_IFCHR, name, sizeof(name)))
+ return -1;
+
+ if (sscanf(name, "drm/%d", &id) != 1) {
+ // If not in /dev/drm/ we have the type in the name
+ if (sscanf(name, "dri/card%d\n", &id) >= 1)
+ return DRM_NODE_PRIMARY;
+ else if (sscanf(name, "dri/control%d\n", &id) >= 1)
+ return DRM_NODE_CONTROL;
+ else if (sscanf(name, "dri/renderD%d\n", &id) >= 1)
+ return DRM_NODE_RENDER;
+ return -1;
+ }
+
+ minor = id;
+#endif
int type = minor >> 6;
if (minor < 0)
int retcode;
sprintf(proc_name, "/proc/dri/%d/name", i);
- if ((fd = open(proc_name, 0, 0)) >= 0) {
+ if ((fd = open(proc_name, O_RDONLY, 0)) >= 0) {
retcode = read(fd, buf, sizeof(buf)-1);
close(fd);
if (retcode) {
*/
drm_public int drmOpenWithType(const char *name, const char *busid, int type)
{
- if (!drmAvailable() && name != NULL && drm_server_info &&
- drm_server_info->load_module) {
+ if (name != NULL && drm_server_info &&
+ drm_server_info->load_module && !drmAvailable()) {
/* try to load the kernel module */
if (!drm_server_info->load_module(name)) {
drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
*
* \param fd file descriptor.
* \param context context.
- * \param flags flags that determine the sate of the hardware when the function
+ * \param flags flags that determine the state of the hardware when the function
* returns.
*
* \return always zero.
drm_public char *drmGetDeviceNameFromFd(int fd)
{
+#ifdef __FreeBSD__
+ struct stat sbuf;
+ int maj, min;
+ int nodetype;
+
+ if (fstat(fd, &sbuf))
+ return NULL;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+ nodetype = drmGetMinorType(maj, min);
+ return drmGetMinorNameForFD(fd, nodetype);
+#else
char name[128];
struct stat sbuf;
dev_t d;
return NULL;
return strdup(name);
+#endif
}
static bool drmNodeIsDRM(int maj, int min)
snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm",
maj, min);
return stat(path, &sbuf) == 0;
+#elif defined(__FreeBSD__)
+ char name[SPECNAMELEN];
+
+ if (!devname_r(makedev(maj, min), S_IFCHR, name, sizeof(name)))
+ return 0;
+ /* Handle drm/ and dri/ as both are present in different FreeBSD version
+ * FreeBSD on amd64/i386/powerpc external kernel modules create node in
+ * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates
+ * only device nodes in /dev/dri/ */
+ return (!strncmp(name, "drm/", 4) || !strncmp(name, "dri/", 4));
#else
return maj == DRM_MAJOR;
#endif
return -1;
}
- type = drmGetMinorType(min);
+ type = drmGetMinorType(maj, min);
if (type == -1)
errno = ENODEV;
return type;
closedir(sysdir);
return NULL;
+#elif defined(__FreeBSD__)
+ struct stat sbuf;
+ char dname[SPECNAMELEN];
+ const char *mname;
+ char name[SPECNAMELEN];
+ int id, maj, min, nodetype, i;
+
+ if (fstat(fd, &sbuf))
+ return NULL;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+
+ if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
+ return NULL;
+
+ if (!devname_r(sbuf.st_rdev, S_IFCHR, dname, sizeof(dname)))
+ return NULL;
+
+ /* Handle both /dev/drm and /dev/dri
+ * FreeBSD on amd64/i386/powerpc external kernel modules create node in
+ * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates
+ * only device nodes in /dev/dri/ */
+
+ /* Get the node type represented by fd so we can deduce the target name */
+ nodetype = drmGetMinorType(maj, min);
+ if (nodetype == -1)
+ return (NULL);
+ mname = drmGetMinorName(type);
+
+ for (i = 0; i < SPECNAMELEN; i++) {
+ if (isalpha(dname[i]) == 0 && dname[i] != '/')
+ break;
+ }
+ if (dname[i] == '\0')
+ return (NULL);
+
+ id = (int)strtol(&dname[i], NULL, 10);
+ id -= drmGetMinorBase(nodetype);
+ snprintf(name, sizeof(name), DRM_DIR_NAME "/%s%d", mname,
+ id + drmGetMinorBase(type));
+
+ return strdup(name);
#else
struct stat sbuf;
char buf[PATH_MAX + 1];
- const char *dev_name;
+ const char *dev_name = drmGetDeviceName(type);
unsigned int maj, min;
- int n, base;
+ int n;
if (fstat(fd, &sbuf))
return NULL;
if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
return NULL;
- switch (type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
- return NULL;
- };
-
- base = drmGetMinorBase(type);
- if (base < 0)
+ if (!dev_name)
return NULL;
- n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min - base);
+ n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min);
if (n == -1 || n >= sizeof(buf))
return NULL;
/* Little white lie to avoid major rework of the existing code */
#define DRM_BUS_VIRTIO 0x10
-static int drmParseSubsystemType(int maj, int min)
-{
#ifdef __linux__
- char path[PATH_MAX + 1];
+static int get_subsystem_type(const char *device_path)
+{
+ char path[PATH_MAX + 1] = "";
char link[PATH_MAX + 1] = "";
char *name;
struct {
{ "/virtio", DRM_BUS_VIRTIO },
};
- snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/subsystem",
- maj, min);
+ strncpy(path, device_path, PATH_MAX);
+ strncat(path, "/subsystem", PATH_MAX);
if (readlink(path, link, PATH_MAX) < 0)
return -errno;
}
return -EINVAL;
-#elif defined(__OpenBSD__) || defined(__DragonFly__)
+}
+#endif
+
+static int drmParseSubsystemType(int maj, int min)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1] = "";
+ char real_path[PATH_MAX + 1] = "";
+ int subsystem_type;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+ subsystem_type = get_subsystem_type(path);
+ /* Try to get the parent (underlying) device type */
+ if (subsystem_type == DRM_BUS_VIRTIO) {
+ /* Assume virtio-pci on error */
+ if (!realpath(path, real_path))
+ return DRM_BUS_VIRTIO;
+ strncat(path, "/..", PATH_MAX);
+ subsystem_type = get_subsystem_type(path);
+ if (subsystem_type < 0)
+ return DRM_BUS_VIRTIO;
+ }
+ return subsystem_type;
+#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
return DRM_BUS_PCI;
#else
#warning "Missing implementation of drmParseSubsystemType"
#endif
}
+#ifdef __linux__
static void
get_pci_path(int maj, int min, char *pci_path)
{
if (term && strncmp(term, "/virtio", 7) == 0)
*term = 0;
}
+#endif
+
+#ifdef __FreeBSD__
+static int get_sysctl_pci_bus_info(int maj, int min, drmPciBusInfoPtr info)
+{
+ char dname[SPECNAMELEN];
+ char sysctl_name[16];
+ char sysctl_val[256];
+ size_t sysctl_len;
+ int id, type, nelem;
+ unsigned int rdev, majmin, domain, bus, dev, func;
+
+ rdev = makedev(maj, min);
+ if (!devname_r(rdev, S_IFCHR, dname, sizeof(dname)))
+ return -EINVAL;
+
+ if (sscanf(dname, "drm/%d\n", &id) != 1)
+ return -EINVAL;
+ type = drmGetMinorType(maj, min);
+ if (type == -1)
+ return -EINVAL;
+
+ /* BUG: This above section is iffy, since it mandates that a driver will
+ * create both card and render node.
+ * If it does not, the next DRM device will create card#X and
+ * renderD#(128+X)-1.
+ * This is a possibility in FreeBSD but for now there is no good way for
+ * obtaining the info.
+ */
+ switch (type) {
+ case DRM_NODE_PRIMARY:
+ break;
+ case DRM_NODE_CONTROL:
+ id -= 64;
+ break;
+ case DRM_NODE_RENDER:
+ id -= 128;
+ break;
+ }
+ if (id < 0)
+ return -EINVAL;
+
+ if (snprintf(sysctl_name, sizeof(sysctl_name), "hw.dri.%d.busid", id) <= 0)
+ return -EINVAL;
+ sysctl_len = sizeof(sysctl_val);
+ if (sysctlbyname(sysctl_name, sysctl_val, &sysctl_len, NULL, 0))
+ return -EINVAL;
+
+ #define bus_fmt "pci:%04x:%02x:%02x.%u"
+
+ nelem = sscanf(sysctl_val, bus_fmt, &domain, &bus, &dev, &func);
+ if (nelem != 4)
+ return -EINVAL;
+ info->domain = domain;
+ info->bus = bus;
+ info->dev = dev;
+ info->func = func;
+
+ return 0;
+}
+#endif
static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
{
struct drm_pciinfo pinfo;
int fd, type;
- type = drmGetMinorType(min);
+ type = drmGetMinorType(maj, min);
if (type == -1)
return -ENODEV;
info->func = pinfo.func;
return 0;
+#elif defined(__FreeBSD__)
+ return get_sysctl_pci_bus_info(maj, min, info);
#else
#warning "Missing implementation of drmParsePciBusInfo"
return -EINVAL;
static int drmGetNodeType(const char *name)
{
- if (strncmp(name, DRM_PRIMARY_MINOR_NAME,
- sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0)
- return DRM_NODE_PRIMARY;
-
if (strncmp(name, DRM_CONTROL_MINOR_NAME,
sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0)
return DRM_NODE_CONTROL;
sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0)
return DRM_NODE_RENDER;
+ if (strncmp(name, DRM_PRIMARY_MINOR_NAME,
+ sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0)
+ return DRM_NODE_PRIMARY;
+
return -EINVAL;
}
struct drm_pciinfo pinfo;
int fd, type;
- type = drmGetMinorType(min);
+ type = drmGetMinorType(maj, min);
if (type == -1)
return -ENODEV;
device->subdevice_id = pinfo.subdevice_id;
return 0;
+#elif defined(__FreeBSD__)
+ drmPciBusInfo info;
+ struct pci_conf_io pc;
+ struct pci_match_conf patterns[1];
+ struct pci_conf results[1];
+ int fd, error;
+
+ if (get_sysctl_pci_bus_info(maj, min, &info) != 0)
+ return -EINVAL;
+
+ fd = open("/dev/pci", O_RDONLY, 0);
+ if (fd < 0)
+ return -errno;
+
+ bzero(&patterns, sizeof(patterns));
+ patterns[0].pc_sel.pc_domain = info.domain;
+ patterns[0].pc_sel.pc_bus = info.bus;
+ patterns[0].pc_sel.pc_dev = info.dev;
+ patterns[0].pc_sel.pc_func = info.func;
+ patterns[0].flags = PCI_GETCONF_MATCH_DOMAIN | PCI_GETCONF_MATCH_BUS
+ | PCI_GETCONF_MATCH_DEV | PCI_GETCONF_MATCH_FUNC;
+ bzero(&pc, sizeof(struct pci_conf_io));
+ pc.num_patterns = 1;
+ pc.pat_buf_len = sizeof(patterns);
+ pc.patterns = patterns;
+ pc.match_buf_len = sizeof(results);
+ pc.matches = results;
+
+ if (ioctl(fd, PCIOCGETCONF, &pc) || pc.status == PCI_GETCONF_ERROR) {
+ error = errno;
+ close(fd);
+ return -error;
+ }
+ close(fd);
+
+ device->vendor_id = results[0].pc_vendor;
+ device->device_id = results[0].pc_device;
+ device->subvendor_id = results[0].pc_subvendor;
+ device->subdevice_id = results[0].pc_subdevice;
+ device->revision_id = results[0].pc_revid;
+
+ return 0;
#else
#warning "Missing implementation of drmParsePciDeviceInfo"
return -EINVAL;
return ret;
}
+#ifdef __linux__
+static int drm_usb_dev_path(int maj, int min, char *path, size_t len)
+{
+ char *value, *tmp_path, *slash;
+
+ snprintf(path, len, "/sys/dev/char/%d:%d/device", maj, min);
+
+ value = sysfs_uevent_get(path, "DEVTYPE");
+ if (!value)
+ return -ENOENT;
+
+ if (strcmp(value, "usb_device") == 0)
+ return 0;
+ if (strcmp(value, "usb_interface") != 0)
+ return -ENOTSUP;
+
+ /* The parent of a usb_interface is a usb_device */
+
+ tmp_path = realpath(path, NULL);
+ if (!tmp_path)
+ return -errno;
+
+ slash = strrchr(tmp_path, '/');
+ if (!slash) {
+ free(tmp_path);
+ return -EINVAL;
+ }
+
+ *slash = '\0';
+
+ if (snprintf(path, len, "%s", tmp_path) >= (int)len) {
+ free(tmp_path);
+ return -EINVAL;
+ }
+
+ free(tmp_path);
+ return 0;
+}
+#endif
+
static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info)
{
#ifdef __linux__
unsigned int bus, dev;
int ret;
- snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+ ret = drm_usb_dev_path(maj, min, path, sizeof(path));
+ if (ret < 0)
+ return ret;
value = sysfs_uevent_get(path, "BUSNUM");
if (!value)
unsigned int vendor, product;
int ret;
- snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+ ret = drm_usb_dev_path(maj, min, path, sizeof(path));
+ if (ret < 0)
+ return ret;
value = sysfs_uevent_get(path, "PRODUCT");
if (!value)
free(value);
}
- *compatible[i] = tmp_name;
+ (*compatible)[i] = tmp_name;
}
return 0;
free:
while (i--)
- free(*compatible[i]);
+ free((*compatible)[i]);
free(*compatible);
return err;
for (j = i + 1; j < count; j++) {
if (drmDevicesEqual(local_devices[i], local_devices[j])) {
local_devices[i]->available_nodes |= local_devices[j]->available_nodes;
- node_type = log2(local_devices[j]->available_nodes);
+ node_type = log2_int(local_devices[j]->available_nodes);
memcpy(local_devices[i]->nodes[node_type],
local_devices[j]->nodes[node_type], drmGetMaxNodeName());
drmFreeDevice(&local_devices[j]);
char node[PATH_MAX + 1];
const char *dev_name;
int node_type, subsystem_type;
- int maj, min, n, ret, base;
+ int maj, min, n, ret;
if (fd == -1 || device == NULL)
return -EINVAL;
if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
return -EINVAL;
- node_type = drmGetMinorType(min);
+ node_type = drmGetMinorType(maj, min);
if (node_type == -1)
return -ENODEV;
- switch (node_type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
- return -EINVAL;
- };
-
- base = drmGetMinorBase(node_type);
- if (base < 0)
+ dev_name = drmGetDeviceName(node_type);
+ if (!dev_name)
return -EINVAL;
- n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base);
+ n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min);
if (n == -1 || n >= PATH_MAX)
return -errno;
if (stat(node, &sbuf))
free(value);
return strdup(path);
+#elif defined(__FreeBSD__)
+ return drmGetDeviceNameFromFd(fd);
#else
struct stat sbuf;
char node[PATH_MAX + 1];
const char *dev_name;
int node_type;
- int maj, min, n, base;
+ int maj, min, n;
if (fstat(fd, &sbuf))
return NULL;
if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
return NULL;
- node_type = drmGetMinorType(min);
+ node_type = drmGetMinorType(maj, min);
if (node_type == -1)
return NULL;
- switch (node_type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
+ dev_name = drmGetDeviceName(node_type);
+ if (!dev_name)
return NULL;
- };
- base = drmGetMinorBase(node_type);
- if (base < 0)
- return NULL;
-
- n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base);
+ n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min);
if (n == -1 || n >= PATH_MAX)
return NULL;
ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &args);
return ret;
}
+
+drm_public int drmSyncobjTimelineSignal(int fd, const uint32_t *handles,
+ uint64_t *points, uint32_t handle_count)
+{
+ struct drm_syncobj_timeline_array args;
+ int ret;
+
+ memclear(args);
+ args.handles = (uintptr_t)handles;
+ args.points = (uintptr_t)points;
+ args.count_handles = handle_count;
+
+ ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args);
+ return ret;
+}
+
+drm_public int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points,
+ unsigned num_handles,
+ int64_t timeout_nsec, unsigned flags,
+ uint32_t *first_signaled)
+{
+ struct drm_syncobj_timeline_wait args;
+ int ret;
+
+ memclear(args);
+ args.handles = (uintptr_t)handles;
+ args.points = (uintptr_t)points;
+ args.timeout_nsec = timeout_nsec;
+ args.count_handles = num_handles;
+ args.flags = flags;
+
+ ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &args);
+ if (ret < 0)
+ return -errno;
+
+ if (first_signaled)
+ *first_signaled = args.first_signaled;
+ return ret;
+}
+
+
+drm_public int drmSyncobjQuery(int fd, uint32_t *handles, uint64_t *points,
+ uint32_t handle_count)
+{
+ struct drm_syncobj_timeline_array args;
+ int ret;
+
+ memclear(args);
+ args.handles = (uintptr_t)handles;
+ args.points = (uintptr_t)points;
+ args.count_handles = handle_count;
+
+ ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+drm_public int drmSyncobjQuery2(int fd, uint32_t *handles, uint64_t *points,
+ uint32_t handle_count, uint32_t flags)
+{
+ struct drm_syncobj_timeline_array args;
+
+ memclear(args);
+ args.handles = (uintptr_t)handles;
+ args.points = (uintptr_t)points;
+ args.count_handles = handle_count;
+ args.flags = flags;
+
+ return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args);
+}
+
+
+drm_public int drmSyncobjTransfer(int fd,
+ uint32_t dst_handle, uint64_t dst_point,
+ uint32_t src_handle, uint64_t src_point,
+ uint32_t flags)
+{
+ struct drm_syncobj_transfer args;
+ int ret;
+
+ memclear(args);
+ args.src_handle = src_handle;
+ args.dst_handle = dst_handle;
+ args.src_point = src_point;
+ args.dst_point = dst_point;
+ args.flags = flags;
+
+ ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &args);
+
+ return ret;
+}