Files
RedBear-OS/local/patches/libdrm/02-redox-dispatch.patch
T
vasilito dc68054305 restore lost packages from 0.2.3 + fix overwritten 0.2.4 files
- Restore 29 recipe symlinks (libdrm, qtbase, dbus, sddm, pipewire, etc.)
- Restore 33 patches (KDE, libdrm, mesa, pipewire, sddm, wireplumber)
- Restore 20+ local/scripts (audit, lint, test, build helpers)
- Restore src/cook/scheduler.rs, status.rs, gnu-config/
- Restore scripts/patch-inclusion-gate.sh, run_mini1.sh, validate-collision-log.sh
- Recover TLC source from HEAD (was overwritten by 0.2.3 checkout)
- Recover 11 local/docs plans from HEAD (were overwritten)
- Recover qt6-wayland-smoke symlink from HEAD
- Fix MOTD: remove garbled ASCII art, use clean text
- Update version: 0.2.0 -> 0.2.4 in os-release, motd, config
- Reduce filesystem_size: 1536 -> 512 MiB
- Add ABSOLUTE RULE to AGENTS.md: never delete/ignore packages
- Reduce pcid scheme log verbosity: info -> debug
2026-06-19 12:39:14 +03:00

807 lines
23 KiB
Diff

diff --git a/xf86drm.c b/xf86drm.c
index 3a10589..207c456 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -88,8 +88,10 @@
#endif
#include "xf86drm.h"
+#include "xf86drm_redox.h"
#include "libdrm_macros.h"
#include "drm_fourcc.h"
+#include "virtgpu_drm.h"
#include "util_math.h"
@@ -113,7 +115,7 @@
#define DRM_MAJOR 226 /* Linux */
#endif
-#if defined(__OpenBSD__) || defined(__DragonFly__)
+#if defined(__OpenBSD__) || defined(__DragonFly__) || defined(__redox__)
struct drm_pciinfo {
uint16_t domain;
uint8_t bus;
@@ -313,7 +315,6 @@ drmGetFormatModifierNameFromArm(uint64_t modifier)
uint64_t type = (modifier >> 52) & 0xf;
FILE *fp;
- size_t size = 0;
char *modifier_name = NULL;
bool result = false;
@@ -321,6 +322,7 @@ drmGetFormatModifierNameFromArm(uint64_t modifier)
fprintf(stderr, "open_memstream not available on Redox\n");
return NULL;
#else
+ size_t size = 0;
fp = open_memstream(&modifier_name, &size);
if (!fp)
return NULL;
@@ -425,12 +427,12 @@ drmGetFormatModifierNameFromAmd(uint64_t modifier)
uint64_t tile_version = AMD_FMT_MOD_GET(TILE_VERSION, modifier);
FILE *fp;
char *mod_amd = NULL;
- size_t size = 0;
#if defined(__redox__)
fprintf(stderr, "open_memstream not available on Redox\n");
return NULL;
#else
+ size_t size = 0;
fp = open_memstream(&mod_amd, &size);
if (!fp)
return NULL;
@@ -703,18 +705,366 @@ drm_public void drmFree(void *pt)
free(pt);
}
+#if defined(__redox__)
+static int redox_drm_write_all(int fd, const void *buf, size_t len)
+{
+ const uint8_t *bytes = buf;
+ size_t offset = 0;
+
+ while (offset < len) {
+ ssize_t written = write(fd, bytes + offset, len - offset);
+ if (written < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return -1;
+ }
+ if (written == 0) {
+ errno = EIO;
+ return -1;
+ }
+ offset += (size_t)written;
+ }
+
+ return 0;
+}
+
+static int redox_drm_read_all(int fd, void *buf, size_t len)
+{
+ uint8_t *bytes = buf;
+ size_t offset = 0;
+
+ while (offset < len) {
+ ssize_t read_count = read(fd, bytes + offset, len - offset);
+ if (read_count < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return -1;
+ }
+ if (read_count == 0) {
+ errno = EIO;
+ return -1;
+ }
+ offset += (size_t)read_count;
+ }
+
+ return 0;
+}
+
+static int redox_drm_send_request(int fd, unsigned long request_code,
+ const void *payload, size_t payload_size)
+{
+ const size_t request_word_size = sizeof(uintptr_t);
+ const size_t total_size = request_word_size + payload_size;
+ uint8_t stack_request[sizeof(uintptr_t)];
+ uint8_t *request_bytes = stack_request;
+ uintptr_t request_word = (uintptr_t)request_code;
+ size_t i;
+
+ if (total_size > sizeof(stack_request)) {
+ request_bytes = drmMalloc(total_size);
+ if (!request_bytes) {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+
+ for (i = 0; i < request_word_size; ++i)
+ request_bytes[i] = (uint8_t)((request_word >> (i * 8)) & 0xffU);
+
+ if (payload_size != 0)
+ memcpy(request_bytes + request_word_size, payload, payload_size);
+
+ if (redox_drm_write_all(fd, request_bytes, total_size) != 0) {
+ if (request_bytes != stack_request)
+ drmFree(request_bytes);
+ return -1;
+ }
+
+ if (request_bytes != stack_request)
+ drmFree(request_bytes);
+
+ return 0;
+}
+
+static int redox_drm_get_response_size(int fd, size_t *response_size)
+{
+ stat_t st;
+
+ if (fstat(fd, &st) != 0)
+ return -1;
+
+ *response_size = (size_t)st.st_size;
+ return 0;
+}
+
+unsigned long redox_translate_request(unsigned long linux_nr)
+{
+ switch (linux_nr) {
+ case 0x0C:
+ return REDOX_DRM_IOCTL_GET_CAP;
+ case 0x0D:
+ return REDOX_DRM_IOCTL_SET_CLIENT_CAP;
+ case 0x09:
+ return REDOX_DRM_IOCTL_GEM_CLOSE;
+ case 0xA6:
+ return REDOX_DRM_IOCTL_MODE_GETENCODER;
+ case 0xB3:
+ return REDOX_DRM_IOCTL_MODE_MAP_DUMB;
+ case 0xB4:
+ return REDOX_DRM_IOCTL_MODE_DESTROY_DUMB;
+ case 0xAF:
+ return REDOX_DRM_IOCTL_MODE_RMFB;
+ /* VirtGPU ioctls (NR 0x41-0x4B) */
+ case 0x41:
+ return REDOX_DRM_IOCTL_VIRTGPU_MAP;
+ case 0x42:
+ return REDOX_DRM_IOCTL_VIRTGPU_EXECBUFFER;
+ case 0x43:
+ return REDOX_DRM_IOCTL_VIRTGPU_GETPARAM;
+ case 0x44:
+ return REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE;
+ case 0x45:
+ return REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_INFO;
+ case 0x46:
+ return REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST;
+ case 0x47:
+ return REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST;
+ case 0x48:
+ return REDOX_DRM_IOCTL_VIRTGPU_WAIT;
+ case 0x49:
+ return REDOX_DRM_IOCTL_VIRTGPU_GET_CAPS;
+ case 0x4A:
+ return REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB;
+ case 0x4B:
+ return REDOX_DRM_IOCTL_VIRTGPU_CONTEXT_INIT;
+ /* Additional standard DRM ioctls */
+ case 0x00:
+ return REDOX_DRM_IOCTL_VERSION;
+ case 0xA0:
+ return REDOX_DRM_IOCTL_MODE_GETRESOURCES;
+ case 0xA1:
+ return REDOX_DRM_IOCTL_MODE_GETCRTC;
+ case 0xA2:
+ return REDOX_DRM_IOCTL_MODE_SETCRTC;
+ case 0xA3:
+ return REDOX_DRM_IOCTL_MODE_GETCONNECTOR;
+ case 0xA4:
+ return REDOX_DRM_IOCTL_MODE_PAGE_FLIP;
+ case 0xA8:
+ return REDOX_DRM_IOCTL_MODE_CREATE_DUMB;
+ case 0xAC:
+ return REDOX_DRM_IOCTL_MODE_ADDFB;
+ case 0x2B:
+ return REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD;
+ case 0x2C:
+ return REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE;
+ /* DRM_IOCTL_GET_PCIINFO — PCI device information for driver discovery */
+ case 0x15:
+ return REDOX_DRM_IOCTL_GET_PCI_INFO;
+ /* DRM auth/master ioctls */
+ case 0x02: /* GET_MAGIC — DRM_IOR(0x02, struct drm_auth) */
+ return REDOX_DRM_IOCTL_GET_MAGIC;
+ case 0x11: /* AUTH_MAGIC — DRM_IOW(0x11, struct drm_auth) */
+ return REDOX_DRM_IOCTL_AUTH_MAGIC;
+ case 0x1e: /* SET_MASTER — DRM_IO(0x1e) */
+ return REDOX_DRM_IOCTL_SET_MASTER;
+ case 0x1f: /* DROP_MASTER — DRM_IO(0x1f) */
+ return REDOX_DRM_IOCTL_DROP_MASTER;
+ default:
+ return 0;
+ }
+}
+
+int redox_drm_exchange(int fd, unsigned long request_code,
+ const void *payload, size_t payload_size,
+ void *response, size_t response_capacity,
+ size_t *response_size)
+{
+ uint8_t stack_buffer[64];
+ uint8_t *response_buffer = stack_buffer;
+ size_t actual_response_size = 0;
+
+ if (redox_drm_send_request(fd, request_code, payload, payload_size) != 0)
+ return -1;
+
+ if (redox_drm_get_response_size(fd, &actual_response_size) != 0)
+ return -1;
+
+ if (response_size)
+ *response_size = actual_response_size;
+
+ if (actual_response_size == 0)
+ return 0;
+
+ if (response && response_capacity >= actual_response_size) {
+ return redox_drm_read_all(fd, response, actual_response_size);
+ }
+
+ if (actual_response_size > sizeof(stack_buffer)) {
+ response_buffer = drmMalloc(actual_response_size);
+ if (!response_buffer) {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+
+ if (redox_drm_read_all(fd, response_buffer, actual_response_size) != 0) {
+ if (response_buffer != stack_buffer)
+ drmFree(response_buffer);
+ return -1;
+ }
+
+ if (response_buffer != stack_buffer)
+ drmFree(response_buffer);
+
+ if (response && response_capacity < actual_response_size) {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ return 0;
+}
+
+int redox_drm_exchange_alloc(int fd, unsigned long request_code,
+ const void *payload, size_t payload_size,
+ void **response, size_t *response_size)
+{
+ size_t actual_response_size = 0;
+ void *allocated_response = NULL;
+
+ if (!response) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (redox_drm_send_request(fd, request_code, payload, payload_size) != 0)
+ return -1;
+
+ if (redox_drm_get_response_size(fd, &actual_response_size) != 0)
+ return -1;
+
+ if (actual_response_size != 0) {
+ allocated_response = drmMalloc(actual_response_size);
+ if (!allocated_response) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ if (redox_drm_read_all(fd, allocated_response, actual_response_size) != 0) {
+ drmFree(allocated_response);
+ return -1;
+ }
+ }
+
+ *response = allocated_response;
+ if (response_size)
+ *response_size = actual_response_size;
+ return 0;
+}
+
+static size_t redox_drm_expected_response_size(unsigned long linux_nr, size_t arg_size)
+{
+ switch (linux_nr) {
+ case 0x00: /* VERSION */
+ case 0x0C:
+ case 0x2B: /* PRIME_HANDLE_TO_FD */
+ case 0x2C: /* PRIME_FD_TO_HANDLE */
+ case 0x41: /* VIRTGPU_MAP */
+ case 0x43: /* VIRTGPU_GETPARAM */
+ case 0x44: /* VIRTGPU_RESOURCE_CREATE */
+ case 0x45: /* VIRTGPU_RESOURCE_INFO */
+ case 0xA0: /* MODE_GETRESOURCES */
+ case 0xA1: /* MODE_GETCRTC */
+ case 0xA3: /* MODE_GETCONNECTOR */
+ case 0xA8: /* MODE_CREATE_DUMB */
+ case 0xAC: /* MODE_ADDFB */
+ case 0xA6:
+ case 0xB3:
+ return arg_size;
+ case 0x02: /* GET_MAGIC — returns struct drm_auth (magic u32) */
+ return arg_size;
+ case 0x11: /* AUTH_MAGIC — returns struct drm_auth (magic u32) */
+ return arg_size;
+ default:
+ return 0;
+ }
+}
+
+int redox_drm_simple_ioctl(int fd, unsigned long request, void *arg)
+{
+ const unsigned long linux_nr = REDOX_LINUX_IOCTL_NR(request);
+ const unsigned long request_code = redox_translate_request(linux_nr);
+ const size_t arg_size = REDOX_LINUX_IOCTL_SIZE(request);
+ const size_t expected_response_size = redox_drm_expected_response_size(linux_nr, arg_size);
+
+ if (request_code == 0) {
+ errno = ENOTTY;
+ return -1;
+ }
+
+ if (linux_nr == 0x42) { /* VIRTGPU_EXECBUFFER */
+ struct drm_virtgpu_execbuffer *eb = arg;
+ size_t total = arg_size + eb->size;
+ uint8_t *buf = drmMalloc((int)total);
+ int ret;
+
+ if (!buf)
+ return -1;
+
+ memcpy(buf, arg, arg_size);
+ if (eb->size > 0 && eb->command)
+ memcpy(buf + arg_size, (void *)(uintptr_t)eb->command, eb->size);
+
+ ret = redox_drm_exchange(fd, request_code, buf, total, NULL, 0, NULL);
+ drmFree(buf);
+ return ret;
+ }
+
+ if (linux_nr == 0x49) { /* VIRTGPU_GET_CAPS */
+ struct drm_virtgpu_get_caps *gc = arg;
+ void *resp;
+ size_t resp_size;
+ int ret;
+
+ ret = redox_drm_exchange_alloc(fd, request_code, arg, arg_size, &resp, &resp_size);
+ if (ret == 0 && resp && resp_size > 0) {
+ size_t copy = resp_size < gc->size ? resp_size : gc->size;
+
+ memcpy((void *)(uintptr_t)gc->addr, resp, copy);
+ drmFree(resp);
+ }
+
+ return ret;
+ }
+
+ if (redox_drm_exchange(fd, request_code,
+ arg, arg ? arg_size : 0,
+ expected_response_size ? arg : NULL,
+ expected_response_size,
+ NULL) != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
/**
* Call ioctl, restarting if it is interrupted
*/
drm_public int
drmIoctl(int fd, unsigned long request, void *arg)
{
+ #if defined(__redox__)
+ return redox_drm_simple_ioctl(fd, request, arg);
+ #else
int ret;
do {
ret = ioctl(fd, request, arg);
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
return ret;
+ #endif
}
static unsigned long drmGetKeyFromFd(int fd)
@@ -1093,6 +1443,7 @@ static int drmGetMinorType(int major, int minor)
return -1;
}
+#if !defined(__redox__)
static const char *drmGetMinorName(int type)
{
switch (type) {
@@ -1104,6 +1455,7 @@ static const char *drmGetMinorName(int type)
return NULL;
}
}
+#endif
/**
* Open the device by bus ID.
@@ -1201,7 +1553,11 @@ static int drmOpenByName(const char *name, int type)
for (i = base; i < base + DRM_MAX_MINOR; i++) {
if ((fd = drmOpenMinor(i, 1, type)) >= 0) {
if ((version = drmGetVersion(fd))) {
+ #if defined(__redox__)
+ if (!version->name || !strcmp(version->name, name)) {
+ #else
if (!strcmp(version->name, name)) {
+ #endif
drmFreeVersion(version);
id = drmGetBusid(fd);
drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
@@ -1354,6 +1710,7 @@ drm_public void drmFreeVersion(drmVersionPtr v)
* Used by drmGetVersion() to free the memory pointed by \p %v as well as all
* the non-null strings pointers in it.
*/
+#if !defined(__redox__)
static void drmFreeKernelVersion(drm_version_t *v)
{
if (!v)
@@ -1363,6 +1720,7 @@ static void drmFreeKernelVersion(drm_version_t *v)
drmFree(v->desc);
drmFree(v);
}
+#endif
/**
@@ -1375,6 +1733,7 @@ static void drmFreeKernelVersion(drm_version_t *v)
* Used by drmGetVersion() to translate the information returned by the ioctl
* interface in a private structure into the public structure counterpart.
*/
+#if !defined(__redox__)
static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
{
d->version_major = s->version_major;
@@ -1387,6 +1746,7 @@ static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
d->desc_len = s->desc_len;
d->desc = s->desc ? strdup(s->desc) : NULL;
}
+#endif
/**
@@ -1406,6 +1766,50 @@ static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
*/
drm_public drmVersionPtr drmGetVersion(int fd)
{
+ #if defined(__redox__)
+ drmVersionPtr retval = drmMalloc(sizeof(*retval));
+ struct redox_drm_version_wire version;
+
+ if (!retval)
+ return NULL;
+
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_VERSION,
+ NULL, 0,
+ &version, sizeof(version),
+ NULL) != 0) {
+ drmFree(retval);
+ return NULL;
+ }
+
+ memclear(*retval);
+ retval->version_major = version.major;
+ retval->version_minor = version.minor;
+ retval->version_patchlevel = version.patch;
+
+ /* The scheme returns a NUL-terminated driver name in version.name.
+ * KWin drm_gpu.cpp dereferences version->name unconditionally
+ * (strstr checks for "i915", "amdgpu", "virtio" etc.) so it must
+ * never be NULL.
+ */
+ version.name[sizeof(version.name) - 1] = '\0';
+ if (version.name[0] != '\0') {
+ size_t len = strlen(version.name);
+ retval->name = drmMalloc(len + 1);
+ if (retval->name) {
+ memcpy(retval->name, version.name, len + 1);
+ retval->name_len = len;
+ }
+ } else {
+ const char fallback[] = "redox-drm";
+ retval->name = drmMalloc(sizeof(fallback));
+ if (retval->name) {
+ memcpy(retval->name, fallback, sizeof(fallback));
+ retval->name_len = sizeof(fallback) - 1;
+ }
+ }
+
+ return retval;
+ #else
drmVersionPtr retval;
drm_version_t *version = drmMalloc(sizeof(*version));
@@ -1436,6 +1840,7 @@ drm_public drmVersionPtr drmGetVersion(int fd)
drmCopyVersion(retval, version);
drmFreeKernelVersion(version);
return retval;
+ #endif
}
@@ -3400,6 +3805,23 @@ drm_public int drmGetNodeTypeFromFd(int fd)
drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags,
int *prime_fd)
{
+ #if defined(__redox__)
+ struct redox_drm_prime_handle_to_fd_wire request;
+ struct redox_drm_prime_handle_to_fd_response_wire response;
+
+ memclear(request);
+ request.handle = handle;
+ request.flags = flags;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD,
+ &request, sizeof(request),
+ &response, sizeof(response),
+ NULL) != 0) {
+ return -errno;
+ }
+
+ *prime_fd = response.fd;
+ return 0;
+ #else
struct drm_prime_handle args;
int ret;
@@ -3413,10 +3835,27 @@ drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags,
*prime_fd = args.fd;
return 0;
+ #endif
}
drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
{
+ #if defined(__redox__)
+ struct redox_drm_prime_fd_to_handle_wire request;
+ struct redox_drm_prime_fd_to_handle_response_wire response;
+
+ memclear(request);
+ request.fd = prime_fd;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE,
+ &request, sizeof(request),
+ &response, sizeof(response),
+ NULL) != 0) {
+ return -errno;
+ }
+
+ *handle = response.handle;
+ return 0;
+ #else
struct drm_prime_handle args;
int ret;
@@ -3428,6 +3867,7 @@ drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
*handle = args.handle;
return 0;
+ #endif
}
drm_public int drmCloseBufferHandle(int fd, uint32_t handle)
@@ -3544,7 +3984,7 @@ static char *drmGetMinorNameForFD(int fd, int type)
n = drmGetNodePath(buf, sizeof(buf), type, min);
if (n < 0)
return NULL;
- if (n == -1 || n >= sizeof(buf))
+ if ((size_t)n >= sizeof(buf))
return NULL;
return strdup(buf);
@@ -3666,7 +4106,7 @@ static int drmParseSubsystemType(int maj, int min)
return DRM_BUS_VIRTIO;
}
return subsystem_type;
-#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
+#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__redox__)
return DRM_BUS_PCI;
#else
#warning "Missing implementation of drmParseSubsystemType"
@@ -3800,6 +4240,21 @@ static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
return 0;
#elif defined(__FreeBSD__)
return get_sysctl_pci_bus_info(maj, min, info);
+#elif defined(__redox__)
+ int rfd = open("/scheme/drm/card0", O_RDONLY);
+ if (rfd < 0)
+ return -errno;
+ uint8_t buf[22];
+ size_t rsize = 0;
+ int ret = redox_drm_exchange(rfd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0, buf, sizeof(buf), &rsize);
+ close(rfd);
+ if (ret != 0 || rsize < 17)
+ return -EIO;
+ info->domain = buf[10] | (buf[11] << 8) | (buf[12] << 16) | (buf[13] << 24);
+ info->bus = buf[14];
+ info->dev = buf[15];
+ info->func = buf[16];
+ return 0;
#else
#warning "Missing implementation of drmParsePciBusInfo"
return -EINVAL;
@@ -4009,6 +4464,23 @@ static int drmParsePciDeviceInfo(int maj, int min,
device->revision_id = results[0].pc_revid;
return 0;
+#elif defined(__redox__)
+ int rfd2 = open("/scheme/drm/card0", O_RDONLY);
+ if (rfd2 < 0)
+ return -errno;
+ uint8_t dbuf[22];
+ size_t drsize = 0;
+ int dret = redox_drm_exchange(rfd2, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0, dbuf, sizeof(dbuf), &drsize);
+ close(rfd2);
+ if (dret != 0 || drsize < 9)
+ return -EIO;
+ device->vendor_id = dbuf[0] | (dbuf[1] << 8);
+ device->device_id = dbuf[2] | (dbuf[3] << 8);
+ device->subvendor_id = dbuf[4] | (dbuf[5] << 8);
+ device->subdevice_id = dbuf[6] | (dbuf[7] << 8);
+ if (drsize >= 9)
+ device->revision_id = dbuf[8];
+ return 0;
#else
#warning "Missing implementation of drmParsePciDeviceInfo"
return -EINVAL;
@@ -4661,6 +5133,66 @@ drm_public int drmGetDeviceFromDevId(dev_t find_rdev, uint32_t flags, drmDeviceP
*device = d;
+ return 0;
+#elif defined(__redox__)
+ /* On Redox there is no /dev/dri/ directory to enumerate.
+ * Instead, open /scheme/drm/card0 and query PCI info to
+ * construct a single drmDevice that serves as both primary
+ * and render node. */
+ drmDevicePtr devp;
+ char *pptr;
+ int max_node_length = 64, i;
+ size_t extra, psize;
+ uint8_t pbuf[22];
+ size_t prsize = 0;
+ int pret, fd;
+
+ if (device == NULL)
+ return -EINVAL;
+ if (drm_device_validate_flags(flags))
+ return -EINVAL;
+
+ fd = open("/scheme/drm/card0", O_RDWR | O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ pret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0,
+ pbuf, sizeof(pbuf), &prsize);
+ close(fd);
+ if (pret != 0 || prsize < 17)
+ return -EIO;
+
+ extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
+ psize = sizeof(drmDevice) + extra + sizeof(drmPciBusInfo) + sizeof(drmPciDeviceInfo);
+ devp = calloc(1, psize);
+ if (!devp)
+ return -ENOMEM;
+
+ devp->bustype = DRM_BUS_PCI;
+ /* Advertise both PRIMARY and RENDER — same path on Redox */
+ devp->available_nodes = (1 << DRM_NODE_PRIMARY) | (1 << DRM_NODE_RENDER);
+ pptr = (char *)devp + sizeof(drmDevice);
+ devp->nodes = (char **)pptr;
+ pptr += DRM_NODE_MAX * sizeof(void *);
+ for (i = 0; i < DRM_NODE_MAX; i++) { devp->nodes[i] = pptr; pptr += max_node_length; }
+ snprintf(devp->nodes[DRM_NODE_PRIMARY], max_node_length, "/scheme/drm/card0");
+ snprintf(devp->nodes[DRM_NODE_RENDER], max_node_length, "/scheme/drm/card0");
+
+ devp->businfo.pci = (drmPciBusInfoPtr)pptr;
+ pptr += sizeof(drmPciBusInfo);
+ devp->businfo.pci->domain = pbuf[10] | (pbuf[11] << 8) | (pbuf[12] << 16) | (pbuf[13] << 24);
+ devp->businfo.pci->bus = pbuf[14];
+ devp->businfo.pci->dev = pbuf[15];
+ devp->businfo.pci->func = pbuf[16];
+
+ devp->deviceinfo.pci = (drmPciDeviceInfoPtr)pptr;
+ devp->deviceinfo.pci->vendor_id = pbuf[0] | (pbuf[1] << 8);
+ devp->deviceinfo.pci->device_id = pbuf[2] | (pbuf[3] << 8);
+ devp->deviceinfo.pci->subvendor_id = pbuf[4] | (pbuf[5] << 8);
+ devp->deviceinfo.pci->subdevice_id = pbuf[6] | (pbuf[7] << 8);
+ devp->deviceinfo.pci->revision_id = pbuf[8];
+
+ *device = devp;
return 0;
#else
drmDevicePtr local_devices[MAX_DRM_NODES];
@@ -4761,6 +5293,66 @@ drm_public int drmGetNodeTypeFromDevId(dev_t devid)
*/
drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
{
+#if defined(__redox__)
+ uint8_t pbuf[22];
+ size_t prsize = 0;
+ int pret;
+ uint16_t pvendor_id, pdevice_id, psubvendor_id, psubdevice_id, pdomain;
+ uint8_t prevision_id, pbus, pdev, pfunc;
+ const char *pnode;
+ int max_node_length, i;
+ size_t extra, psize;
+ drmDevicePtr devp;
+ char *pptr;
+
+ pret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0,
+ pbuf, sizeof(pbuf), &prsize);
+ if (pret != 0 || prsize < 17)
+ return -EIO;
+
+ pvendor_id = pbuf[0] | (pbuf[1] << 8);
+ pdevice_id = pbuf[2] | (pbuf[3] << 8);
+ psubvendor_id = pbuf[4] | (pbuf[5] << 8);
+ psubdevice_id = pbuf[6] | (pbuf[7] << 8);
+ prevision_id = pbuf[8];
+ pdomain = pbuf[10] | (pbuf[11] << 8) | (pbuf[12] << 16) | (pbuf[13] << 24);
+ pbus = pbuf[14];
+ pdev = pbuf[15];
+ pfunc = pbuf[16];
+
+ pnode = "/scheme/drm/card0";
+ max_node_length = 64;
+ extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
+ psize = sizeof(drmDevice) + extra + sizeof(drmPciBusInfo) + sizeof(drmPciDeviceInfo);
+ devp = calloc(1, psize);
+ if (!devp)
+ return -ENOMEM;
+
+ devp->bustype = DRM_BUS_PCI;
+ devp->available_nodes = 1 << DRM_NODE_PRIMARY;
+ pptr = (char *)devp + sizeof(drmDevice);
+ devp->nodes = (char **)pptr;
+ pptr += DRM_NODE_MAX * sizeof(void *);
+ for (i = 0; i < DRM_NODE_MAX; i++) { devp->nodes[i] = pptr; pptr += max_node_length; }
+ snprintf(devp->nodes[DRM_NODE_PRIMARY], max_node_length, "%s", pnode);
+
+ devp->businfo.pci = (drmPciBusInfoPtr)pptr;
+ pptr += sizeof(drmPciBusInfo);
+ devp->businfo.pci->domain = pdomain;
+ devp->businfo.pci->bus = pbus;
+ devp->businfo.pci->dev = pdev;
+ devp->businfo.pci->func = pfunc;
+
+ devp->deviceinfo.pci = (drmPciDeviceInfoPtr)pptr;
+ devp->deviceinfo.pci->vendor_id = pvendor_id;
+ devp->deviceinfo.pci->device_id = pdevice_id;
+ devp->deviceinfo.pci->subvendor_id = psubvendor_id;
+ devp->deviceinfo.pci->subdevice_id = psubdevice_id;
+ devp->deviceinfo.pci->revision_id = prevision_id;
+
+ *device = devp;
+ return 0;
+#else
struct stat sbuf;
if (fd == -1)
@@ -4773,6 +5365,7 @@ drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
return -EINVAL;
return drmGetDeviceFromDevId(sbuf.st_rdev, flags, device);
+#endif
}
/**