Changeset View
Changeset View
Standalone View
Standalone View
graphics/libdrm/files/patch-xf86drm.c
--- xf86drm.c.orig 2017-01-30 19:04:05 UTC | --- xf86drm.c.orig 2017-03-21 19:07:25 UTC | ||||
+++ xf86drm.c | +++ xf86drm.c | ||||
@@ -62,6 +62,10 @@ | @@ -49,6 +49,9 @@ | ||||
#include <signal.h> | |||||
#include <time.h> | |||||
#include <sys/types.h> | |||||
+#ifdef HAVE_SYS_SYSCTL_H | |||||
+#include <sys/sysctl.h> | |||||
+#endif | |||||
#include <sys/stat.h> | |||||
#define stat_t struct stat | |||||
#include <sys/ioctl.h> | |||||
@@ -62,6 +65,10 @@ | |||||
#endif | #endif | ||||
#include <math.h> | #include <math.h> | ||||
+#ifdef HAVE_LIBDEVQ | +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | ||||
+#include "libdevq.h" | +#include <sys/pciio.h> | ||||
+#endif | +#endif | ||||
+ | + | ||||
/* Not all systems have MAP_FAILED defined */ | /* Not all systems have MAP_FAILED defined */ | ||||
#ifndef MAP_FAILED | #ifndef MAP_FAILED | ||||
#define MAP_FAILED ((void *)-1) | #define MAP_FAILED ((void *)-1) | ||||
@@ -82,8 +86,12 @@ | @@ -72,18 +79,8 @@ | ||||
#define DRM_RENDER_MINOR_NAME "renderD" | |||||
#endif | |||||
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | #include "util_math.h" | ||||
-#ifdef __OpenBSD__ | |||||
-#define DRM_PRIMARY_MINOR_NAME "drm" | |||||
-#define DRM_CONTROL_MINOR_NAME "drmC" | |||||
-#define DRM_RENDER_MINOR_NAME "drmR" | |||||
-#else | |||||
-#define DRM_PRIMARY_MINOR_NAME "card" | |||||
-#define DRM_CONTROL_MINOR_NAME "controlD" | |||||
-#define DRM_RENDER_MINOR_NAME "renderD" | |||||
-#endif | |||||
- | |||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | |||||
-#define DRM_MAJOR 145 | -#define DRM_MAJOR 145 | ||||
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | +#define DRM_MAJOR 0 /* n/a: Major ID on systems with devfs is not meaningful */ | ||||
+#define DRM_MAJOR 0 | |||||
+#endif | |||||
+ | |||||
+#if defined(__DragonFly__) | |||||
+#define DRM_MAJOR 65 /* was 145 XXX needs checking */ | |||||
#endif | #endif | ||||
#ifdef __NetBSD__ | #ifdef __NetBSD__ | ||||
@@ -548,6 +556,7 @@ static int drmGetMinorType(int minor) | @@ -180,7 +177,7 @@ void drmFree(void *pt) | ||||
} | } | ||||
/** | |||||
- * Call ioctl, restarting if it is interupted | |||||
+ * Call ioctl, restarting if it is interrupted | |||||
*/ | |||||
int | |||||
drmIoctl(int fd, unsigned long request, void *arg) | |||||
@@ -223,6 +220,89 @@ drmHashEntry *drmGetEntry(int fd) | |||||
return entry; | |||||
} | } | ||||
+#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__DragonFly__) | +static int drmGetMinorBase(int type) | ||||
static const char *drmGetMinorName(int type) | +{ | ||||
+ switch (type) { | |||||
+ case DRM_NODE_PRIMARY: | |||||
+ case DRM_NODE_CONTROL: | |||||
+ case DRM_NODE_RENDER: | |||||
+ return type << 6; | |||||
+ default: | |||||
+ return -1; | |||||
+ }; | |||||
+} | |||||
+ | |||||
+static int drmGetMinorType(int minor) | |||||
+{ | |||||
+ if (minor < 0) | |||||
+ return -1; | |||||
+ | |||||
+ int type = minor >> 6; | |||||
+ switch (type) { | |||||
+ case DRM_NODE_PRIMARY: | |||||
+ case DRM_NODE_CONTROL: | |||||
+ case DRM_NODE_RENDER: | |||||
+ return type; | |||||
+ default: | |||||
+ return -1; | |||||
+ } | |||||
+} | |||||
+ | |||||
+#ifdef __linux__ | |||||
+static const char *drmGetMinorName(int type) | |||||
+{ | |||||
+ switch (type) { | |||||
+ case DRM_NODE_PRIMARY: | |||||
+ return DRM_PRIMARY_MINOR_NAME; | |||||
+ case DRM_NODE_CONTROL: | |||||
+ return DRM_CONTROL_MINOR_NAME; | |||||
+ case DRM_NODE_RENDER: | |||||
+ return DRM_RENDER_MINOR_NAME; | |||||
+ default: | |||||
+ return NULL; | |||||
+ } | |||||
+} | |||||
+#endif | |||||
+ | |||||
+static const char *drmGetDeviceName(int type) | |||||
+{ | |||||
+ switch (type) { | |||||
+ case DRM_NODE_PRIMARY: | |||||
+ return DRM_DEV_NAME; | |||||
+ case DRM_NODE_CONTROL: | |||||
+ return DRM_CONTROL_DEV_NAME; | |||||
+ case DRM_NODE_RENDER: | |||||
+ return DRM_RENDER_DEV_NAME; | |||||
+ default: | |||||
+ return NULL; | |||||
+ } | |||||
+} | |||||
+ | |||||
+static int drmGetNodeNumber(const char *name) | |||||
+{ | |||||
+ size_t name_len = strnlen(name, DRM_NODE_NAME_MAX); | |||||
+ while (name_len && isdigit(name[name_len - 1])) | |||||
+ --name_len; | |||||
+ return strtol(name + name_len, NULL, 10); | |||||
+} | |||||
+ | |||||
+static int drmGetNodeType(const char *name) | |||||
+{ | |||||
+ if (strncmp(name, DRM_PRIMARY_MINOR_NAME, | |||||
+ sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0) | |||||
+ return DRM_NODE_PRIMARY; | |||||
+ | |||||
+ if (strncmp(name, DRM_CONTROL_MINOR_NAME, | |||||
+ sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0) | |||||
+ return DRM_NODE_CONTROL; | |||||
+ | |||||
+ if (strncmp(name, DRM_RENDER_MINOR_NAME, | |||||
+ sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0) | |||||
+ return DRM_NODE_RENDER; | |||||
+ | |||||
+ return -1; | |||||
+} | |||||
+ | |||||
/** | |||||
* Compare two busid strings | |||||
* | |||||
@@ -290,7 +370,7 @@ static int drmMatchBusID(const char *id1 | |||||
* | |||||
* \internal | |||||
* Checks for failure. If failure was caused by signal call chown again. | |||||
- * If any other failure happened then it will output error mesage using | |||||
+ * If any other failure happened then it will output error message using | |||||
* drmMsg() call. | |||||
*/ | |||||
#if !defined(UDEV) | |||||
@@ -327,8 +407,8 @@ static int chown_check_return(const char | |||||
static int drmOpenDevice(dev_t dev, int minor, int type) | |||||
{ | { | ||||
switch (type) { | stat_t st; | ||||
@@ -561,6 +570,7 @@ static const char *drmGetMinorName(int t | - const char *dev_name; | ||||
return NULL; | - char buf[64]; | ||||
} | + const char *dev_name = drmGetDeviceName(type); | ||||
} | + char buf[DRM_NODE_NAME_MAX]; | ||||
int fd; | |||||
mode_t devmode = DRM_DEV_MODE, serv_mode; | |||||
gid_t serv_group; | |||||
@@ -338,21 +418,14 @@ static int drmOpenDevice(dev_t dev, int | |||||
gid_t group = DRM_DEV_GID; | |||||
#endif | |||||
- switch (type) { | |||||
- case DRM_NODE_PRIMARY: | |||||
- dev_name = DRM_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_CONTROL: | |||||
- dev_name = DRM_CONTROL_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_RENDER: | |||||
- dev_name = DRM_RENDER_DEV_NAME; | |||||
- break; | |||||
- default: | |||||
+ if (!dev_name) | |||||
return -EINVAL; | |||||
- }; | |||||
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | |||||
+ sprintf(buf, dev_name, DRM_DIR_NAME, minor + drmGetMinorBase(type)); | |||||
+#else | |||||
sprintf(buf, dev_name, DRM_DIR_NAME, minor); | |||||
+#endif | +#endif | ||||
drmMsg("drmOpenDevice: node name is %s\n", buf); | |||||
if (drm_server_info && drm_server_info->get_perms) { | |||||
@@ -456,27 +529,20 @@ wait_for_udev: | |||||
static int drmOpenMinor(int minor, int create, int type) | |||||
{ | |||||
int fd; | |||||
- char buf[64]; | |||||
- const char *dev_name; | |||||
+ char buf[DRM_NODE_NAME_MAX]; | |||||
+ const char *dev_name = drmGetDeviceName(type); | |||||
if (create) | |||||
return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type); | |||||
- switch (type) { | |||||
- case DRM_NODE_PRIMARY: | |||||
- dev_name = DRM_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_CONTROL: | |||||
- dev_name = DRM_CONTROL_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_RENDER: | |||||
- dev_name = DRM_RENDER_DEV_NAME; | |||||
- break; | |||||
- default: | |||||
+ if (!dev_name) | |||||
return -EINVAL; | |||||
- }; | |||||
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | |||||
+ sprintf(buf, dev_name, DRM_DIR_NAME, minor + drmGetMinorBase(type)); | |||||
+#else | |||||
sprintf(buf, dev_name, DRM_DIR_NAME, minor); | |||||
+#endif | |||||
if ((fd = open(buf, O_RDWR, 0)) >= 0) | |||||
return fd; | |||||
return -errno; | |||||
@@ -517,51 +583,6 @@ int drmAvailable(void) | |||||
return retval; | |||||
} | |||||
-static int drmGetMinorBase(int type) | |||||
-{ | |||||
- switch (type) { | |||||
- case DRM_NODE_PRIMARY: | |||||
- return 0; | |||||
- case DRM_NODE_CONTROL: | |||||
- return 64; | |||||
- case DRM_NODE_RENDER: | |||||
- return 128; | |||||
- default: | |||||
- return -1; | |||||
- }; | |||||
-} | |||||
- | |||||
-static int drmGetMinorType(int minor) | |||||
-{ | |||||
- int type = minor >> 6; | |||||
- | |||||
- if (minor < 0) | |||||
- return -1; | |||||
- | |||||
- switch (type) { | |||||
- case DRM_NODE_PRIMARY: | |||||
- case DRM_NODE_CONTROL: | |||||
- case DRM_NODE_RENDER: | |||||
- return type; | |||||
- default: | |||||
- return -1; | |||||
- } | |||||
-} | |||||
- | |||||
-static const char *drmGetMinorName(int type) | |||||
-{ | |||||
- switch (type) { | |||||
- case DRM_NODE_PRIMARY: | |||||
- return DRM_PRIMARY_MINOR_NAME; | |||||
- case DRM_NODE_CONTROL: | |||||
- return DRM_CONTROL_MINOR_NAME; | |||||
- case DRM_NODE_RENDER: | |||||
- return DRM_RENDER_MINOR_NAME; | |||||
- default: | |||||
- return NULL; | |||||
- } | |||||
-} | |||||
- | |||||
/** | /** | ||||
* Open the device by bus ID. | * Open the device by bus ID. | ||||
@@ -2734,7 +2744,7 @@ int drmGetNodeTypeFromFd(int fd) | * | ||||
maj = major(sbuf.st_rdev); | @@ -2699,33 +2720,40 @@ int drmDropMaster(int fd) | ||||
min = minor(sbuf.st_rdev); | |||||
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) { | char *drmGetDeviceNameFromFd(int fd) | ||||
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) { | { | ||||
errno = EINVAL; | - char name[128]; | ||||
return -1; | - struct stat sbuf; | ||||
- dev_t d; | |||||
- int i; | |||||
- | |||||
/* The whole drmOpen thing is a fiasco and we need to find a way | |||||
* back to just using open(2). For now, however, lets just make | |||||
* things worse with even more ad hoc directory walking code to | |||||
* discover the device file name. */ | |||||
+ stat_t sbuf; | |||||
fstat(fd, &sbuf); | |||||
- d = sbuf.st_rdev; | |||||
+ dev_t d = sbuf.st_rdev; | |||||
- for (i = 0; i < DRM_MAX_MINOR; i++) { | |||||
+ for (int i = 0; i < DRM_MAX_MINOR; i++) { | |||||
+ char name[DRM_NODE_NAME_MAX]; | |||||
snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i); | |||||
if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d) | |||||
- break; | |||||
+ return strdup(name); | |||||
} | } | ||||
@@ -2833,6 +2843,15 @@ static char *drmGetMinorNameForFD(int fd | - if (i == DRM_MAX_MINOR) | ||||
- return NULL; | |||||
- | |||||
- return strdup(name); | |||||
+ return NULL; | |||||
} | |||||
int drmGetNodeTypeFromFd(int fd) | |||||
{ | |||||
- struct stat sbuf; | |||||
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | |||||
+ char *name = drmGetDeviceNameFromFd2(fd); | |||||
+ if (!name) { | |||||
+ errno = ENODEV; | |||||
+ return -1; | |||||
+ } | |||||
+ | |||||
+ int type = drmGetNodeType(name); | |||||
+ free(name); | |||||
+ if (type < 0) | |||||
+ errno = ENODEV; | |||||
+ return type; | |||||
+#else | |||||
+ stat_t sbuf; | |||||
int maj, min, type; | |||||
if (fstat(fd, &sbuf)) | |||||
@@ -2743,6 +2771,7 @@ int drmGetNodeTypeFromFd(int fd) | |||||
if (type == -1) | |||||
errno = ENODEV; | |||||
return type; | |||||
+#endif | |||||
} | |||||
int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd) | |||||
@@ -2782,7 +2811,7 @@ static char *drmGetMinorNameForFD(int fd | |||||
#ifdef __linux__ | |||||
DIR *sysdir; | |||||
struct dirent *pent, *ent; | |||||
- struct stat sbuf; | |||||
+ stat_t sbuf; | |||||
const char *name = drmGetMinorName(type); | |||||
int len; | |||||
char dev_name[64], buf[64]; | |||||
@@ -2833,13 +2862,35 @@ static char *drmGetMinorNameForFD(int fd | |||||
out_close_dir: | out_close_dir: | ||||
closedir(sysdir); | closedir(sysdir); | ||||
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | ||||
+ struct stat buf; | + const char *dev_name = drmGetDeviceName(type); | ||||
+ char name[64]; | + if (!dev_name) | ||||
+ return NULL; | |||||
+ | + | ||||
+ fstat(fd, &buf); | + char *name = drmGetDeviceNameFromFd2(fd); | ||||
+ snprintf(name, sizeof(name), "/dev/%s", | + if (!name) | ||||
+ devname(buf.st_rdev, S_IFCHR)); | + return NULL; | ||||
+ | + | ||||
+ return strdup(name); | + int oldnum = drmGetNodeNumber(name); | ||||
+ int oldtype = drmGetMinorType(oldnum); | |||||
+ if (oldtype < 0) { | |||||
+ free(name); | |||||
+ return NULL; | |||||
+ } | |||||
+ | |||||
+ int newnum = oldnum - drmGetMinorBase(oldtype) + drmGetMinorBase(type); | |||||
+ snprintf(name, DRM_NODE_NAME_MAX, dev_name, DRM_DIR_NAME, newnum); | |||||
+ return name; | |||||
#else | #else | ||||
struct stat sbuf; | - struct stat sbuf; | ||||
char buf[PATH_MAX + 1]; | - char buf[PATH_MAX + 1]; | ||||
@@ -2960,7 +2979,7 @@ static int drmParseSubsystemType(int maj | - const char *dev_name; | ||||
+ stat_t sbuf; | |||||
+ char buf[DRM_NODE_NAME_MAX]; | |||||
+ const char *dev_name = drmGetDeviceName(type); | |||||
unsigned int maj, min; | |||||
int n, base; | |||||
+ if (!dev_name) | |||||
+ return NULL; | |||||
+ | |||||
if (fstat(fd, &sbuf)) | |||||
return NULL; | |||||
@@ -2849,20 +2900,6 @@ out_close_dir: | |||||
if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | |||||
return NULL; | |||||
- switch (type) { | |||||
- case DRM_NODE_PRIMARY: | |||||
- dev_name = DRM_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_CONTROL: | |||||
- dev_name = DRM_CONTROL_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_RENDER: | |||||
- dev_name = DRM_RENDER_DEV_NAME; | |||||
- break; | |||||
- default: | |||||
- return NULL; | |||||
- }; | |||||
- | |||||
base = drmGetMinorBase(type); | |||||
if (base < 0) | |||||
return NULL; | |||||
@@ -2960,7 +2997,7 @@ static int drmParseSubsystemType(int maj | |||||
return DRM_BUS_HOST1X; | return DRM_BUS_HOST1X; | ||||
return -EINVAL; | return -EINVAL; | ||||
-#elif defined(__OpenBSD__) | -#elif defined(__OpenBSD__) | ||||
+#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | +#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | ||||
return DRM_BUS_PCI; | return DRM_BUS_PCI; | ||||
#else | #else | ||||
#warning "Missing implementation of drmParseSubsystemType" | #warning "Missing implementation of drmParseSubsystemType" | ||||
@@ -3023,6 +3042,61 @@ static int drmParsePciBusInfo(int maj, i | @@ -2968,7 +3005,8 @@ static int drmParseSubsystemType(int maj | ||||
#endif | #endif | ||||
} | } | ||||
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | -static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) | ||||
+static int drmParsePciBusInfo(const char *node, int node_type, | |||||
+ int maj, int min, drmPciBusInfoPtr info) | |||||
{ | |||||
#ifdef __linux__ | |||||
unsigned int domain, bus, dev, func; | |||||
@@ -3017,6 +3055,50 @@ static int drmParsePciBusInfo(int maj, i | |||||
info->func = pinfo.func; | |||||
return 0; | |||||
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | |||||
+/* | + /* | ||||
+ * XXX temporary workaround, because FreeBSD doesn't provide | + * Only the primary nodes can be mapped to hw.dri.%i via major/minor | ||||
+ * pcibus device sysctl trees for renderD and controlD nodes (yet) | + * Determine the primary node by offset and use its major/minor pair | ||||
+ */ | + */ | ||||
+static void | + if (node_type != DRM_NODE_PRIMARY) { | ||||
+drmBSDDeviceNameHack(const char *path, char *hacked_path, int length) | + char name[DRM_NODE_NAME_MAX]; | ||||
+{ | + snprintf(name, sizeof(name), DRM_DEV_NAME, DRM_DIR_NAME, | ||||
+ int start, number; | + drmGetNodeNumber(node) - drmGetMinorBase(node_type)); | ||||
+ const char *errstr; | |||||
+ | + | ||||
+ if (strcmp(path, DRM_DIR_NAME "/controlD") > 0) { | + stat_t sbuf; | ||||
+ start = 17; | + if (stat(name, &sbuf)) | ||||
+ number = strtonum(&path[start], 0, 256, &errstr) - 64; | |||||
+ snprintf(hacked_path, length, "%s/card%i", DRM_DIR_NAME, number); | |||||
+ } else if (strcmp(path, DRM_DIR_NAME "/renderD") > 0) { | |||||
+ start = 16; | |||||
+ number = strtonum(&path[start], 0, 256, &errstr) - 128; | |||||
+ snprintf(hacked_path, length, "%s/card%i", DRM_DIR_NAME, number); | |||||
+ } else | |||||
+ snprintf(hacked_path, length, "%s", path); | |||||
+ | |||||
+ return; | |||||
+} | |||||
+ | |||||
+static int | |||||
+drmParsePciBusInfoBSD(const char *path, drmPciBusInfoPtr info) | |||||
+{ | |||||
+ int fd, ret; | |||||
+ int domain = 0, bus = 0, slot = 0, function = 0; | |||||
+ char hacked_path[PATH_MAX + 1]; | |||||
+ | |||||
+ drmBSDDeviceNameHack(path, hacked_path, PATH_MAX); | |||||
+ fd = open(hacked_path, O_RDONLY); | |||||
+ | |||||
+ if (fd < 0) | |||||
+ return -errno; | + return -errno; | ||||
+ | + | ||||
+ ret = devq_device_get_pcibusaddr(fd, &domain, &bus, &slot, &function); | + maj = major(sbuf.st_rdev); | ||||
+ | + min = minor(sbuf.st_rdev); | ||||
+ if (ret < 0) { | |||||
+ close(fd); | |||||
+ return -1; | |||||
+ } | + } | ||||
+ /* | |||||
+ * Major/minor appear after the driver name in the hw.dri.%i.name node | |||||
+ * Find the node with matching major/minor pair and parse the bus ID | |||||
+ */ | |||||
+ const char *name_fmt = "%*s %x pci:%u:%u:%u.%u"; | |||||
+ for (int i = 0; i < DRM_MAX_MINOR; ++i) { | |||||
+ char name[16], value[256]; | |||||
+ size_t length = sizeof(value); | |||||
+ snprintf(name, sizeof(name), "hw.dri.%i.name", i); | |||||
+ | + | ||||
+ info->domain = (uint16_t) domain; | + if (sysctlbyname(name, value, &length, NULL, 0)) | ||||
+ info->bus = (uint8_t) bus; | + continue; | ||||
+ info->dev = (uint8_t) slot; | |||||
+ info->func = (uint8_t) function; | |||||
+ | + | ||||
+ close(fd); | + unsigned int rdev = 0, domain = 0, bus = 0, slot = 0, func = 0; | ||||
+ value[length] = '\0'; | |||||
+ if (sscanf(value, name_fmt, &rdev, &domain, &bus, &slot, &func) != 5) | |||||
+ continue; | |||||
+ | |||||
+ if (rdev == makedev(maj, min)) { | |||||
+ info->domain = domain; | |||||
+ info->bus = bus; | |||||
+ info->dev = slot; | |||||
+ info->func = func; | |||||
+ return 0; | + return 0; | ||||
+} | + } | ||||
+#endif | + } | ||||
+ | + return -ENODEV; | ||||
static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b) | #else | ||||
{ | #warning "Missing implementation of drmParsePciBusInfo" | ||||
if (a == NULL || b == NULL) | return -EINVAL; | ||||
@@ -3188,6 +3262,36 @@ static int drmParsePciDeviceInfo(int maj | @@ -3051,32 +3133,6 @@ static int drmCompareBusInfo(drmDevicePt | ||||
#endif | return -1; | ||||
} | } | ||||
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | -static int drmGetNodeType(const char *name) | ||||
+static int drmParsePciDeviceInfoBSD(const char *path, | -{ | ||||
+ drmPciDeviceInfoPtr device, | - if (strncmp(name, DRM_PRIMARY_MINOR_NAME, | ||||
+ uint32_t flags) | - sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0) | ||||
+{ | - return DRM_NODE_PRIMARY; | ||||
+ int fd, vendor_id = 0, device_id = 0, subvendor_id = 0, | - | ||||
+ subdevice_id = 0, revision_id = 0; | - if (strncmp(name, DRM_CONTROL_MINOR_NAME, | ||||
+ char hacked_path[PATH_MAX + 1]; | - sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0) | ||||
- return DRM_NODE_CONTROL; | |||||
- | |||||
- if (strncmp(name, DRM_RENDER_MINOR_NAME, | |||||
- sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0) | |||||
- return DRM_NODE_RENDER; | |||||
- | |||||
- return -EINVAL; | |||||
-} | |||||
- | |||||
-static int drmGetMaxNodeName(void) | |||||
-{ | |||||
- return sizeof(DRM_DIR_NAME) + | |||||
- MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), | |||||
- sizeof(DRM_CONTROL_MINOR_NAME), | |||||
- sizeof(DRM_RENDER_MINOR_NAME)) + | |||||
- 3 /* length of the node number */; | |||||
-} | |||||
- | |||||
#ifdef __linux__ | |||||
static int parse_separate_sysfs_files(int maj, int min, | |||||
drmPciDeviceInfoPtr device, | |||||
@@ -3146,6 +3202,7 @@ static int parse_config_sysfs_file(int m | |||||
#endif | |||||
static int drmParsePciDeviceInfo(int maj, int min, | |||||
+ drmPciBusInfoPtr info, | |||||
drmPciDeviceInfoPtr device, | |||||
uint32_t flags) | |||||
{ | |||||
@@ -3182,6 +3239,43 @@ static int drmParsePciDeviceInfo(int maj | |||||
device->subdevice_id = pinfo.subdevice_id; | |||||
return 0; | |||||
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | |||||
+ struct pci_conf_io pc; | |||||
+ struct pci_match_conf patterns[1]; | |||||
+ struct pci_conf results[1]; | |||||
+ | + | ||||
+ drmBSDDeviceNameHack(path, hacked_path, PATH_MAX); | + int fd = open("/dev/pci", O_RDONLY, 0); | ||||
+ | |||||
+ fd = open(hacked_path, O_RDONLY); | |||||
+ | |||||
+ if (fd < 0) | + if (fd < 0) | ||||
+ return -errno; | + return -errno; | ||||
+ | + | ||||
+ devq_device_get_pciid_full_from_fd(fd, &vendor_id, &device_id, | + bzero(&patterns, sizeof(patterns)); | ||||
+ &subvendor_id, &subdevice_id, &revision_id); | + patterns[0].pc_sel.pc_domain = info->domain; | ||||
+ patterns[0].pc_sel.pc_bus = info->bus; | |||||
+ patterns[0].pc_sel.pc_dev = info->dev; | |||||
+ patterns[0].pc_sel.pc_func = info->func; | |||||
+ patterns[0].flags = PCI_GETCONF_MATCH_DOMAIN | PCI_GETCONF_MATCH_BUS | |||||
+ | PCI_GETCONF_MATCH_DEV | PCI_GETCONF_MATCH_FUNC; | |||||
+ bzero(&pc, sizeof(struct pci_conf_io)); | |||||
+ pc.num_patterns = 1; | |||||
+ pc.pat_buf_len = sizeof(patterns); | |||||
+ pc.patterns = patterns; | |||||
+ pc.match_buf_len = sizeof(results); | |||||
+ pc.matches = results; | |||||
+ | + | ||||
+ device->vendor_id = (uint16_t) vendor_id; | + if (ioctl(fd, PCIOCGETCONF, &pc) || pc.status == PCI_GETCONF_ERROR) { | ||||
+ device->device_id = (uint16_t) device_id; | + int error = errno; | ||||
+ device->subvendor_id = (uint16_t) subvendor_id; | |||||
+ device->subdevice_id = (uint16_t) subdevice_id; | |||||
+ device->revision_id = (uint8_t) revision_id; | |||||
+ | |||||
+ close(fd); | + close(fd); | ||||
+ return 0; | + return -error; | ||||
+} | + } | ||||
+#endif | + close(fd); | ||||
+ | + | ||||
static void drmFreePlatformDevice(drmDevicePtr device) | + device->vendor_id = results[0].pc_vendor; | ||||
{ | + device->device_id = results[0].pc_device; | ||||
if (device->deviceinfo.platform) { | + device->subvendor_id = results[0].pc_subvendor; | ||||
@@ -3308,7 +3412,11 @@ static int drmProcessPciDevice(drmDevice | + device->subdevice_id = results[0].pc_subdevice; | ||||
+ device->revision_id = results[0].pc_revid; | |||||
+ | |||||
+ return 0; | |||||
#else | |||||
#warning "Missing implementation of drmParsePciDeviceInfo" | |||||
return -EINVAL; | |||||
@@ -3262,7 +3356,7 @@ static drmDevicePtr drmDeviceAlloc(unsig | |||||
unsigned int i; | |||||
char *ptr; | |||||
- max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); | |||||
+ max_node_length = ALIGN(DRM_NODE_NAME_MAX, sizeof(void *)); | |||||
extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length); | |||||
size = sizeof(*device) + extra + bus_size + device_size; | |||||
@@ -3308,7 +3402,7 @@ static int drmProcessPciDevice(drmDevice | |||||
dev->businfo.pci = (drmPciBusInfoPtr)addr; | dev->businfo.pci = (drmPciBusInfoPtr)addr; | ||||
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | - ret = drmParsePciBusInfo(maj, min, dev->businfo.pci); | ||||
+ ret = drmParsePciBusInfoBSD(node, dev->businfo.pci); | + ret = drmParsePciBusInfo(node, node_type, maj, min, dev->businfo.pci); | ||||
+#else | |||||
ret = drmParsePciBusInfo(maj, min, dev->businfo.pci); | |||||
+#endif | |||||
if (ret) | if (ret) | ||||
goto free_device; | goto free_device; | ||||
@@ -3316,8 +3424,11 @@ static int drmProcessPciDevice(drmDevice | @@ -3317,7 +3411,7 @@ static int drmProcessPciDevice(drmDevice | ||||
if (fetch_deviceinfo) { | |||||
addr += sizeof(drmPciBusInfo); | addr += sizeof(drmPciBusInfo); | ||||
dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr; | dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr; | ||||
- | |||||
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | - ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags); | ||||
+ ret = drmParsePciDeviceInfoBSD(node, dev->deviceinfo.pci, flags); | + ret = drmParsePciDeviceInfo(maj, min, dev->businfo.pci, dev->deviceinfo.pci, flags); | ||||
+#else | |||||
ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags); | |||||
+#endif | |||||
if (ret) | if (ret) | ||||
goto free_device; | goto free_device; | ||||
} | } | ||||
@@ -3786,7 +3897,7 @@ int drmGetDevice2(int fd, uint32_t flags | @@ -3667,7 +3761,7 @@ static void drmFoldDuplicatedDevices(drm | ||||
local_devices[i]->available_nodes |= local_devices[j]->available_nodes; | |||||
node_type = log2(local_devices[j]->available_nodes); | |||||
memcpy(local_devices[i]->nodes[node_type], | |||||
- local_devices[j]->nodes[node_type], drmGetMaxNodeName()); | |||||
+ local_devices[j]->nodes[node_type], DRM_NODE_NAME_MAX); | |||||
drmFreeDevice(&local_devices[j]); | |||||
} | |||||
} | |||||
@@ -3685,7 +3779,7 @@ drm_device_validate_flags(uint32_t flags | |||||
* Get information about the opened drm device | |||||
* | |||||
* \param fd file descriptor of the drm device | |||||
- * \param flags feature/behaviour bitmask | |||||
+ * \param flags feature/behavior bitmask | |||||
* \param device the address of a drmDevicePtr where the information | |||||
* will be allocated in stored | |||||
* | |||||
@@ -3703,8 +3797,8 @@ int drmGetDevice2(int fd, uint32_t flags | |||||
* Avoid stat'ing all of /dev needlessly by implementing this custom path. | |||||
*/ | |||||
drmDevicePtr d; | |||||
- struct stat sbuf; | |||||
- char node[PATH_MAX + 1]; | |||||
+ stat_t sbuf; | |||||
+ char node[DRM_NODE_NAME_MAX]; | |||||
const char *dev_name; | |||||
int node_type, subsystem_type; | |||||
int maj, min, n, ret, base; | |||||
@@ -3725,26 +3819,16 @@ int drmGetDevice2(int fd, uint32_t flags | |||||
if (node_type == -1) | |||||
return -ENODEV; | |||||
- switch (node_type) { | |||||
- case DRM_NODE_PRIMARY: | |||||
- dev_name = DRM_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_CONTROL: | |||||
- dev_name = DRM_CONTROL_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_RENDER: | |||||
- dev_name = DRM_RENDER_DEV_NAME; | |||||
- break; | |||||
- default: | |||||
+ dev_name = drmGetDeviceName(node_type); | |||||
+ if (!dev_name) | |||||
return -EINVAL; | |||||
- }; | |||||
base = drmGetMinorBase(node_type); | |||||
if (base < 0) | |||||
return -EINVAL; | |||||
- n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base); | |||||
- if (n == -1 || n >= PATH_MAX) | |||||
+ n = snprintf(node, sizeof(node), dev_name, DRM_DIR_NAME, min - base); | |||||
+ if (n == -1 || n >= sizeof(node)) | |||||
return -errno; | |||||
if (stat(node, &sbuf)) | |||||
return -EINVAL; | |||||
@@ -3765,8 +3849,8 @@ int drmGetDevice2(int fd, uint32_t flags | |||||
drmDevicePtr d; | |||||
DIR *sysdir; | |||||
struct dirent *dent; | |||||
- struct stat sbuf; | |||||
- char node[PATH_MAX + 1]; | |||||
+ stat_t sbuf; | |||||
+ char node[DRM_NODE_NAME_MAX]; | |||||
int node_type, subsystem_type; | |||||
int maj, min; | |||||
int ret, i, node_count; | |||||
@@ -3786,7 +3870,7 @@ int drmGetDevice2(int fd, uint32_t flags | |||||
maj = major(sbuf.st_rdev); | maj = major(sbuf.st_rdev); | ||||
min = minor(sbuf.st_rdev); | min = minor(sbuf.st_rdev); | ||||
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | ||||
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | + if ((DRM_MAJOR && maj != DRM_MAJOR) || !S_ISCHR(sbuf.st_mode)) | ||||
return -EINVAL; | return -EINVAL; | ||||
subsystem_type = drmParseSubsystemType(maj, min); | subsystem_type = drmParseSubsystemType(maj, min); | ||||
@@ -3814,7 +3925,7 @@ int drmGetDevice2(int fd, uint32_t flags | @@ -3807,14 +3891,14 @@ int drmGetDevice2(int fd, uint32_t flags | ||||
if (node_type < 0) | |||||
continue; | |||||
- snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name); | |||||
+ snprintf(node, sizeof(node), "%s/%s", DRM_DIR_NAME, dent->d_name); | |||||
if (stat(node, &sbuf)) | |||||
continue; | |||||
maj = major(sbuf.st_rdev); | maj = major(sbuf.st_rdev); | ||||
min = minor(sbuf.st_rdev); | min = minor(sbuf.st_rdev); | ||||
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | ||||
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | + if ((DRM_MAJOR && maj != DRM_MAJOR) || !S_ISCHR(sbuf.st_mode)) | ||||
continue; | continue; | ||||
if (drmParseSubsystemType(maj, min) != subsystem_type) | if (drmParseSubsystemType(maj, min) != subsystem_type) | ||||
@@ -3964,7 +4075,7 @@ int drmGetDevices2(uint32_t flags, drmDe | @@ -3912,7 +3996,7 @@ int drmGetDevice(int fd, drmDevicePtr *d | ||||
/** | |||||
* Get drm devices on the system | |||||
* | |||||
- * \param flags feature/behaviour bitmask | |||||
+ * \param flags feature/behavior bitmask | |||||
* \param devices the array of devices with drmDevicePtr elements | |||||
* can be NULL to get the device number first | |||||
* \param max_devices the maximum number of devices for the array | |||||
@@ -3931,8 +4015,8 @@ int drmGetDevices2(uint32_t flags, drmDe | |||||
drmDevicePtr device; | |||||
DIR *sysdir; | |||||
struct dirent *dent; | |||||
- struct stat sbuf; | |||||
- char node[PATH_MAX + 1]; | |||||
+ stat_t sbuf; | |||||
+ char node[DRM_NODE_NAME_MAX]; | |||||
int node_type, subsystem_type; | |||||
int maj, min; | |||||
int ret, i, node_count, device_count; | |||||
@@ -3957,14 +4041,14 @@ int drmGetDevices2(uint32_t flags, drmDe | |||||
if (node_type < 0) | |||||
continue; | |||||
- snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name); | |||||
+ snprintf(node, sizeof(node), "%s/%s", DRM_DIR_NAME, dent->d_name); | |||||
if (stat(node, &sbuf)) | |||||
continue; | |||||
maj = major(sbuf.st_rdev); | maj = major(sbuf.st_rdev); | ||||
min = minor(sbuf.st_rdev); | min = minor(sbuf.st_rdev); | ||||
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | ||||
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | + if ((DRM_MAJOR && maj != DRM_MAJOR) || !S_ISCHR(sbuf.st_mode)) | ||||
continue; | continue; | ||||
subsystem_type = drmParseSubsystemType(maj, min); | subsystem_type = drmParseSubsystemType(maj, min); | ||||
@@ -4108,7 +4219,7 @@ char *drmGetDeviceNameFromFd2(int fd) | @@ -4072,7 +4156,7 @@ int drmGetDevices(drmDevicePtr devices[] | ||||
maj = major(sbuf.st_rdev); | char *drmGetDeviceNameFromFd2(int fd) | ||||
min = minor(sbuf.st_rdev); | { | ||||
#ifdef __linux__ | |||||
- struct stat sbuf; | |||||
+ stat_t sbuf; | |||||
char path[PATH_MAX + 1], *value; | |||||
unsigned int maj, min; | |||||
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | @@ -4095,9 +4179,26 @@ char *drmGetDeviceNameFromFd2(int fd) | ||||
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) | free(value); | ||||
return strdup(path); | |||||
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | |||||
+ stat_t sbuf; | |||||
+ if (fstat(fd, &sbuf)) | |||||
+ return NULL; | |||||
+ | |||||
+ dev_t rdev = sbuf.st_rdev; | |||||
+ /* minor numbers don't depend on node name suffix, search for a match */ | |||||
+ for (int i = 0; i < DRM_MAX_MINOR; ++i) { | |||||
+ char node[DRM_NODE_NAME_MAX]; | |||||
+ for (int j = 0; j < DRM_NODE_MAX; ++j) { | |||||
+ snprintf(node, sizeof(node), drmGetDeviceName(j), | |||||
+ DRM_DIR_NAME, drmGetMinorBase(j) + i); | |||||
+ if (stat(node, &sbuf) == 0 && sbuf.st_rdev == rdev) | |||||
+ return strdup(node); | |||||
+ } | |||||
+ } | |||||
+ return NULL; | |||||
#else | |||||
- struct stat sbuf; | |||||
- char node[PATH_MAX + 1]; | |||||
+ stat_t sbuf; | |||||
+ char node[DRM_NODE_NAME_MAX]; | |||||
const char *dev_name; | |||||
int node_type; | |||||
int maj, min, n, base; | |||||
@@ -4115,26 +4216,16 @@ char *drmGetDeviceNameFromFd2(int fd) | |||||
if (node_type == -1) | |||||
return NULL; | return NULL; | ||||
node_type = drmGetMinorType(min); | - switch (node_type) { | ||||
- case DRM_NODE_PRIMARY: | |||||
- dev_name = DRM_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_CONTROL: | |||||
- dev_name = DRM_CONTROL_DEV_NAME; | |||||
- break; | |||||
- case DRM_NODE_RENDER: | |||||
- dev_name = DRM_RENDER_DEV_NAME; | |||||
- break; | |||||
- default: | |||||
+ dev_name = drmGetDeviceName(node_type); | |||||
+ if (!dev_name) | |||||
return NULL; | |||||
- }; | |||||
base = drmGetMinorBase(node_type); | |||||
if (base < 0) | |||||
return NULL; | |||||
- n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base); | |||||
- if (n == -1 || n >= PATH_MAX) | |||||
+ n = snprintf(node, sizeof(node), dev_name, DRM_DIR_NAME, min - base); | |||||
+ if (n == -1 || n >= sizeof(node)) | |||||
return NULL; | |||||
return strdup(node); |