xf86drm.c revision 424e9256
122944501Smrg/** 222944501Smrg * \file xf86drm.c 322944501Smrg * User-level interface to DRM device 422944501Smrg * 522944501Smrg * \author Rickard E. (Rik) Faith <faith@valinux.com> 622944501Smrg * \author Kevin E. Martin <martin@valinux.com> 722944501Smrg */ 822944501Smrg 922944501Smrg/* 1022944501Smrg * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 1122944501Smrg * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 1222944501Smrg * All Rights Reserved. 1322944501Smrg * 1422944501Smrg * Permission is hereby granted, free of charge, to any person obtaining a 1522944501Smrg * copy of this software and associated documentation files (the "Software"), 1622944501Smrg * to deal in the Software without restriction, including without limitation 1722944501Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1822944501Smrg * and/or sell copies of the Software, and to permit persons to whom the 1922944501Smrg * Software is furnished to do so, subject to the following conditions: 2022944501Smrg * 2122944501Smrg * The above copyright notice and this permission notice (including the next 2222944501Smrg * paragraph) shall be included in all copies or substantial portions of the 2322944501Smrg * Software. 2422944501Smrg * 2522944501Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2622944501Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2722944501Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2822944501Smrg * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2922944501Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 3022944501Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 3122944501Smrg * DEALINGS IN THE SOFTWARE. 3222944501Smrg */ 3322944501Smrg 3422944501Smrg#ifdef HAVE_CONFIG_H 3522944501Smrg# include <config.h> 3622944501Smrg#endif 3722944501Smrg#include <stdio.h> 3822944501Smrg#include <stdlib.h> 3922944501Smrg#include <unistd.h> 4022944501Smrg#include <string.h> 4122944501Smrg#include <strings.h> 4222944501Smrg#include <ctype.h> 43424e9256Smrg#include <dirent.h> 44424e9256Smrg#include <stddef.h> 4522944501Smrg#include <fcntl.h> 4622944501Smrg#include <errno.h> 4722944501Smrg#include <signal.h> 4822944501Smrg#include <time.h> 4922944501Smrg#include <sys/types.h> 5022944501Smrg#include <sys/stat.h> 5122944501Smrg#define stat_t struct stat 5222944501Smrg#include <sys/ioctl.h> 5322944501Smrg#include <sys/time.h> 5422944501Smrg#include <stdarg.h> 55424e9256Smrg#ifdef HAVE_SYS_MKDEV_H 56424e9256Smrg# include <sys/mkdev.h> /* defines major(), minor(), and makedev() on Solaris */ 57424e9256Smrg#endif 5822944501Smrg 5922944501Smrg/* Not all systems have MAP_FAILED defined */ 6022944501Smrg#ifndef MAP_FAILED 6122944501Smrg#define MAP_FAILED ((void *)-1) 6222944501Smrg#endif 6322944501Smrg 6422944501Smrg#include "xf86drm.h" 65424e9256Smrg#include "libdrm_macros.h" 6622944501Smrg 6722944501Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 6822944501Smrg#define DRM_MAJOR 145 6922944501Smrg#endif 7022944501Smrg 7122944501Smrg#ifdef __NetBSD__ 722e6867f6Smrg#undef DRM_MAJOR 732e6867f6Smrg#define DRM_MAJOR 180 7422944501Smrg#endif 7522944501Smrg 7622944501Smrg# ifdef __OpenBSD__ 7722944501Smrg# define DRM_MAJOR 81 7822944501Smrg# endif 7922944501Smrg 8022944501Smrg#ifndef DRM_MAJOR 8122944501Smrg#define DRM_MAJOR 226 /* Linux */ 8222944501Smrg#endif 8322944501Smrg 8422944501Smrg/* 8522944501Smrg * This definition needs to be changed on some systems if dev_t is a structure. 8622944501Smrg * If there is a header file we can get it from, there would be best. 8722944501Smrg */ 8822944501Smrg#ifndef makedev 8922944501Smrg#define makedev(x,y) ((dev_t)(((x) << 8) | (y))) 9022944501Smrg#endif 9122944501Smrg 9222944501Smrg#define DRM_MSG_VERBOSITY 3 9322944501Smrg 94424e9256Smrg#define memclear(s) memset(&s, 0, sizeof(s)) 9522944501Smrg 9622944501Smrgstatic drmServerInfoPtr drm_server_info; 9722944501Smrg 9822944501Smrgvoid drmSetServerInfo(drmServerInfoPtr info) 9922944501Smrg{ 10022944501Smrg drm_server_info = info; 10122944501Smrg} 10222944501Smrg 10322944501Smrg/** 10422944501Smrg * Output a message to stderr. 10522944501Smrg * 10622944501Smrg * \param format printf() like format string. 10722944501Smrg * 10822944501Smrg * \internal 10922944501Smrg * This function is a wrapper around vfprintf(). 11022944501Smrg */ 11122944501Smrg 112a7d7de1eSmrgstatic int DRM_PRINTFLIKE(1, 0) 113a7d7de1eSmrgdrmDebugPrint(const char *format, va_list ap) 11422944501Smrg{ 11522944501Smrg return vfprintf(stderr, format, ap); 11622944501Smrg} 11722944501Smrg 11822944501Smrgvoid 11922944501SmrgdrmMsg(const char *format, ...) 12022944501Smrg{ 12122944501Smrg va_list ap; 12222944501Smrg const char *env; 12322944501Smrg if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) || drm_server_info) 12422944501Smrg { 12522944501Smrg va_start(ap, format); 12622944501Smrg if (drm_server_info) { 12722944501Smrg drm_server_info->debug_print(format,ap); 12822944501Smrg } else { 129424e9256Smrg drmDebugPrint(format, ap); 13022944501Smrg } 13122944501Smrg va_end(ap); 13222944501Smrg } 13322944501Smrg} 13422944501Smrg 13522944501Smrgstatic void *drmHashTable = NULL; /* Context switch callbacks */ 13622944501Smrg 13722944501Smrgvoid *drmGetHashTable(void) 13822944501Smrg{ 13922944501Smrg return drmHashTable; 14022944501Smrg} 14122944501Smrg 14222944501Smrgvoid *drmMalloc(int size) 14322944501Smrg{ 144424e9256Smrg return calloc(1, size); 14522944501Smrg} 14622944501Smrg 14722944501Smrgvoid drmFree(void *pt) 14822944501Smrg{ 149424e9256Smrg free(pt); 15022944501Smrg} 15122944501Smrg 15222944501Smrg/** 15322944501Smrg * Call ioctl, restarting if it is interupted 15422944501Smrg */ 15522944501Smrgint 15622944501SmrgdrmIoctl(int fd, unsigned long request, void *arg) 15722944501Smrg{ 15822944501Smrg int ret; 15922944501Smrg 16022944501Smrg do { 16122944501Smrg ret = ioctl(fd, request, arg); 16222944501Smrg } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 16322944501Smrg return ret; 16422944501Smrg} 16522944501Smrg 16622944501Smrgstatic unsigned long drmGetKeyFromFd(int fd) 16722944501Smrg{ 16822944501Smrg stat_t st; 16922944501Smrg 17022944501Smrg st.st_rdev = 0; 17122944501Smrg fstat(fd, &st); 17222944501Smrg return st.st_rdev; 17322944501Smrg} 17422944501Smrg 17522944501SmrgdrmHashEntry *drmGetEntry(int fd) 17622944501Smrg{ 17722944501Smrg unsigned long key = drmGetKeyFromFd(fd); 17822944501Smrg void *value; 17922944501Smrg drmHashEntry *entry; 18022944501Smrg 18122944501Smrg if (!drmHashTable) 18222944501Smrg drmHashTable = drmHashCreate(); 18322944501Smrg 18422944501Smrg if (drmHashLookup(drmHashTable, key, &value)) { 18522944501Smrg entry = drmMalloc(sizeof(*entry)); 18622944501Smrg entry->fd = fd; 18722944501Smrg entry->f = NULL; 18822944501Smrg entry->tagTable = drmHashCreate(); 18922944501Smrg drmHashInsert(drmHashTable, key, entry); 19022944501Smrg } else { 19122944501Smrg entry = value; 19222944501Smrg } 19322944501Smrg return entry; 19422944501Smrg} 19522944501Smrg 19622944501Smrg/** 19722944501Smrg * Compare two busid strings 19822944501Smrg * 19922944501Smrg * \param first 20022944501Smrg * \param second 20122944501Smrg * 20222944501Smrg * \return 1 if matched. 20322944501Smrg * 20422944501Smrg * \internal 20522944501Smrg * This function compares two bus ID strings. It understands the older 20622944501Smrg * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is 20722944501Smrg * domain, b is bus, d is device, f is function. 20822944501Smrg */ 2096d98c517Smrgstatic int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok) 21022944501Smrg{ 21122944501Smrg /* First, check if the IDs are exactly the same */ 21222944501Smrg if (strcasecmp(id1, id2) == 0) 21322944501Smrg return 1; 21422944501Smrg 21522944501Smrg /* Try to match old/new-style PCI bus IDs. */ 21622944501Smrg if (strncasecmp(id1, "pci", 3) == 0) { 21722944501Smrg unsigned int o1, b1, d1, f1; 21822944501Smrg unsigned int o2, b2, d2, f2; 21922944501Smrg int ret; 22022944501Smrg 22122944501Smrg ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1); 22222944501Smrg if (ret != 4) { 22322944501Smrg o1 = 0; 22422944501Smrg ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1); 22522944501Smrg if (ret != 3) 22622944501Smrg return 0; 22722944501Smrg } 22822944501Smrg 22922944501Smrg ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2); 23022944501Smrg if (ret != 4) { 23122944501Smrg o2 = 0; 23222944501Smrg ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2); 23322944501Smrg if (ret != 3) 23422944501Smrg return 0; 23522944501Smrg } 23622944501Smrg 2376d98c517Smrg /* If domains aren't properly supported by the kernel interface, 2386d98c517Smrg * just ignore them, which sucks less than picking a totally random 2396d98c517Smrg * card with "open by name" 2406d98c517Smrg */ 2416d98c517Smrg if (!pci_domain_ok) 2426d98c517Smrg o1 = o2 = 0; 2436d98c517Smrg 24422944501Smrg if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2)) 24522944501Smrg return 0; 24622944501Smrg else 24722944501Smrg return 1; 24822944501Smrg } 24922944501Smrg return 0; 25022944501Smrg} 25122944501Smrg 25222944501Smrg/** 25322944501Smrg * Handles error checking for chown call. 25422944501Smrg * 25522944501Smrg * \param path to file. 25622944501Smrg * \param id of the new owner. 25722944501Smrg * \param id of the new group. 25822944501Smrg * 25922944501Smrg * \return zero if success or -1 if failure. 26022944501Smrg * 26122944501Smrg * \internal 26222944501Smrg * Checks for failure. If failure was caused by signal call chown again. 26322944501Smrg * If any other failure happened then it will output error mesage using 26422944501Smrg * drmMsg() call. 26522944501Smrg */ 266424e9256Smrg#if !defined(UDEV) 26722944501Smrgstatic int chown_check_return(const char *path, uid_t owner, gid_t group) 26822944501Smrg{ 26922944501Smrg int rv; 27022944501Smrg 27122944501Smrg do { 27222944501Smrg rv = chown(path, owner, group); 27322944501Smrg } while (rv != 0 && errno == EINTR); 27422944501Smrg 27522944501Smrg if (rv == 0) 27622944501Smrg return 0; 27722944501Smrg 27822944501Smrg drmMsg("Failed to change owner or group for file %s! %d: %s\n", 27922944501Smrg path, errno, strerror(errno)); 28022944501Smrg return -1; 28122944501Smrg} 282424e9256Smrg#endif 28322944501Smrg 28422944501Smrg/** 28522944501Smrg * Open the DRM device, creating it if necessary. 28622944501Smrg * 28722944501Smrg * \param dev major and minor numbers of the device. 28822944501Smrg * \param minor minor number of the device. 28922944501Smrg * 29022944501Smrg * \return a file descriptor on success, or a negative value on error. 29122944501Smrg * 29222944501Smrg * \internal 29322944501Smrg * Assembles the device name from \p minor and opens it, creating the device 29422944501Smrg * special file node with the major and minor numbers specified by \p dev and 29522944501Smrg * parent directory if necessary and was called by root. 29622944501Smrg */ 297424e9256Smrgstatic int drmOpenDevice(dev_t dev, int minor, int type) 29822944501Smrg{ 29922944501Smrg stat_t st; 300424e9256Smrg const char *dev_name; 30122944501Smrg char buf[64]; 30222944501Smrg int fd; 30322944501Smrg mode_t devmode = DRM_DEV_MODE, serv_mode; 304424e9256Smrg gid_t serv_group; 305424e9256Smrg#if !defined(UDEV) 30622944501Smrg int isroot = !geteuid(); 30722944501Smrg uid_t user = DRM_DEV_UID; 308424e9256Smrg gid_t group = DRM_DEV_GID; 309424e9256Smrg#endif 310424e9256Smrg 311424e9256Smrg switch (type) { 312424e9256Smrg case DRM_NODE_PRIMARY: 313424e9256Smrg dev_name = DRM_DEV_NAME; 314424e9256Smrg break; 315424e9256Smrg case DRM_NODE_CONTROL: 316424e9256Smrg dev_name = DRM_CONTROL_DEV_NAME; 317424e9256Smrg break; 318424e9256Smrg case DRM_NODE_RENDER: 319424e9256Smrg dev_name = DRM_RENDER_DEV_NAME; 320424e9256Smrg break; 321424e9256Smrg default: 322424e9256Smrg return -EINVAL; 323424e9256Smrg }; 324424e9256Smrg 325424e9256Smrg sprintf(buf, dev_name, DRM_DIR_NAME, minor); 32622944501Smrg drmMsg("drmOpenDevice: node name is %s\n", buf); 32722944501Smrg 32822944501Smrg if (drm_server_info) { 32922944501Smrg drm_server_info->get_perms(&serv_group, &serv_mode); 33022944501Smrg devmode = serv_mode ? serv_mode : DRM_DEV_MODE; 33122944501Smrg devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); 33222944501Smrg } 33322944501Smrg 33422944501Smrg#if !defined(UDEV) 33522944501Smrg if (stat(DRM_DIR_NAME, &st)) { 33622944501Smrg if (!isroot) 33722944501Smrg return DRM_ERR_NOT_ROOT; 33822944501Smrg mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE); 33922944501Smrg chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */ 34022944501Smrg chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE); 34122944501Smrg } 34222944501Smrg 34322944501Smrg /* Check if the device node exists and create it if necessary. */ 34422944501Smrg if (stat(buf, &st)) { 34522944501Smrg if (!isroot) 34622944501Smrg return DRM_ERR_NOT_ROOT; 34722944501Smrg remove(buf); 34822944501Smrg mknod(buf, S_IFCHR | devmode, dev); 34922944501Smrg } 35022944501Smrg 35122944501Smrg if (drm_server_info) { 352424e9256Smrg group = ((int)serv_group >= 0) ? serv_group : DRM_DEV_GID; 35322944501Smrg chown_check_return(buf, user, group); 35422944501Smrg chmod(buf, devmode); 35522944501Smrg } 35622944501Smrg#else 35722944501Smrg /* if we modprobed then wait for udev */ 35822944501Smrg { 35922944501Smrg int udev_count = 0; 36022944501Smrgwait_for_udev: 36122944501Smrg if (stat(DRM_DIR_NAME, &st)) { 36222944501Smrg usleep(20); 36322944501Smrg udev_count++; 36422944501Smrg 36522944501Smrg if (udev_count == 50) 36622944501Smrg return -1; 36722944501Smrg goto wait_for_udev; 36822944501Smrg } 36922944501Smrg 37022944501Smrg if (stat(buf, &st)) { 37122944501Smrg usleep(20); 37222944501Smrg udev_count++; 37322944501Smrg 37422944501Smrg if (udev_count == 50) 37522944501Smrg return -1; 37622944501Smrg goto wait_for_udev; 37722944501Smrg } 37822944501Smrg } 37922944501Smrg#endif 38022944501Smrg 38122944501Smrg fd = open(buf, O_RDWR, 0); 38222944501Smrg drmMsg("drmOpenDevice: open result is %d, (%s)\n", 38322944501Smrg fd, fd < 0 ? strerror(errno) : "OK"); 38422944501Smrg if (fd >= 0) 38522944501Smrg return fd; 38622944501Smrg 3879ce4edccSmrg#if !defined(UDEV) 38822944501Smrg /* Check if the device node is not what we expect it to be, and recreate it 38922944501Smrg * and try again if so. 39022944501Smrg */ 39122944501Smrg if (st.st_rdev != dev) { 39222944501Smrg if (!isroot) 39322944501Smrg return DRM_ERR_NOT_ROOT; 39422944501Smrg remove(buf); 39522944501Smrg mknod(buf, S_IFCHR | devmode, dev); 39622944501Smrg if (drm_server_info) { 39722944501Smrg chown_check_return(buf, user, group); 39822944501Smrg chmod(buf, devmode); 39922944501Smrg } 40022944501Smrg } 40122944501Smrg fd = open(buf, O_RDWR, 0); 40222944501Smrg drmMsg("drmOpenDevice: open result is %d, (%s)\n", 40322944501Smrg fd, fd < 0 ? strerror(errno) : "OK"); 40422944501Smrg if (fd >= 0) 40522944501Smrg return fd; 40622944501Smrg 40722944501Smrg drmMsg("drmOpenDevice: Open failed\n"); 40822944501Smrg remove(buf); 4099ce4edccSmrg#endif 41022944501Smrg return -errno; 41122944501Smrg} 41222944501Smrg 41322944501Smrg 41422944501Smrg/** 41522944501Smrg * Open the DRM device 41622944501Smrg * 41722944501Smrg * \param minor device minor number. 41822944501Smrg * \param create allow to create the device if set. 41922944501Smrg * 42022944501Smrg * \return a file descriptor on success, or a negative value on error. 42122944501Smrg * 42222944501Smrg * \internal 42322944501Smrg * Calls drmOpenDevice() if \p create is set, otherwise assembles the device 42422944501Smrg * name from \p minor and opens it. 42522944501Smrg */ 42622944501Smrgstatic int drmOpenMinor(int minor, int create, int type) 42722944501Smrg{ 42822944501Smrg int fd; 42922944501Smrg char buf[64]; 430424e9256Smrg const char *dev_name; 43122944501Smrg 43222944501Smrg if (create) 43322944501Smrg return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type); 43422944501Smrg 435424e9256Smrg switch (type) { 436424e9256Smrg case DRM_NODE_PRIMARY: 437424e9256Smrg dev_name = DRM_DEV_NAME; 438424e9256Smrg break; 439424e9256Smrg case DRM_NODE_CONTROL: 440424e9256Smrg dev_name = DRM_CONTROL_DEV_NAME; 441424e9256Smrg break; 442424e9256Smrg case DRM_NODE_RENDER: 443424e9256Smrg dev_name = DRM_RENDER_DEV_NAME; 444424e9256Smrg break; 445424e9256Smrg default: 446424e9256Smrg return -EINVAL; 447424e9256Smrg }; 448424e9256Smrg 449424e9256Smrg sprintf(buf, dev_name, DRM_DIR_NAME, minor); 45022944501Smrg if ((fd = open(buf, O_RDWR, 0)) >= 0) 45122944501Smrg return fd; 45222944501Smrg return -errno; 45322944501Smrg} 45422944501Smrg 45522944501Smrg 45622944501Smrg/** 45722944501Smrg * Determine whether the DRM kernel driver has been loaded. 45822944501Smrg * 45922944501Smrg * \return 1 if the DRM driver is loaded, 0 otherwise. 46022944501Smrg * 46122944501Smrg * \internal 46222944501Smrg * Determine the presence of the kernel driver by attempting to open the 0 46322944501Smrg * minor and get version information. For backward compatibility with older 46422944501Smrg * Linux implementations, /proc/dri is also checked. 46522944501Smrg */ 46622944501Smrgint drmAvailable(void) 46722944501Smrg{ 46822944501Smrg drmVersionPtr version; 46922944501Smrg int retval = 0; 47022944501Smrg int fd; 47122944501Smrg 472424e9256Smrg if ((fd = drmOpenMinor(0, 1, DRM_NODE_PRIMARY)) < 0) { 47322944501Smrg#ifdef __linux__ 47422944501Smrg /* Try proc for backward Linux compatibility */ 47522944501Smrg if (!access("/proc/dri/0", R_OK)) 47622944501Smrg return 1; 47722944501Smrg#endif 47822944501Smrg return 0; 47922944501Smrg } 48022944501Smrg 48122944501Smrg if ((version = drmGetVersion(fd))) { 48222944501Smrg retval = 1; 48322944501Smrg drmFreeVersion(version); 48422944501Smrg } 48522944501Smrg close(fd); 48622944501Smrg 48722944501Smrg return retval; 48822944501Smrg} 48922944501Smrg 490424e9256Smrgstatic int drmGetMinorBase(int type) 491424e9256Smrg{ 492424e9256Smrg switch (type) { 493424e9256Smrg case DRM_NODE_PRIMARY: 494424e9256Smrg return 0; 495424e9256Smrg case DRM_NODE_CONTROL: 496424e9256Smrg return 64; 497424e9256Smrg case DRM_NODE_RENDER: 498424e9256Smrg return 128; 499424e9256Smrg default: 500424e9256Smrg return -1; 501424e9256Smrg }; 502424e9256Smrg} 503424e9256Smrg 504424e9256Smrgstatic int drmGetMinorType(int minor) 505424e9256Smrg{ 506424e9256Smrg int type = minor >> 6; 507424e9256Smrg 508424e9256Smrg if (minor < 0) 509424e9256Smrg return -1; 510424e9256Smrg 511424e9256Smrg switch (type) { 512424e9256Smrg case DRM_NODE_PRIMARY: 513424e9256Smrg case DRM_NODE_CONTROL: 514424e9256Smrg case DRM_NODE_RENDER: 515424e9256Smrg return type; 516424e9256Smrg default: 517424e9256Smrg return -1; 518424e9256Smrg } 519424e9256Smrg} 520424e9256Smrg 521424e9256Smrgstatic const char *drmGetMinorName(int type) 522424e9256Smrg{ 523424e9256Smrg switch (type) { 524424e9256Smrg case DRM_NODE_PRIMARY: 525424e9256Smrg return "card"; 526424e9256Smrg case DRM_NODE_CONTROL: 527424e9256Smrg return "controlD"; 528424e9256Smrg case DRM_NODE_RENDER: 529424e9256Smrg return "renderD"; 530424e9256Smrg default: 531424e9256Smrg return NULL; 532424e9256Smrg } 533424e9256Smrg} 53422944501Smrg 53522944501Smrg/** 53622944501Smrg * Open the device by bus ID. 53722944501Smrg * 53822944501Smrg * \param busid bus ID. 539424e9256Smrg * \param type device node type. 54022944501Smrg * 54122944501Smrg * \return a file descriptor on success, or a negative value on error. 54222944501Smrg * 54322944501Smrg * \internal 54422944501Smrg * This function attempts to open every possible minor (up to DRM_MAX_MINOR), 54522944501Smrg * comparing the device bus ID with the one supplied. 54622944501Smrg * 54722944501Smrg * \sa drmOpenMinor() and drmGetBusid(). 54822944501Smrg */ 549424e9256Smrgstatic int drmOpenByBusid(const char *busid, int type) 55022944501Smrg{ 5516d98c517Smrg int i, pci_domain_ok = 1; 55222944501Smrg int fd; 55322944501Smrg const char *buf; 55422944501Smrg drmSetVersion sv; 555424e9256Smrg int base = drmGetMinorBase(type); 556424e9256Smrg 557424e9256Smrg if (base < 0) 558424e9256Smrg return -1; 55922944501Smrg 56022944501Smrg drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); 561424e9256Smrg for (i = base; i < base + DRM_MAX_MINOR; i++) { 562424e9256Smrg fd = drmOpenMinor(i, 1, type); 56322944501Smrg drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); 56422944501Smrg if (fd >= 0) { 5656d98c517Smrg /* We need to try for 1.4 first for proper PCI domain support 5666d98c517Smrg * and if that fails, we know the kernel is busted 5676d98c517Smrg */ 56822944501Smrg sv.drm_di_major = 1; 5696d98c517Smrg sv.drm_di_minor = 4; 57022944501Smrg sv.drm_dd_major = -1; /* Don't care */ 57122944501Smrg sv.drm_dd_minor = -1; /* Don't care */ 5726d98c517Smrg if (drmSetInterfaceVersion(fd, &sv)) { 5736d98c517Smrg#ifndef __alpha__ 5746d98c517Smrg pci_domain_ok = 0; 5756d98c517Smrg#endif 5766d98c517Smrg sv.drm_di_major = 1; 5776d98c517Smrg sv.drm_di_minor = 1; 5786d98c517Smrg sv.drm_dd_major = -1; /* Don't care */ 5796d98c517Smrg sv.drm_dd_minor = -1; /* Don't care */ 580a7d7de1eSmrg drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n"); 5816d98c517Smrg drmSetInterfaceVersion(fd, &sv); 5822e6867f6Smrg } 58322944501Smrg buf = drmGetBusid(fd); 58422944501Smrg drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf); 5856d98c517Smrg if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) { 58622944501Smrg drmFreeBusid(buf); 58722944501Smrg return fd; 58822944501Smrg } 58922944501Smrg if (buf) 59022944501Smrg drmFreeBusid(buf); 59122944501Smrg close(fd); 59222944501Smrg } 59322944501Smrg } 59422944501Smrg return -1; 59522944501Smrg} 59622944501Smrg 59722944501Smrg 59822944501Smrg/** 59922944501Smrg * Open the device by name. 60022944501Smrg * 60122944501Smrg * \param name driver name. 602424e9256Smrg * \param type the device node type. 60322944501Smrg * 60422944501Smrg * \return a file descriptor on success, or a negative value on error. 60522944501Smrg * 60622944501Smrg * \internal 60722944501Smrg * This function opens the first minor number that matches the driver name and 60822944501Smrg * isn't already in use. If it's in use it then it will already have a bus ID 60922944501Smrg * assigned. 61022944501Smrg * 61122944501Smrg * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid(). 61222944501Smrg */ 613424e9256Smrgstatic int drmOpenByName(const char *name, int type) 61422944501Smrg{ 61522944501Smrg int i; 61622944501Smrg int fd; 61722944501Smrg drmVersionPtr version; 61822944501Smrg char * id; 619424e9256Smrg int base = drmGetMinorBase(type); 620424e9256Smrg 621424e9256Smrg if (base < 0) 622424e9256Smrg return -1; 62322944501Smrg 62422944501Smrg /* 62522944501Smrg * Open the first minor number that matches the driver name and isn't 62622944501Smrg * already in use. If it's in use it will have a busid assigned already. 62722944501Smrg */ 628424e9256Smrg for (i = base; i < base + DRM_MAX_MINOR; i++) { 629424e9256Smrg if ((fd = drmOpenMinor(i, 1, type)) >= 0) { 63022944501Smrg if ((version = drmGetVersion(fd))) { 63122944501Smrg if (!strcmp(version->name, name)) { 63222944501Smrg drmFreeVersion(version); 63322944501Smrg id = drmGetBusid(fd); 63422944501Smrg drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL"); 63522944501Smrg if (!id || !*id) { 63622944501Smrg if (id) 63722944501Smrg drmFreeBusid(id); 63822944501Smrg return fd; 63922944501Smrg } else { 64022944501Smrg drmFreeBusid(id); 64122944501Smrg } 64222944501Smrg } else { 64322944501Smrg drmFreeVersion(version); 64422944501Smrg } 64522944501Smrg } 64622944501Smrg close(fd); 64722944501Smrg } 64822944501Smrg } 64922944501Smrg 65022944501Smrg#ifdef __linux__ 65122944501Smrg /* Backward-compatibility /proc support */ 65222944501Smrg for (i = 0; i < 8; i++) { 65322944501Smrg char proc_name[64], buf[512]; 65422944501Smrg char *driver, *pt, *devstring; 65522944501Smrg int retcode; 65622944501Smrg 65722944501Smrg sprintf(proc_name, "/proc/dri/%d/name", i); 65822944501Smrg if ((fd = open(proc_name, 0, 0)) >= 0) { 65922944501Smrg retcode = read(fd, buf, sizeof(buf)-1); 66022944501Smrg close(fd); 66122944501Smrg if (retcode) { 66222944501Smrg buf[retcode-1] = '\0'; 66322944501Smrg for (driver = pt = buf; *pt && *pt != ' '; ++pt) 66422944501Smrg ; 66522944501Smrg if (*pt) { /* Device is next */ 66622944501Smrg *pt = '\0'; 66722944501Smrg if (!strcmp(driver, name)) { /* Match */ 66822944501Smrg for (devstring = ++pt; *pt && *pt != ' '; ++pt) 66922944501Smrg ; 67022944501Smrg if (*pt) { /* Found busid */ 671424e9256Smrg return drmOpenByBusid(++pt, type); 67222944501Smrg } else { /* No busid */ 673424e9256Smrg return drmOpenDevice(strtol(devstring, NULL, 0),i, type); 67422944501Smrg } 67522944501Smrg } 67622944501Smrg } 67722944501Smrg } 67822944501Smrg } 67922944501Smrg } 68022944501Smrg#endif 68122944501Smrg 68222944501Smrg return -1; 68322944501Smrg} 68422944501Smrg 68522944501Smrg 68622944501Smrg/** 68722944501Smrg * Open the DRM device. 68822944501Smrg * 68922944501Smrg * Looks up the specified name and bus ID, and opens the device found. The 69022944501Smrg * entry in /dev/dri is created if necessary and if called by root. 69122944501Smrg * 69222944501Smrg * \param name driver name. Not referenced if bus ID is supplied. 69322944501Smrg * \param busid bus ID. Zero if not known. 69422944501Smrg * 69522944501Smrg * \return a file descriptor on success, or a negative value on error. 69622944501Smrg * 69722944501Smrg * \internal 69822944501Smrg * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() 69922944501Smrg * otherwise. 70022944501Smrg */ 70122944501Smrgint drmOpen(const char *name, const char *busid) 702424e9256Smrg{ 703424e9256Smrg return drmOpenWithType(name, busid, DRM_NODE_PRIMARY); 704424e9256Smrg} 705424e9256Smrg 706424e9256Smrg/** 707424e9256Smrg * Open the DRM device with specified type. 708424e9256Smrg * 709424e9256Smrg * Looks up the specified name and bus ID, and opens the device found. The 710424e9256Smrg * entry in /dev/dri is created if necessary and if called by root. 711424e9256Smrg * 712424e9256Smrg * \param name driver name. Not referenced if bus ID is supplied. 713424e9256Smrg * \param busid bus ID. Zero if not known. 714424e9256Smrg * \param type the device node type to open, PRIMARY, CONTROL or RENDER 715424e9256Smrg * 716424e9256Smrg * \return a file descriptor on success, or a negative value on error. 717424e9256Smrg * 718424e9256Smrg * \internal 719424e9256Smrg * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() 720424e9256Smrg * otherwise. 721424e9256Smrg */ 722424e9256Smrgint drmOpenWithType(const char *name, const char *busid, int type) 72322944501Smrg{ 72422944501Smrg if (!drmAvailable() && name != NULL && drm_server_info) { 725424e9256Smrg /* try to load the kernel module */ 72622944501Smrg if (!drm_server_info->load_module(name)) { 72722944501Smrg drmMsg("[drm] failed to load kernel module \"%s\"\n", name); 72822944501Smrg return -1; 72922944501Smrg } 73022944501Smrg } 73122944501Smrg 73222944501Smrg if (busid) { 733424e9256Smrg int fd = drmOpenByBusid(busid, type); 73422944501Smrg if (fd >= 0) 73522944501Smrg return fd; 73622944501Smrg } 73722944501Smrg 73822944501Smrg if (name) 739424e9256Smrg return drmOpenByName(name, type); 74022944501Smrg 74122944501Smrg return -1; 74222944501Smrg} 74322944501Smrg 74422944501Smrgint drmOpenControl(int minor) 74522944501Smrg{ 74622944501Smrg return drmOpenMinor(minor, 0, DRM_NODE_CONTROL); 74722944501Smrg} 74822944501Smrg 749424e9256Smrgint drmOpenRender(int minor) 750424e9256Smrg{ 751424e9256Smrg return drmOpenMinor(minor, 0, DRM_NODE_RENDER); 752424e9256Smrg} 753424e9256Smrg 75422944501Smrg/** 75522944501Smrg * Free the version information returned by drmGetVersion(). 75622944501Smrg * 75722944501Smrg * \param v pointer to the version information. 75822944501Smrg * 75922944501Smrg * \internal 76022944501Smrg * It frees the memory pointed by \p %v as well as all the non-null strings 76122944501Smrg * pointers in it. 76222944501Smrg */ 76322944501Smrgvoid drmFreeVersion(drmVersionPtr v) 76422944501Smrg{ 76522944501Smrg if (!v) 76622944501Smrg return; 76722944501Smrg drmFree(v->name); 76822944501Smrg drmFree(v->date); 76922944501Smrg drmFree(v->desc); 77022944501Smrg drmFree(v); 77122944501Smrg} 77222944501Smrg 77322944501Smrg 77422944501Smrg/** 77522944501Smrg * Free the non-public version information returned by the kernel. 77622944501Smrg * 77722944501Smrg * \param v pointer to the version information. 77822944501Smrg * 77922944501Smrg * \internal 78022944501Smrg * Used by drmGetVersion() to free the memory pointed by \p %v as well as all 78122944501Smrg * the non-null strings pointers in it. 78222944501Smrg */ 78322944501Smrgstatic void drmFreeKernelVersion(drm_version_t *v) 78422944501Smrg{ 78522944501Smrg if (!v) 78622944501Smrg return; 78722944501Smrg drmFree(v->name); 78822944501Smrg drmFree(v->date); 78922944501Smrg drmFree(v->desc); 79022944501Smrg drmFree(v); 79122944501Smrg} 79222944501Smrg 79322944501Smrg 79422944501Smrg/** 79522944501Smrg * Copy version information. 79622944501Smrg * 79722944501Smrg * \param d destination pointer. 79822944501Smrg * \param s source pointer. 79922944501Smrg * 80022944501Smrg * \internal 80122944501Smrg * Used by drmGetVersion() to translate the information returned by the ioctl 80222944501Smrg * interface in a private structure into the public structure counterpart. 80322944501Smrg */ 80422944501Smrgstatic void drmCopyVersion(drmVersionPtr d, const drm_version_t *s) 80522944501Smrg{ 80622944501Smrg d->version_major = s->version_major; 80722944501Smrg d->version_minor = s->version_minor; 80822944501Smrg d->version_patchlevel = s->version_patchlevel; 80922944501Smrg d->name_len = s->name_len; 8109ce4edccSmrg d->name = strdup(s->name); 81122944501Smrg d->date_len = s->date_len; 8129ce4edccSmrg d->date = strdup(s->date); 81322944501Smrg d->desc_len = s->desc_len; 8149ce4edccSmrg d->desc = strdup(s->desc); 81522944501Smrg} 81622944501Smrg 81722944501Smrg 81822944501Smrg/** 81922944501Smrg * Query the driver version information. 82022944501Smrg * 82122944501Smrg * \param fd file descriptor. 82222944501Smrg * 82322944501Smrg * \return pointer to a drmVersion structure which should be freed with 82422944501Smrg * drmFreeVersion(). 82522944501Smrg * 82622944501Smrg * \note Similar information is available via /proc/dri. 82722944501Smrg * 82822944501Smrg * \internal 82922944501Smrg * It gets the version information via successive DRM_IOCTL_VERSION ioctls, 83022944501Smrg * first with zeros to get the string lengths, and then the actually strings. 83122944501Smrg * It also null-terminates them since they might not be already. 83222944501Smrg */ 83322944501SmrgdrmVersionPtr drmGetVersion(int fd) 83422944501Smrg{ 83522944501Smrg drmVersionPtr retval; 83622944501Smrg drm_version_t *version = drmMalloc(sizeof(*version)); 83722944501Smrg 838424e9256Smrg memclear(*version); 83922944501Smrg 84022944501Smrg if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { 84122944501Smrg drmFreeKernelVersion(version); 84222944501Smrg return NULL; 84322944501Smrg } 84422944501Smrg 84522944501Smrg if (version->name_len) 84622944501Smrg version->name = drmMalloc(version->name_len + 1); 84722944501Smrg if (version->date_len) 84822944501Smrg version->date = drmMalloc(version->date_len + 1); 84922944501Smrg if (version->desc_len) 85022944501Smrg version->desc = drmMalloc(version->desc_len + 1); 85122944501Smrg 85222944501Smrg if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { 85322944501Smrg drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno)); 85422944501Smrg drmFreeKernelVersion(version); 85522944501Smrg return NULL; 85622944501Smrg } 85722944501Smrg 85822944501Smrg /* The results might not be null-terminated strings, so terminate them. */ 85922944501Smrg if (version->name_len) version->name[version->name_len] = '\0'; 86022944501Smrg if (version->date_len) version->date[version->date_len] = '\0'; 86122944501Smrg if (version->desc_len) version->desc[version->desc_len] = '\0'; 86222944501Smrg 86322944501Smrg retval = drmMalloc(sizeof(*retval)); 86422944501Smrg drmCopyVersion(retval, version); 86522944501Smrg drmFreeKernelVersion(version); 86622944501Smrg return retval; 86722944501Smrg} 86822944501Smrg 86922944501Smrg 87022944501Smrg/** 87122944501Smrg * Get version information for the DRM user space library. 87222944501Smrg * 87322944501Smrg * This version number is driver independent. 87422944501Smrg * 87522944501Smrg * \param fd file descriptor. 87622944501Smrg * 87722944501Smrg * \return version information. 87822944501Smrg * 87922944501Smrg * \internal 88022944501Smrg * This function allocates and fills a drm_version structure with a hard coded 88122944501Smrg * version number. 88222944501Smrg */ 88322944501SmrgdrmVersionPtr drmGetLibVersion(int fd) 88422944501Smrg{ 88522944501Smrg drm_version_t *version = drmMalloc(sizeof(*version)); 88622944501Smrg 88722944501Smrg /* Version history: 88822944501Smrg * NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it 88922944501Smrg * revision 1.0.x = original DRM interface with no drmGetLibVersion 89022944501Smrg * entry point and many drm<Device> extensions 89122944501Smrg * revision 1.1.x = added drmCommand entry points for device extensions 89222944501Smrg * added drmGetLibVersion to identify libdrm.a version 89322944501Smrg * revision 1.2.x = added drmSetInterfaceVersion 89422944501Smrg * modified drmOpen to handle both busid and name 89522944501Smrg * revision 1.3.x = added server + memory manager 89622944501Smrg */ 89722944501Smrg version->version_major = 1; 89822944501Smrg version->version_minor = 3; 89922944501Smrg version->version_patchlevel = 0; 90022944501Smrg 90122944501Smrg return (drmVersionPtr)version; 90222944501Smrg} 90322944501Smrg 90420131375Smrgint drmGetCap(int fd, uint64_t capability, uint64_t *value) 90520131375Smrg{ 906424e9256Smrg struct drm_get_cap cap; 90720131375Smrg int ret; 90820131375Smrg 909424e9256Smrg memclear(cap); 910424e9256Smrg cap.capability = capability; 911424e9256Smrg 91220131375Smrg ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap); 91320131375Smrg if (ret) 91420131375Smrg return ret; 91520131375Smrg 91620131375Smrg *value = cap.value; 91720131375Smrg return 0; 91820131375Smrg} 91920131375Smrg 92020131375Smrgint drmSetClientCap(int fd, uint64_t capability, uint64_t value) 92120131375Smrg{ 922424e9256Smrg struct drm_set_client_cap cap; 923424e9256Smrg 924424e9256Smrg memclear(cap); 925424e9256Smrg cap.capability = capability; 926424e9256Smrg cap.value = value; 92720131375Smrg 92820131375Smrg return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap); 92920131375Smrg} 93022944501Smrg 93122944501Smrg/** 93222944501Smrg * Free the bus ID information. 93322944501Smrg * 93422944501Smrg * \param busid bus ID information string as given by drmGetBusid(). 93522944501Smrg * 93622944501Smrg * \internal 93722944501Smrg * This function is just frees the memory pointed by \p busid. 93822944501Smrg */ 93922944501Smrgvoid drmFreeBusid(const char *busid) 94022944501Smrg{ 94122944501Smrg drmFree((void *)busid); 94222944501Smrg} 94322944501Smrg 94422944501Smrg 94522944501Smrg/** 94622944501Smrg * Get the bus ID of the device. 94722944501Smrg * 94822944501Smrg * \param fd file descriptor. 94922944501Smrg * 95022944501Smrg * \return bus ID string. 95122944501Smrg * 95222944501Smrg * \internal 95322944501Smrg * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to 95422944501Smrg * get the string length and data, passing the arguments in a drm_unique 95522944501Smrg * structure. 95622944501Smrg */ 95722944501Smrgchar *drmGetBusid(int fd) 95822944501Smrg{ 95922944501Smrg drm_unique_t u; 96022944501Smrg 961424e9256Smrg memclear(u); 96222944501Smrg 96322944501Smrg if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) 96422944501Smrg return NULL; 96522944501Smrg u.unique = drmMalloc(u.unique_len + 1); 96622944501Smrg if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) 96722944501Smrg return NULL; 96822944501Smrg u.unique[u.unique_len] = '\0'; 96922944501Smrg 97022944501Smrg return u.unique; 97122944501Smrg} 97222944501Smrg 97322944501Smrg 97422944501Smrg/** 97522944501Smrg * Set the bus ID of the device. 97622944501Smrg * 97722944501Smrg * \param fd file descriptor. 97822944501Smrg * \param busid bus ID string. 97922944501Smrg * 98022944501Smrg * \return zero on success, negative on failure. 98122944501Smrg * 98222944501Smrg * \internal 98322944501Smrg * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing 98422944501Smrg * the arguments in a drm_unique structure. 98522944501Smrg */ 98622944501Smrgint drmSetBusid(int fd, const char *busid) 98722944501Smrg{ 98822944501Smrg drm_unique_t u; 98922944501Smrg 990424e9256Smrg memclear(u); 99122944501Smrg u.unique = (char *)busid; 99222944501Smrg u.unique_len = strlen(busid); 99322944501Smrg 99422944501Smrg if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) { 99522944501Smrg return -errno; 99622944501Smrg } 99722944501Smrg return 0; 99822944501Smrg} 99922944501Smrg 100022944501Smrgint drmGetMagic(int fd, drm_magic_t * magic) 100122944501Smrg{ 100222944501Smrg drm_auth_t auth; 100322944501Smrg 1004424e9256Smrg memclear(auth); 1005424e9256Smrg 100622944501Smrg *magic = 0; 100722944501Smrg if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) 100822944501Smrg return -errno; 100922944501Smrg *magic = auth.magic; 101022944501Smrg return 0; 101122944501Smrg} 101222944501Smrg 101322944501Smrgint drmAuthMagic(int fd, drm_magic_t magic) 101422944501Smrg{ 101522944501Smrg drm_auth_t auth; 101622944501Smrg 1017424e9256Smrg memclear(auth); 101822944501Smrg auth.magic = magic; 101922944501Smrg if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) 102022944501Smrg return -errno; 102122944501Smrg return 0; 102222944501Smrg} 102322944501Smrg 102422944501Smrg/** 102522944501Smrg * Specifies a range of memory that is available for mapping by a 102622944501Smrg * non-root process. 102722944501Smrg * 102822944501Smrg * \param fd file descriptor. 102922944501Smrg * \param offset usually the physical address. The actual meaning depends of 103022944501Smrg * the \p type parameter. See below. 103122944501Smrg * \param size of the memory in bytes. 103222944501Smrg * \param type type of the memory to be mapped. 103322944501Smrg * \param flags combination of several flags to modify the function actions. 103422944501Smrg * \param handle will be set to a value that may be used as the offset 103522944501Smrg * parameter for mmap(). 103622944501Smrg * 103722944501Smrg * \return zero on success or a negative value on error. 103822944501Smrg * 103922944501Smrg * \par Mapping the frame buffer 104022944501Smrg * For the frame buffer 104122944501Smrg * - \p offset will be the physical address of the start of the frame buffer, 104222944501Smrg * - \p size will be the size of the frame buffer in bytes, and 104322944501Smrg * - \p type will be DRM_FRAME_BUFFER. 104422944501Smrg * 104522944501Smrg * \par 104622944501Smrg * The area mapped will be uncached. If MTRR support is available in the 104722944501Smrg * kernel, the frame buffer area will be set to write combining. 104822944501Smrg * 104922944501Smrg * \par Mapping the MMIO register area 105022944501Smrg * For the MMIO register area, 105122944501Smrg * - \p offset will be the physical address of the start of the register area, 105222944501Smrg * - \p size will be the size of the register area bytes, and 105322944501Smrg * - \p type will be DRM_REGISTERS. 105422944501Smrg * \par 105522944501Smrg * The area mapped will be uncached. 105622944501Smrg * 105722944501Smrg * \par Mapping the SAREA 105822944501Smrg * For the SAREA, 105922944501Smrg * - \p offset will be ignored and should be set to zero, 106022944501Smrg * - \p size will be the desired size of the SAREA in bytes, 106122944501Smrg * - \p type will be DRM_SHM. 106222944501Smrg * 106322944501Smrg * \par 106422944501Smrg * A shared memory area of the requested size will be created and locked in 106522944501Smrg * kernel memory. This area may be mapped into client-space by using the handle 106622944501Smrg * returned. 106722944501Smrg * 106822944501Smrg * \note May only be called by root. 106922944501Smrg * 107022944501Smrg * \internal 107122944501Smrg * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing 107222944501Smrg * the arguments in a drm_map structure. 107322944501Smrg */ 107422944501Smrgint drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type, 107522944501Smrg drmMapFlags flags, drm_handle_t *handle) 107622944501Smrg{ 107722944501Smrg drm_map_t map; 107822944501Smrg 1079424e9256Smrg memclear(map); 108022944501Smrg map.offset = offset; 108122944501Smrg map.size = size; 108222944501Smrg map.type = type; 108322944501Smrg map.flags = flags; 108422944501Smrg if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map)) 108522944501Smrg return -errno; 108622944501Smrg if (handle) 108720131375Smrg *handle = (drm_handle_t)(uintptr_t)map.handle; 108822944501Smrg return 0; 108922944501Smrg} 109022944501Smrg 109122944501Smrgint drmRmMap(int fd, drm_handle_t handle) 109222944501Smrg{ 109322944501Smrg drm_map_t map; 109422944501Smrg 1095424e9256Smrg memclear(map); 109620131375Smrg map.handle = (void *)(uintptr_t)handle; 109722944501Smrg 109822944501Smrg if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map)) 109922944501Smrg return -errno; 110022944501Smrg return 0; 110122944501Smrg} 110222944501Smrg 110322944501Smrg/** 110422944501Smrg * Make buffers available for DMA transfers. 110522944501Smrg * 110622944501Smrg * \param fd file descriptor. 110722944501Smrg * \param count number of buffers. 110822944501Smrg * \param size size of each buffer. 110922944501Smrg * \param flags buffer allocation flags. 111022944501Smrg * \param agp_offset offset in the AGP aperture 111122944501Smrg * 111222944501Smrg * \return number of buffers allocated, negative on error. 111322944501Smrg * 111422944501Smrg * \internal 111522944501Smrg * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl. 111622944501Smrg * 111722944501Smrg * \sa drm_buf_desc. 111822944501Smrg */ 111922944501Smrgint drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, 112022944501Smrg int agp_offset) 112122944501Smrg{ 112222944501Smrg drm_buf_desc_t request; 112322944501Smrg 1124424e9256Smrg memclear(request); 112522944501Smrg request.count = count; 112622944501Smrg request.size = size; 112722944501Smrg request.flags = flags; 112822944501Smrg request.agp_start = agp_offset; 112922944501Smrg 113022944501Smrg if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request)) 113122944501Smrg return -errno; 113222944501Smrg return request.count; 113322944501Smrg} 113422944501Smrg 113522944501Smrgint drmMarkBufs(int fd, double low, double high) 113622944501Smrg{ 113722944501Smrg drm_buf_info_t info; 113822944501Smrg int i; 113922944501Smrg 1140424e9256Smrg memclear(info); 114122944501Smrg 114222944501Smrg if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) 114322944501Smrg return -EINVAL; 114422944501Smrg 114522944501Smrg if (!info.count) 114622944501Smrg return -EINVAL; 114722944501Smrg 114822944501Smrg if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 114922944501Smrg return -ENOMEM; 115022944501Smrg 115122944501Smrg if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 115222944501Smrg int retval = -errno; 115322944501Smrg drmFree(info.list); 115422944501Smrg return retval; 115522944501Smrg } 115622944501Smrg 115722944501Smrg for (i = 0; i < info.count; i++) { 115822944501Smrg info.list[i].low_mark = low * info.list[i].count; 115922944501Smrg info.list[i].high_mark = high * info.list[i].count; 116022944501Smrg if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) { 116122944501Smrg int retval = -errno; 116222944501Smrg drmFree(info.list); 116322944501Smrg return retval; 116422944501Smrg } 116522944501Smrg } 116622944501Smrg drmFree(info.list); 116722944501Smrg 116822944501Smrg return 0; 116922944501Smrg} 117022944501Smrg 117122944501Smrg/** 117222944501Smrg * Free buffers. 117322944501Smrg * 117422944501Smrg * \param fd file descriptor. 117522944501Smrg * \param count number of buffers to free. 117622944501Smrg * \param list list of buffers to be freed. 117722944501Smrg * 117822944501Smrg * \return zero on success, or a negative value on failure. 117922944501Smrg * 118022944501Smrg * \note This function is primarily used for debugging. 118122944501Smrg * 118222944501Smrg * \internal 118322944501Smrg * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing 118422944501Smrg * the arguments in a drm_buf_free structure. 118522944501Smrg */ 118622944501Smrgint drmFreeBufs(int fd, int count, int *list) 118722944501Smrg{ 118822944501Smrg drm_buf_free_t request; 118922944501Smrg 1190424e9256Smrg memclear(request); 119122944501Smrg request.count = count; 119222944501Smrg request.list = list; 119322944501Smrg if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request)) 119422944501Smrg return -errno; 119522944501Smrg return 0; 119622944501Smrg} 119722944501Smrg 119822944501Smrg 119922944501Smrg/** 120022944501Smrg * Close the device. 120122944501Smrg * 120222944501Smrg * \param fd file descriptor. 120322944501Smrg * 120422944501Smrg * \internal 120522944501Smrg * This function closes the file descriptor. 120622944501Smrg */ 120722944501Smrgint drmClose(int fd) 120822944501Smrg{ 120922944501Smrg unsigned long key = drmGetKeyFromFd(fd); 121022944501Smrg drmHashEntry *entry = drmGetEntry(fd); 121122944501Smrg 121222944501Smrg drmHashDestroy(entry->tagTable); 121322944501Smrg entry->fd = 0; 121422944501Smrg entry->f = NULL; 121522944501Smrg entry->tagTable = NULL; 121622944501Smrg 121722944501Smrg drmHashDelete(drmHashTable, key); 121822944501Smrg drmFree(entry); 121922944501Smrg 122022944501Smrg return close(fd); 122122944501Smrg} 122222944501Smrg 122322944501Smrg 122422944501Smrg/** 122522944501Smrg * Map a region of memory. 122622944501Smrg * 122722944501Smrg * \param fd file descriptor. 122822944501Smrg * \param handle handle returned by drmAddMap(). 122922944501Smrg * \param size size in bytes. Must match the size used by drmAddMap(). 123022944501Smrg * \param address will contain the user-space virtual address where the mapping 123122944501Smrg * begins. 123222944501Smrg * 123322944501Smrg * \return zero on success, or a negative value on failure. 123422944501Smrg * 123522944501Smrg * \internal 123622944501Smrg * This function is a wrapper for mmap(). 123722944501Smrg */ 123822944501Smrgint drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address) 123922944501Smrg{ 124022944501Smrg static unsigned long pagesize_mask = 0; 124122944501Smrg 124222944501Smrg if (fd < 0) 124322944501Smrg return -EINVAL; 124422944501Smrg 124522944501Smrg if (!pagesize_mask) 124622944501Smrg pagesize_mask = getpagesize() - 1; 124722944501Smrg 124822944501Smrg size = (size + pagesize_mask) & ~pagesize_mask; 124922944501Smrg 1250a884aba1Smrg *address = drm_mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle); 125122944501Smrg if (*address == MAP_FAILED) 125222944501Smrg return -errno; 125322944501Smrg return 0; 125422944501Smrg} 125522944501Smrg 125622944501Smrg 125722944501Smrg/** 125822944501Smrg * Unmap mappings obtained with drmMap(). 125922944501Smrg * 126022944501Smrg * \param address address as given by drmMap(). 126122944501Smrg * \param size size in bytes. Must match the size used by drmMap(). 126222944501Smrg * 126322944501Smrg * \return zero on success, or a negative value on failure. 126422944501Smrg * 126522944501Smrg * \internal 126622944501Smrg * This function is a wrapper for munmap(). 126722944501Smrg */ 126822944501Smrgint drmUnmap(drmAddress address, drmSize size) 126922944501Smrg{ 1270a884aba1Smrg return drm_munmap(address, size); 127122944501Smrg} 127222944501Smrg 127322944501SmrgdrmBufInfoPtr drmGetBufInfo(int fd) 127422944501Smrg{ 127522944501Smrg drm_buf_info_t info; 127622944501Smrg drmBufInfoPtr retval; 127722944501Smrg int i; 127822944501Smrg 1279424e9256Smrg memclear(info); 128022944501Smrg 128122944501Smrg if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) 128222944501Smrg return NULL; 128322944501Smrg 128422944501Smrg if (info.count) { 128522944501Smrg if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 128622944501Smrg return NULL; 128722944501Smrg 128822944501Smrg if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 128922944501Smrg drmFree(info.list); 129022944501Smrg return NULL; 129122944501Smrg } 129222944501Smrg 129322944501Smrg retval = drmMalloc(sizeof(*retval)); 129422944501Smrg retval->count = info.count; 129522944501Smrg retval->list = drmMalloc(info.count * sizeof(*retval->list)); 129622944501Smrg for (i = 0; i < info.count; i++) { 129722944501Smrg retval->list[i].count = info.list[i].count; 129822944501Smrg retval->list[i].size = info.list[i].size; 129922944501Smrg retval->list[i].low_mark = info.list[i].low_mark; 130022944501Smrg retval->list[i].high_mark = info.list[i].high_mark; 130122944501Smrg } 130222944501Smrg drmFree(info.list); 130322944501Smrg return retval; 130422944501Smrg } 130522944501Smrg return NULL; 130622944501Smrg} 130722944501Smrg 130822944501Smrg/** 130922944501Smrg * Map all DMA buffers into client-virtual space. 131022944501Smrg * 131122944501Smrg * \param fd file descriptor. 131222944501Smrg * 131322944501Smrg * \return a pointer to a ::drmBufMap structure. 131422944501Smrg * 131522944501Smrg * \note The client may not use these buffers until obtaining buffer indices 131622944501Smrg * with drmDMA(). 131722944501Smrg * 131822944501Smrg * \internal 131922944501Smrg * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned 132022944501Smrg * information about the buffers in a drm_buf_map structure into the 132122944501Smrg * client-visible data structures. 132222944501Smrg */ 132322944501SmrgdrmBufMapPtr drmMapBufs(int fd) 132422944501Smrg{ 132522944501Smrg drm_buf_map_t bufs; 132622944501Smrg drmBufMapPtr retval; 132722944501Smrg int i; 132822944501Smrg 1329424e9256Smrg memclear(bufs); 133022944501Smrg if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) 133122944501Smrg return NULL; 133222944501Smrg 133322944501Smrg if (!bufs.count) 133422944501Smrg return NULL; 133522944501Smrg 133622944501Smrg if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list)))) 133722944501Smrg return NULL; 133822944501Smrg 133922944501Smrg if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) { 134022944501Smrg drmFree(bufs.list); 134122944501Smrg return NULL; 134222944501Smrg } 134322944501Smrg 134422944501Smrg retval = drmMalloc(sizeof(*retval)); 134522944501Smrg retval->count = bufs.count; 134622944501Smrg retval->list = drmMalloc(bufs.count * sizeof(*retval->list)); 134722944501Smrg for (i = 0; i < bufs.count; i++) { 134822944501Smrg retval->list[i].idx = bufs.list[i].idx; 134922944501Smrg retval->list[i].total = bufs.list[i].total; 135022944501Smrg retval->list[i].used = 0; 135122944501Smrg retval->list[i].address = bufs.list[i].address; 135222944501Smrg } 135322944501Smrg 135422944501Smrg drmFree(bufs.list); 135522944501Smrg 135622944501Smrg return retval; 135722944501Smrg} 135822944501Smrg 135922944501Smrg 136022944501Smrg/** 136122944501Smrg * Unmap buffers allocated with drmMapBufs(). 136222944501Smrg * 136322944501Smrg * \return zero on success, or negative value on failure. 136422944501Smrg * 136522944501Smrg * \internal 136622944501Smrg * Calls munmap() for every buffer stored in \p bufs and frees the 136722944501Smrg * memory allocated by drmMapBufs(). 136822944501Smrg */ 136922944501Smrgint drmUnmapBufs(drmBufMapPtr bufs) 137022944501Smrg{ 137122944501Smrg int i; 137222944501Smrg 137322944501Smrg for (i = 0; i < bufs->count; i++) { 1374a884aba1Smrg drm_munmap(bufs->list[i].address, bufs->list[i].total); 137522944501Smrg } 137622944501Smrg 137722944501Smrg drmFree(bufs->list); 137822944501Smrg drmFree(bufs); 137922944501Smrg 138022944501Smrg return 0; 138122944501Smrg} 138222944501Smrg 138322944501Smrg 138422944501Smrg#define DRM_DMA_RETRY 16 138522944501Smrg 138622944501Smrg/** 138722944501Smrg * Reserve DMA buffers. 138822944501Smrg * 138922944501Smrg * \param fd file descriptor. 139022944501Smrg * \param request 139122944501Smrg * 139222944501Smrg * \return zero on success, or a negative value on failure. 139322944501Smrg * 139422944501Smrg * \internal 139522944501Smrg * Assemble the arguments into a drm_dma structure and keeps issuing the 139622944501Smrg * DRM_IOCTL_DMA ioctl until success or until maximum number of retries. 139722944501Smrg */ 139822944501Smrgint drmDMA(int fd, drmDMAReqPtr request) 139922944501Smrg{ 140022944501Smrg drm_dma_t dma; 140122944501Smrg int ret, i = 0; 140222944501Smrg 140322944501Smrg dma.context = request->context; 140422944501Smrg dma.send_count = request->send_count; 140522944501Smrg dma.send_indices = request->send_list; 140622944501Smrg dma.send_sizes = request->send_sizes; 140722944501Smrg dma.flags = request->flags; 140822944501Smrg dma.request_count = request->request_count; 140922944501Smrg dma.request_size = request->request_size; 141022944501Smrg dma.request_indices = request->request_list; 141122944501Smrg dma.request_sizes = request->request_sizes; 141222944501Smrg dma.granted_count = 0; 141322944501Smrg 141422944501Smrg do { 141522944501Smrg ret = ioctl( fd, DRM_IOCTL_DMA, &dma ); 141622944501Smrg } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY ); 141722944501Smrg 141822944501Smrg if ( ret == 0 ) { 141922944501Smrg request->granted_count = dma.granted_count; 142022944501Smrg return 0; 142122944501Smrg } else { 142222944501Smrg return -errno; 142322944501Smrg } 142422944501Smrg} 142522944501Smrg 142622944501Smrg 142722944501Smrg/** 142822944501Smrg * Obtain heavyweight hardware lock. 142922944501Smrg * 143022944501Smrg * \param fd file descriptor. 143122944501Smrg * \param context context. 143222944501Smrg * \param flags flags that determine the sate of the hardware when the function 143322944501Smrg * returns. 143422944501Smrg * 143522944501Smrg * \return always zero. 143622944501Smrg * 143722944501Smrg * \internal 143822944501Smrg * This function translates the arguments into a drm_lock structure and issue 143922944501Smrg * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired. 144022944501Smrg */ 144122944501Smrgint drmGetLock(int fd, drm_context_t context, drmLockFlags flags) 144222944501Smrg{ 144322944501Smrg drm_lock_t lock; 144422944501Smrg 1445424e9256Smrg memclear(lock); 144622944501Smrg lock.context = context; 144722944501Smrg lock.flags = 0; 144822944501Smrg if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 144922944501Smrg if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 145022944501Smrg if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 145122944501Smrg if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 145222944501Smrg if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 145322944501Smrg if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 145422944501Smrg 145522944501Smrg while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock)) 145622944501Smrg ; 145722944501Smrg return 0; 145822944501Smrg} 145922944501Smrg 146022944501Smrg/** 146122944501Smrg * Release the hardware lock. 146222944501Smrg * 146322944501Smrg * \param fd file descriptor. 146422944501Smrg * \param context context. 146522944501Smrg * 146622944501Smrg * \return zero on success, or a negative value on failure. 146722944501Smrg * 146822944501Smrg * \internal 146922944501Smrg * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the 147022944501Smrg * argument in a drm_lock structure. 147122944501Smrg */ 147222944501Smrgint drmUnlock(int fd, drm_context_t context) 147322944501Smrg{ 147422944501Smrg drm_lock_t lock; 147522944501Smrg 1476424e9256Smrg memclear(lock); 147722944501Smrg lock.context = context; 147822944501Smrg return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock); 147922944501Smrg} 148022944501Smrg 148122944501Smrgdrm_context_t *drmGetReservedContextList(int fd, int *count) 148222944501Smrg{ 148322944501Smrg drm_ctx_res_t res; 148422944501Smrg drm_ctx_t *list; 148522944501Smrg drm_context_t * retval; 148622944501Smrg int i; 148722944501Smrg 1488424e9256Smrg memclear(res); 148922944501Smrg if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) 149022944501Smrg return NULL; 149122944501Smrg 149222944501Smrg if (!res.count) 149322944501Smrg return NULL; 149422944501Smrg 149522944501Smrg if (!(list = drmMalloc(res.count * sizeof(*list)))) 149622944501Smrg return NULL; 149722944501Smrg if (!(retval = drmMalloc(res.count * sizeof(*retval)))) { 149822944501Smrg drmFree(list); 149922944501Smrg return NULL; 150022944501Smrg } 150122944501Smrg 150222944501Smrg res.contexts = list; 150322944501Smrg if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) 150422944501Smrg return NULL; 150522944501Smrg 150622944501Smrg for (i = 0; i < res.count; i++) 150722944501Smrg retval[i] = list[i].handle; 150822944501Smrg drmFree(list); 150922944501Smrg 151022944501Smrg *count = res.count; 151122944501Smrg return retval; 151222944501Smrg} 151322944501Smrg 151422944501Smrgvoid drmFreeReservedContextList(drm_context_t *pt) 151522944501Smrg{ 151622944501Smrg drmFree(pt); 151722944501Smrg} 151822944501Smrg 151922944501Smrg/** 152022944501Smrg * Create context. 152122944501Smrg * 152222944501Smrg * Used by the X server during GLXContext initialization. This causes 152322944501Smrg * per-context kernel-level resources to be allocated. 152422944501Smrg * 152522944501Smrg * \param fd file descriptor. 152622944501Smrg * \param handle is set on success. To be used by the client when requesting DMA 152722944501Smrg * dispatch with drmDMA(). 152822944501Smrg * 152922944501Smrg * \return zero on success, or a negative value on failure. 153022944501Smrg * 153122944501Smrg * \note May only be called by root. 153222944501Smrg * 153322944501Smrg * \internal 153422944501Smrg * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the 153522944501Smrg * argument in a drm_ctx structure. 153622944501Smrg */ 153722944501Smrgint drmCreateContext(int fd, drm_context_t *handle) 153822944501Smrg{ 153922944501Smrg drm_ctx_t ctx; 154022944501Smrg 1541424e9256Smrg memclear(ctx); 154222944501Smrg if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) 154322944501Smrg return -errno; 154422944501Smrg *handle = ctx.handle; 154522944501Smrg return 0; 154622944501Smrg} 154722944501Smrg 154822944501Smrgint drmSwitchToContext(int fd, drm_context_t context) 154922944501Smrg{ 155022944501Smrg drm_ctx_t ctx; 155122944501Smrg 1552424e9256Smrg memclear(ctx); 155322944501Smrg ctx.handle = context; 155422944501Smrg if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) 155522944501Smrg return -errno; 155622944501Smrg return 0; 155722944501Smrg} 155822944501Smrg 155922944501Smrgint drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags) 156022944501Smrg{ 156122944501Smrg drm_ctx_t ctx; 156222944501Smrg 156322944501Smrg /* 156422944501Smrg * Context preserving means that no context switches are done between DMA 156522944501Smrg * buffers from one context and the next. This is suitable for use in the 156622944501Smrg * X server (which promises to maintain hardware context), or in the 156722944501Smrg * client-side library when buffers are swapped on behalf of two threads. 156822944501Smrg */ 1569424e9256Smrg memclear(ctx); 157022944501Smrg ctx.handle = context; 157122944501Smrg if (flags & DRM_CONTEXT_PRESERVED) 157222944501Smrg ctx.flags |= _DRM_CONTEXT_PRESERVED; 157322944501Smrg if (flags & DRM_CONTEXT_2DONLY) 157422944501Smrg ctx.flags |= _DRM_CONTEXT_2DONLY; 157522944501Smrg if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) 157622944501Smrg return -errno; 157722944501Smrg return 0; 157822944501Smrg} 157922944501Smrg 158022944501Smrgint drmGetContextFlags(int fd, drm_context_t context, 158122944501Smrg drm_context_tFlagsPtr flags) 158222944501Smrg{ 158322944501Smrg drm_ctx_t ctx; 158422944501Smrg 1585424e9256Smrg memclear(ctx); 158622944501Smrg ctx.handle = context; 158722944501Smrg if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx)) 158822944501Smrg return -errno; 158922944501Smrg *flags = 0; 159022944501Smrg if (ctx.flags & _DRM_CONTEXT_PRESERVED) 159122944501Smrg *flags |= DRM_CONTEXT_PRESERVED; 159222944501Smrg if (ctx.flags & _DRM_CONTEXT_2DONLY) 159322944501Smrg *flags |= DRM_CONTEXT_2DONLY; 159422944501Smrg return 0; 159522944501Smrg} 159622944501Smrg 159722944501Smrg/** 159822944501Smrg * Destroy context. 159922944501Smrg * 160022944501Smrg * Free any kernel-level resources allocated with drmCreateContext() associated 160122944501Smrg * with the context. 160222944501Smrg * 160322944501Smrg * \param fd file descriptor. 160422944501Smrg * \param handle handle given by drmCreateContext(). 160522944501Smrg * 160622944501Smrg * \return zero on success, or a negative value on failure. 160722944501Smrg * 160822944501Smrg * \note May only be called by root. 160922944501Smrg * 161022944501Smrg * \internal 161122944501Smrg * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the 161222944501Smrg * argument in a drm_ctx structure. 161322944501Smrg */ 161422944501Smrgint drmDestroyContext(int fd, drm_context_t handle) 161522944501Smrg{ 161622944501Smrg drm_ctx_t ctx; 1617424e9256Smrg 1618424e9256Smrg memclear(ctx); 161922944501Smrg ctx.handle = handle; 162022944501Smrg if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx)) 162122944501Smrg return -errno; 162222944501Smrg return 0; 162322944501Smrg} 162422944501Smrg 162522944501Smrgint drmCreateDrawable(int fd, drm_drawable_t *handle) 162622944501Smrg{ 162722944501Smrg drm_draw_t draw; 1628424e9256Smrg 1629424e9256Smrg memclear(draw); 163022944501Smrg if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) 163122944501Smrg return -errno; 163222944501Smrg *handle = draw.handle; 163322944501Smrg return 0; 163422944501Smrg} 163522944501Smrg 163622944501Smrgint drmDestroyDrawable(int fd, drm_drawable_t handle) 163722944501Smrg{ 163822944501Smrg drm_draw_t draw; 1639424e9256Smrg 1640424e9256Smrg memclear(draw); 164122944501Smrg draw.handle = handle; 164222944501Smrg if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw)) 164322944501Smrg return -errno; 164422944501Smrg return 0; 164522944501Smrg} 164622944501Smrg 164722944501Smrgint drmUpdateDrawableInfo(int fd, drm_drawable_t handle, 164822944501Smrg drm_drawable_info_type_t type, unsigned int num, 164922944501Smrg void *data) 165022944501Smrg{ 165122944501Smrg drm_update_draw_t update; 165222944501Smrg 1653424e9256Smrg memclear(update); 165422944501Smrg update.handle = handle; 165522944501Smrg update.type = type; 165622944501Smrg update.num = num; 165722944501Smrg update.data = (unsigned long long)(unsigned long)data; 165822944501Smrg 165922944501Smrg if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update)) 166022944501Smrg return -errno; 166122944501Smrg 166222944501Smrg return 0; 166322944501Smrg} 166422944501Smrg 166522944501Smrg/** 166622944501Smrg * Acquire the AGP device. 166722944501Smrg * 166822944501Smrg * Must be called before any of the other AGP related calls. 166922944501Smrg * 167022944501Smrg * \param fd file descriptor. 167122944501Smrg * 167222944501Smrg * \return zero on success, or a negative value on failure. 167322944501Smrg * 167422944501Smrg * \internal 167522944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl. 167622944501Smrg */ 167722944501Smrgint drmAgpAcquire(int fd) 167822944501Smrg{ 167922944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) 168022944501Smrg return -errno; 168122944501Smrg return 0; 168222944501Smrg} 168322944501Smrg 168422944501Smrg 168522944501Smrg/** 168622944501Smrg * Release the AGP device. 168722944501Smrg * 168822944501Smrg * \param fd file descriptor. 168922944501Smrg * 169022944501Smrg * \return zero on success, or a negative value on failure. 169122944501Smrg * 169222944501Smrg * \internal 169322944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl. 169422944501Smrg */ 169522944501Smrgint drmAgpRelease(int fd) 169622944501Smrg{ 169722944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) 169822944501Smrg return -errno; 169922944501Smrg return 0; 170022944501Smrg} 170122944501Smrg 170222944501Smrg 170322944501Smrg/** 170422944501Smrg * Set the AGP mode. 170522944501Smrg * 170622944501Smrg * \param fd file descriptor. 170722944501Smrg * \param mode AGP mode. 170822944501Smrg * 170922944501Smrg * \return zero on success, or a negative value on failure. 171022944501Smrg * 171122944501Smrg * \internal 171222944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the 171322944501Smrg * argument in a drm_agp_mode structure. 171422944501Smrg */ 171522944501Smrgint drmAgpEnable(int fd, unsigned long mode) 171622944501Smrg{ 171722944501Smrg drm_agp_mode_t m; 171822944501Smrg 1719424e9256Smrg memclear(m); 172022944501Smrg m.mode = mode; 172122944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) 172222944501Smrg return -errno; 172322944501Smrg return 0; 172422944501Smrg} 172522944501Smrg 172622944501Smrg 172722944501Smrg/** 172822944501Smrg * Allocate a chunk of AGP memory. 172922944501Smrg * 173022944501Smrg * \param fd file descriptor. 173122944501Smrg * \param size requested memory size in bytes. Will be rounded to page boundary. 173222944501Smrg * \param type type of memory to allocate. 173322944501Smrg * \param address if not zero, will be set to the physical address of the 173422944501Smrg * allocated memory. 173522944501Smrg * \param handle on success will be set to a handle of the allocated memory. 173622944501Smrg * 173722944501Smrg * \return zero on success, or a negative value on failure. 173822944501Smrg * 173922944501Smrg * \internal 174022944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the 174122944501Smrg * arguments in a drm_agp_buffer structure. 174222944501Smrg */ 174322944501Smrgint drmAgpAlloc(int fd, unsigned long size, unsigned long type, 174422944501Smrg unsigned long *address, drm_handle_t *handle) 174522944501Smrg{ 174622944501Smrg drm_agp_buffer_t b; 174722944501Smrg 1748424e9256Smrg memclear(b); 174922944501Smrg *handle = DRM_AGP_NO_HANDLE; 175022944501Smrg b.size = size; 175122944501Smrg b.type = type; 175222944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) 175322944501Smrg return -errno; 175422944501Smrg if (address != 0UL) 175522944501Smrg *address = b.physical; 175622944501Smrg *handle = b.handle; 175722944501Smrg return 0; 175822944501Smrg} 175922944501Smrg 176022944501Smrg 176122944501Smrg/** 176222944501Smrg * Free a chunk of AGP memory. 176322944501Smrg * 176422944501Smrg * \param fd file descriptor. 176522944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 176622944501Smrg * 176722944501Smrg * \return zero on success, or a negative value on failure. 176822944501Smrg * 176922944501Smrg * \internal 177022944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the 177122944501Smrg * argument in a drm_agp_buffer structure. 177222944501Smrg */ 177322944501Smrgint drmAgpFree(int fd, drm_handle_t handle) 177422944501Smrg{ 177522944501Smrg drm_agp_buffer_t b; 177622944501Smrg 1777424e9256Smrg memclear(b); 177822944501Smrg b.handle = handle; 177922944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b)) 178022944501Smrg return -errno; 178122944501Smrg return 0; 178222944501Smrg} 178322944501Smrg 178422944501Smrg 178522944501Smrg/** 178622944501Smrg * Bind a chunk of AGP memory. 178722944501Smrg * 178822944501Smrg * \param fd file descriptor. 178922944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 179022944501Smrg * \param offset offset in bytes. It will round to page boundary. 179122944501Smrg * 179222944501Smrg * \return zero on success, or a negative value on failure. 179322944501Smrg * 179422944501Smrg * \internal 179522944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the 179622944501Smrg * argument in a drm_agp_binding structure. 179722944501Smrg */ 179822944501Smrgint drmAgpBind(int fd, drm_handle_t handle, unsigned long offset) 179922944501Smrg{ 180022944501Smrg drm_agp_binding_t b; 180122944501Smrg 1802424e9256Smrg memclear(b); 180322944501Smrg b.handle = handle; 180422944501Smrg b.offset = offset; 180522944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b)) 180622944501Smrg return -errno; 180722944501Smrg return 0; 180822944501Smrg} 180922944501Smrg 181022944501Smrg 181122944501Smrg/** 181222944501Smrg * Unbind a chunk of AGP memory. 181322944501Smrg * 181422944501Smrg * \param fd file descriptor. 181522944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 181622944501Smrg * 181722944501Smrg * \return zero on success, or a negative value on failure. 181822944501Smrg * 181922944501Smrg * \internal 182022944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing 182122944501Smrg * the argument in a drm_agp_binding structure. 182222944501Smrg */ 182322944501Smrgint drmAgpUnbind(int fd, drm_handle_t handle) 182422944501Smrg{ 182522944501Smrg drm_agp_binding_t b; 182622944501Smrg 1827424e9256Smrg memclear(b); 182822944501Smrg b.handle = handle; 182922944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) 183022944501Smrg return -errno; 183122944501Smrg return 0; 183222944501Smrg} 183322944501Smrg 183422944501Smrg 183522944501Smrg/** 183622944501Smrg * Get AGP driver major version number. 183722944501Smrg * 183822944501Smrg * \param fd file descriptor. 183922944501Smrg * 184022944501Smrg * \return major version number on success, or a negative value on failure.. 184122944501Smrg * 184222944501Smrg * \internal 184322944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 184422944501Smrg * necessary information in a drm_agp_info structure. 184522944501Smrg */ 184622944501Smrgint drmAgpVersionMajor(int fd) 184722944501Smrg{ 184822944501Smrg drm_agp_info_t i; 184922944501Smrg 1850424e9256Smrg memclear(i); 1851424e9256Smrg 185222944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 185322944501Smrg return -errno; 185422944501Smrg return i.agp_version_major; 185522944501Smrg} 185622944501Smrg 185722944501Smrg 185822944501Smrg/** 185922944501Smrg * Get AGP driver minor version number. 186022944501Smrg * 186122944501Smrg * \param fd file descriptor. 186222944501Smrg * 186322944501Smrg * \return minor version number on success, or a negative value on failure. 186422944501Smrg * 186522944501Smrg * \internal 186622944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 186722944501Smrg * necessary information in a drm_agp_info structure. 186822944501Smrg */ 186922944501Smrgint drmAgpVersionMinor(int fd) 187022944501Smrg{ 187122944501Smrg drm_agp_info_t i; 187222944501Smrg 1873424e9256Smrg memclear(i); 1874424e9256Smrg 187522944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 187622944501Smrg return -errno; 187722944501Smrg return i.agp_version_minor; 187822944501Smrg} 187922944501Smrg 188022944501Smrg 188122944501Smrg/** 188222944501Smrg * Get AGP mode. 188322944501Smrg * 188422944501Smrg * \param fd file descriptor. 188522944501Smrg * 188622944501Smrg * \return mode on success, or zero on failure. 188722944501Smrg * 188822944501Smrg * \internal 188922944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 189022944501Smrg * necessary information in a drm_agp_info structure. 189122944501Smrg */ 189222944501Smrgunsigned long drmAgpGetMode(int fd) 189322944501Smrg{ 189422944501Smrg drm_agp_info_t i; 189522944501Smrg 1896424e9256Smrg memclear(i); 1897424e9256Smrg 189822944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 189922944501Smrg return 0; 190022944501Smrg return i.mode; 190122944501Smrg} 190222944501Smrg 190322944501Smrg 190422944501Smrg/** 190522944501Smrg * Get AGP aperture base. 190622944501Smrg * 190722944501Smrg * \param fd file descriptor. 190822944501Smrg * 190922944501Smrg * \return aperture base on success, zero on failure. 191022944501Smrg * 191122944501Smrg * \internal 191222944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 191322944501Smrg * necessary information in a drm_agp_info structure. 191422944501Smrg */ 191522944501Smrgunsigned long drmAgpBase(int fd) 191622944501Smrg{ 191722944501Smrg drm_agp_info_t i; 191822944501Smrg 1919424e9256Smrg memclear(i); 1920424e9256Smrg 192122944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 192222944501Smrg return 0; 192322944501Smrg return i.aperture_base; 192422944501Smrg} 192522944501Smrg 192622944501Smrg 192722944501Smrg/** 192822944501Smrg * Get AGP aperture size. 192922944501Smrg * 193022944501Smrg * \param fd file descriptor. 193122944501Smrg * 193222944501Smrg * \return aperture size on success, zero on failure. 193322944501Smrg * 193422944501Smrg * \internal 193522944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 193622944501Smrg * necessary information in a drm_agp_info structure. 193722944501Smrg */ 193822944501Smrgunsigned long drmAgpSize(int fd) 193922944501Smrg{ 194022944501Smrg drm_agp_info_t i; 194122944501Smrg 1942424e9256Smrg memclear(i); 1943424e9256Smrg 194422944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 194522944501Smrg return 0; 194622944501Smrg return i.aperture_size; 194722944501Smrg} 194822944501Smrg 194922944501Smrg 195022944501Smrg/** 195122944501Smrg * Get used AGP memory. 195222944501Smrg * 195322944501Smrg * \param fd file descriptor. 195422944501Smrg * 195522944501Smrg * \return memory used on success, or zero on failure. 195622944501Smrg * 195722944501Smrg * \internal 195822944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 195922944501Smrg * necessary information in a drm_agp_info structure. 196022944501Smrg */ 196122944501Smrgunsigned long drmAgpMemoryUsed(int fd) 196222944501Smrg{ 196322944501Smrg drm_agp_info_t i; 196422944501Smrg 1965424e9256Smrg memclear(i); 1966424e9256Smrg 196722944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 196822944501Smrg return 0; 196922944501Smrg return i.memory_used; 197022944501Smrg} 197122944501Smrg 197222944501Smrg 197322944501Smrg/** 197422944501Smrg * Get available AGP memory. 197522944501Smrg * 197622944501Smrg * \param fd file descriptor. 197722944501Smrg * 197822944501Smrg * \return memory available on success, or zero on failure. 197922944501Smrg * 198022944501Smrg * \internal 198122944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 198222944501Smrg * necessary information in a drm_agp_info structure. 198322944501Smrg */ 198422944501Smrgunsigned long drmAgpMemoryAvail(int fd) 198522944501Smrg{ 198622944501Smrg drm_agp_info_t i; 198722944501Smrg 1988424e9256Smrg memclear(i); 1989424e9256Smrg 199022944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 199122944501Smrg return 0; 199222944501Smrg return i.memory_allowed; 199322944501Smrg} 199422944501Smrg 199522944501Smrg 199622944501Smrg/** 199722944501Smrg * Get hardware vendor ID. 199822944501Smrg * 199922944501Smrg * \param fd file descriptor. 200022944501Smrg * 200122944501Smrg * \return vendor ID on success, or zero on failure. 200222944501Smrg * 200322944501Smrg * \internal 200422944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 200522944501Smrg * necessary information in a drm_agp_info structure. 200622944501Smrg */ 200722944501Smrgunsigned int drmAgpVendorId(int fd) 200822944501Smrg{ 200922944501Smrg drm_agp_info_t i; 201022944501Smrg 2011424e9256Smrg memclear(i); 2012424e9256Smrg 201322944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 201422944501Smrg return 0; 201522944501Smrg return i.id_vendor; 201622944501Smrg} 201722944501Smrg 201822944501Smrg 201922944501Smrg/** 202022944501Smrg * Get hardware device ID. 202122944501Smrg * 202222944501Smrg * \param fd file descriptor. 202322944501Smrg * 202422944501Smrg * \return zero on success, or zero on failure. 202522944501Smrg * 202622944501Smrg * \internal 202722944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 202822944501Smrg * necessary information in a drm_agp_info structure. 202922944501Smrg */ 203022944501Smrgunsigned int drmAgpDeviceId(int fd) 203122944501Smrg{ 203222944501Smrg drm_agp_info_t i; 203322944501Smrg 2034424e9256Smrg memclear(i); 2035424e9256Smrg 203622944501Smrg if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 203722944501Smrg return 0; 203822944501Smrg return i.id_device; 203922944501Smrg} 204022944501Smrg 204122944501Smrgint drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle) 204222944501Smrg{ 204322944501Smrg drm_scatter_gather_t sg; 204422944501Smrg 2045424e9256Smrg memclear(sg); 2046424e9256Smrg 204722944501Smrg *handle = 0; 204822944501Smrg sg.size = size; 204922944501Smrg if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) 205022944501Smrg return -errno; 205122944501Smrg *handle = sg.handle; 205222944501Smrg return 0; 205322944501Smrg} 205422944501Smrg 205522944501Smrgint drmScatterGatherFree(int fd, drm_handle_t handle) 205622944501Smrg{ 205722944501Smrg drm_scatter_gather_t sg; 205822944501Smrg 2059424e9256Smrg memclear(sg); 206022944501Smrg sg.handle = handle; 206122944501Smrg if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg)) 206222944501Smrg return -errno; 206322944501Smrg return 0; 206422944501Smrg} 206522944501Smrg 206622944501Smrg/** 206722944501Smrg * Wait for VBLANK. 206822944501Smrg * 206922944501Smrg * \param fd file descriptor. 207022944501Smrg * \param vbl pointer to a drmVBlank structure. 207122944501Smrg * 207222944501Smrg * \return zero on success, or a negative value on failure. 207322944501Smrg * 207422944501Smrg * \internal 207522944501Smrg * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl. 207622944501Smrg */ 207722944501Smrgint drmWaitVBlank(int fd, drmVBlankPtr vbl) 207822944501Smrg{ 207922944501Smrg struct timespec timeout, cur; 208022944501Smrg int ret; 208122944501Smrg 208222944501Smrg ret = clock_gettime(CLOCK_MONOTONIC, &timeout); 208322944501Smrg if (ret < 0) { 208420131375Smrg fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno)); 208522944501Smrg goto out; 208622944501Smrg } 208722944501Smrg timeout.tv_sec++; 208822944501Smrg 208922944501Smrg do { 209022944501Smrg ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl); 209122944501Smrg vbl->request.type &= ~DRM_VBLANK_RELATIVE; 209222944501Smrg if (ret && errno == EINTR) { 209322944501Smrg clock_gettime(CLOCK_MONOTONIC, &cur); 209422944501Smrg /* Timeout after 1s */ 209522944501Smrg if (cur.tv_sec > timeout.tv_sec + 1 || 209622944501Smrg (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >= 209722944501Smrg timeout.tv_nsec)) { 209822944501Smrg errno = EBUSY; 209922944501Smrg ret = -1; 210022944501Smrg break; 210122944501Smrg } 210222944501Smrg } 210322944501Smrg } while (ret && errno == EINTR); 210422944501Smrg 210522944501Smrgout: 210622944501Smrg return ret; 210722944501Smrg} 210822944501Smrg 210922944501Smrgint drmError(int err, const char *label) 211022944501Smrg{ 211122944501Smrg switch (err) { 211222944501Smrg case DRM_ERR_NO_DEVICE: 211322944501Smrg fprintf(stderr, "%s: no device\n", label); 211422944501Smrg break; 211522944501Smrg case DRM_ERR_NO_ACCESS: 211622944501Smrg fprintf(stderr, "%s: no access\n", label); 211722944501Smrg break; 211822944501Smrg case DRM_ERR_NOT_ROOT: 211922944501Smrg fprintf(stderr, "%s: not root\n", label); 212022944501Smrg break; 212122944501Smrg case DRM_ERR_INVALID: 212222944501Smrg fprintf(stderr, "%s: invalid args\n", label); 212322944501Smrg break; 212422944501Smrg default: 212522944501Smrg if (err < 0) 212622944501Smrg err = -err; 212722944501Smrg fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) ); 212822944501Smrg break; 212922944501Smrg } 213022944501Smrg 213122944501Smrg return 1; 213222944501Smrg} 213322944501Smrg 213422944501Smrg/** 213522944501Smrg * Install IRQ handler. 213622944501Smrg * 213722944501Smrg * \param fd file descriptor. 213822944501Smrg * \param irq IRQ number. 213922944501Smrg * 214022944501Smrg * \return zero on success, or a negative value on failure. 214122944501Smrg * 214222944501Smrg * \internal 214322944501Smrg * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the 214422944501Smrg * argument in a drm_control structure. 214522944501Smrg */ 214622944501Smrgint drmCtlInstHandler(int fd, int irq) 214722944501Smrg{ 214822944501Smrg drm_control_t ctl; 214922944501Smrg 2150424e9256Smrg memclear(ctl); 215122944501Smrg ctl.func = DRM_INST_HANDLER; 215222944501Smrg ctl.irq = irq; 215322944501Smrg if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) 215422944501Smrg return -errno; 215522944501Smrg return 0; 215622944501Smrg} 215722944501Smrg 215822944501Smrg 215922944501Smrg/** 216022944501Smrg * Uninstall IRQ handler. 216122944501Smrg * 216222944501Smrg * \param fd file descriptor. 216322944501Smrg * 216422944501Smrg * \return zero on success, or a negative value on failure. 216522944501Smrg * 216622944501Smrg * \internal 216722944501Smrg * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the 216822944501Smrg * argument in a drm_control structure. 216922944501Smrg */ 217022944501Smrgint drmCtlUninstHandler(int fd) 217122944501Smrg{ 217222944501Smrg drm_control_t ctl; 217322944501Smrg 2174424e9256Smrg memclear(ctl); 217522944501Smrg ctl.func = DRM_UNINST_HANDLER; 217622944501Smrg ctl.irq = 0; 217722944501Smrg if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) 217822944501Smrg return -errno; 217922944501Smrg return 0; 218022944501Smrg} 218122944501Smrg 218222944501Smrgint drmFinish(int fd, int context, drmLockFlags flags) 218322944501Smrg{ 218422944501Smrg drm_lock_t lock; 218522944501Smrg 2186424e9256Smrg memclear(lock); 218722944501Smrg lock.context = context; 218822944501Smrg if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 218922944501Smrg if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 219022944501Smrg if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 219122944501Smrg if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 219222944501Smrg if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 219322944501Smrg if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 219422944501Smrg if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock)) 219522944501Smrg return -errno; 219622944501Smrg return 0; 219722944501Smrg} 219822944501Smrg 219922944501Smrg/** 220022944501Smrg * Get IRQ from bus ID. 220122944501Smrg * 220222944501Smrg * \param fd file descriptor. 220322944501Smrg * \param busnum bus number. 220422944501Smrg * \param devnum device number. 220522944501Smrg * \param funcnum function number. 220622944501Smrg * 220722944501Smrg * \return IRQ number on success, or a negative value on failure. 220822944501Smrg * 220922944501Smrg * \internal 221022944501Smrg * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the 221122944501Smrg * arguments in a drm_irq_busid structure. 221222944501Smrg */ 221322944501Smrgint drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum) 221422944501Smrg{ 221522944501Smrg drm_irq_busid_t p; 221622944501Smrg 2217424e9256Smrg memclear(p); 221822944501Smrg p.busnum = busnum; 221922944501Smrg p.devnum = devnum; 222022944501Smrg p.funcnum = funcnum; 222122944501Smrg if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) 222222944501Smrg return -errno; 222322944501Smrg return p.irq; 222422944501Smrg} 222522944501Smrg 222622944501Smrgint drmAddContextTag(int fd, drm_context_t context, void *tag) 222722944501Smrg{ 222822944501Smrg drmHashEntry *entry = drmGetEntry(fd); 222922944501Smrg 223022944501Smrg if (drmHashInsert(entry->tagTable, context, tag)) { 223122944501Smrg drmHashDelete(entry->tagTable, context); 223222944501Smrg drmHashInsert(entry->tagTable, context, tag); 223322944501Smrg } 223422944501Smrg return 0; 223522944501Smrg} 223622944501Smrg 223722944501Smrgint drmDelContextTag(int fd, drm_context_t context) 223822944501Smrg{ 223922944501Smrg drmHashEntry *entry = drmGetEntry(fd); 224022944501Smrg 224122944501Smrg return drmHashDelete(entry->tagTable, context); 224222944501Smrg} 224322944501Smrg 224422944501Smrgvoid *drmGetContextTag(int fd, drm_context_t context) 224522944501Smrg{ 224622944501Smrg drmHashEntry *entry = drmGetEntry(fd); 224722944501Smrg void *value; 224822944501Smrg 224922944501Smrg if (drmHashLookup(entry->tagTable, context, &value)) 225022944501Smrg return NULL; 225122944501Smrg 225222944501Smrg return value; 225322944501Smrg} 225422944501Smrg 225522944501Smrgint drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, 225622944501Smrg drm_handle_t handle) 225722944501Smrg{ 225822944501Smrg drm_ctx_priv_map_t map; 225922944501Smrg 2260424e9256Smrg memclear(map); 226122944501Smrg map.ctx_id = ctx_id; 226220131375Smrg map.handle = (void *)(uintptr_t)handle; 226322944501Smrg 226422944501Smrg if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) 226522944501Smrg return -errno; 226622944501Smrg return 0; 226722944501Smrg} 226822944501Smrg 226922944501Smrgint drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, 227022944501Smrg drm_handle_t *handle) 227122944501Smrg{ 227222944501Smrg drm_ctx_priv_map_t map; 227322944501Smrg 2274424e9256Smrg memclear(map); 227522944501Smrg map.ctx_id = ctx_id; 227622944501Smrg 227722944501Smrg if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) 227822944501Smrg return -errno; 227922944501Smrg if (handle) 228020131375Smrg *handle = (drm_handle_t)(uintptr_t)map.handle; 228122944501Smrg 228222944501Smrg return 0; 228322944501Smrg} 228422944501Smrg 228522944501Smrgint drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, 228622944501Smrg drmMapType *type, drmMapFlags *flags, drm_handle_t *handle, 228722944501Smrg int *mtrr) 228822944501Smrg{ 228922944501Smrg drm_map_t map; 229022944501Smrg 2291424e9256Smrg memclear(map); 229222944501Smrg map.offset = idx; 229322944501Smrg if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map)) 229422944501Smrg return -errno; 229522944501Smrg *offset = map.offset; 229622944501Smrg *size = map.size; 229722944501Smrg *type = map.type; 229822944501Smrg *flags = map.flags; 229922944501Smrg *handle = (unsigned long)map.handle; 230022944501Smrg *mtrr = map.mtrr; 230122944501Smrg return 0; 230222944501Smrg} 230322944501Smrg 230422944501Smrgint drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, 230522944501Smrg unsigned long *magic, unsigned long *iocs) 230622944501Smrg{ 230722944501Smrg drm_client_t client; 230822944501Smrg 2309424e9256Smrg memclear(client); 231022944501Smrg client.idx = idx; 231122944501Smrg if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client)) 231222944501Smrg return -errno; 231322944501Smrg *auth = client.auth; 231422944501Smrg *pid = client.pid; 231522944501Smrg *uid = client.uid; 231622944501Smrg *magic = client.magic; 231722944501Smrg *iocs = client.iocs; 231822944501Smrg return 0; 231922944501Smrg} 232022944501Smrg 232122944501Smrgint drmGetStats(int fd, drmStatsT *stats) 232222944501Smrg{ 232322944501Smrg drm_stats_t s; 2324424e9256Smrg unsigned i; 232522944501Smrg 2326424e9256Smrg memclear(s); 232722944501Smrg if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s)) 232822944501Smrg return -errno; 232922944501Smrg 233022944501Smrg stats->count = 0; 233122944501Smrg memset(stats, 0, sizeof(*stats)); 233222944501Smrg if (s.count > sizeof(stats->data)/sizeof(stats->data[0])) 233322944501Smrg return -1; 233422944501Smrg 233522944501Smrg#define SET_VALUE \ 233622944501Smrg stats->data[i].long_format = "%-20.20s"; \ 233722944501Smrg stats->data[i].rate_format = "%8.8s"; \ 233822944501Smrg stats->data[i].isvalue = 1; \ 233922944501Smrg stats->data[i].verbose = 0 234022944501Smrg 234122944501Smrg#define SET_COUNT \ 234222944501Smrg stats->data[i].long_format = "%-20.20s"; \ 234322944501Smrg stats->data[i].rate_format = "%5.5s"; \ 234422944501Smrg stats->data[i].isvalue = 0; \ 234522944501Smrg stats->data[i].mult_names = "kgm"; \ 234622944501Smrg stats->data[i].mult = 1000; \ 234722944501Smrg stats->data[i].verbose = 0 234822944501Smrg 234922944501Smrg#define SET_BYTE \ 235022944501Smrg stats->data[i].long_format = "%-20.20s"; \ 235122944501Smrg stats->data[i].rate_format = "%5.5s"; \ 235222944501Smrg stats->data[i].isvalue = 0; \ 235322944501Smrg stats->data[i].mult_names = "KGM"; \ 235422944501Smrg stats->data[i].mult = 1024; \ 235522944501Smrg stats->data[i].verbose = 0 235622944501Smrg 235722944501Smrg 235822944501Smrg stats->count = s.count; 235922944501Smrg for (i = 0; i < s.count; i++) { 236022944501Smrg stats->data[i].value = s.data[i].value; 236122944501Smrg switch (s.data[i].type) { 236222944501Smrg case _DRM_STAT_LOCK: 236322944501Smrg stats->data[i].long_name = "Lock"; 236422944501Smrg stats->data[i].rate_name = "Lock"; 236522944501Smrg SET_VALUE; 236622944501Smrg break; 236722944501Smrg case _DRM_STAT_OPENS: 236822944501Smrg stats->data[i].long_name = "Opens"; 236922944501Smrg stats->data[i].rate_name = "O"; 237022944501Smrg SET_COUNT; 237122944501Smrg stats->data[i].verbose = 1; 237222944501Smrg break; 237322944501Smrg case _DRM_STAT_CLOSES: 237422944501Smrg stats->data[i].long_name = "Closes"; 237522944501Smrg stats->data[i].rate_name = "Lock"; 237622944501Smrg SET_COUNT; 237722944501Smrg stats->data[i].verbose = 1; 237822944501Smrg break; 237922944501Smrg case _DRM_STAT_IOCTLS: 238022944501Smrg stats->data[i].long_name = "Ioctls"; 238122944501Smrg stats->data[i].rate_name = "Ioc/s"; 238222944501Smrg SET_COUNT; 238322944501Smrg break; 238422944501Smrg case _DRM_STAT_LOCKS: 238522944501Smrg stats->data[i].long_name = "Locks"; 238622944501Smrg stats->data[i].rate_name = "Lck/s"; 238722944501Smrg SET_COUNT; 238822944501Smrg break; 238922944501Smrg case _DRM_STAT_UNLOCKS: 239022944501Smrg stats->data[i].long_name = "Unlocks"; 239122944501Smrg stats->data[i].rate_name = "Unl/s"; 239222944501Smrg SET_COUNT; 239322944501Smrg break; 239422944501Smrg case _DRM_STAT_IRQ: 239522944501Smrg stats->data[i].long_name = "IRQs"; 239622944501Smrg stats->data[i].rate_name = "IRQ/s"; 239722944501Smrg SET_COUNT; 239822944501Smrg break; 239922944501Smrg case _DRM_STAT_PRIMARY: 240022944501Smrg stats->data[i].long_name = "Primary Bytes"; 240122944501Smrg stats->data[i].rate_name = "PB/s"; 240222944501Smrg SET_BYTE; 240322944501Smrg break; 240422944501Smrg case _DRM_STAT_SECONDARY: 240522944501Smrg stats->data[i].long_name = "Secondary Bytes"; 240622944501Smrg stats->data[i].rate_name = "SB/s"; 240722944501Smrg SET_BYTE; 240822944501Smrg break; 240922944501Smrg case _DRM_STAT_DMA: 241022944501Smrg stats->data[i].long_name = "DMA"; 241122944501Smrg stats->data[i].rate_name = "DMA/s"; 241222944501Smrg SET_COUNT; 241322944501Smrg break; 241422944501Smrg case _DRM_STAT_SPECIAL: 241522944501Smrg stats->data[i].long_name = "Special DMA"; 241622944501Smrg stats->data[i].rate_name = "dma/s"; 241722944501Smrg SET_COUNT; 241822944501Smrg break; 241922944501Smrg case _DRM_STAT_MISSED: 242022944501Smrg stats->data[i].long_name = "Miss"; 242122944501Smrg stats->data[i].rate_name = "Ms/s"; 242222944501Smrg SET_COUNT; 242322944501Smrg break; 242422944501Smrg case _DRM_STAT_VALUE: 242522944501Smrg stats->data[i].long_name = "Value"; 242622944501Smrg stats->data[i].rate_name = "Value"; 242722944501Smrg SET_VALUE; 242822944501Smrg break; 242922944501Smrg case _DRM_STAT_BYTE: 243022944501Smrg stats->data[i].long_name = "Bytes"; 243122944501Smrg stats->data[i].rate_name = "B/s"; 243222944501Smrg SET_BYTE; 243322944501Smrg break; 243422944501Smrg case _DRM_STAT_COUNT: 243522944501Smrg default: 243622944501Smrg stats->data[i].long_name = "Count"; 243722944501Smrg stats->data[i].rate_name = "Cnt/s"; 243822944501Smrg SET_COUNT; 243922944501Smrg break; 244022944501Smrg } 244122944501Smrg } 244222944501Smrg return 0; 244322944501Smrg} 244422944501Smrg 244522944501Smrg/** 244622944501Smrg * Issue a set-version ioctl. 244722944501Smrg * 244822944501Smrg * \param fd file descriptor. 244922944501Smrg * \param drmCommandIndex command index 245022944501Smrg * \param data source pointer of the data to be read and written. 245122944501Smrg * \param size size of the data to be read and written. 245222944501Smrg * 245322944501Smrg * \return zero on success, or a negative value on failure. 245422944501Smrg * 245522944501Smrg * \internal 245622944501Smrg * It issues a read-write ioctl given by 245722944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 245822944501Smrg */ 245922944501Smrgint drmSetInterfaceVersion(int fd, drmSetVersion *version) 246022944501Smrg{ 246122944501Smrg int retcode = 0; 246222944501Smrg drm_set_version_t sv; 246322944501Smrg 2464424e9256Smrg memclear(sv); 246522944501Smrg sv.drm_di_major = version->drm_di_major; 246622944501Smrg sv.drm_di_minor = version->drm_di_minor; 246722944501Smrg sv.drm_dd_major = version->drm_dd_major; 246822944501Smrg sv.drm_dd_minor = version->drm_dd_minor; 246922944501Smrg 247022944501Smrg if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) { 247122944501Smrg retcode = -errno; 247222944501Smrg } 247322944501Smrg 247422944501Smrg version->drm_di_major = sv.drm_di_major; 247522944501Smrg version->drm_di_minor = sv.drm_di_minor; 247622944501Smrg version->drm_dd_major = sv.drm_dd_major; 247722944501Smrg version->drm_dd_minor = sv.drm_dd_minor; 247822944501Smrg 247922944501Smrg return retcode; 248022944501Smrg} 248122944501Smrg 248222944501Smrg/** 248322944501Smrg * Send a device-specific command. 248422944501Smrg * 248522944501Smrg * \param fd file descriptor. 248622944501Smrg * \param drmCommandIndex command index 248722944501Smrg * 248822944501Smrg * \return zero on success, or a negative value on failure. 248922944501Smrg * 249022944501Smrg * \internal 249122944501Smrg * It issues a ioctl given by 249222944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 249322944501Smrg */ 249422944501Smrgint drmCommandNone(int fd, unsigned long drmCommandIndex) 249522944501Smrg{ 249622944501Smrg unsigned long request; 249722944501Smrg 249822944501Smrg request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex); 249922944501Smrg 2500424e9256Smrg if (drmIoctl(fd, request, NULL)) { 250122944501Smrg return -errno; 250222944501Smrg } 250322944501Smrg return 0; 250422944501Smrg} 250522944501Smrg 250622944501Smrg 250722944501Smrg/** 250822944501Smrg * Send a device-specific read command. 250922944501Smrg * 251022944501Smrg * \param fd file descriptor. 251122944501Smrg * \param drmCommandIndex command index 251222944501Smrg * \param data destination pointer of the data to be read. 251322944501Smrg * \param size size of the data to be read. 251422944501Smrg * 251522944501Smrg * \return zero on success, or a negative value on failure. 251622944501Smrg * 251722944501Smrg * \internal 251822944501Smrg * It issues a read ioctl given by 251922944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 252022944501Smrg */ 252122944501Smrgint drmCommandRead(int fd, unsigned long drmCommandIndex, void *data, 252222944501Smrg unsigned long size) 252322944501Smrg{ 252422944501Smrg unsigned long request; 252522944501Smrg 252622944501Smrg request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE, 252722944501Smrg DRM_COMMAND_BASE + drmCommandIndex, size); 252822944501Smrg 252922944501Smrg if (drmIoctl(fd, request, data)) { 253022944501Smrg return -errno; 253122944501Smrg } 253222944501Smrg return 0; 253322944501Smrg} 253422944501Smrg 253522944501Smrg 253622944501Smrg/** 253722944501Smrg * Send a device-specific write command. 253822944501Smrg * 253922944501Smrg * \param fd file descriptor. 254022944501Smrg * \param drmCommandIndex command index 254122944501Smrg * \param data source pointer of the data to be written. 254222944501Smrg * \param size size of the data to be written. 254322944501Smrg * 254422944501Smrg * \return zero on success, or a negative value on failure. 254522944501Smrg * 254622944501Smrg * \internal 254722944501Smrg * It issues a write ioctl given by 254822944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 254922944501Smrg */ 255022944501Smrgint drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data, 255122944501Smrg unsigned long size) 255222944501Smrg{ 255322944501Smrg unsigned long request; 255422944501Smrg 255522944501Smrg request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE, 255622944501Smrg DRM_COMMAND_BASE + drmCommandIndex, size); 255722944501Smrg 255822944501Smrg if (drmIoctl(fd, request, data)) { 255922944501Smrg return -errno; 256022944501Smrg } 256122944501Smrg return 0; 256222944501Smrg} 256322944501Smrg 256422944501Smrg 256522944501Smrg/** 256622944501Smrg * Send a device-specific read-write command. 256722944501Smrg * 256822944501Smrg * \param fd file descriptor. 256922944501Smrg * \param drmCommandIndex command index 257022944501Smrg * \param data source pointer of the data to be read and written. 257122944501Smrg * \param size size of the data to be read and written. 257222944501Smrg * 257322944501Smrg * \return zero on success, or a negative value on failure. 257422944501Smrg * 257522944501Smrg * \internal 257622944501Smrg * It issues a read-write ioctl given by 257722944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 257822944501Smrg */ 257922944501Smrgint drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data, 258022944501Smrg unsigned long size) 258122944501Smrg{ 258222944501Smrg unsigned long request; 258322944501Smrg 258422944501Smrg request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE, 258522944501Smrg DRM_COMMAND_BASE + drmCommandIndex, size); 258622944501Smrg 258722944501Smrg if (drmIoctl(fd, request, data)) 258822944501Smrg return -errno; 258922944501Smrg return 0; 259022944501Smrg} 259122944501Smrg 259222944501Smrg#define DRM_MAX_FDS 16 259322944501Smrgstatic struct { 259422944501Smrg char *BusID; 259522944501Smrg int fd; 259622944501Smrg int refcount; 2597424e9256Smrg int type; 259822944501Smrg} connection[DRM_MAX_FDS]; 259922944501Smrg 260022944501Smrgstatic int nr_fds = 0; 260122944501Smrg 260222944501Smrgint drmOpenOnce(void *unused, 260322944501Smrg const char *BusID, 260422944501Smrg int *newlyopened) 2605424e9256Smrg{ 2606424e9256Smrg return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY); 2607424e9256Smrg} 2608424e9256Smrg 2609424e9256Smrgint drmOpenOnceWithType(const char *BusID, int *newlyopened, int type) 261022944501Smrg{ 261122944501Smrg int i; 261222944501Smrg int fd; 261322944501Smrg 261422944501Smrg for (i = 0; i < nr_fds; i++) 2615424e9256Smrg if ((strcmp(BusID, connection[i].BusID) == 0) && 2616424e9256Smrg (connection[i].type == type)) { 261722944501Smrg connection[i].refcount++; 261822944501Smrg *newlyopened = 0; 261922944501Smrg return connection[i].fd; 262022944501Smrg } 262122944501Smrg 2622424e9256Smrg fd = drmOpenWithType(NULL, BusID, type); 262322944501Smrg if (fd <= 0 || nr_fds == DRM_MAX_FDS) 262422944501Smrg return fd; 262522944501Smrg 262622944501Smrg connection[nr_fds].BusID = strdup(BusID); 262722944501Smrg connection[nr_fds].fd = fd; 262822944501Smrg connection[nr_fds].refcount = 1; 2629424e9256Smrg connection[nr_fds].type = type; 263022944501Smrg *newlyopened = 1; 263122944501Smrg 263222944501Smrg if (0) 263322944501Smrg fprintf(stderr, "saved connection %d for %s %d\n", 263422944501Smrg nr_fds, connection[nr_fds].BusID, 263522944501Smrg strcmp(BusID, connection[nr_fds].BusID)); 263622944501Smrg 263722944501Smrg nr_fds++; 263822944501Smrg 263922944501Smrg return fd; 264022944501Smrg} 264122944501Smrg 264222944501Smrgvoid drmCloseOnce(int fd) 264322944501Smrg{ 264422944501Smrg int i; 264522944501Smrg 264622944501Smrg for (i = 0; i < nr_fds; i++) { 264722944501Smrg if (fd == connection[i].fd) { 264822944501Smrg if (--connection[i].refcount == 0) { 264922944501Smrg drmClose(connection[i].fd); 265022944501Smrg free(connection[i].BusID); 265122944501Smrg 265222944501Smrg if (i < --nr_fds) 265322944501Smrg connection[i] = connection[nr_fds]; 265422944501Smrg 265522944501Smrg return; 265622944501Smrg } 265722944501Smrg } 265822944501Smrg } 265922944501Smrg} 266022944501Smrg 266122944501Smrgint drmSetMaster(int fd) 266222944501Smrg{ 2663424e9256Smrg return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL); 266422944501Smrg} 266522944501Smrg 266622944501Smrgint drmDropMaster(int fd) 266722944501Smrg{ 2668424e9256Smrg return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL); 266922944501Smrg} 267022944501Smrg 267122944501Smrgchar *drmGetDeviceNameFromFd(int fd) 267222944501Smrg{ 267322944501Smrg char name[128]; 267422944501Smrg struct stat sbuf; 267522944501Smrg dev_t d; 267622944501Smrg int i; 267722944501Smrg 267822944501Smrg /* The whole drmOpen thing is a fiasco and we need to find a way 267922944501Smrg * back to just using open(2). For now, however, lets just make 268022944501Smrg * things worse with even more ad hoc directory walking code to 268122944501Smrg * discover the device file name. */ 268222944501Smrg 268322944501Smrg fstat(fd, &sbuf); 268422944501Smrg d = sbuf.st_rdev; 268522944501Smrg 268622944501Smrg for (i = 0; i < DRM_MAX_MINOR; i++) { 268722944501Smrg snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i); 268822944501Smrg if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d) 268922944501Smrg break; 269022944501Smrg } 269122944501Smrg if (i == DRM_MAX_MINOR) 269222944501Smrg return NULL; 269322944501Smrg 26949ce4edccSmrg return strdup(name); 269522944501Smrg} 269620131375Smrg 2697424e9256Smrgint drmGetNodeTypeFromFd(int fd) 2698424e9256Smrg{ 2699424e9256Smrg struct stat sbuf; 2700424e9256Smrg int maj, min, type; 2701424e9256Smrg 2702424e9256Smrg if (fstat(fd, &sbuf)) 2703424e9256Smrg return -1; 2704424e9256Smrg 2705424e9256Smrg maj = major(sbuf.st_rdev); 2706424e9256Smrg min = minor(sbuf.st_rdev); 2707424e9256Smrg 2708424e9256Smrg if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) { 2709424e9256Smrg errno = EINVAL; 2710424e9256Smrg return -1; 2711424e9256Smrg } 2712424e9256Smrg 2713424e9256Smrg type = drmGetMinorType(min); 2714424e9256Smrg if (type == -1) 2715424e9256Smrg errno = ENODEV; 2716424e9256Smrg return type; 2717424e9256Smrg} 2718424e9256Smrg 271920131375Smrgint drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd) 272020131375Smrg{ 272120131375Smrg struct drm_prime_handle args; 272220131375Smrg int ret; 272320131375Smrg 2724424e9256Smrg memclear(args); 2725424e9256Smrg args.fd = -1; 272620131375Smrg args.handle = handle; 272720131375Smrg args.flags = flags; 272820131375Smrg ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args); 272920131375Smrg if (ret) 273020131375Smrg return ret; 273120131375Smrg 273220131375Smrg *prime_fd = args.fd; 273320131375Smrg return 0; 273420131375Smrg} 273520131375Smrg 273620131375Smrgint drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle) 273720131375Smrg{ 273820131375Smrg struct drm_prime_handle args; 273920131375Smrg int ret; 274020131375Smrg 2741424e9256Smrg memclear(args); 274220131375Smrg args.fd = prime_fd; 274320131375Smrg ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args); 274420131375Smrg if (ret) 274520131375Smrg return ret; 274620131375Smrg 274720131375Smrg *handle = args.handle; 274820131375Smrg return 0; 274920131375Smrg} 2750424e9256Smrg 2751424e9256Smrgstatic char *drmGetMinorNameForFD(int fd, int type) 2752424e9256Smrg{ 2753424e9256Smrg#ifdef __linux__ 2754424e9256Smrg DIR *sysdir; 2755424e9256Smrg struct dirent *pent, *ent; 2756424e9256Smrg struct stat sbuf; 2757424e9256Smrg const char *name = drmGetMinorName(type); 2758424e9256Smrg int len; 2759424e9256Smrg char dev_name[64], buf[64]; 2760424e9256Smrg long name_max; 2761424e9256Smrg int maj, min; 2762424e9256Smrg 2763424e9256Smrg if (!name) 2764424e9256Smrg return NULL; 2765424e9256Smrg 2766424e9256Smrg len = strlen(name); 2767424e9256Smrg 2768424e9256Smrg if (fstat(fd, &sbuf)) 2769424e9256Smrg return NULL; 2770424e9256Smrg 2771424e9256Smrg maj = major(sbuf.st_rdev); 2772424e9256Smrg min = minor(sbuf.st_rdev); 2773424e9256Smrg 2774424e9256Smrg if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) 2775424e9256Smrg return NULL; 2776424e9256Smrg 2777424e9256Smrg snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min); 2778424e9256Smrg 2779424e9256Smrg sysdir = opendir(buf); 2780424e9256Smrg if (!sysdir) 2781424e9256Smrg return NULL; 2782424e9256Smrg 2783424e9256Smrg name_max = fpathconf(dirfd(sysdir), _PC_NAME_MAX); 2784424e9256Smrg if (name_max == -1) 2785424e9256Smrg goto out_close_dir; 2786424e9256Smrg 2787424e9256Smrg pent = malloc(offsetof(struct dirent, d_name) + name_max + 1); 2788424e9256Smrg if (pent == NULL) 2789424e9256Smrg goto out_close_dir; 2790424e9256Smrg 2791424e9256Smrg while (readdir_r(sysdir, pent, &ent) == 0 && ent != NULL) { 2792424e9256Smrg if (strncmp(ent->d_name, name, len) == 0) { 2793424e9256Smrg free(pent); 2794424e9256Smrg closedir(sysdir); 2795424e9256Smrg 2796424e9256Smrg snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s", 2797424e9256Smrg ent->d_name); 2798424e9256Smrg return strdup(dev_name); 2799424e9256Smrg } 2800424e9256Smrg } 2801424e9256Smrg 2802424e9256Smrg free(pent); 2803424e9256Smrg 2804424e9256Smrgout_close_dir: 2805424e9256Smrg closedir(sysdir); 2806424e9256Smrg#endif 2807424e9256Smrg return NULL; 2808424e9256Smrg} 2809424e9256Smrg 2810424e9256Smrgchar *drmGetPrimaryDeviceNameFromFd(int fd) 2811424e9256Smrg{ 2812424e9256Smrg return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY); 2813424e9256Smrg} 2814424e9256Smrg 2815424e9256Smrgchar *drmGetRenderDeviceNameFromFd(int fd) 2816424e9256Smrg{ 2817424e9256Smrg return drmGetMinorNameForFD(fd, DRM_NODE_RENDER); 2818424e9256Smrg} 2819